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;
|
Fbo default_fbo;
|
||||||
|
|
||||||
GHashTable *textures;
|
GHashTable *textures;
|
||||||
|
GHashTable *pointer_textures;
|
||||||
|
|
||||||
const Texture *bound_source_texture;
|
const Texture *bound_source_texture;
|
||||||
const Fbo *bound_fbo;
|
const Fbo *bound_fbo;
|
||||||
@ -119,6 +120,7 @@ gsk_gl_driver_finalize (GObject *gobject)
|
|||||||
gdk_gl_context_make_current (self->gl_context);
|
gdk_gl_context_make_current (self->gl_context);
|
||||||
|
|
||||||
g_clear_pointer (&self->textures, g_hash_table_unref);
|
g_clear_pointer (&self->textures, g_hash_table_unref);
|
||||||
|
g_clear_pointer (&self->pointer_textures, g_hash_table_unref);
|
||||||
g_clear_object (&self->profiler);
|
g_clear_object (&self->profiler);
|
||||||
|
|
||||||
if (self->gl_context == gdk_gl_context_get_current ())
|
if (self->gl_context == gdk_gl_context_get_current ())
|
||||||
@ -263,7 +265,28 @@ gsk_gl_driver_collect_textures (GskGLDriver *self)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
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);
|
return old_size - g_hash_table_size (self->textures);
|
||||||
@ -307,26 +330,6 @@ gsk_gl_driver_get_fbo (GskGLDriver *self,
|
|||||||
return &t->fbo;
|
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 *
|
static Texture *
|
||||||
create_texture (GskGLDriver *self,
|
create_texture (GskGLDriver *self,
|
||||||
float fwidth,
|
float fwidth,
|
||||||
@ -351,21 +354,7 @@ create_texture (GskGLDriver *self,
|
|||||||
height = MIN (height, self->max_texture_size);
|
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);
|
glGenTextures (1, &texture_id);
|
||||||
|
|
||||||
t = texture_new ();
|
t = texture_new ();
|
||||||
t->texture_id = texture_id;
|
t->texture_id = texture_id;
|
||||||
t->width = width;
|
t->width = width;
|
||||||
@ -547,6 +536,31 @@ gsk_gl_driver_get_texture_for_texture (GskGLDriver *self,
|
|||||||
return t->texture_id;
|
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
|
int
|
||||||
gsk_gl_driver_create_permanent_texture (GskGLDriver *self,
|
gsk_gl_driver_create_permanent_texture (GskGLDriver *self,
|
||||||
float width,
|
float width,
|
||||||
|
@ -33,6 +33,11 @@ int gsk_gl_driver_get_texture_for_texture (GskGLDriver *driver
|
|||||||
GdkTexture *texture,
|
GdkTexture *texture,
|
||||||
int min_filter,
|
int min_filter,
|
||||||
int mag_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,
|
int gsk_gl_driver_create_permanent_texture (GskGLDriver *driver,
|
||||||
float width,
|
float width,
|
||||||
float height);
|
float height);
|
||||||
|
@ -2255,7 +2255,7 @@ add_offscreen_ops (GskGLRenderer *self,
|
|||||||
float min_y,
|
float min_y,
|
||||||
float max_y,
|
float max_y,
|
||||||
GskRenderNode *child_node,
|
GskRenderNode *child_node,
|
||||||
int *texture_id,
|
int *texture_id_out,
|
||||||
gboolean *is_offscreen,
|
gboolean *is_offscreen,
|
||||||
gboolean force_offscreen,
|
gboolean force_offscreen,
|
||||||
gboolean reset_clip)
|
gboolean reset_clip)
|
||||||
@ -2271,6 +2271,7 @@ add_offscreen_ops (GskGLRenderer *self,
|
|||||||
graphene_rect_t prev_viewport;
|
graphene_rect_t prev_viewport;
|
||||||
graphene_matrix_t item_proj;
|
graphene_matrix_t item_proj;
|
||||||
GskRoundedRect prev_clip;
|
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
|
/* 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. */
|
* 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);
|
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_id_out = gsk_gl_driver_get_texture_for_texture (self->gl_driver,
|
||||||
texture,
|
texture,
|
||||||
gl_min_filter,
|
gl_min_filter,
|
||||||
gl_mag_filter);
|
gl_mag_filter);
|
||||||
*is_offscreen = FALSE;
|
*is_offscreen = FALSE;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
*texture_id = gsk_gl_driver_create_texture (self->gl_driver, width, height);
|
/* Check if we've already cached the drawn texture. */
|
||||||
gsk_gl_driver_bind_source_texture (self->gl_driver, *texture_id);
|
{
|
||||||
gsk_gl_driver_init_texture_empty (self->gl_driver, *texture_id);
|
const int cached_id = gsk_gl_driver_get_texture_for_pointer (self->gl_driver, child_node);
|
||||||
render_target = gsk_gl_driver_create_render_target (self->gl_driver, *texture_id, TRUE, TRUE);
|
|
||||||
|
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,
|
graphene_matrix_init_ortho (&item_proj,
|
||||||
min_x * scale, max_x * scale,
|
min_x * scale, max_x * scale,
|
||||||
@ -2328,6 +2342,9 @@ add_offscreen_ops (GskGLRenderer *self,
|
|||||||
ops_set_render_target (builder, prev_render_target);
|
ops_set_render_target (builder, prev_render_target);
|
||||||
|
|
||||||
*is_offscreen = TRUE;
|
*is_offscreen = TRUE;
|
||||||
|
*texture_id_out = texture_id;
|
||||||
|
|
||||||
|
gsk_gl_driver_set_texture_for_pointer (self->gl_driver, child_node, texture_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
Loading…
Reference in New Issue
Block a user