gl: Do less work to maintain caches

Remember which atlases were removed, and only
check those when looking for icons or glyphs
to remove. For most frames, we don't have to
check at all since no atlases were removed.
This commit is contained in:
Matthias Clasen 2019-10-11 20:42:24 -04:00
parent 9b61bfb3c8
commit 8839e10d44
7 changed files with 65 additions and 49 deletions

View File

@ -312,41 +312,46 @@ gsk_gl_glyph_cache_lookup (GskGLGlyphCache *cache,
}
void
gsk_gl_glyph_cache_begin_frame (GskGLGlyphCache *self)
gsk_gl_glyph_cache_begin_frame (GskGLGlyphCache *self,
GPtrArray *removed_atlases)
{
GHashTableIter iter;
GlyphCacheKey *key;
GskGLCachedGlyph *value;
guint dropped = 0;
self->timestamp++;
if (removed_atlases->len > 0)
{
guint dropped = 0;
g_hash_table_iter_init (&iter, self->hash_table);
while (g_hash_table_iter_next (&iter, (gpointer *)&key, (gpointer *)&value))
{
if (g_ptr_array_find (removed_atlases, value->atlas, NULL))
{
g_hash_table_iter_remove (&iter);
dropped++;
}
}
GSK_NOTE(GLYPH_CACHE, if (dropped > 0) g_message ("Dropped %d glyphs", dropped));
}
g_hash_table_iter_init (&iter, self->hash_table);
while (g_hash_table_iter_next (&iter, (gpointer *)&key, (gpointer *)&value))
{
guint pos;
const guint age = self->timestamp - value->timestamp;
if (!g_ptr_array_find (self->atlases->atlases, value->atlas, &pos))
if (age > MAX_FRAME_AGE)
{
g_hash_table_iter_remove (&iter);
dropped++;
}
else
{
const guint age = self->timestamp - value->timestamp;
GskGLTextureAtlas *atlas = value->atlas;
if (age > MAX_FRAME_AGE)
if (atlas && value->used)
{
GskGLTextureAtlas *atlas = value->atlas;
if (atlas && value->used)
{
gsk_gl_texture_atlas_mark_unused (atlas, value->draw_width, value->draw_height);
value->used = FALSE;
}
gsk_gl_texture_atlas_mark_unused (atlas, value->draw_width, value->draw_height);
value->used = FALSE;
}
}
}
GSK_NOTE(GLYPH_CACHE, if (dropped > 0) g_message ("Dropped %d glyphs", dropped));
}

View File

@ -72,7 +72,8 @@ GskGLGlyphCache * gsk_gl_glyph_cache_new (GdkDisplay *display
GskGLTextureAtlases *atlases);
GskGLGlyphCache * gsk_gl_glyph_cache_ref (GskGLGlyphCache *self);
void gsk_gl_glyph_cache_unref (GskGLGlyphCache *self);
void gsk_gl_glyph_cache_begin_frame (GskGLGlyphCache *self);
void gsk_gl_glyph_cache_begin_frame (GskGLGlyphCache *self,
GPtrArray *removed_atlases);
gboolean gsk_gl_glyph_cache_lookup (GskGLGlyphCache *self,
GlyphCacheKey *lookup,
GskGLDriver *driver,

View File

@ -64,40 +64,43 @@ gsk_gl_icon_cache_unref (GskGLIconCache *self)
}
void
gsk_gl_icon_cache_begin_frame (GskGLIconCache *self)
gsk_gl_icon_cache_begin_frame (GskGLIconCache *self,
GPtrArray *removed_atlases)
{
GHashTableIter iter;
GdkTexture *texture;
IconData *icon_data;
/* Increase frame age of all icons */
/* Drop icons on removed atlases */
if (removed_atlases->len > 0)
{
g_hash_table_iter_init (&iter, self->icons);
while (g_hash_table_iter_next (&iter, (gpointer *)&texture, (gpointer *)&icon_data))
{
if (g_ptr_array_find (removed_atlases, icon_data->atlas, NULL))
g_hash_table_iter_remove (&iter);
}
}
/* Increase frame age of all remaining icons */
g_hash_table_iter_init (&iter, self->icons);
while (g_hash_table_iter_next (&iter, (gpointer *)&texture, (gpointer *)&icon_data))
{
guint pos;
icon_data->frame_age ++;
if (!g_ptr_array_find (self->atlases->atlases, icon_data->atlas, &pos))
if (icon_data->frame_age > MAX_FRAME_AGE)
{
g_hash_table_iter_remove (&iter);
}
else
{
icon_data->frame_age ++;
if (icon_data->frame_age > MAX_FRAME_AGE)
if (icon_data->used)
{
if (icon_data->used)
{
const int w = icon_data->texture_rect.size.width * icon_data->atlas->width;
const int h = icon_data->texture_rect.size.height * icon_data->atlas->height;
gsk_gl_texture_atlas_mark_unused (icon_data->atlas, w + 2, h + 2);
icon_data->used = FALSE;
}
/* We do NOT remove the icon here. Instead, We wait until we drop the entire atlas.
* This way we can revive it when we use it again. */
const int w = icon_data->texture_rect.size.width * icon_data->atlas->width;
const int h = icon_data->texture_rect.size.height * icon_data->atlas->height;
gsk_gl_texture_atlas_mark_unused (icon_data->atlas, w + 2, h + 2);
icon_data->used = FALSE;
}
/* We do NOT remove the icon here. Instead, We wait until we drop the entire atlas.
* This way we can revive it when we use it again.
*/
}
}
}

View File

@ -24,7 +24,8 @@ GskGLIconCache * gsk_gl_icon_cache_new (GdkDisplay *display,
GskGLTextureAtlases *atlases);
GskGLIconCache * gsk_gl_icon_cache_ref (GskGLIconCache *self);
void gsk_gl_icon_cache_unref (GskGLIconCache *self);
void gsk_gl_icon_cache_begin_frame (GskGLIconCache *self);
void gsk_gl_icon_cache_begin_frame (GskGLIconCache *self,
GPtrArray *removed_atlases);
void gsk_gl_icon_cache_lookup_or_add (GskGLIconCache *self,
GdkTexture *texture,
int *out_texture_id,

View File

@ -3181,6 +3181,7 @@ gsk_gl_renderer_do_render (GskRenderer *renderer,
GskProfiler *profiler;
gint64 gpu_time, cpu_time, start_time;
#endif
GPtrArray *removed;
#ifdef G_ENABLE_DEBUG
profiler = gsk_renderer_get_profiler (renderer);
@ -3204,10 +3205,12 @@ gsk_gl_renderer_do_render (GskRenderer *renderer,
ORTHO_FAR_PLANE);
graphene_matrix_scale (&projection, 1, -1, 1);
gsk_gl_texture_atlases_begin_frame (self->atlases);
gsk_gl_glyph_cache_begin_frame (self->glyph_cache);
gsk_gl_icon_cache_begin_frame (self->icon_cache);
removed = g_ptr_array_new ();
gsk_gl_texture_atlases_begin_frame (self->atlases, removed);
gsk_gl_glyph_cache_begin_frame (self->glyph_cache, removed);
gsk_gl_icon_cache_begin_frame (self->icon_cache, removed);
gsk_gl_shadow_cache_begin_frame (&self->shadow_cache, self->gl_driver);
g_ptr_array_unref (removed);
ops_set_projection (&self->op_builder, &projection);
ops_set_viewport (&self->op_builder, viewport);

View File

@ -74,7 +74,8 @@ write_atlas_to_png (GskGLTextureAtlas *atlas,
#endif
void
gsk_gl_texture_atlases_begin_frame (GskGLTextureAtlases *self)
gsk_gl_texture_atlases_begin_frame (GskGLTextureAtlases *self,
GPtrArray *removed)
{
int i;
@ -94,6 +95,7 @@ gsk_gl_texture_atlases_begin_frame (GskGLTextureAtlases *self)
atlas->texture_id = 0;
}
g_ptr_array_add (removed, atlas);
g_ptr_array_remove_index (self->atlases, i);
}
}

View File

@ -35,7 +35,8 @@ GskGLTextureAtlases *gsk_gl_texture_atlases_new (void);
GskGLTextureAtlases *gsk_gl_texture_atlases_ref (GskGLTextureAtlases *atlases);
void gsk_gl_texture_atlases_unref (GskGLTextureAtlases *atlases);
void gsk_gl_texture_atlases_begin_frame (GskGLTextureAtlases *atlases);
void gsk_gl_texture_atlases_begin_frame (GskGLTextureAtlases *atlases,
GPtrArray *removed);
gboolean gsk_gl_texture_atlases_pack (GskGLTextureAtlases *atlases,
int width,
int height,