summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthias Clasen <mclasen@redhat.com>2018-01-17 20:15:45 -0500
committerMatthias Clasen <mclasen@redhat.com>2018-01-17 20:15:45 -0500
commit5e302ae2cc62d2e1d7cae9e6efb3b32b368c7b30 (patch)
treee9c5e72cf07a25ffdefedcada676c6cfbcdf3f20
parent34c63b8e4f5068e855283e54bf76233a4e575a59 (diff)
downloadgtk+-5e302ae2cc62d2e1d7cae9e6efb3b32b368c7b30.tar.gz
Add a way to release GL resources
The inspector may hold on to render nodes and textures beyond the lifetime of the widget (and thus the GL resources). To handle this situation, allow the widget to explicitly release the GL resources, and make the texture available on the clent-side as a cairo surface. This lets the recorder still show the content after the widget is gone.
-rw-r--r--gdk/gdktexture.c72
-rw-r--r--gdk/gdktexture.h3
2 files changed, 69 insertions, 6 deletions
diff --git a/gdk/gdktexture.c b/gdk/gdktexture.c
index c87ed57a1d..f85b096ec0 100644
--- a/gdk/gdktexture.c
+++ b/gdk/gdktexture.c
@@ -443,6 +443,8 @@ struct _GdkGLTexture {
GdkGLContext *context;
int id;
+ cairo_surface_t *saved;
+
GDestroyNotify destroy;
gpointer data;
};
@@ -458,10 +460,21 @@ gdk_gl_texture_dispose (GObject *object)
{
GdkGLTexture *self = GDK_GL_TEXTURE (object);
- g_object_unref (self->context);
-
if (self->destroy)
- self->destroy (self->data);
+ {
+ self->destroy (self->data);
+ self->destroy = NULL;
+ self->data = NULL;
+ }
+
+ g_clear_object (&self->context);
+ self->id = 0;
+
+ if (self->saved)
+ {
+ cairo_surface_destroy (self->saved);
+ self->saved = NULL;
+ }
G_OBJECT_CLASS (gdk_gl_texture_parent_class)->dispose (object);
}
@@ -474,7 +487,6 @@ gdk_gl_texture_download (GdkTexture *texture,
GdkGLTexture *self = GDK_GL_TEXTURE (texture);
cairo_surface_t *surface;
cairo_t *cr;
- GdkWindow *window;
surface = cairo_image_surface_create_for_data (data,
CAIRO_FORMAT_ARGB32,
@@ -482,8 +494,21 @@ gdk_gl_texture_download (GdkTexture *texture,
stride);
cr = cairo_create (surface);
- window = gdk_gl_context_get_window (self->context);
- gdk_cairo_draw_from_gl (cr, window, self->id, GL_TEXTURE, 1, 0, 0, texture->width, texture->height);
+
+ if (self->saved)
+ {
+ cairo_set_source_surface (cr, self->saved, 0, 0);
+ cairo_paint (cr);
+ }
+ else
+ {
+ GdkWindow *window;
+
+ window = gdk_gl_context_get_window (self->context);
+ gdk_cairo_draw_from_gl (cr, window, self->id, GL_TEXTURE, 1, 0, 0,
+ texture->width, texture->height);
+ }
+
cairo_destroy (cr);
cairo_surface_finish (surface);
cairo_surface_destroy (surface);
@@ -516,6 +541,41 @@ gdk_gl_texture_get_id (GdkGLTexture *self)
return self->id;
}
+void
+gdk_texture_release_gl (GdkTexture *texture)
+{
+ GdkGLTexture *self;
+ GdkWindow *window;
+ cairo_t *cr;
+
+ g_return_if_fail (GDK_IS_GL_TEXTURE (texture));
+
+ self = GDK_GL_TEXTURE (texture);
+
+ g_return_if_fail (self->saved == NULL);
+
+ self->saved = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
+ texture->width, texture->height);
+
+ cr = cairo_create (self->saved);
+
+ window = gdk_gl_context_get_window (self->context);
+ gdk_cairo_draw_from_gl (cr, window, self->id, GL_TEXTURE, 1, 0, 0,
+ texture->width, texture->height);
+
+ cairo_destroy (cr);
+
+ if (self->destroy)
+ {
+ self->destroy (self->data);
+ self->destroy = NULL;
+ self->data = NULL;
+ }
+
+ g_clear_object (&self->context);
+ self->id = 0;
+}
+
/**
* gdk_texture_new_for_pixbuf:
* @pixbuf: a #GdkPixbuf
diff --git a/gdk/gdktexture.h b/gdk/gdktexture.h
index 4f3ead2321..ae7ac812f2 100644
--- a/gdk/gdktexture.h
+++ b/gdk/gdktexture.h
@@ -65,6 +65,9 @@ GdkTexture * gdk_texture_new_for_gl (GdkGLContext
gpointer data);
GDK_AVAILABLE_IN_3_94
+void gdk_texture_release_gl (GdkTexture *texture);
+
+GDK_AVAILABLE_IN_3_94
int gdk_texture_get_width (GdkTexture *texture);
GDK_AVAILABLE_IN_3_94
int gdk_texture_get_height (GdkTexture *texture);