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;
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;

View file

@ -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)