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.
This commit is contained in:
Kovid Goyal 2022-10-12 17:51:19 +05:30
parent 48a4edc199
commit 6890e265b6
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
3 changed files with 13 additions and 4 deletions

View File

@ -54,6 +54,8 @@ Detailed list of changes
- Update to Unicode 15.0 (:pull:`5542`) - 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] 0.26.3 [2022-09-22]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

View File

@ -104,9 +104,10 @@ init_buffer_pair(_GLFWWaylandBufferPair *pair, size_t width, size_t height, unsi
static bool static bool
window_has_buffer(_GLFWwindow *window, struct wl_buffer *q) { window_has_buffer(_GLFWwindow *window, struct wl_buffer *q) {
#define Q(which) decs.which.buffer.a == q || decs.which.buffer.b == q #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; }
return Q(left) || Q(top) || Q(right) || Q(bottom); Q(left); Q(top); Q(right); Q(bottom);
#undef Q #undef Q
return false;
} }
static void 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) { 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->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 = 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); wl_buffer_add_listener(pair->a, &handle_buffer_events, (void*)window_id);
*offset += pair->size_in_bytes; *offset += pair->size_in_bytes;
pair->data.b = data + *offset; 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 = 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); wl_buffer_add_listener(pair->b, &handle_buffer_events, (void*)window_id);
*offset += pair->size_in_bytes; *offset += pair->size_in_bytes;
pair->front = pair->a; pair->back = pair->b; pair->front = pair->a; pair->back = pair->b;
@ -331,6 +334,8 @@ free_csd_surfaces(_GLFWwindow *window) {
static void static void
free_csd_buffers(_GLFWwindow *window) { free_csd_buffers(_GLFWwindow *window) {
#define d(which) { \ #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)); \ memset(&decs.which.buffer, 0, sizeof(_GLFWWaylandBufferPair)); \
} }
d(left); d(top); d(right); d(bottom); d(left); d(top); d(right); d(bottom);
@ -353,9 +358,10 @@ create_csd_surfaces(_GLFWwindow *window, _GLFWWaylandCSDEdge *s) {
} }
#define damage_csd(which, xbuffer) \ #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_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 bool
ensure_csd_resources(_GLFWwindow *window) { ensure_csd_resources(_GLFWwindow *window) {

1
glfw/wl_platform.h vendored
View File

@ -104,6 +104,7 @@ typedef struct _GLFWWaylandBufferPair {
struct { uint8_t *a, *b, *front, *back; } data; struct { uint8_t *a, *b, *front, *back; } data;
bool has_pending_update; bool has_pending_update;
size_t size_in_bytes, width, height, stride; size_t size_in_bytes, width, height, stride;
bool a_needs_to_be_destroyed, b_needs_to_be_destroyed;
} _GLFWWaylandBufferPair; } _GLFWWaylandBufferPair;
typedef struct _GLFWWaylandCSDEdge { typedef struct _GLFWWaylandCSDEdge {