From 5ecc1913326efcece5ec29dc0d90f40edd545548 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix=20Poisot?= Date: Fri, 31 Jan 2025 18:36:07 +0000 Subject: [PATCH] scene: add buffer release point to 'sample' event --- include/wlr/types/wlr_scene.h | 4 ++++ types/scene/wlr_scene.c | 36 +++++++++++++++++++++++++++++++---- 2 files changed, 36 insertions(+), 4 deletions(-) diff --git a/include/wlr/types/wlr_scene.h b/include/wlr/types/wlr_scene.h index 0f4aa4c27..f864708a6 100644 --- a/include/wlr/types/wlr_scene.h +++ b/include/wlr/types/wlr_scene.h @@ -154,6 +154,8 @@ struct wlr_scene_outputs_update_event { struct wlr_scene_output_sample_event { struct wlr_scene_output *output; bool direct_scanout; + struct wlr_drm_syncobj_timeline *release_timeline; + uint64_t release_point; }; struct wlr_scene_frame_done_event { @@ -260,6 +262,8 @@ struct wlr_scene_output { struct wlr_drm_syncobj_timeline *in_timeline; uint64_t in_point; + struct wlr_drm_syncobj_timeline *out_timeline; + uint64_t out_point; } WLR_PRIVATE; }; diff --git a/types/scene/wlr_scene.c b/types/scene/wlr_scene.c index d2327eda2..f033386aa 100644 --- a/types/scene/wlr_scene.c +++ b/types/scene/wlr_scene.c @@ -1142,6 +1142,11 @@ static struct wlr_texture *scene_buffer_get_texture( return texture; } +static void scene_buffer_sample(struct wlr_scene_buffer *buffer, + struct wlr_scene_output_sample_event *event, struct wl_event_loop* loop) { + wl_signal_emit_mutable(&buffer->events.output_sample, event); +} + void scene_node_get_size(struct wlr_scene_node *node, int *width, int *height) { *width = 0; *height = 0; @@ -1481,8 +1486,10 @@ static void scene_entry_render(struct render_list_entry *entry, const struct ren struct wlr_scene_output_sample_event sample_event = { .output = data->output, .direct_scanout = false, + .release_timeline = data->output->in_timeline, + .release_point = data->output->in_point, }; - wl_signal_emit_mutable(&scene_buffer->events.output_sample, &sample_event); + scene_buffer_sample(scene_buffer, &sample_event, data->output->output->event_loop); if (entry->highlight_transparent_region) { wlr_render_pass_add_rect(data->render_pass, &(struct wlr_render_rect_options){ @@ -1694,7 +1701,10 @@ struct wlr_scene_output *wlr_scene_output_create(struct wlr_scene *scene, if (drm_fd >= 0 && output->backend->features.timeline && output->renderer != NULL && output->renderer->features.timeline) { scene_output->in_timeline = wlr_drm_syncobj_timeline_create(drm_fd); - if (scene_output->in_timeline == NULL) { + scene_output->out_timeline = wlr_drm_syncobj_timeline_create(drm_fd); + if (scene_output->in_timeline == NULL || scene_output->out_timeline == NULL) { + wlr_drm_syncobj_timeline_unref(scene_output->in_timeline); + wlr_drm_syncobj_timeline_unref(scene_output->out_timeline); return NULL; } } @@ -1749,7 +1759,14 @@ void wlr_scene_output_destroy(struct wlr_scene_output *scene_output) { wl_list_remove(&scene_output->output_commit.link); wl_list_remove(&scene_output->output_damage.link); wl_list_remove(&scene_output->output_needs_frame.link); - wlr_drm_syncobj_timeline_unref(scene_output->in_timeline); + if (scene_output->in_timeline != NULL) { + wlr_drm_syncobj_timeline_signal(scene_output->in_timeline, UINT64_MAX); + wlr_drm_syncobj_timeline_unref(scene_output->in_timeline); + } + if (scene_output->out_timeline != NULL) { + wlr_drm_syncobj_timeline_signal(scene_output->out_timeline, UINT64_MAX); + wlr_drm_syncobj_timeline_unref(scene_output->out_timeline); + } wl_array_release(&scene_output->render_list); free(scene_output); } @@ -2023,6 +2040,12 @@ static enum scene_direct_scanout_result scene_entry_try_direct_scanout( if (buffer->wait_timeline != NULL) { wlr_output_state_set_wait_timeline(&pending, buffer->wait_timeline, buffer->wait_point); } + + if (scene_output->out_timeline) { + scene_output->out_point++; + wlr_output_state_set_signal_timeline(&pending, scene_output->out_timeline, scene_output->out_point); + } + if (!wlr_output_test_state(scene_output->output, &pending)) { wlr_output_state_finish(&pending); return SCANOUT_CANDIDATE; @@ -2034,8 +2057,10 @@ static enum scene_direct_scanout_result scene_entry_try_direct_scanout( struct wlr_scene_output_sample_event sample_event = { .output = scene_output, .direct_scanout = true, + .release_timeline = data->output->out_timeline, + .release_point = data->output->out_point, }; - wl_signal_emit_mutable(&buffer->events.output_sample, &sample_event); + scene_buffer_sample(buffer, &sample_event, scene_output->output->event_loop); return SCANOUT_SUCCESS; } @@ -2414,6 +2439,9 @@ bool wlr_scene_output_build_state(struct wlr_scene_output *scene_output, if (scene_output->in_timeline != NULL) { wlr_output_state_set_wait_timeline(state, scene_output->in_timeline, scene_output->in_point); + scene_output->out_point++; + wlr_output_state_set_signal_timeline(state, scene_output->out_timeline, + scene_output->out_point); } scene_output_state_attempt_gamma(scene_output, state);