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.
This commit is contained in:
Matthias Clasen 2018-01-17 20:15:45 -05:00
parent 34c63b8e4f
commit 5e302ae2cc
2 changed files with 69 additions and 6 deletions

View File

@ -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

View File

@ -64,6 +64,9 @@ GdkTexture * gdk_texture_new_for_gl (GdkGLContext
GDestroyNotify destroy,
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