From 52b6316e9c0192493e6a7e063f771d5ce1aaf872 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergio=20G=C3=B3mez?= Date: Wed, 26 Nov 2025 10:35:20 -0500 Subject: [PATCH] commit-timing-v1: add scene implementation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Sergio Gómez --- include/wlr/types/wlr_scene.h | 11 ++++++ types/scene/surface.c | 9 +++++ types/scene/wlr_scene.c | 74 +++++++++++++++++++++++++++++++++++ 3 files changed, 94 insertions(+) diff --git a/include/wlr/types/wlr_scene.h b/include/wlr/types/wlr_scene.h index 2363c93ce..013d100a1 100644 --- a/include/wlr/types/wlr_scene.h +++ b/include/wlr/types/wlr_scene.h @@ -104,12 +104,17 @@ struct wlr_scene { struct wlr_linux_dmabuf_v1 *linux_dmabuf_v1; struct wlr_gamma_control_manager_v1 *gamma_control_manager_v1; struct wlr_color_manager_v1 *color_manager_v1; + struct wlr_commit_timing_manager_v1 *commit_timing_manager_v1; + struct wl_list commit_timers; // wlr_commit_timer_v1.scene_link struct { struct wl_listener linux_dmabuf_v1_destroy; struct wl_listener gamma_control_manager_v1_destroy; struct wl_listener gamma_control_manager_v1_set_gamma; struct wl_listener color_manager_v1_destroy; + struct wl_listener commit_timing_manager_v1_destroy; + struct wl_listener commit_timing_manager_v1_new_timer; + struct wl_listener commit_timer_v1_destroy; enum wlr_scene_debug_damage_option debug_damage_option; bool direct_scanout; @@ -383,6 +388,12 @@ void wlr_scene_set_gamma_control_manager_v1(struct wlr_scene *scene, */ void wlr_scene_set_color_manager_v1(struct wlr_scene *scene, struct wlr_color_manager_v1 *manager); +/** + * Handles commit_timing_manager_v1 for all surfaces and their primary outputs in the scene. + */ +void wlr_scene_set_commit_timing_manager_v1(struct wlr_scene *scene, + struct wlr_commit_timing_manager_v1 *timing_manager); + /** * Add a node displaying nothing but its children. */ diff --git a/types/scene/surface.c b/types/scene/surface.c index 0c24208cb..068b34d7a 100644 --- a/types/scene/surface.c +++ b/types/scene/surface.c @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include @@ -106,6 +107,14 @@ static void handle_scene_buffer_outputs_update( wlr_color_manager_v1_set_surface_preferred_image_description(scene->color_manager_v1, surface->surface, &img_desc); } + + struct wlr_commit_timer_v1 *timer; + wl_list_for_each(timer, &scene->commit_timers, scene_link) { + if (timer->surface == surface->surface && surface->buffer->active_outputs && + timer->output != surface->buffer->primary_output->output) { + wlr_commit_timer_v1_set_output(timer, surface->buffer->primary_output->output); + } + } } static void handle_scene_buffer_output_enter( diff --git a/types/scene/wlr_scene.c b/types/scene/wlr_scene.c index cb374258d..c7caa73b5 100644 --- a/types/scene/wlr_scene.c +++ b/types/scene/wlr_scene.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -181,6 +182,7 @@ struct wlr_scene *wlr_scene_create(void) { scene_tree_init(&scene->tree, NULL); wl_list_init(&scene->outputs); + wl_list_init(&scene->commit_timers); wl_list_init(&scene->linux_dmabuf_v1_destroy.link); wl_list_init(&scene->gamma_control_manager_v1_destroy.link); wl_list_init(&scene->gamma_control_manager_v1_set_gamma.link); @@ -1604,6 +1606,78 @@ void wlr_scene_set_color_manager_v1(struct wlr_scene *scene, struct wlr_color_ma wl_signal_add(&manager->events.destroy, &scene->color_manager_v1_destroy); } +static void scene_handle_commit_timer_v1_destroy(struct wl_listener *listener, + void *data) { + struct wlr_scene *scene = + wl_container_of(listener, scene, commit_timer_v1_destroy); + struct wlr_commit_timer_v1 *timer = data; + struct wlr_surface *surface = timer->surface; + + struct wlr_commit_timer_v1 *tmp_timer; + wl_list_for_each_safe(timer, tmp_timer, &scene->commit_timers, scene_link) { + if (timer->surface == surface) { + wl_list_remove(&timer->scene_link); + } + } +} + +static void timer_set_output(struct wlr_scene_buffer *scene_buffer, int x, int y, void *data) { + struct wlr_scene_surface *scene_surface = + wlr_scene_surface_try_from_buffer(scene_buffer); + if (!scene_surface) { + return; + } + + struct wlr_commit_timer_v1 *timer = data; + if (scene_surface->surface == timer->surface) { + struct wlr_scene_output *primary_output = scene_surface->buffer->primary_output; + if (primary_output) { + wlr_commit_timer_v1_set_output(timer, primary_output->output); + } + } +} + +static void scene_handle_commit_timing_manager_v1_new_timer(struct wl_listener *listener, + void *data) { + struct wlr_scene *scene = + wl_container_of(listener, scene, commit_timing_manager_v1_new_timer); + struct wlr_commit_timing_manager_v1_new_timer_event *event = data; + struct wlr_commit_timer_v1 *timer = event->timer; + + wl_list_insert(&scene->commit_timers, &timer->scene_link); + scene->commit_timer_v1_destroy.notify = scene_handle_commit_timer_v1_destroy; + wl_signal_add(&timer->events.destroy, &scene->commit_timer_v1_destroy); + + wlr_scene_node_for_each_buffer(&scene->tree.node, timer_set_output, event->timer); +} + +static void scene_handle_commit_timing_manager_v1_destroy(struct wl_listener *listener, + void *data) { + struct wlr_scene *scene = + wl_container_of(listener, scene, commit_timing_manager_v1_destroy); + wl_list_remove(&scene->commit_timing_manager_v1_destroy.link); + wl_list_init(&scene->commit_timing_manager_v1_destroy.link); + wl_list_remove(&scene->commit_timing_manager_v1_new_timer.link); + wl_list_init(&scene->commit_timing_manager_v1_new_timer.link); + scene->commit_timing_manager_v1 = NULL; +} + +void wlr_scene_set_commit_timing_manager_v1(struct wlr_scene *scene, + struct wlr_commit_timing_manager_v1 *commit_timing) { + assert(scene->commit_timing_manager_v1 == NULL); + + scene->commit_timing_manager_v1 = commit_timing; + + scene->commit_timing_manager_v1_new_timer.notify = + scene_handle_commit_timing_manager_v1_new_timer; + wl_signal_add(&commit_timing->events.new_timer, + &scene->commit_timing_manager_v1_new_timer); + scene->commit_timing_manager_v1_destroy.notify = + scene_handle_commit_timing_manager_v1_destroy; + wl_signal_add(&commit_timing->events.destroy, + &scene->commit_timing_manager_v1_destroy); +} + static void scene_output_handle_destroy(struct wlr_addon *addon) { struct wlr_scene_output *scene_output = wl_container_of(addon, scene_output, addon);