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
This commit is contained in:
Matthias Clasen
2024-04-11 12:48:01 -04:00
parent ed072b4b5d
commit 9dad71513c

View File

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