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 <leandro.ribeiro@collabora.com>
(cherry picked from commit 04a85ab71c)
This commit is contained in:
Leandro Ribeiro 2026-03-31 15:48:48 -03:00 committed by Marius Vlad
parent 655eec74e8
commit f8d466fefa
2 changed files with 9 additions and 15 deletions

View file

@ -503,7 +503,7 @@ struct drm_writeback_state {
enum writeback_screenshot_state state; enum writeback_screenshot_state state;
struct weston_capture_task *ct; struct weston_capture_task *ct;
struct wl_listener buffer_destroy_listener; struct wl_listener ct_destroy_listener;
struct drm_fb *fb; struct drm_fb *fb;
int32_t out_fence_fd; int32_t out_fence_fd;

View file

@ -740,26 +740,22 @@ drm_writeback_state_free(struct weston_compositor *c,
drm_fb_unref(*fb); drm_fb_unref(*fb);
wl_array_release(&state->referenced_fbs); wl_array_release(&state->referenced_fbs);
wl_list_remove(&state->buffer_destroy_listener.link);
free(state); free(state);
} }
static void 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 = struct drm_writeback_state *state =
container_of(listener, struct drm_writeback_state, container_of(listener, struct drm_writeback_state,
buffer_destroy_listener); ct_destroy_listener);
/** /**
* Client buffer destroyed while the wb job was scheduled. * Capture task was retired, so drop it from the state. The state is
* weston_capture_task_buffer_destroy_handler() retires the capture task
* when the buffer is gone, so drop it from the state. The state is
* destroyed once the wb job completes. * destroyed once the wb job completes.
*/ */
state->ct = NULL; state->ct = NULL;
wl_list_remove(&state->buffer_destroy_listener.link); wl_list_remove(&state->ct_destroy_listener.link);
} }
static void 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->state = DRM_OUTPUT_WB_SCREENSHOT_PREPARE_COMMIT;
output->wb_state->ct = ct; output->wb_state->ct = ct;
output->wb_state->buffer_destroy_listener.notify = output->wb_state->ct_destroy_listener.notify = drm_writeback_state_ct_destroy_handler;
drm_writeback_state_buffer_destroy_handler; weston_capture_task_add_destroy_listener(ct, &output->wb_state->ct_destroy_listener);
wl_resource_add_destroy_listener(buffer->resource,
&output->wb_state->buffer_destroy_listener);
return; return;
@ -3448,7 +3442,7 @@ drm_writeback_success_screenshot(struct drm_writeback_state *state)
/** /**
* Capture task already retired, see * 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. * state.
*/ */
if (!state->ct) if (!state->ct)
@ -3490,7 +3484,7 @@ drm_writeback_fail_screenshot(struct drm_writeback_state *state,
/** /**
* Capture task already retired, see * 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. * state.
*/ */
if (!state->ct) if (!state->ct)