From 849b950763ce39dcd0f33d7e075e90a6b48e7d0f Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Wed, 9 Oct 2019 21:49:43 -0400 Subject: [PATCH] gl: glyph cache tweaks Reduce the cost of lookups by storing the hash value directly. --- gsk/gl/gskglglyphcache.c | 61 +++++++++------------------------ gsk/gl/gskglglyphcacheprivate.h | 31 ++++++++++++----- gsk/gl/gskglrenderer.c | 16 ++++----- 3 files changed, 47 insertions(+), 61 deletions(-) diff --git a/gsk/gl/gskglglyphcache.c b/gsk/gl/gskglglyphcache.c index d1cf5b06f7..f6206ca1f4 100644 --- a/gsk/gl/gskglglyphcache.c +++ b/gsk/gl/gskglglyphcache.c @@ -87,11 +87,7 @@ glyph_cache_hash (gconstpointer v) { const GlyphCacheKey *key = v; - return GPOINTER_TO_UINT (key->font) ^ - key->glyph ^ - (key->xshift << 24) ^ - (key->yshift << 26) ^ - key->scale; + return key->hash; } static void @@ -147,7 +143,7 @@ render_glyph (GlyphCacheKey *key, glyph_info.glyph = key->glyph; glyph_info.geometry.width = value->draw_width * 1024; - if (key->glyph & PANGO_GLYPH_UNKNOWN_FLAG) + if (glyph_info.glyph & PANGO_GLYPH_UNKNOWN_FLAG) glyph_info.geometry.x_offset = 0; else glyph_info.geometry.x_offset = - value->draw_x * 1024; @@ -247,31 +243,15 @@ add_to_cache (GskGLGlyphCache *self, upload_glyph (key, value); } -#define PHASE(x) ((int)(floor (4 * (x + 0.125)) - 4 * floor (x + 0.125))) - gboolean gsk_gl_glyph_cache_lookup (GskGLGlyphCache *cache, - PangoFont *font, - PangoGlyph glyph, - float x, - float y, - float scale, + GlyphCacheKey *lookup, GskGLDriver *driver, const GskGLCachedGlyph **cached_glyph_out) { GskGLCachedGlyph *value; - guint xshift = PHASE (x); - guint yshift = PHASE (y); - const guint key_scale = (guint)(scale * 1024); - value = g_hash_table_lookup (cache->hash_table, - &(GlyphCacheKey) { - .font = font, - .glyph = glyph, - .xshift = xshift, - .yshift = yshift, - .scale = key_scale - }); + value = g_hash_table_lookup (cache->hash_table, lookup); if (value) { @@ -279,30 +259,26 @@ gsk_gl_glyph_cache_lookup (GskGLGlyphCache *cache, if (age > MAX_FRAME_AGE) { - GskGLTextureAtlas *atlas = value->atlas; - - if (atlas && !value->used) + if (value->atlas && !value->used) { - gsk_gl_texture_atlas_mark_used (atlas, value->draw_width, value->draw_height); + gsk_gl_texture_atlas_mark_used (value->atlas, value->draw_width, value->draw_height); value->used = TRUE; } - - value->timestamp = cache->timestamp; } value->timestamp = cache->timestamp; + *cached_glyph_out = value; } - - if (value == NULL) + else { GlyphCacheKey *key; PangoRectangle ink_rect; - pango_font_get_glyph_extents (font, glyph, &ink_rect, NULL); + pango_font_get_glyph_extents (lookup->font, lookup->glyph, &ink_rect, NULL); pango_extents_to_pixels (&ink_rect, NULL); - if (xshift != 0) + if (lookup->xshift != 0) ink_rect.width += 1; - if (yshift != 0) + if (lookup->yshift != 0) ink_rect.height += 1; value = g_new0 (GskGLCachedGlyph, 1); @@ -316,11 +292,12 @@ gsk_gl_glyph_cache_lookup (GskGLGlyphCache *cache, key = g_new0 (GlyphCacheKey, 1); - key->font = g_object_ref (font); - key->glyph = glyph; - key->xshift = xshift; - key->yshift = yshift; - key->scale = key_scale; + key->font = g_object_ref (lookup->font); + key->glyph = lookup->glyph; + key->xshift = lookup->xshift; + key->yshift = lookup->yshift; + key->scale = lookup->scale; + key->hash = lookup->hash; if (key->scale > 0 && value->draw_width * key->scale / 1024 > 0 && @@ -330,10 +307,6 @@ gsk_gl_glyph_cache_lookup (GskGLGlyphCache *cache, *cached_glyph_out = value; g_hash_table_insert (cache->hash_table, key, value); } - else - { - *cached_glyph_out = value; - } return (*cached_glyph_out)->atlas != NULL; } diff --git a/gsk/gl/gskglglyphcacheprivate.h b/gsk/gl/gskglglyphcacheprivate.h index aca44c9835..da1b018fd3 100644 --- a/gsk/gl/gskglglyphcacheprivate.h +++ b/gsk/gl/gskglglyphcacheprivate.h @@ -22,11 +22,30 @@ typedef struct { PangoFont *font; PangoGlyph glyph; - guint xshift; - guint yshift; - guint scale; /* times 1024 */ + guint xshift : 3; + guint yshift : 3; + guint scale : 26; /* times 1024 */ + guint hash; } GlyphCacheKey; +#define PHASE(x) ((int)(floor (4 * (x + 0.125)) - 4 * floor (x + 0.125))) + +static inline void +glyph_cache_key_set_glyph_and_shift (GlyphCacheKey *key, + PangoGlyph glyph, + float x, + float y) +{ + key->glyph = glyph; + key->xshift = PHASE (x); + key->yshift = PHASE (y); + key->hash = GPOINTER_TO_UINT (key->font) ^ + key->glyph ^ + (key->xshift << 24) ^ + (key->yshift << 26) ^ + key->scale; +} + typedef struct _GskGLCachedGlyph GskGLCachedGlyph; struct _GskGLCachedGlyph @@ -55,11 +74,7 @@ GskGLGlyphCache * gsk_gl_glyph_cache_ref (GskGLGlyphCache *se void gsk_gl_glyph_cache_unref (GskGLGlyphCache *self); void gsk_gl_glyph_cache_begin_frame (GskGLGlyphCache *self); gboolean gsk_gl_glyph_cache_lookup (GskGLGlyphCache *self, - PangoFont *font, - PangoGlyph glyph, - float x, - float y, - float scale, + GlyphCacheKey *lookup, GskGLDriver *driver, const GskGLCachedGlyph **cached_glyph_out); diff --git a/gsk/gl/gskglrenderer.c b/gsk/gl/gskglrenderer.c index 8ea44f9b0f..2ed9d1e9a6 100644 --- a/gsk/gl/gskglrenderer.c +++ b/gsk/gl/gskglrenderer.c @@ -552,6 +552,7 @@ render_text_node (GskGLRenderer *self, const graphene_point_t *offset = gsk_text_node_get_offset (node); float x = offset->x + builder->dx; float y = offset->y + builder->dy; + GlyphCacheKey lookup; /* If the font has color glyphs, we don't need to recolor anything */ if (!force_color && gsk_text_node_has_color_glyphs (node)) @@ -564,6 +565,9 @@ render_text_node (GskGLRenderer *self, ops_set_color (builder, color); } + lookup.font = (PangoFont *)font; + lookup.scale = (guint) (text_scale * 1024); + /* We use one quad per character, unlike the other nodes which * use at most one quad altogether */ for (i = 0; i < num_glyphs; i++) @@ -581,19 +585,13 @@ render_text_node (GskGLRenderer *self, cx = (double)(x_position + gi->geometry.x_offset) / PANGO_SCALE; cy = (double)(gi->geometry.y_offset) / PANGO_SCALE; + glyph_cache_key_set_glyph_and_shift (&lookup, gi->glyph, x + cx, y + cy); + gsk_gl_glyph_cache_lookup (self->glyph_cache, - (PangoFont *)font, - gi->glyph, - x + cx, - y + cy, - text_scale, + &lookup, self->gl_driver, &glyph); - /* e.g. whitespace */ - if (glyph->draw_width <= 0 || glyph->draw_height <= 0) - goto next; - if (glyph->texture_id == 0) goto next;