gpu: Add a front cache

This copies the approach taken in the gl renderer to avoid much
of the hash table lookup overhead by means of a front cache.
This commit is contained in:
Matthias Clasen
2024-01-20 10:59:08 -05:00
parent 498bf67cec
commit c5988a22a4

View File

@@ -32,6 +32,15 @@ typedef struct _GskGpuCachedGlyph GskGpuCachedGlyph;
typedef struct _GskGpuCachedTexture GskGpuCachedTexture;
typedef struct _GskGpuDevicePrivate GskGpuDevicePrivate;
typedef struct _GlyphKey GlyphKey;
struct _GlyphKey
{
PangoFont *font;
PangoGlyph glyph;
GskGpuGlyphLookupFlags flags;
float scale;
};
struct _GskGpuDevicePrivate
{
GdkDisplay *display;
@@ -45,6 +54,11 @@ struct _GskGpuDevicePrivate
GHashTable *glyph_cache;
GskGpuCachedAtlas *current_atlas;
struct {
GlyphKey key;
GskGpuCachedGlyph *value;
} front[256];
};
G_DEFINE_TYPE_WITH_PRIVATE (GskGpuDevice, gsk_gpu_device, G_TYPE_OBJECT)
@@ -392,10 +406,7 @@ struct _GskGpuCachedGlyph
{
GskGpuCached parent;
PangoFont *font;
PangoGlyph glyph;
GskGpuGlyphLookupFlags flags;
float scale;
GlyphKey key;
GskGpuImage *image;
graphene_rect_t bounds;
@@ -411,7 +422,7 @@ gsk_gpu_cached_glyph_free (GskGpuDevice *device,
g_hash_table_remove (priv->glyph_cache, self);
g_object_unref (self->font);
g_object_unref (self->key.font);
g_object_unref (self->image);
g_free (self);
@@ -434,10 +445,10 @@ gsk_gpu_cached_glyph_hash (gconstpointer data)
{
const GskGpuCachedGlyph *glyph = data;
return GPOINTER_TO_UINT (glyph->font) ^
glyph->glyph ^
(glyph->flags << 24) ^
((guint) glyph->scale * PANGO_SCALE);
return GPOINTER_TO_UINT (glyph->key.font) ^
glyph->key.glyph ^
(glyph->key.flags << 24) ^
((guint) glyph->key.scale * PANGO_SCALE);
}
static gboolean
@@ -447,10 +458,10 @@ gsk_gpu_cached_glyph_equal (gconstpointer v1,
const GskGpuCachedGlyph *glyph1 = v1;
const GskGpuCachedGlyph *glyph2 = v2;
return glyph1->font == glyph2->font
&& glyph1->glyph == glyph2->glyph
&& glyph1->flags == glyph2->flags
&& glyph1->scale == glyph2->scale;
return glyph1->key.font == glyph2->key.font
&& glyph1->key.glyph == glyph2->key.glyph
&& glyph1->key.flags == glyph2->key.flags
&& glyph1->key.scale == glyph2->key.scale;
}
static const GskGpuCachedClass GSK_GPU_CACHED_GLYPH_CLASS =
@@ -762,10 +773,10 @@ gsk_gpu_device_lookup_glyph_image (GskGpuDevice *self,
{
GskGpuDevicePrivate *priv = gsk_gpu_device_get_instance_private (self);
GskGpuCachedGlyph lookup = {
.font = font,
.glyph = glyph,
.flags = flags,
.scale = scale
.key.font = font,
.key.glyph = glyph,
.key.flags = flags,
.key.scale = scale
};
GskGpuCachedGlyph *cache;
PangoRectangle ink_rect;
@@ -773,14 +784,32 @@ gsk_gpu_device_lookup_glyph_image (GskGpuDevice *self,
graphene_point_t origin;
GskGpuImage *image;
gsize atlas_x, atlas_y, padding;
guint64 timestamp = gsk_gpu_frame_get_timestamp (frame);
guint front_index = glyph & 0xFF;
if (memcmp (&lookup.key, &priv->front[front_index], sizeof (GlyphKey)) == 0)
{
cache = priv->front[front_index].value;
gsk_gpu_cached_use (self, (GskGpuCached *) cache, timestamp);
*out_bounds = cache->bounds;
*out_origin = cache->origin;
return cache->image;
}
cache = g_hash_table_lookup (priv->glyph_cache, &lookup);
if (cache)
{
gsk_gpu_cached_use (self, (GskGpuCached *) cache, gsk_gpu_frame_get_timestamp (frame));
memcpy (&priv->front[front_index].key, &lookup.key, sizeof (GlyphKey));
priv->front[front_index].value = cache;
gsk_gpu_cached_use (self, (GskGpuCached *) cache, timestamp);
*out_bounds = cache->bounds;
*out_origin = cache->origin;
return cache->image;
}
@@ -792,7 +821,7 @@ gsk_gpu_device_lookup_glyph_image (GskGpuDevice *self,
padding = 1;
image = gsk_gpu_device_add_atlas_image (self,
gsk_gpu_frame_get_timestamp (frame),
timestamp,
rect.size.width + 2 * padding, rect.size.height + 2 * padding,
&atlas_x, &atlas_y);
if (image)
@@ -811,10 +840,10 @@ gsk_gpu_device_lookup_glyph_image (GskGpuDevice *self,
cache = gsk_gpu_cached_new (self, &GSK_GPU_CACHED_GLYPH_CLASS, NULL);
}
cache->font = g_object_ref (font),
cache->glyph = glyph,
cache->flags = flags,
cache->scale = scale,
cache->key.font = g_object_ref (font),
cache->key.glyph = glyph,
cache->key.flags = flags,
cache->key.scale = scale,
cache->bounds = rect,
cache->image = image,
((GskGpuCached *) cache)->pixels = (rect.size.width + 2 * padding) * (rect.size.height + 2 * padding);
@@ -836,10 +865,14 @@ gsk_gpu_device_lookup_glyph_image (GskGpuDevice *self,
cache->origin.y + padding));
g_hash_table_insert (priv->glyph_cache, cache, cache);
gsk_gpu_cached_use (self, (GskGpuCached *) cache, gsk_gpu_frame_get_timestamp (frame));
gsk_gpu_cached_use (self, (GskGpuCached *) cache, timestamp);
memcpy (&priv->front[front_index].key, &lookup.key, sizeof (GlyphKey));
priv->front[front_index].value = cache;
*out_bounds = cache->bounds;
*out_origin = cache->origin;
return cache->image;
}