gdk: cache native indexed conversion tables

This commit is contained in:
Daemonratte 2026-09-01 15:04:50 +02:00
commit db79889ab4

View file

@ -117,7 +117,7 @@ struct _GdkRgbCmapInfo
GdkRgbInfo *image_info; GdkRgbInfo *image_info;
GdkRgbCmap *cmap; GdkRgbCmap *cmap;
guchar lut[256]; /* For 8-bit modes */ guchar lut[1]; /* variable-sized private LUT */
}; };
static GdkRgbCmapInfo *gdk_rgb_cmap_get_info (GdkRgbCmap *cmap, GdkRgbInfo *image_info); static GdkRgbCmapInfo *gdk_rgb_cmap_get_info (GdkRgbCmap *cmap, GdkRgbInfo *image_info);
@ -3508,6 +3508,61 @@ gdk_rgb_convert_indexed_lut (GdkRgbInfo *image_info, GdkImage *image,
} }
#define DEFINE_GDK_RGB_INDEXED_888_CONVERTER(name, shift0, shift2) \
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) \
{ \
const guchar *src = buf; \
guchar *dst = ((guchar *) image->mem) + \
y0 * image->bpl + x0 * 3; \
gint x, y; \
\
(void) image_info; \
(void) x_align; \
(void) y_align; \
\
for (y = 0; y < height; y++) \
{ \
const guchar *p = src; \
guchar *q = dst; \
\
for (x = 0; x < width; x++) \
{ \
guint32 rgb = cmap->colors[p[x]]; \
\
q[0] = rgb >> (shift0); \
q[1] = rgb >> 8; \
q[2] = rgb >> (shift2); \
q += 3; \
} \
\
src += rowstride; \
dst += image->bpl; \
} \
}
DEFINE_GDK_RGB_INDEXED_888_CONVERTER (
gdk_rgb_convert_indexed_888_lsb,
0,
16)
DEFINE_GDK_RGB_INDEXED_888_CONVERTER (
gdk_rgb_convert_indexed_888_msb,
16,
0)
#undef DEFINE_GDK_RGB_INDEXED_888_CONVERTER
static void static void
gdk_rgb_gray_to_stage (guchar *stage, gdk_rgb_gray_to_stage (guchar *stage,
const guchar *buf, gint rowstride, gint width, gint height, const guchar *buf, gint rowstride, gint width, gint height,
@ -4001,6 +4056,7 @@ gdk_rgb_select_conv (GdkRgbInfo *image_info)
case GDK_RGB_FORMAT_555_BR: case GDK_RGB_FORMAT_555_BR:
conv_gray = gdk_rgb_convert_gray_555_br; conv_gray = gdk_rgb_convert_gray_555_br;
conv_gray_d = gdk_rgb_convert_gray_555_br; conv_gray_d = gdk_rgb_convert_gray_555_br;
conv_indexed = gdk_rgb_convert_indexed_lut;
break; break;
case GDK_RGB_FORMAT_565: case GDK_RGB_FORMAT_565:
@ -4013,6 +4069,7 @@ gdk_rgb_select_conv (GdkRgbInfo *image_info)
case GDK_RGB_FORMAT_565_BR: case GDK_RGB_FORMAT_565_BR:
conv_gray = gdk_rgb_convert_gray_565_br; conv_gray = gdk_rgb_convert_gray_565_br;
conv_gray_d = gdk_rgb_convert_gray_565_br; conv_gray_d = gdk_rgb_convert_gray_565_br;
conv_indexed = gdk_rgb_convert_indexed_lut;
break; break;
case GDK_RGB_FORMAT_0888: case GDK_RGB_FORMAT_0888:
@ -4032,26 +4089,35 @@ gdk_rgb_select_conv (GdkRgbInfo *image_info)
break; break;
case GDK_RGB_FORMAT_888_LSB: case GDK_RGB_FORMAT_888_LSB:
conv_gray = gdk_rgb_convert_gray_888;
conv_gray_d = gdk_rgb_convert_gray_888;
conv_indexed = gdk_rgb_convert_indexed_888_lsb;
break;
case GDK_RGB_FORMAT_888_MSB: case GDK_RGB_FORMAT_888_MSB:
conv_gray = gdk_rgb_convert_gray_888; conv_gray = gdk_rgb_convert_gray_888;
conv_gray_d = gdk_rgb_convert_gray_888; conv_gray_d = gdk_rgb_convert_gray_888;
conv_indexed = gdk_rgb_convert_indexed_888_msb;
break; break;
case GDK_RGB_FORMAT_8880_BR: case GDK_RGB_FORMAT_8880_BR:
conv_gray = gdk_rgb_convert_gray_8880_br; conv_gray = gdk_rgb_convert_gray_8880_br;
conv_gray_d = gdk_rgb_convert_gray_8880_br; conv_gray_d = gdk_rgb_convert_gray_8880_br;
conv_indexed = gdk_rgb_convert_indexed_lut;
break; break;
case GDK_RGB_FORMAT_101010_R_LOW_LSB: case GDK_RGB_FORMAT_101010_R_LOW_LSB:
case GDK_RGB_FORMAT_101010_B_LOW_LSB: case GDK_RGB_FORMAT_101010_B_LOW_LSB:
conv_gray = gdk_rgb_convert_gray_101010_lsb; conv_gray = gdk_rgb_convert_gray_101010_lsb;
conv_gray_d = gdk_rgb_convert_gray_101010_lsb; conv_gray_d = gdk_rgb_convert_gray_101010_lsb;
conv_indexed = gdk_rgb_convert_indexed_lut;
break; break;
case GDK_RGB_FORMAT_101010_R_LOW_MSB: case GDK_RGB_FORMAT_101010_R_LOW_MSB:
case GDK_RGB_FORMAT_101010_B_LOW_MSB: case GDK_RGB_FORMAT_101010_B_LOW_MSB:
conv_gray = gdk_rgb_convert_gray_101010_msb; conv_gray = gdk_rgb_convert_gray_101010_msb;
conv_gray_d = gdk_rgb_convert_gray_101010_msb; conv_gray_d = gdk_rgb_convert_gray_101010_msb;
conv_indexed = gdk_rgb_convert_indexed_lut;
break; break;
default: default:
@ -4967,48 +5033,123 @@ gdk_draw_gray_image (GdkDrawable *drawable,
static GdkRgbCmapInfo * static GdkRgbCmapInfo *
gdk_rgb_cmap_get_info (GdkRgbCmap *cmap, gdk_rgb_cmap_get_info (GdkRgbCmap *cmap,
GdkRgbInfo *image_info) GdkRgbInfo *image_info)
{ {
GSList *tmp_list; GSList *tmp_list;
GdkRgbCmapInfo *cmap_info; GdkRgbCmapInfo *cmap_info;
int i, j; gsize lut_bytes;
guint32 rgb; gboolean lut8;
gint i;
/* We don't need a LUT for TrueColor or DirectColor visuals */ lut8 =
if (image_info->bpp != 1 || image_info->bpp == 1 &&
!(image_info->visual->type == GDK_VISUAL_PSEUDO_COLOR || (image_info->visual->type == GDK_VISUAL_PSEUDO_COLOR ||
image_info->visual->type == GDK_VISUAL_STATIC_COLOR || image_info->visual->type == GDK_VISUAL_STATIC_COLOR ||
image_info->visual->type == GDK_VISUAL_GRAYSCALE)) image_info->visual->type == GDK_VISUAL_GRAYSCALE);
return NULL;
tmp_list = cmap->info_list; if (lut8)
lut_bytes = 256;
while (tmp_list) else
{ {
cmap_info = tmp_list->data; switch (image_info->format)
if (cmap_info->image_info == image_info) {
return cmap_info; case GDK_RGB_FORMAT_565:
tmp_list = tmp_list->next; case GDK_RGB_FORMAT_565_BR:
case GDK_RGB_FORMAT_555:
case GDK_RGB_FORMAT_555_BR:
lut_bytes = 256 * sizeof (guint16);
break;
case GDK_RGB_FORMAT_0888:
case GDK_RGB_FORMAT_0888_BR:
case GDK_RGB_FORMAT_8880_BR:
case GDK_RGB_FORMAT_101010_R_LOW_LSB:
case GDK_RGB_FORMAT_101010_B_LOW_LSB:
case GDK_RGB_FORMAT_101010_R_LOW_MSB:
case GDK_RGB_FORMAT_101010_B_LOW_MSB:
lut_bytes = 256 * sizeof (guint32);
break;
default:
return NULL;
}
} }
cmap_info = g_new (GdkRgbCmapInfo, 1); for (tmp_list = cmap->info_list;
tmp_list;
tmp_list = tmp_list->next)
{
cmap_info = tmp_list->data;
if (cmap_info->image_info == image_info)
return cmap_info;
}
cmap_info =
g_malloc (G_STRUCT_OFFSET (GdkRgbCmapInfo, lut) +
lut_bytes);
cmap_info->image_info = image_info; cmap_info->image_info = image_info;
cmap_info->cmap = cmap; cmap_info->cmap = cmap;
for (i = 0; i < cmap->n_colors; i++) if (lut8)
{ {
rgb = cmap->colors[i]; for (i = 0; i < cmap->n_colors; i++)
j = ((rgb & 0xf00000) >> 12) | {
((rgb & 0xf000) >> 8) | guint32 rgb = cmap->colors[i];
((rgb & 0xf0) >> 4); gint j;
j = ((rgb & 0xf00000) >> 12) |
((rgb & 0x00f000) >> 8) |
((rgb & 0x0000f0) >> 4);
#ifdef VERBOSE #ifdef VERBOSE
g_print ("%d %x %x\n", i, j, image_info->colorcube[j]); g_print ("%d %x %x\n",
i, j, image_info->colorcube[j]);
#endif #endif
cmap_info->lut[i] = image_info->colorcube[j];
cmap_info->lut[i] =
image_info->colorcube[j];
}
}
else
{
GdkImage image;
guchar stage[256 * 3];
for (i = 0; i < cmap->n_colors; i++)
{
guint32 rgb = cmap->colors[i];
stage[i * 3 + 0] = rgb >> 16;
stage[i * 3 + 1] = rgb >> 8;
stage[i * 3 + 2] = rgb;
}
memset (&image, 0, sizeof (image));
image.mem = cmap_info->lut;
image.bpl = cmap->n_colors * image_info->bpp;
g_assert (image_info->conv != NULL);
image_info->conv (image_info,
&image,
0, 0,
cmap->n_colors, 1,
stage,
cmap->n_colors * 3,
0, 0,
NULL);
} }
cmap->info_list = g_slist_prepend (cmap->info_list, cmap_info); cmap->info_list =
image_info->cmap_info_list = g_slist_prepend (image_info->cmap_info_list, cmap_info); g_slist_prepend (cmap->info_list,
cmap_info);
image_info->cmap_info_list =
g_slist_prepend (image_info->cmap_info_list,
cmap_info);
return cmap_info; return cmap_info;
} }