diff options
-rw-r--r-- | gsk/gskgldriver.c | 88 | ||||
-rw-r--r-- | gsk/gskgldriverprivate.h | 9 | ||||
-rw-r--r-- | gsk/gskglrenderer.c | 20 | ||||
-rw-r--r-- | gsk/gsktexture.c | 41 | ||||
-rw-r--r-- | gsk/gsktextureprivate.h | 12 |
5 files changed, 128 insertions, 42 deletions
diff --git a/gsk/gskgldriver.c b/gsk/gskgldriver.c index da21f6ae72..edb6653135 100644 --- a/gsk/gskgldriver.c +++ b/gsk/gskgldriver.c @@ -3,6 +3,7 @@ #include "gskgldriverprivate.h" #include "gskdebugprivate.h" +#include "gsktextureprivate.h" #include <gdk/gdk.h> #include <epoxy/gl.h> @@ -14,8 +15,8 @@ typedef struct { GLuint min_filter; GLuint mag_filter; GArray *fbos; + GskTexture *user; gboolean in_use : 1; - gboolean reserved : 1; } Texture; typedef struct { @@ -76,7 +77,8 @@ texture_free (gpointer data) { Texture *t = data; - g_warn_if_fail (!t->reserved); + if (t->user) + gsk_texture_clear_render_data (t->user); g_clear_pointer (&t->fbos, g_array_unref); glDeleteTextures (1, &t->texture_id); @@ -272,7 +274,7 @@ gsk_gl_driver_collect_textures (GskGLDriver *driver) { Texture *t = value_p; - if (t->reserved) + if (t->user) continue; if (t->in_use) @@ -383,17 +385,14 @@ find_texture_by_size (GHashTable *textures, return NULL; } -int -gsk_gl_driver_create_texture (GskGLDriver *driver, - gboolean reserve, - int width, - int height) +static Texture * +create_texture (GskGLDriver *driver, + int width, + int height) { guint texture_id; Texture *t; - g_return_val_if_fail (GSK_IS_GL_DRIVER (driver), -1); - if (width >= driver->max_texture_size || height >= driver->max_texture_size) { @@ -406,13 +405,12 @@ gsk_gl_driver_create_texture (GskGLDriver *driver, } t = find_texture_by_size (driver->textures, width, height); - if (t != NULL && !t->in_use) + if (t != NULL && !t->in_use && t->user == NULL) { GSK_NOTE (OPENGL, g_print ("Reusing Texture(%d) for size %dx%d\n", t->texture_id, t->width, t->height)); t->in_use = TRUE; - t->reserved = reserve; - return t->texture_id; + return t; } glGenTextures (1, &texture_id); @@ -424,25 +422,67 @@ gsk_gl_driver_create_texture (GskGLDriver *driver, t->min_filter = GL_NEAREST; t->mag_filter = GL_NEAREST; t->in_use = TRUE; - t->reserved = reserve; g_hash_table_insert (driver->textures, GINT_TO_POINTER (texture_id), t); - return t->texture_id; + return t; } -void -gsk_gl_driver_release_texture (GskGLDriver *driver, - int texture_id) +static void +gsk_gl_driver_release_texture (gpointer data) +{ + Texture *t = data; + + t->user = NULL; +} + +int +gsk_gl_driver_get_texture_for_texture (GskGLDriver *driver, + GskTexture *texture, + int min_filter, + int mag_filter) { Texture *t; + cairo_surface_t *surface; + + g_return_val_if_fail (GSK_IS_GL_DRIVER (driver), -1); + g_return_val_if_fail (GSK_IS_TEXTURE (texture), -1); + + t = gsk_texture_get_render_data (texture, driver); + + if (t) + { + if (t->min_filter == min_filter && t->mag_filter == mag_filter) + return t->texture_id; + } - g_return_if_fail (GSK_IS_GL_DRIVER (driver)); - - t = gsk_gl_driver_get_texture (driver, texture_id); - g_return_if_fail (t != NULL); - g_return_if_fail (t->reserved); + t = create_texture (driver, gsk_texture_get_width (texture), gsk_texture_get_height (texture)); + + if (gsk_texture_set_render_data (texture, driver, t, gsk_gl_driver_release_texture)) + t->user = texture; - t->reserved = FALSE; + surface = gsk_texture_download (texture); + gsk_gl_driver_bind_source_texture (driver, t->texture_id); + gsk_gl_driver_init_texture_with_surface (driver, + t->texture_id, + surface, + min_filter, + mag_filter); + + return t->texture_id; +} + +int +gsk_gl_driver_create_texture (GskGLDriver *driver, + int width, + int height) +{ + Texture *t; + + g_return_val_if_fail (GSK_IS_GL_DRIVER (driver), -1); + + t = create_texture (driver, width, height); + + return t->texture_id; } static Vao * diff --git a/gsk/gskgldriverprivate.h b/gsk/gskgldriverprivate.h index 636f59c889..64f9be1f81 100644 --- a/gsk/gskgldriverprivate.h +++ b/gsk/gskgldriverprivate.h @@ -5,6 +5,8 @@ #include <gdk/gdk.h> #include <graphene.h> +#include <gsk/gsktexture.h> + G_BEGIN_DECLS #define GSK_TYPE_GL_DRIVER (gsk_gl_driver_get_type ()) @@ -23,12 +25,13 @@ int gsk_gl_driver_get_max_texture_size (GskGLDriver *driver void gsk_gl_driver_begin_frame (GskGLDriver *driver); void gsk_gl_driver_end_frame (GskGLDriver *driver); +int gsk_gl_driver_get_texture_for_texture (GskGLDriver *driver, + GskTexture *texture, + int min_filter, + int mag_filter); int gsk_gl_driver_create_texture (GskGLDriver *driver, - gboolean reserved, int width, int height); -void gsk_gl_driver_release_texture (GskGLDriver *driver, - int texture_id); int gsk_gl_driver_create_vao_for_quad (GskGLDriver *driver, int position_id, int uv_id, diff --git a/gsk/gskglrenderer.c b/gsk/gskglrenderer.c index c6824acac9..6834e32ea8 100644 --- a/gsk/gskglrenderer.c +++ b/gsk/gskglrenderer.c @@ -153,7 +153,6 @@ gsk_gl_renderer_create_buffers (GskGLRenderer *self, if (self->texture_id == 0) { self->texture_id = gsk_gl_driver_create_texture (self->gl_driver, - FALSE, width * scale_factor, height * scale_factor); gsk_gl_driver_bind_source_texture (self->gl_driver, self->texture_id); @@ -695,7 +694,7 @@ gsk_gl_renderer_add_render_item (GskGLRenderer *self, if (render_node_needs_render_target (node)) { item.render_data.render_target_id = - gsk_gl_driver_create_texture (self->gl_driver, FALSE, item.size.width, item.size.height); + gsk_gl_driver_create_texture (self->gl_driver, item.size.width, item.size.height); gsk_gl_driver_init_texture_empty (self->gl_driver, item.render_data.render_target_id); gsk_gl_driver_create_render_target (self->gl_driver, item.render_data.render_target_id, TRUE, TRUE); @@ -711,22 +710,14 @@ gsk_gl_renderer_add_render_item (GskGLRenderer *self, if (gsk_render_node_has_texture (node)) { GskTexture *texture = gsk_render_node_get_texture (node); - cairo_surface_t *surface = gsk_texture_download (texture); int gl_min_filter = GL_NEAREST, gl_mag_filter = GL_NEAREST; get_gl_scaling_filters (node, &gl_min_filter, &gl_mag_filter); - /* Upload the Cairo surface to a GL texture */ - item.render_data.texture_id = gsk_gl_driver_create_texture (self->gl_driver, - FALSE, - item.size.width, - item.size.height); - gsk_gl_driver_bind_source_texture (self->gl_driver, item.render_data.texture_id); - gsk_gl_driver_init_texture_with_surface (self->gl_driver, - item.render_data.texture_id, - surface, - gl_min_filter, - gl_mag_filter); + item.render_data.texture_id = gsk_gl_driver_get_texture_for_texture (self->gl_driver, + texture, + gl_min_filter, + gl_mag_filter); } else if (gsk_render_node_has_surface (node)) { @@ -737,7 +728,6 @@ gsk_gl_renderer_add_render_item (GskGLRenderer *self, /* Upload the Cairo surface to a GL texture */ item.render_data.texture_id = gsk_gl_driver_create_texture (self->gl_driver, - FALSE, item.size.width, item.size.height); gsk_gl_driver_bind_source_texture (self->gl_driver, item.render_data.texture_id); diff --git a/gsk/gsktexture.c b/gsk/gsktexture.c index 8ccfcbac1a..ceb36b2e50 100644 --- a/gsk/gsktexture.c +++ b/gsk/gsktexture.c @@ -35,6 +35,7 @@ #include "gsktextureprivate.h" #include "gskdebugprivate.h" +#include "gskrenderer.h" /** * GskTexture: (ref-func gsk_texture_ref) (unref-func gsk_texture_unref) @@ -49,6 +50,8 @@ G_DEFINE_BOXED_TYPE(GskTexture, gsk_texture, gsk_texture_ref, gsk_texture_unref) static void gsk_texture_finalize (GskTexture *self) { + gsk_texture_clear_render_data (self); + self->klass->finalize (self); g_free (self); @@ -278,3 +281,41 @@ gsk_texture_download (GskTexture *texture) return texture->klass->download (texture); } +gboolean +gsk_texture_set_render_data (GskTexture *self, + gpointer key, + gpointer data, + GDestroyNotify notify) +{ + g_return_val_if_fail (data != NULL, FALSE); + + if (self->render_key != NULL) + return FALSE; + + self->render_key = key; + self->render_data = data; + self->render_notify = notify; + + return TRUE; +} + +void +gsk_texture_clear_render_data (GskTexture *self) +{ + if (self->render_notify) + self->render_notify (self->render_data); + + self->render_key = NULL; + self->render_data = NULL; + self->render_notify = NULL; +} + +gpointer +gsk_texture_get_render_data (GskTexture *self, + gpointer key) +{ + if (self->render_key != key) + return NULL; + + return self->render_data; +} diff --git a/gsk/gsktextureprivate.h b/gsk/gsktextureprivate.h index 78d96de611..c8d94b6789 100644 --- a/gsk/gsktextureprivate.h +++ b/gsk/gsktextureprivate.h @@ -19,6 +19,10 @@ struct _GskTexture int width; int height; + + gpointer render_key; + gpointer render_data; + GDestroyNotify render_notify; }; struct _GskTextureClass { @@ -35,6 +39,14 @@ gpointer gsk_texture_new (const GskTextureClass GskTexture * gsk_texture_new_for_surface (cairo_surface_t *surface); cairo_surface_t * gsk_texture_download (GskTexture *texture); +gboolean gsk_texture_set_render_data (GskTexture *self, + gpointer key, + gpointer data, + GDestroyNotify notify); +void gsk_texture_clear_render_data (GskTexture *self); +gpointer gsk_texture_get_render_data (GskTexture *self, + gpointer key); + G_END_DECLS #endif /* __GSK_TEXTURE_PRIVATE_H__ */ |