forked from AuroraMiddleware/gtk
gl renderer: Cache offscreen textures per node, not size
This commit is contained in:
parent
12378f0afa
commit
c0cf592336
@ -46,6 +46,7 @@ struct _GskGLDriver
|
||||
Fbo default_fbo;
|
||||
|
||||
GHashTable *textures;
|
||||
GHashTable *pointer_textures;
|
||||
|
||||
const Texture *bound_source_texture;
|
||||
const Fbo *bound_fbo;
|
||||
@ -119,6 +120,7 @@ gsk_gl_driver_finalize (GObject *gobject)
|
||||
gdk_gl_context_make_current (self->gl_context);
|
||||
|
||||
g_clear_pointer (&self->textures, g_hash_table_unref);
|
||||
g_clear_pointer (&self->pointer_textures, g_hash_table_unref);
|
||||
g_clear_object (&self->profiler);
|
||||
|
||||
if (self->gl_context == gdk_gl_context_get_current ())
|
||||
@ -263,7 +265,28 @@ gsk_gl_driver_collect_textures (GskGLDriver *self)
|
||||
}
|
||||
}
|
||||
else
|
||||
g_hash_table_iter_remove (&iter);
|
||||
{
|
||||
/* Remove from self->pointer_textures. */
|
||||
/* TODO: Is there a better way for this? */
|
||||
if (self->pointer_textures)
|
||||
{
|
||||
GHashTableIter pointer_iter;
|
||||
gpointer value;
|
||||
gpointer p;
|
||||
|
||||
g_hash_table_iter_init (&pointer_iter, self->pointer_textures);
|
||||
while (g_hash_table_iter_next (&pointer_iter, &p, &value))
|
||||
{
|
||||
if (GPOINTER_TO_INT (value) == t->texture_id)
|
||||
{
|
||||
g_hash_table_iter_remove (&pointer_iter);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
g_hash_table_iter_remove (&iter);
|
||||
}
|
||||
}
|
||||
|
||||
return old_size - g_hash_table_size (self->textures);
|
||||
@ -307,26 +330,6 @@ gsk_gl_driver_get_fbo (GskGLDriver *self,
|
||||
return &t->fbo;
|
||||
}
|
||||
|
||||
static Texture *
|
||||
find_texture_by_size (GHashTable *textures,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
GHashTableIter iter;
|
||||
gpointer value_p = NULL;
|
||||
|
||||
g_hash_table_iter_init (&iter, textures);
|
||||
while (g_hash_table_iter_next (&iter, NULL, &value_p))
|
||||
{
|
||||
Texture *t = value_p;
|
||||
|
||||
if (t->width == width && t->height == height)
|
||||
return t;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static Texture *
|
||||
create_texture (GskGLDriver *self,
|
||||
float fwidth,
|
||||
@ -351,21 +354,7 @@ create_texture (GskGLDriver *self,
|
||||
height = MIN (height, self->max_texture_size);
|
||||
}
|
||||
|
||||
t = find_texture_by_size (self->textures, width, height);
|
||||
if (t != NULL && !t->in_use && t->user == NULL)
|
||||
{
|
||||
GSK_NOTE (OPENGL, g_message ("Reusing Texture(%d) for size %dx%d",
|
||||
t->texture_id, t->width, t->height));
|
||||
t->in_use = TRUE;
|
||||
|
||||
#ifdef G_ENABLE_DEBUG
|
||||
gsk_profiler_counter_inc (self->profiler, self->counters.reused_textures);
|
||||
#endif
|
||||
return t;
|
||||
}
|
||||
|
||||
glGenTextures (1, &texture_id);
|
||||
|
||||
t = texture_new ();
|
||||
t->texture_id = texture_id;
|
||||
t->width = width;
|
||||
@ -547,6 +536,31 @@ gsk_gl_driver_get_texture_for_texture (GskGLDriver *self,
|
||||
return t->texture_id;
|
||||
}
|
||||
|
||||
int
|
||||
gsk_gl_driver_get_texture_for_pointer (GskGLDriver *self,
|
||||
gpointer pointer)
|
||||
{
|
||||
int id = 0;
|
||||
|
||||
if (G_UNLIKELY (self->pointer_textures == NULL))
|
||||
self->pointer_textures = g_hash_table_new (NULL, NULL);
|
||||
|
||||
id = GPOINTER_TO_INT (g_hash_table_lookup (self->pointer_textures, pointer));
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
void
|
||||
gsk_gl_driver_set_texture_for_pointer (GskGLDriver *self,
|
||||
gpointer pointer,
|
||||
int texture_id)
|
||||
{
|
||||
if (G_UNLIKELY (self->pointer_textures == NULL))
|
||||
self->pointer_textures = g_hash_table_new (NULL, NULL);
|
||||
|
||||
g_hash_table_insert (self->pointer_textures, pointer, GINT_TO_POINTER (texture_id));
|
||||
}
|
||||
|
||||
int
|
||||
gsk_gl_driver_create_permanent_texture (GskGLDriver *self,
|
||||
float width,
|
||||
|
@ -33,6 +33,11 @@ int gsk_gl_driver_get_texture_for_texture (GskGLDriver *driver
|
||||
GdkTexture *texture,
|
||||
int min_filter,
|
||||
int mag_filter);
|
||||
int gsk_gl_driver_get_texture_for_pointer (GskGLDriver *driver,
|
||||
gpointer pointer);
|
||||
void gsk_gl_driver_set_texture_for_pointer (GskGLDriver *driver,
|
||||
gpointer pointer,
|
||||
int texture_id);
|
||||
int gsk_gl_driver_create_permanent_texture (GskGLDriver *driver,
|
||||
float width,
|
||||
float height);
|
||||
|
@ -2255,7 +2255,7 @@ add_offscreen_ops (GskGLRenderer *self,
|
||||
float min_y,
|
||||
float max_y,
|
||||
GskRenderNode *child_node,
|
||||
int *texture_id,
|
||||
int *texture_id_out,
|
||||
gboolean *is_offscreen,
|
||||
gboolean force_offscreen,
|
||||
gboolean reset_clip)
|
||||
@ -2271,6 +2271,7 @@ add_offscreen_ops (GskGLRenderer *self,
|
||||
graphene_rect_t prev_viewport;
|
||||
graphene_matrix_t item_proj;
|
||||
GskRoundedRect prev_clip;
|
||||
int texture_id = 0;
|
||||
|
||||
/* We need the child node as a texture. If it already is one, we don't need to draw
|
||||
* it on a framebuffer of course. */
|
||||
@ -2281,18 +2282,31 @@ add_offscreen_ops (GskGLRenderer *self,
|
||||
|
||||
get_gl_scaling_filters (child_node, &gl_min_filter, &gl_mag_filter);
|
||||
|
||||
*texture_id = gsk_gl_driver_get_texture_for_texture (self->gl_driver,
|
||||
texture,
|
||||
gl_min_filter,
|
||||
gl_mag_filter);
|
||||
*texture_id_out = gsk_gl_driver_get_texture_for_texture (self->gl_driver,
|
||||
texture,
|
||||
gl_min_filter,
|
||||
gl_mag_filter);
|
||||
*is_offscreen = FALSE;
|
||||
return;
|
||||
}
|
||||
|
||||
*texture_id = gsk_gl_driver_create_texture (self->gl_driver, width, height);
|
||||
gsk_gl_driver_bind_source_texture (self->gl_driver, *texture_id);
|
||||
gsk_gl_driver_init_texture_empty (self->gl_driver, *texture_id);
|
||||
render_target = gsk_gl_driver_create_render_target (self->gl_driver, *texture_id, TRUE, TRUE);
|
||||
/* Check if we've already cached the drawn texture. */
|
||||
{
|
||||
const int cached_id = gsk_gl_driver_get_texture_for_pointer (self->gl_driver, child_node);
|
||||
|
||||
if (cached_id != 0)
|
||||
{
|
||||
*texture_id_out = cached_id;
|
||||
/* We didn't render it offscreen, but hand out an offscreen texture id */
|
||||
*is_offscreen = TRUE;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
texture_id = gsk_gl_driver_create_texture (self->gl_driver, width, height);
|
||||
gsk_gl_driver_bind_source_texture (self->gl_driver, texture_id);
|
||||
gsk_gl_driver_init_texture_empty (self->gl_driver, texture_id);
|
||||
render_target = gsk_gl_driver_create_render_target (self->gl_driver, texture_id, TRUE, TRUE);
|
||||
|
||||
graphene_matrix_init_ortho (&item_proj,
|
||||
min_x * scale, max_x * scale,
|
||||
@ -2328,6 +2342,9 @@ add_offscreen_ops (GskGLRenderer *self,
|
||||
ops_set_render_target (builder, prev_render_target);
|
||||
|
||||
*is_offscreen = TRUE;
|
||||
*texture_id_out = texture_id;
|
||||
|
||||
gsk_gl_driver_set_texture_for_pointer (self->gl_driver, child_node, texture_id);
|
||||
}
|
||||
|
||||
static void
|
||||
|
Loading…
Reference in New Issue
Block a user