gdk: add endian-aware 30-bit RGB converters
Add specialized converters for both 10:10:10 channel layouts and both X image byte orders.
Preserve depth-30 padding bits, avoid invalid negative shifts in the generic converter and select endian conversion at compile time.
Validated with a real Xvfb 30-bit A/B pixel test and cross-target endian store checks.
Derived from downstream commit 02a2c61f2d.
Co-authored-by: Daemonratte <daemonratte@daemonratte.net>
This commit is contained in:
parent
00177dd11c
commit
71023e0333
1 changed files with 90 additions and 0 deletions
90
gdk/gdkrgb.c
90
gdk/gdkrgb.c
|
|
@ -2242,6 +2242,68 @@ gdk_rgb_convert_8880_br (GdkRgbInfo *image_info, GdkImage *image,
|
|||
}
|
||||
}
|
||||
|
||||
#define DEFINE_GDK_RGB_CONVERT_101010(name, high, low, to_order) \
|
||||
static void \
|
||||
name (GdkRgbInfo *image_info, GdkImage *image, \
|
||||
gint x0, gint y0, gint width, gint height, \
|
||||
const guchar *buf, int rowstride, \
|
||||
gint x_align, gint y_align, GdkRgbCmap *cmap) \
|
||||
{ \
|
||||
int y, w; \
|
||||
guchar *obuf, *p; \
|
||||
gint bpl; \
|
||||
const guchar *bptr, *bp2; \
|
||||
guint32 r, g, b; \
|
||||
guint32 pixel; \
|
||||
guint32 alpha_mask; \
|
||||
\
|
||||
alpha_mask = image_info->visual->depth == 32 ? 0xc0000000U : 0; \
|
||||
\
|
||||
bptr = buf; \
|
||||
bpl = image->bpl; \
|
||||
obuf = ((guchar *) image->mem) + y0 * bpl + x0 * 4; \
|
||||
\
|
||||
for (y = 0; y < height; y++) \
|
||||
{ \
|
||||
bp2 = bptr; \
|
||||
p = obuf; \
|
||||
w = width; \
|
||||
\
|
||||
while (w--) \
|
||||
{ \
|
||||
r = *bp2++; \
|
||||
g = *bp2++; \
|
||||
b = *bp2++; \
|
||||
\
|
||||
r = (r << 2) | (r >> 6); \
|
||||
g = (g << 2) | (g >> 6); \
|
||||
b = (b << 2) | (b >> 6); \
|
||||
\
|
||||
pixel = alpha_mask | \
|
||||
(high << 20) | \
|
||||
(g << 10) | \
|
||||
low; \
|
||||
\
|
||||
*((guint32 *) p) = to_order (pixel); \
|
||||
p += 4; \
|
||||
} \
|
||||
\
|
||||
bptr += rowstride; \
|
||||
obuf += bpl; \
|
||||
} \
|
||||
}
|
||||
|
||||
DEFINE_GDK_RGB_CONVERT_101010 (gdk_rgb_convert_101010_r_low_lsb,
|
||||
b, r, GUINT32_TO_LE)
|
||||
DEFINE_GDK_RGB_CONVERT_101010 (gdk_rgb_convert_101010_b_low_lsb,
|
||||
r, b, GUINT32_TO_LE)
|
||||
DEFINE_GDK_RGB_CONVERT_101010 (gdk_rgb_convert_101010_r_low_msb,
|
||||
b, r, GUINT32_TO_BE)
|
||||
DEFINE_GDK_RGB_CONVERT_101010 (gdk_rgb_convert_101010_b_low_msb,
|
||||
r, b, GUINT32_TO_BE)
|
||||
|
||||
#undef DEFINE_GDK_RGB_CONVERT_101010
|
||||
|
||||
/* Generic truecolor/directcolor conversion function. Slow, but these
|
||||
are oddball modes. */
|
||||
static void
|
||||
|
|
@ -3195,6 +3257,34 @@ gdk_rgb_select_conv (GdkRgbInfo *image_info)
|
|||
#endif
|
||||
}
|
||||
#endif
|
||||
else if (bpp == 32 && (depth == 30 || depth == 32) &&
|
||||
vtype == GDK_VISUAL_TRUE_COLOR &&
|
||||
byte_order == GDK_LSB_FIRST &&
|
||||
red_mask == 0x000003ff &&
|
||||
green_mask == 0x000ffc00 &&
|
||||
blue_mask == 0x3ff00000)
|
||||
conv = gdk_rgb_convert_101010_r_low_lsb;
|
||||
else if (bpp == 32 && (depth == 30 || depth == 32) &&
|
||||
vtype == GDK_VISUAL_TRUE_COLOR &&
|
||||
byte_order == GDK_LSB_FIRST &&
|
||||
red_mask == 0x3ff00000 &&
|
||||
green_mask == 0x000ffc00 &&
|
||||
blue_mask == 0x000003ff)
|
||||
conv = gdk_rgb_convert_101010_b_low_lsb;
|
||||
else if (bpp == 32 && (depth == 30 || depth == 32) &&
|
||||
vtype == GDK_VISUAL_TRUE_COLOR &&
|
||||
byte_order == GDK_MSB_FIRST &&
|
||||
red_mask == 0x000003ff &&
|
||||
green_mask == 0x000ffc00 &&
|
||||
blue_mask == 0x3ff00000)
|
||||
conv = gdk_rgb_convert_101010_r_low_msb;
|
||||
else if (bpp == 32 && (depth == 30 || depth == 32) &&
|
||||
vtype == GDK_VISUAL_TRUE_COLOR &&
|
||||
byte_order == GDK_MSB_FIRST &&
|
||||
red_mask == 0x3ff00000 &&
|
||||
green_mask == 0x000ffc00 &&
|
||||
blue_mask == 0x000003ff)
|
||||
conv = gdk_rgb_convert_101010_b_low_msb;
|
||||
else if (vtype == GDK_VISUAL_TRUE_COLOR && byte_order == GDK_LSB_FIRST)
|
||||
{
|
||||
conv = gdk_rgb_convert_truecolor_lsb;
|
||||
|
|
|
|||
Loading…
Reference in a new issue