From 9dad71513c20e6af50be3fe8910eb206146fe8ea Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Thu, 11 Apr 2024 12:48:01 -0400 Subject: [PATCH] glarea: Clean up dispose We were getting our gl and dmabuf texture mixed up and ending up freeing the Texture structs while they were still used as callback data for dmabuf texture destroys. Avoid that by keeping separate pointers for the gl and dmabuf textures. Fixes: #6623 --- gtk/gtkglarea.c | 61 ++++++++++++++++++++++++++++--------------------- 1 file changed, 35 insertions(+), 26 deletions(-) diff --git a/gtk/gtkglarea.c b/gtk/gtkglarea.c index 9cd9d661cf..871e086ef0 100644 --- a/gtk/gtkglarea.c +++ b/gtk/gtkglarea.c @@ -156,7 +156,8 @@ typedef struct { GdkGLTextureBuilder *builder; - GdkTexture *holder; + GdkTexture *gl_texture; + GdkTexture *dmabuf_texture; } Texture; typedef struct { @@ -415,16 +416,20 @@ delete_one_texture (gpointer data) Texture *texture = data; guint id; - if (texture->holder) - gdk_gl_texture_release (GDK_GL_TEXTURE (texture->holder)); + if (texture->gl_texture) + { + gdk_gl_texture_release (GDK_GL_TEXTURE (texture->gl_texture)); + texture->gl_texture = NULL; + } id = gdk_gl_texture_builder_get_id (texture->builder); if (id != 0) glDeleteTextures (1, &id); - g_object_unref (texture->builder); + g_clear_object (&texture->builder); - g_free (texture); + if (texture->gl_texture == NULL && texture->dmabuf_texture == NULL) + g_free (texture); } static void @@ -449,7 +454,7 @@ gtk_gl_area_ensure_texture (GtkGLArea *area) link = l; l = l->next; - if (texture->holder) + if (texture->gl_texture) continue; priv->textures = g_list_delete_link (priv->textures, link); @@ -466,7 +471,8 @@ gtk_gl_area_ensure_texture (GtkGLArea *area) GLuint id; priv->texture = g_new (Texture, 1); - priv->texture->holder = NULL; + priv->texture->gl_texture = NULL; + priv->texture->dmabuf_texture = NULL; priv->texture->builder = gdk_gl_texture_builder_new (); gdk_gl_texture_builder_set_context (priv->texture->builder, priv->context); @@ -524,7 +530,7 @@ gtk_gl_area_allocate_texture (GtkGLArea *area) if (priv->texture == NULL) return; - g_assert (priv->texture->holder == NULL); + g_assert (priv->texture->gl_texture == NULL); scale = gtk_widget_get_scale_factor (widget); width = gtk_widget_get_width (widget) * scale; @@ -706,7 +712,7 @@ gtk_gl_area_draw_error_screen (GtkGLArea *area, } static void -release_texture (gpointer data) +release_gl_texture (gpointer data) { Texture *texture = data; gpointer sync; @@ -718,7 +724,7 @@ release_texture (gpointer data) gdk_gl_texture_builder_set_sync (texture->builder, NULL); } - texture->holder = NULL; + texture->gl_texture = NULL; } static void @@ -735,10 +741,14 @@ release_dmabuf_texture (gpointer data) { Texture *texture = data; - release_dmabuf (gdk_dmabuf_texture_get_dmabuf (GDK_DMABUF_TEXTURE (texture->holder))); - g_object_set_data (G_OBJECT (texture->holder), "gltexture", NULL); + g_clear_object (&texture->gl_texture); - texture->holder = NULL; + if (texture->dmabuf_texture == NULL) + return; + + release_dmabuf (gdk_dmabuf_texture_get_dmabuf (GDK_DMABUF_TEXTURE (texture->dmabuf_texture ))); + + texture->dmabuf_texture = NULL; } static void @@ -784,8 +794,8 @@ gtk_gl_area_snapshot (GtkWidget *widget, { Texture *texture; gpointer sync = NULL; - GdkTexture *gltexture; GdkDmabuf dmabuf; + GdkTexture *holder; if (priv->needs_render || priv->auto_render) { @@ -809,9 +819,10 @@ gtk_gl_area_snapshot (GtkWidget *widget, gdk_gl_texture_builder_set_sync (texture->builder, sync); - gltexture = gdk_gl_texture_builder_build (texture->builder, - release_texture, - texture); + texture->gl_texture = gdk_gl_texture_builder_build (texture->builder, + release_gl_texture, + texture); + holder = texture->gl_texture; if (gdk_gl_context_export_dmabuf (priv->context, gdk_gl_texture_builder_get_id (texture->builder), @@ -820,22 +831,20 @@ gtk_gl_area_snapshot (GtkWidget *widget, GdkDmabufTextureBuilder *builder = gdk_dmabuf_texture_builder_new (); gdk_dmabuf_texture_builder_set_display (builder, gdk_gl_context_get_display (priv->context)); - gdk_dmabuf_texture_builder_set_width (builder, gdk_texture_get_width (gltexture)); - gdk_dmabuf_texture_builder_set_height (builder, gdk_texture_get_height (gltexture)); + gdk_dmabuf_texture_builder_set_width (builder, gdk_texture_get_width (texture->gl_texture)); + gdk_dmabuf_texture_builder_set_height (builder, gdk_texture_get_height (texture->gl_texture)); gdk_dmabuf_texture_builder_set_premultiplied (builder, TRUE); gdk_dmabuf_texture_builder_set_dmabuf (builder, &dmabuf); - texture->holder = gdk_dmabuf_texture_builder_build (builder, release_dmabuf_texture, texture, NULL); + texture->dmabuf_texture = gdk_dmabuf_texture_builder_build (builder, release_dmabuf_texture, texture, NULL); g_object_unref (builder); - if (texture->holder != NULL) - g_object_set_data_full (G_OBJECT (texture->holder), "gltexture", gltexture, g_object_unref); + if (texture->dmabuf_texture != NULL) + holder = texture->dmabuf_texture; else release_dmabuf (&dmabuf); } - else - texture->holder = gltexture; /* Our texture is rendered by OpenGL, so it is upside down, * compared to what GSK expects, so flip it back. @@ -844,13 +853,13 @@ gtk_gl_area_snapshot (GtkWidget *widget, gtk_snapshot_translate (snapshot, &GRAPHENE_POINT_INIT (0, gtk_widget_get_height (widget))); gtk_snapshot_scale (snapshot, 1, -1); gtk_snapshot_append_texture (snapshot, - texture->holder, + holder, &GRAPHENE_RECT_INIT (0, 0, gtk_widget_get_width (widget), gtk_widget_get_height (widget))); gtk_snapshot_restore (snapshot); - g_object_unref (texture->holder); + g_object_unref (holder); } else {