From 16f9ca03b3a7794f3b621769ada91aa578f1b4d5 Mon Sep 17 00:00:00 2001 From: Kenny Levinsen Date: Tue, 15 Oct 2024 16:21:49 +0200 Subject: [PATCH 1/2] desktop/output: Wait for all pageflips to clear To allow a non-blocking modeset to succeed, we need to wait for all pageflips to clear first. --- sway/desktop/output.c | 59 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 58 insertions(+), 1 deletion(-) diff --git a/sway/desktop/output.c b/sway/desktop/output.c index a4eaa4b334..c8fa17b641 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -391,12 +391,69 @@ void update_output_manager_config(struct sway_server *server) { ipc_event_output(); } +// Placeholder while all render tasks clear up +static void handle_frame_nop(struct wl_listener *listener, void *user_data) {} + +static void handle_frame_clear(struct wl_listener *listener, void *user_data) { + struct sway_output *output = wl_container_of(listener, output, frame); + output->frame.notify = handle_frame_nop; + + sway_log(SWAY_DEBUG, "Render task for %s cleared", output->wlr_output->name); + + wl_list_for_each(output, &root->all_outputs, link) { + if (output == root->fallback_output) { + continue; + } + if (output->frame.notify != handle_frame_nop) { + return; + } + } + + // All done! + sway_log(SWAY_DEBUG, "All render tasks cleared, modestting"); + wl_list_for_each(output, &root->all_outputs, link) { + if (output == root->fallback_output) { + continue; + } + output->frame.notify = handle_frame; + } + apply_stored_output_configs(); +} + static int timer_modeset_handle(void *data) { struct sway_server *server = data; wl_event_source_remove(server->delayed_modeset); server->delayed_modeset = NULL; - apply_stored_output_configs(); + bool wait = false; + struct sway_output *output; + wl_list_for_each(output, &root->all_outputs, link) { + if (output == root->fallback_output) { + continue; + } + if (output->wlr_output->frame_pending) { + output->frame.notify = handle_frame_clear; + wait = true; + sway_log(SWAY_DEBUG, "Awaiting render task on %s", output->wlr_output->name); + } else { + output->frame.notify = handle_frame_nop; + } + } + + if (!wait) { + // Nothing to wait for, go ahead + sway_log(SWAY_DEBUG, "No render tasks to wait for, modesetting"); + wl_list_for_each(output, &root->all_outputs, link) { + if (output == root->fallback_output) { + continue; + } + output->frame.notify = handle_frame; + } + apply_stored_output_configs(); + return 0; + } + + return 0; } From 7a50d03d3b158fbb9be909f6ed371a24569fbd00 Mon Sep 17 00:00:00 2001 From: Kenny Levinsen Date: Tue, 15 Oct 2024 16:43:57 +0200 Subject: [PATCH 2/2] WIP silence error that happens a lot after modeset --- sway/desktop/output.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sway/desktop/output.c b/sway/desktop/output.c index c8fa17b641..5996a6bd05 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c @@ -296,7 +296,7 @@ static int output_repaint_timer_handler(void *data) { } if (!wlr_output_commit_state(output->wlr_output, &pending)) { - sway_log(SWAY_ERROR, "Page-flip failed on output %s", output->wlr_output->name); + // sway_log(SWAY_ERROR, "Page-flip failed on output %s", output->wlr_output->name); } wlr_output_state_finish(&pending); return 0;