gdk: add direct gray format converters

This commit is contained in:
Daemonratte 2026-09-01 15:04:49 +02:00
commit 5212f7ef37

View file

@ -3542,50 +3542,145 @@ gdk_rgb_gray_to_stage (guchar *stage,
/* Generic gray conversion function - convert to 24bit packed, then go
from there. */
static void
gdk_rgb_convert_gray_0888_native (GdkRgbInfo *image_info, GdkImage *image,
gint x0, gint y0, gint width, gint height,
const guchar *buf, gint rowstride,
gint x_align, gint y_align, GdkRgbCmap *cmap)
{
gint y, w;
gint bpl = image->bpl;
guchar *obuf = ((guchar *) image->mem) + y0 * bpl + x0 * 4;
for (y = 0; y < height; y++)
{
const guchar *p = buf;
guchar *q = obuf;
w = width;
while (w--)
{
guchar g = *p++;
/*
* Store bytes explicitly here. Word-store performance varies by
* microarchitecture even within one ISA, so keep this generic path
* free of CPU-specific runtime dispatch.
*/
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
q[0] = g;
q[1] = g;
q[2] = g;
q[3] = 0xff;
#else
q[0] = 0xff;
q[1] = g;
q[2] = g;
q[3] = g;
#endif
q += 4;
}
buf += rowstride;
obuf += bpl;
}
#define DEFINE_GDK_RGB_GRAY_DIRECT(name, qtype, pixel_bytes, setup, store) \
static void \
name (GdkRgbInfo *image_info, \
GdkImage *image, \
gint x0, \
gint y0, \
gint width, \
gint height, \
const guchar *buf, \
gint rowstride, \
gint x_align, \
gint y_align, \
GdkRgbCmap *cmap) \
{ \
const guchar *src = buf; \
guchar *dst = ((guchar *) image->mem) + \
y0 * image->bpl + x0 * (pixel_bytes); \
gint x, y; \
\
setup \
\
(void) x_align; \
(void) y_align; \
(void) cmap; \
\
for (y = 0; y < height; y++) \
{ \
const guchar *p = src; \
qtype *q = (qtype *) dst; \
\
for (x = 0; x < width; x++) \
{ \
guint32 g = *p++; \
store \
} \
\
src += rowstride; \
dst += image->bpl; \
} \
}
DEFINE_GDK_RGB_GRAY_DIRECT (
gdk_rgb_convert_gray_555_br,
guint16,
2,
(void) image_info;,
guint16 pixel =
((g & 0xf8) << 7) |
((g & 0xf8) << 2) |
(g >> 3);
*q++ = (guint16) ((pixel << 8) | (pixel >> 8));)
DEFINE_GDK_RGB_GRAY_DIRECT (
gdk_rgb_convert_gray_565_br,
guint16,
2,
(void) image_info;,
guint16 pixel =
((g & 0xf8) << 8) |
((g & 0xfc) << 3) |
(g >> 3);
*q++ = (guint16) ((pixel << 8) | (pixel >> 8));)
DEFINE_GDK_RGB_GRAY_DIRECT (
gdk_rgb_convert_gray_888,
guchar,
3,
(void) image_info;,
q[0] = g;
q[1] = g;
q[2] = g;
q += 3;)
DEFINE_GDK_RGB_GRAY_DIRECT (
gdk_rgb_convert_gray_0888,
guchar,
4,
(void) image_info;,
q[0] = g;
q[1] = g;
q[2] = g;
q[3] = 0xff;
q += 4;)
DEFINE_GDK_RGB_GRAY_DIRECT (
gdk_rgb_convert_gray_0888_br,
guchar,
4,
(void) image_info;,
q[0] = 0xff;
q[1] = g;
q[2] = g;
q[3] = g;
q += 4;)
DEFINE_GDK_RGB_GRAY_DIRECT (
gdk_rgb_convert_gray_8880_br,
guint32,
4,
(void) image_info;,
*q++ =
(g << 16) |
(g << 8) |
g;)
DEFINE_GDK_RGB_GRAY_DIRECT (
gdk_rgb_convert_gray_101010_lsb,
guint32,
4,
guint32 alpha_mask =
image_info->visual->depth == 32
? 0xc0000000U
: 0;,
guint32 g10 =
(g << 2) | (g >> 6);
*q++ = GUINT32_TO_LE (
alpha_mask |
(g10 << 20) |
(g10 << 10) |
g10);)
DEFINE_GDK_RGB_GRAY_DIRECT (
gdk_rgb_convert_gray_101010_msb,
guint32,
4,
guint32 alpha_mask =
image_info->visual->depth == 32
? 0xc0000000U
: 0;,
guint32 g10 =
(g << 2) | (g >> 6);
*q++ = GUINT32_TO_BE (
alpha_mask |
(g10 << 20) |
(g10 << 10) |
g10);)
#undef DEFINE_GDK_RGB_GRAY_DIRECT
DEFINE_STAGED_CONVERTER (gdk_rgb_convert_gray_generic,
conv, gdk_rgb_gray_to_stage)
@ -3903,6 +3998,11 @@ gdk_rgb_select_conv (GdkRgbInfo *image_info)
conv_indexed = gdk_rgb_convert_indexed_lut;
break;
case GDK_RGB_FORMAT_555_BR:
conv_gray = gdk_rgb_convert_gray_555_br;
conv_gray_d = gdk_rgb_convert_gray_555_br;
break;
case GDK_RGB_FORMAT_565:
conv_32 = gdk_rgb_convert_32_565;
conv_32_d = gdk_rgb_convert_32_565_d;
@ -3910,26 +4010,50 @@ gdk_rgb_select_conv (GdkRgbInfo *image_info)
conv_indexed = gdk_rgb_convert_indexed_lut;
break;
case GDK_RGB_FORMAT_565_BR:
conv_gray = gdk_rgb_convert_gray_565_br;
conv_gray_d = gdk_rgb_convert_gray_565_br;
break;
case GDK_RGB_FORMAT_0888:
conv_32 = gdk_rgb_convert_32_0888;
conv_32_d = gdk_rgb_convert_32_0888;
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
conv_gray = gdk_rgb_convert_gray_0888_native;
conv_gray_d = gdk_rgb_convert_gray_0888_native;
#endif
conv_gray = gdk_rgb_convert_gray_0888;
conv_gray_d = gdk_rgb_convert_gray_0888;
conv_indexed = gdk_rgb_convert_indexed_lut;
break;
case GDK_RGB_FORMAT_0888_BR:
conv_32 = gdk_rgb_convert_32_0888_br;
conv_32_d = gdk_rgb_convert_32_0888_br;
#if G_BYTE_ORDER == G_BIG_ENDIAN
conv_gray = gdk_rgb_convert_gray_0888_native;
conv_gray_d = gdk_rgb_convert_gray_0888_native;
#endif
conv_gray = gdk_rgb_convert_gray_0888_br;
conv_gray_d = gdk_rgb_convert_gray_0888_br;
conv_indexed = gdk_rgb_convert_indexed_lut;
break;
case GDK_RGB_FORMAT_888_LSB:
case GDK_RGB_FORMAT_888_MSB:
conv_gray = gdk_rgb_convert_gray_888;
conv_gray_d = gdk_rgb_convert_gray_888;
break;
case GDK_RGB_FORMAT_8880_BR:
conv_gray = gdk_rgb_convert_gray_8880_br;
conv_gray_d = gdk_rgb_convert_gray_8880_br;
break;
case GDK_RGB_FORMAT_101010_R_LOW_LSB:
case GDK_RGB_FORMAT_101010_B_LOW_LSB:
conv_gray = gdk_rgb_convert_gray_101010_lsb;
conv_gray_d = gdk_rgb_convert_gray_101010_lsb;
break;
case GDK_RGB_FORMAT_101010_R_LOW_MSB:
case GDK_RGB_FORMAT_101010_B_LOW_MSB:
conv_gray = gdk_rgb_convert_gray_101010_msb;
conv_gray_d = gdk_rgb_convert_gray_101010_msb;
break;
default:
break;
}