mirror of
https://gitlab.freedesktop.org/wayland/weston.git
synced 2026-05-07 11:58:03 +02:00
drm: handle client buffer destroyed while writeback scheduled
Currently when a client buffer gets destroyed, the output capture task
gets destroyed with weston_capture_task_buffer_destroy_handler().
The problem is that we may have a writeback task scheduled, so
wb_state->ct would be pointing to a ct that has already been retired
and destroyed.
In this commit we start handling this case.
Signed-off-by: Leandro Ribeiro <leandro.ribeiro@collabora.com>
(cherry picked from commit 1152c53e58)
Signed-off-by: Marius Vlad <marius.vlad@collabora.com>
This commit is contained in:
parent
65c7cc45b3
commit
641ac3ef82
2 changed files with 48 additions and 2 deletions
|
|
@ -472,6 +472,7 @@ struct drm_writeback_state {
|
|||
|
||||
enum writeback_screenshot_state state;
|
||||
struct weston_capture_task *ct;
|
||||
struct wl_listener buffer_destroy_listener;
|
||||
|
||||
struct drm_fb *fb;
|
||||
int32_t out_fence_fd;
|
||||
|
|
|
|||
|
|
@ -570,9 +570,28 @@ drm_writeback_state_free(struct drm_writeback_state *state)
|
|||
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)
|
||||
{
|
||||
struct drm_writeback_state *state =
|
||||
container_of(listener, struct drm_writeback_state,
|
||||
buffer_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
|
||||
* destroyed once the wb job completes.
|
||||
*/
|
||||
state->ct = NULL;
|
||||
wl_list_remove(&state->buffer_destroy_listener.link);
|
||||
}
|
||||
|
||||
static void
|
||||
drm_output_pick_writeback_capture_task(struct drm_output *output)
|
||||
{
|
||||
|
|
@ -626,6 +645,11 @@ 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);
|
||||
|
||||
return;
|
||||
|
||||
err_fb:
|
||||
|
|
@ -2899,12 +2923,21 @@ static void
|
|||
drm_writeback_success_screenshot(struct drm_writeback_state *state)
|
||||
{
|
||||
struct drm_output *output = state->output;
|
||||
struct weston_buffer *buffer =
|
||||
weston_capture_task_get_buffer(state->ct);
|
||||
struct weston_buffer *buffer;
|
||||
int width, height;
|
||||
int dst_stride, src_stride;
|
||||
uint32_t *src, *dst;
|
||||
|
||||
/**
|
||||
* Capture task already retired, see
|
||||
* drm_writeback_state_buffer_destroy_handler(). Here we destroy the wb
|
||||
* state.
|
||||
*/
|
||||
if (!state->ct)
|
||||
goto destroy_state;
|
||||
|
||||
buffer = weston_capture_task_get_buffer(state->ct);
|
||||
|
||||
src = state->fb->map;
|
||||
src_stride = state->fb->strides[0];
|
||||
|
||||
|
|
@ -2921,6 +2954,8 @@ drm_writeback_success_screenshot(struct drm_writeback_state *state)
|
|||
wl_shm_buffer_end_access(buffer->shm_buffer);
|
||||
|
||||
weston_capture_task_retire_complete(state->ct);
|
||||
|
||||
destroy_state:
|
||||
drm_writeback_state_free(state);
|
||||
output->wb_state = NULL;
|
||||
}
|
||||
|
|
@ -2931,7 +2966,17 @@ drm_writeback_fail_screenshot(struct drm_writeback_state *state,
|
|||
{
|
||||
struct drm_output *output = state->output;
|
||||
|
||||
/**
|
||||
* Capture task already retired, see
|
||||
* drm_writeback_state_buffer_destroy_handler(). Here we destroy the wb
|
||||
* state.
|
||||
*/
|
||||
if (!state->ct)
|
||||
goto destroy_state;
|
||||
|
||||
weston_capture_task_retire_failed(state->ct, err_msg);
|
||||
|
||||
destroy_state:
|
||||
drm_writeback_state_free(state);
|
||||
output->wb_state = NULL;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue