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:
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user