gl: glyph cache tweaks

Reduce the cost of lookups by storing
the hash value directly.
This commit is contained in:
Matthias Clasen 2019-10-09 21:49:43 -04:00
parent 8937cd992d
commit 849b950763
3 changed files with 47 additions and 61 deletions

View File

@ -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;
}

View File

@ -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);

View File

@ -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;