summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gsk/gskgldriver.c88
-rw-r--r--gsk/gskgldriverprivate.h9
-rw-r--r--gsk/gskglrenderer.c20
-rw-r--r--gsk/gsktexture.c41
-rw-r--r--gsk/gsktextureprivate.h12
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__ */