From f8d466fefae42a94e2e3dfdab942d7d5e96bfeba Mon Sep 17 00:00:00 2001 From: Leandro Ribeiro Date: Tue, 31 Mar 2026 15:48:48 -0300 Subject: [PATCH] drm: use output capture task destroy listener for writeback No behavior changes; this is a follow-up of "drm: handle client buffer destroyed while writeback scheduled". That commit protects against clients disconnecting while a writeback job is scheduled, which could otherwise lead to crashes if the buffer is destroyed before the wb job completes. However, output capture provides the same functionality: it listens to the client buffer destroy event to retire the capture task. Instead of listening to the wl_buffer destroy event, simply listen to the capture task destroy event. GL renderer already follows this pattern, and now DRM aligns with it. See also: weston_capture_task_buffer_destroy_handler() weston_capture_task_add_destroy_listener() Signed-off-by: Leandro Ribeiro (cherry picked from commit 04a85ab71cdf16e71647bd35a6d7c756565fe77c) --- libweston/backend-drm/drm-internal.h | 2 +- libweston/backend-drm/drm.c | 22 ++++++++-------------- 2 files changed, 9 insertions(+), 15 deletions(-) diff --git a/libweston/backend-drm/drm-internal.h b/libweston/backend-drm/drm-internal.h index c65239fb7..30195717a 100644 --- a/libweston/backend-drm/drm-internal.h +++ b/libweston/backend-drm/drm-internal.h @@ -503,7 +503,7 @@ struct drm_writeback_state { enum writeback_screenshot_state state; struct weston_capture_task *ct; - struct wl_listener buffer_destroy_listener; + struct wl_listener ct_destroy_listener; struct drm_fb *fb; int32_t out_fence_fd; diff --git a/libweston/backend-drm/drm.c b/libweston/backend-drm/drm.c index 6db8232e8..5de386bc1 100644 --- a/libweston/backend-drm/drm.c +++ b/libweston/backend-drm/drm.c @@ -740,26 +740,22 @@ drm_writeback_state_free(struct weston_compositor *c, drm_fb_unref(*fb); wl_array_release(&state->referenced_fbs); - wl_list_remove(&state->buffer_destroy_listener.link); - free(state); } static void -drm_writeback_state_buffer_destroy_handler(struct wl_listener *listener, void *data) +drm_writeback_state_ct_destroy_handler(struct wl_listener *listener, void *data) { struct drm_writeback_state *state = container_of(listener, struct drm_writeback_state, - buffer_destroy_listener); + ct_destroy_listener); /** - * Client buffer destroyed while the wb job was scheduled. - * weston_capture_task_buffer_destroy_handler() retires the capture task - * when the buffer is gone, so drop it from the state. The state is + * Capture task was retired, so drop it from the state. The state is * destroyed once the wb job completes. */ state->ct = NULL; - wl_list_remove(&state->buffer_destroy_listener.link); + wl_list_remove(&state->ct_destroy_listener.link); } static void @@ -843,10 +839,8 @@ drm_output_pick_writeback_capture_task(struct drm_output *output) output->wb_state->state = DRM_OUTPUT_WB_SCREENSHOT_PREPARE_COMMIT; output->wb_state->ct = ct; - output->wb_state->buffer_destroy_listener.notify = - drm_writeback_state_buffer_destroy_handler; - wl_resource_add_destroy_listener(buffer->resource, - &output->wb_state->buffer_destroy_listener); + output->wb_state->ct_destroy_listener.notify = drm_writeback_state_ct_destroy_handler; + weston_capture_task_add_destroy_listener(ct, &output->wb_state->ct_destroy_listener); return; @@ -3448,7 +3442,7 @@ drm_writeback_success_screenshot(struct drm_writeback_state *state) /** * Capture task already retired, see - * drm_writeback_state_buffer_destroy_handler(). Here we destroy the wb + * drm_writeback_state_ct_destroy_handler(). Here we destroy the wb * state. */ if (!state->ct) @@ -3490,7 +3484,7 @@ drm_writeback_fail_screenshot(struct drm_writeback_state *state, /** * Capture task already retired, see - * drm_writeback_state_buffer_destroy_handler(). Here we destroy the wb + * drm_writeback_state_ct_destroy_handler(). Here we destroy the wb * state. */ if (!state->ct)