diff options
author | Matthias Clasen <mclasen@redhat.com> | 2018-01-17 20:15:45 -0500 |
---|---|---|
committer | Matthias Clasen <mclasen@redhat.com> | 2018-01-17 20:15:45 -0500 |
commit | 5e302ae2cc62d2e1d7cae9e6efb3b32b368c7b30 (patch) | |
tree | e9c5e72cf07a25ffdefedcada676c6cfbcdf3f20 | |
parent | 34c63b8e4f5068e855283e54bf76233a4e575a59 (diff) | |
download | gtk+-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.c | 72 | ||||
-rw-r--r-- | gdk/gdktexture.h | 3 |
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); |