From 45409c6e9f4dde6d2c3d1cf894cbb49571da77e1 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 | 67 +++++++++++++++++++++++++++++++++++ 3 files changed, 86 insertions(+) diff --git a/include/wlr/types/wlr_scene.h b/include/wlr/types/wlr_scene.h index f6f97cfea..4b1896abd 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; @@ -135,6 +140,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 e6ea1333a..1f12fd1d8 100644 --- a/types/scene/surface.c +++ b/types/scene/surface.c @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -100,6 +101,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 (event->size == 0) { + if (surface->fifo) { + wlr_fifo_v1_set_output(surface->fifo, NULL); + } return; } @@ -142,6 +146,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_sample( diff --git a/types/scene/wlr_scene.c b/types/scene/wlr_scene.c index 7231422e8..172170749 100644 --- a/types/scene/wlr_scene.c +++ b/types/scene/wlr_scene.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -1626,6 +1627,72 @@ 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 scene_fifo_set_output(struct wlr_scene_node *node, struct wlr_fifo_v1 *fifo) { + if (node->type == WLR_SCENE_NODE_TREE) { + struct wlr_scene_tree *scene_tree = wlr_scene_tree_from_node(node); + struct wlr_scene_node *child; + wl_list_for_each(child, &scene_tree->children, link) { + scene_fifo_set_output(child, fifo); + } + } + if (node->type != WLR_SCENE_NODE_BUFFER) { + return; + } + + struct wlr_scene_buffer *scene_buffer = wlr_scene_buffer_from_node(node); + struct wlr_scene_surface *scene_surface = + wlr_scene_surface_try_from_buffer(scene_buffer); + if (!scene_surface) { + return; + } + + 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; + + scene_fifo_set_output(&scene->tree.node, 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);