From 0bfcb700b9e524d6e3adf9a2137f6c155168eadb Mon Sep 17 00:00:00 2001 From: Derek Foreman Date: Thu, 16 Oct 2025 14:59:35 -0500 Subject: [PATCH] compositor/shells: Require shells to flag outputs as ready to allow repaint We've added a curtain to the shells so at startup we have something to render, but this causes a flicker if someone is trying to have a seamless transition from boot to weston. Add a ready flag that allows the shell to indicate repaints are safe, so we can remove the curtains and have no wasted frames at startup. Signed-off-by: Derek Foreman --- desktop-shell/shell.c | 1 + fullscreen-shell/fullscreen-shell.c | 2 ++ include/libweston/libweston.h | 9 ++++++++ ivi-shell/ivi-layout.c | 1 + kiosk-shell/kiosk-shell.c | 1 + libweston/compositor.c | 33 +++++++++++++++++++++++++++++ lua-shell/lua-shell.c | 10 +++++++++ lua-shell/shell.lua | 3 +++ tests/weston-test-desktop-shell.c | 1 + 9 files changed, 61 insertions(+) diff --git a/desktop-shell/shell.c b/desktop-shell/shell.c index 8bc23a6ed..5ec897ddd 100644 --- a/desktop-shell/shell.c +++ b/desktop-shell/shell.c @@ -2662,6 +2662,7 @@ background_committed(struct weston_surface *es, sh_output->output->pos); weston_view_move_to_layer(sh_output->background_view, &shell->background_layer.view_list); + weston_output_set_ready(sh_output->output); } static void diff --git a/fullscreen-shell/fullscreen-shell.c b/fullscreen-shell/fullscreen-shell.c index 733e1a3e3..2ba37a22c 100644 --- a/fullscreen-shell/fullscreen-shell.c +++ b/fullscreen-shell/fullscreen-shell.c @@ -353,6 +353,8 @@ fs_output_create(struct fullscreen_shell *shell, struct weston_output *output) } } + weston_output_set_ready(output); + return fsout; } diff --git a/include/libweston/libweston.h b/include/libweston/libweston.h index b59efaf84..d671989a9 100644 --- a/include/libweston/libweston.h +++ b/include/libweston/libweston.h @@ -541,6 +541,12 @@ struct weston_output { enum weston_vrr_mode vrr_mode; enum weston_color_format color_format; + + /** + * Set by the shell to indicate there's some content for this + * output to display. + */ + bool ready; }; enum weston_pointer_motion_mask { @@ -2715,6 +2721,9 @@ weston_output_set_color_format(struct weston_output *output, uint32_t weston_output_get_supported_color_formats(struct weston_output *output); +void +weston_output_set_ready(struct weston_output *output); + #ifdef __cplusplus } #endif diff --git a/ivi-shell/ivi-layout.c b/ivi-shell/ivi-layout.c index 335ab1df1..9d15e8ca0 100644 --- a/ivi-shell/ivi-layout.c +++ b/ivi-shell/ivi-layout.c @@ -353,6 +353,7 @@ create_ivi_screen(struct ivi_layout *layout, struct weston_output *output) &layout->layout_layer.view_list); weston_view_set_output(iviscrn->temporary_curtain->view, output); + weston_output_set_ready(output); } static void diff --git a/kiosk-shell/kiosk-shell.c b/kiosk-shell/kiosk-shell.c index 50971e357..58525874d 100644 --- a/kiosk-shell/kiosk-shell.c +++ b/kiosk-shell/kiosk-shell.c @@ -824,6 +824,7 @@ kiosk_shell_output_create(struct kiosk_shell *shell, struct weston_output *outpu kiosk_shell_output_recreate_background(shoutput); kiosk_shell_output_configure(shoutput); + weston_output_set_ready(output); return shoutput; } diff --git a/libweston/compositor.c b/libweston/compositor.c index 082233738..d9733d1db 100644 --- a/libweston/compositor.c +++ b/libweston/compositor.c @@ -3904,6 +3904,9 @@ output_repaint_timer_handler(void *data) compositor->last_repaint_start = now; wl_list_for_each(output, &compositor->output_list, link) { + if (!output->ready) + continue; + if (!weston_output_check_repaint(output, &now)) { output->will_repaint = false; continue; @@ -4336,6 +4339,9 @@ weston_output_schedule_repaint(struct weston_output *output) struct weston_compositor *compositor = output->compositor; struct wl_event_loop *loop; + if (!output->ready) + return; + if (compositor->state == WESTON_COMPOSITOR_SLEEPING || compositor->state == WESTON_COMPOSITOR_OFFSCREEN) return; @@ -10495,3 +10501,30 @@ weston_get_backend_type(struct weston_backend *backend) assert(backend); return backend->backend_type; } + +/** Inform the compositor that an output is ready for its first repaint + * + * When a new output is added, it may not have any content to be + * displayed. This could lead to strange flickers or hangs at + * startup if uninitialized buffers become attached for + * scanout. To prevent this, we assert that the output has + * content to display. + * + * The shell must inform the compositor when content such as a + * background is in the scene graph and this output can safely + * be repainted. + * + * Only needs to be called once per output, and an output + * can never become unready. + * + * \param output the output that has become ready + * \ingroup output + */ +WL_EXPORT void +weston_output_set_ready(struct weston_output *output) +{ + if (!output->ready) { + output->ready = true; + weston_output_schedule_repaint(output); + } +} diff --git a/lua-shell/lua-shell.c b/lua-shell/lua-shell.c index 42e0404eb..bf083970f 100644 --- a/lua-shell/lua-shell.c +++ b/lua-shell/lua-shell.c @@ -921,6 +921,15 @@ lua_shell_env_output_is_enabled(struct lua_State *lua) return 1; } +static int +lua_shell_env_output_set_ready(struct lua_State *lua) +{ + struct lua_shell_output *shoutput = get_output_from_arg(lua, 1); + + weston_output_set_ready(shoutput->output); + return 0; +} + static int lua_shell_env_output_set_private(struct lua_State *lua) { @@ -954,6 +963,7 @@ lua_shell_env_init_output(struct lua_shell *shell) { "is_enabled", lua_shell_env_output_is_enabled }, { "set_private", lua_shell_env_output_set_private }, { "get_private", lua_shell_env_output_get_private }, + { "set_ready", lua_shell_env_output_set_ready }, { NULL, NULL } }; diff --git a/lua-shell/shell.lua b/lua-shell/shell.lua index f2c1ff25f..498902b3d 100644 --- a/lua-shell/shell.lua +++ b/lua-shell/shell.lua @@ -95,6 +95,9 @@ function my_output_create(output) pd.background_view = bv output:set_private(pd) + + -- Must set ready or no repaints will take place + output:set_ready() end function output_moved(output, move_x, move_y) diff --git a/tests/weston-test-desktop-shell.c b/tests/weston-test-desktop-shell.c index 7f7c6e21d..09a0121e5 100644 --- a/tests/weston-test-desktop-shell.c +++ b/tests/weston-test-desktop-shell.c @@ -338,6 +338,7 @@ wet_shell_init(struct weston_compositor *ec, screenshooter_create(ec); desktest_shell_add_bindings(dts); + weston_output_set_ready(output); return 0;