From 6890e265b651835eb6168ef56a68315de4a54a52 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Wed, 12 Oct 2022 17:51:19 +0530 Subject: [PATCH] GNOME Wayland: Fix a memory leak in gnome-shell when using client side decorations destroy CSD buffers that were never attached explicitly, as mutter does not send release events for these even when the pool is destroyed. --- docs/changelog.rst | 2 ++ glfw/wl_client_side_decorations.c | 14 ++++++++++---- glfw/wl_platform.h | 1 + 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/docs/changelog.rst b/docs/changelog.rst index 1d6ee2c57..371afd4dc 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -54,6 +54,8 @@ Detailed list of changes - Update to Unicode 15.0 (:pull:`5542`) +- GNOME Wayland: Fix a memory leak in gnome-shell when using client side decorations + 0.26.3 [2022-09-22] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/glfw/wl_client_side_decorations.c b/glfw/wl_client_side_decorations.c index 3e0a5ab5e..c66cbcdff 100644 --- a/glfw/wl_client_side_decorations.c +++ b/glfw/wl_client_side_decorations.c @@ -104,9 +104,10 @@ init_buffer_pair(_GLFWWaylandBufferPair *pair, size_t width, size_t height, unsi static bool window_has_buffer(_GLFWwindow *window, struct wl_buffer *q) { -#define Q(which) decs.which.buffer.a == q || decs.which.buffer.b == q - return Q(left) || Q(top) || Q(right) || Q(bottom); +#define Q(which) if (decs.which.buffer.a == q) { decs.which.buffer.a_needs_to_be_destroyed = false; return true; } if (decs.which.buffer.b == q) { decs.which.buffer.b_needs_to_be_destroyed = false; return true; } + Q(left); Q(top); Q(right); Q(bottom); #undef Q + return false; } static void @@ -122,10 +123,12 @@ static void alloc_buffer_pair(uintptr_t window_id, _GLFWWaylandBufferPair *pair, struct wl_shm_pool *pool, uint8_t *data, size_t *offset) { pair->data.a = data + *offset; pair->a = wl_shm_pool_create_buffer(pool, *offset, pair->width, pair->height, pair->stride, WL_SHM_FORMAT_ARGB8888); + pair->a_needs_to_be_destroyed = true; wl_buffer_add_listener(pair->a, &handle_buffer_events, (void*)window_id); *offset += pair->size_in_bytes; pair->data.b = data + *offset; pair->b = wl_shm_pool_create_buffer(pool, *offset, pair->width, pair->height, pair->stride, WL_SHM_FORMAT_ARGB8888); + pair->b_needs_to_be_destroyed = true; wl_buffer_add_listener(pair->b, &handle_buffer_events, (void*)window_id); *offset += pair->size_in_bytes; pair->front = pair->a; pair->back = pair->b; @@ -331,6 +334,8 @@ free_csd_surfaces(_GLFWwindow *window) { static void free_csd_buffers(_GLFWwindow *window) { #define d(which) { \ + if (decs.which.buffer.a_needs_to_be_destroyed && decs.which.buffer.a) wl_buffer_destroy(decs.which.buffer.a); \ + if (decs.which.buffer.b_needs_to_be_destroyed && decs.which.buffer.b) wl_buffer_destroy(decs.which.buffer.b); \ memset(&decs.which.buffer, 0, sizeof(_GLFWWaylandBufferPair)); \ } d(left); d(top); d(right); d(bottom); @@ -353,9 +358,10 @@ create_csd_surfaces(_GLFWwindow *window, _GLFWWaylandCSDEdge *s) { } #define damage_csd(which, xbuffer) \ - wl_surface_attach(decs.which.surface, xbuffer, 0, 0); \ + wl_surface_attach(decs.which.surface, (xbuffer), 0, 0); \ wl_surface_damage(decs.which.surface, 0, 0, decs.which.buffer.width, decs.which.buffer.height); \ - wl_surface_commit(decs.which.surface) + wl_surface_commit(decs.which.surface); \ + if (decs.which.buffer.a == (xbuffer)) { decs.which.buffer.a_needs_to_be_destroyed = false; } else { decs.which.buffer.b_needs_to_be_destroyed = false; } bool ensure_csd_resources(_GLFWwindow *window) { diff --git a/glfw/wl_platform.h b/glfw/wl_platform.h index a32f45ed6..5749be720 100644 --- a/glfw/wl_platform.h +++ b/glfw/wl_platform.h @@ -104,6 +104,7 @@ typedef struct _GLFWWaylandBufferPair { struct { uint8_t *a, *b, *front, *back; } data; bool has_pending_update; size_t size_in_bytes, width, height, stride; + bool a_needs_to_be_destroyed, b_needs_to_be_destroyed; } _GLFWWaylandBufferPair; typedef struct _GLFWWaylandCSDEdge {