From 9de6dc096403dfd3d2ebf9646163e9b1388ea563 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergio=20G=C3=B3mez?= Date: Wed, 26 Nov 2025 10:56:16 -0500 Subject: [PATCH] fifo-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 | 12 ++++++++ types/scene/surface.c | 7 +++++ types/scene/wlr_scene.c | 56 +++++++++++++++++++++++++++++++++++ 3 files changed, 75 insertions(+) diff --git a/include/wlr/types/wlr_scene.h b/include/wlr/types/wlr_scene.h index 46635f4bf..52d99d643 100644 --- a/include/wlr/types/wlr_scene.h +++ b/include/wlr/types/wlr_scene.h @@ -104,6 +104,7 @@ 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_fifo_manager_v1 *fifo_manager_v1; bool restack_xwayland_surfaces; @@ -112,6 +113,8 @@ struct wlr_scene { 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 fifo_manager_v1_destroy; + struct wl_listener fifo_manager_v1_new_fifo; enum wlr_scene_debug_damage_option debug_damage_option; bool direct_scanout; @@ -125,6 +128,8 @@ struct wlr_scene_surface { struct wlr_scene_buffer *buffer; struct wlr_surface *surface; + struct wlr_fifo_v1 *fifo; + struct { struct wlr_box clip; @@ -137,6 +142,7 @@ struct wlr_scene_surface { struct wl_listener frame_done; struct wl_listener surface_destroy; struct wl_listener surface_commit; + struct wl_listener fifo_v1_destroy; } WLR_PRIVATE; }; @@ -381,6 +387,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 fifo_v1 for all surfaces and their primary outputs in the scene. + */ +void wlr_scene_set_fifo_manager_v1(struct wlr_scene *scene, + struct wlr_fifo_manager_v1 *fifo_manager); + /** * Add a node displaying nothing but its children. */ diff --git a/types/scene/surface.c b/types/scene/surface.c index bce8c74a6..bac89b556 100644 --- a/types/scene/surface.c +++ b/types/scene/surface.c @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -99,6 +100,9 @@ static void handle_scene_buffer_outputs_update( // If the surface is no longer visible on any output, keep the last sent // preferred configuration to avoid unnecessary redraws if (wl_list_empty(&surface->surface->current_outputs)) { + if (surface->fifo) { + wlr_fifo_v1_set_output(surface->fifo, NULL); + } return; } @@ -112,6 +116,9 @@ static void handle_scene_buffer_outputs_update( wlr_color_manager_v1_set_surface_preferred_image_description(scene->color_manager_v1, surface->surface, &img_desc); } + if (surface->fifo) { + wlr_fifo_v1_set_output(surface->fifo, 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 e7d628d01..41a58f117 100644 --- a/types/scene/wlr_scene.c +++ b/types/scene/wlr_scene.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -1640,6 +1641,61 @@ 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_surface_handle_fifo_v1_destroy(struct wl_listener *listener, + void *data) { + struct wlr_scene_surface *surface = + wl_container_of(listener, surface, fifo_v1_destroy); + wl_list_remove(&surface->fifo_v1_destroy.link); + surface->fifo = NULL; +} + +static void fifo_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_fifo_v1 *fifo = data; + if (scene_surface->surface == fifo->surface) { + scene_surface->fifo = fifo; + scene_surface->fifo_v1_destroy.notify = scene_surface_handle_fifo_v1_destroy; + wl_signal_add(&fifo->events.destroy, &scene_surface->fifo_v1_destroy); + wlr_fifo_v1_set_output(fifo, scene_buffer->primary_output ? + scene_buffer->primary_output->output : NULL); + } +} + +static void scene_handle_fifo_manager_v1_new_fifo(struct wl_listener *listener, + void *data) { + struct wlr_scene *scene = + wl_container_of(listener, scene, fifo_manager_v1_new_fifo); + struct wlr_fifo_manager_v1_new_fifo_event *event = data; + + wlr_scene_node_for_each_buffer(&scene->tree.node, fifo_set_output, event->fifo); +} + +static void scene_handle_fifo_manager_v1_destroy(struct wl_listener *listener, + void *data) { + struct wlr_scene *scene = + wl_container_of(listener, scene, fifo_manager_v1_destroy); + wl_list_remove(&scene->fifo_manager_v1_destroy.link); + wl_list_init(&scene->fifo_manager_v1_destroy.link); + wl_list_remove(&scene->fifo_manager_v1_new_fifo.link); + wl_list_init(&scene->fifo_manager_v1_new_fifo.link); + scene->fifo_manager_v1 = NULL; +} + +void wlr_scene_set_fifo_manager_v1(struct wlr_scene *scene, + struct wlr_fifo_manager_v1 *fifo_manager) { + assert(scene->fifo_manager_v1 == NULL); + scene->fifo_manager_v1 = fifo_manager; + scene->fifo_manager_v1_new_fifo.notify = scene_handle_fifo_manager_v1_new_fifo; + wl_signal_add(&fifo_manager->events.new_fifo, &scene->fifo_manager_v1_new_fifo); + scene->fifo_manager_v1_destroy.notify = scene_handle_fifo_manager_v1_destroy; + wl_signal_add(&fifo_manager->events.destroy, &scene->fifo_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);