summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEmmanuele Bassi <ebassi@gnome.org>2016-08-04 12:37:54 +0100
committerEmmanuele Bassi <ebassi@gnome.org>2016-08-09 17:31:55 +0100
commit82e35ddbd53461b7985ae9dfba43e00c63988979 (patch)
tree60b5a3d535730492da76bd8ffba85ad2ab1693e9
parent79bace4f81a739adced16c80db552e337e4f3327 (diff)
downloadgtk+-82e35ddbd53461b7985ae9dfba43e00c63988979.tar.gz
gsk: Recycle textures across frames
We keep the textures used inside a frame around until the end of the following frame; whenever we need a texture with the same size, and it's not marked in use, then we just reuse the existing texture.
-rw-r--r--gsk/gskgldriver.c55
-rw-r--r--gsk/gskgldriverprivate.h2
-rw-r--r--gsk/gskglrenderer.c3
3 files changed, 59 insertions, 1 deletions
diff --git a/gsk/gskgldriver.c b/gsk/gskgldriver.c
index 52d8631df5..443a0ad840 100644
--- a/gsk/gskgldriver.c
+++ b/gsk/gskgldriver.c
@@ -14,6 +14,7 @@ typedef struct {
GLuint min_filter;
GLuint mag_filter;
GArray *fbos;
+ gboolean in_use : 1;
} Texture;
typedef struct {
@@ -106,9 +107,14 @@ gsk_gl_driver_finalize (GObject *gobject)
{
GskGLDriver *self = GSK_GL_DRIVER (gobject);
+ gdk_gl_context_make_current (self->gl_context);
+
g_clear_pointer (&self->textures, g_hash_table_unref);
g_clear_pointer (&self->vaos, g_hash_table_unref);
+ if (self->gl_context == gdk_gl_context_get_current ())
+ gdk_gl_context_clear_current ();
+
g_clear_object (&self->gl_context);
G_OBJECT_CLASS (gsk_gl_driver_parent_class)->finalize (gobject);
@@ -232,6 +238,27 @@ gsk_gl_driver_end_frame (GskGLDriver *driver)
driver->in_frame = FALSE;
}
+void
+gsk_gl_driver_collect_textures (GskGLDriver *driver)
+{
+ GHashTableIter iter;
+ gpointer value_p = NULL;
+
+ g_return_if_fail (GSK_IS_GL_DRIVER (driver));
+ g_return_if_fail (!driver->in_frame);
+
+ g_hash_table_iter_init (&iter, driver->textures);
+ while (g_hash_table_iter_next (&iter, NULL, &value_p))
+ {
+ Texture *t = value_p;
+
+ if (t->in_use)
+ t->in_use = FALSE;
+ else
+ g_hash_table_iter_remove (&iter);
+ }
+}
+
static Texture *
gsk_gl_driver_get_texture (GskGLDriver *driver,
int texture_id)
@@ -268,6 +295,26 @@ gsk_gl_driver_get_fbo (GskGLDriver *driver,
return &g_array_index (t->fbos, Fbo, 0);
}
+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;
+}
+
int
gsk_gl_driver_create_texture (GskGLDriver *driver,
int width,
@@ -278,6 +325,13 @@ gsk_gl_driver_create_texture (GskGLDriver *driver,
g_return_val_if_fail (GSK_IS_GL_DRIVER (driver), -1);
+ t = find_texture_by_size (driver->textures, width, height);
+ if (t != NULL && !t->in_use)
+ {
+ t->in_use = TRUE;
+ return t->texture_id;
+ }
+
glGenTextures (1, &texture_id);
t = texture_new ();
@@ -286,6 +340,7 @@ gsk_gl_driver_create_texture (GskGLDriver *driver,
t->height = height;
t->min_filter = GL_NEAREST;
t->mag_filter = GL_NEAREST;
+ t->in_use = TRUE;
g_hash_table_insert (driver->textures, GINT_TO_POINTER (texture_id), t);
return t->texture_id;
diff --git a/gsk/gskgldriverprivate.h b/gsk/gskgldriverprivate.h
index 30eaffa1fb..b69a387ca7 100644
--- a/gsk/gskgldriverprivate.h
+++ b/gsk/gskgldriverprivate.h
@@ -56,6 +56,8 @@ void gsk_gl_driver_destroy_texture (GskGLDriver *driver
void gsk_gl_driver_destroy_vao (GskGLDriver *driver,
int vao_id);
+void gsk_gl_driver_collect_textures (GskGLDriver *driver);
+
G_END_DECLS
#endif /* __GSK_GL_DRIVER_PRIVATE_H__ */
diff --git a/gsk/gskglrenderer.c b/gsk/gskglrenderer.c
index de6b2c3d22..1e3dcd2e3d 100644
--- a/gsk/gskglrenderer.c
+++ b/gsk/gskglrenderer.c
@@ -798,7 +798,6 @@ static void
render_item_clear (RenderItem *item,
GskGLRenderer *self)
{
- gsk_gl_driver_destroy_texture (self->gl_driver, item->render_data.texture_id);
gsk_gl_driver_destroy_vao (self->gl_driver, item->render_data.vao_id);
}
@@ -820,6 +819,8 @@ gsk_gl_renderer_clear_tree (GskGLRenderer *self)
}
g_clear_pointer (&self->render_items, g_array_unref);
+
+ gsk_gl_driver_collect_textures (self->gl_driver);
}
static void