From c6cc446e63e1fb2a7c326b94ffbdd43839acfc9b Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Tue, 26 Sep 2023 12:49:32 +0100 Subject: [PATCH 1/4] broadway: Plug a leak in the GSK renderer We are leaking the Cairo image surface when creating a new node. Fixes: #6120 --- gsk/broadway/gskbroadwayrenderer.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/gsk/broadway/gskbroadwayrenderer.c b/gsk/broadway/gskbroadwayrenderer.c index e8a3ad0df4..c52c2d5e4e 100644 --- a/gsk/broadway/gskbroadwayrenderer.c +++ b/gsk/broadway/gskbroadwayrenderer.c @@ -902,6 +902,8 @@ gsk_broadway_renderer_add_node (GskRenderer *renderer, add_float (nodes, width); add_float (nodes, height); add_uint32 (nodes, texture_id); + + cairo_surface_destroy (surface); } } From 0b64fa88a126c5faa133c9296bd5df91bfe0acb4 Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Tue, 26 Sep 2023 12:57:52 +0100 Subject: [PATCH 2/4] docs: Clarify the behaviour of gdk_texture_new_for_surface() Cairo surfaces are not GObject instances, so we should be more explicit in the behaviour of the memory management, to avoid leaks. --- gdk/gdktexture.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/gdk/gdktexture.c b/gdk/gdktexture.c index ca53f036c2..01ed8dc43f 100644 --- a/gdk/gdktexture.c +++ b/gdk/gdktexture.c @@ -345,7 +345,9 @@ gdk_texture_init (GdkTexture *self) * * Creates a new texture object representing the surface. * - * @surface must be an image surface with format `CAIRO_FORMAT_ARGB32`. + * The @surface must be an image surface with format `CAIRO_FORMAT_ARGB32`. + * + * The newly created texture will acquire a reference on the @surface. * * Returns: a new `GdkTexture` */ @@ -364,7 +366,7 @@ gdk_texture_new_for_surface (cairo_surface_t *surface) * cairo_image_surface_get_stride (surface), (GDestroyNotify) cairo_surface_destroy, cairo_surface_reference (surface)); - + texture = gdk_memory_texture_new (cairo_image_surface_get_width (surface), cairo_image_surface_get_height (surface), GDK_MEMORY_DEFAULT, @@ -819,7 +821,7 @@ gdk_texture_set_render_data (GdkTexture *self, GDestroyNotify notify) { g_return_val_if_fail (data != NULL, FALSE); - + if (self->render_key != NULL) return FALSE; From 90be2baf8bd593991550ba46b45871039d53df46 Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Tue, 26 Sep 2023 14:40:37 +0100 Subject: [PATCH 3/4] broadway: Plug another leak When getting a colorized texture we're downloading the texture as a Cairo surface, and then feeding it to another texture, but we never drop the reference of the new surface. --- gsk/broadway/gskbroadwayrenderer.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/gsk/broadway/gskbroadwayrenderer.c b/gsk/broadway/gskbroadwayrenderer.c index c52c2d5e4e..1343525a92 100644 --- a/gsk/broadway/gskbroadwayrenderer.c +++ b/gsk/broadway/gskbroadwayrenderer.c @@ -453,7 +453,7 @@ get_colorized_texture (GdkTexture *texture, const graphene_matrix_t *color_matrix, const graphene_vec4_t *color_offset) { - cairo_surface_t *surface = gdk_texture_download_surface (texture); + cairo_surface_t *surface; cairo_surface_t *image_surface; graphene_vec4_t pixel; guint32* pixel_data; @@ -475,6 +475,7 @@ get_colorized_texture (GdkTexture *texture, return g_object_ref (colorized->texture); } + surface = gdk_texture_download_surface (texture); image_surface = cairo_surface_map_to_image (surface, NULL); data = cairo_image_surface_get_data (image_surface); width = cairo_image_surface_get_width (image_surface); @@ -536,6 +537,8 @@ get_colorized_texture (GdkTexture *texture, colorized_list, (GDestroyNotify)colorized_texture_free_list); } + cairo_surface_destroy (surface); + return colorized_texture; } From 3ea723730bb0a9608dd973c9383f70b873909f62 Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Tue, 26 Sep 2023 14:44:05 +0100 Subject: [PATCH 4/4] broadway: Do not add an extra reference when caching textures We just created a GdkTexture, so we don't need to acquire a reference if we're transferring the ownership to the node cache. --- gsk/broadway/gskbroadwayrenderer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gsk/broadway/gskbroadwayrenderer.c b/gsk/broadway/gskbroadwayrenderer.c index 1343525a92..9b945b8fd2 100644 --- a/gsk/broadway/gskbroadwayrenderer.c +++ b/gsk/broadway/gskbroadwayrenderer.c @@ -614,7 +614,7 @@ gsk_broadway_renderer_add_node (GskRenderer *renderer, } texture = gdk_texture_new_for_surface (image_surface); - g_ptr_array_add (self->node_textures, g_object_ref (texture)); /* Transfers ownership to node_textures */ + g_ptr_array_add (self->node_textures, texture); /* Transfers ownership to node_textures */ texture_id = gdk_broadway_display_ensure_texture (display, texture); add_rect (nodes, &node->bounds, offset_x, offset_y);