From 6e773592f647fdc0f937e10da73ba9067097806d Mon Sep 17 00:00:00 2001 From: Consolatis <35009135+Consolatis@users.noreply.github.com> Date: Mon, 22 Jan 2024 15:21:18 +0100 Subject: [PATCH] src/output.c: properly test new output configurations Fixes #1458 --- src/output.c | 64 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 63 insertions(+), 1 deletion(-) diff --git a/src/output.c b/src/output.c index ed039545..650a338e 100644 --- a/src/output.c +++ b/src/output.c @@ -7,9 +7,11 @@ */ #define _POSIX_C_SOURCE 200809L +#include #include #include #include +#include #include #include #include @@ -483,8 +485,68 @@ output_config_apply(struct server *server, static bool verify_output_config_v1(const struct wlr_output_configuration_v1 *config) { - /* TODO implement */ + const char *err_msg = NULL; + struct wlr_output_configuration_head_v1 *head; + wl_list_for_each(head, &config->heads, link) { + if (!head->state.enabled) { + continue; + } + + /* Handle custom modes */ + if (!head->state.mode) { + int32_t refresh = head->state.custom_mode.refresh; + + if (wlr_output_is_drm(head->state.output) && refresh == 0) { + /* + * wlroots has a bug which causes a divide by zero + * when setting the refresh rate to 0 on a DRM output. + * It is already fixed but not part of an official 0.17.x + * release. Even it would be we still need to carry the + * fix here to prevent older 0.17.x releases from crashing. + * + * https://gitlab.freedesktop.org/wlroots/wlroots/-/issues/3791 + */ + err_msg = "DRM backend does not support a refresh rate of 0"; + goto custom_mode_failed; + } + + if (wlr_output_is_wl(head->state.output) && refresh != 0) { + /* Wayland backend does not support refresh rates */ + err_msg = "Wayland backend refresh rate unsupported"; + goto custom_mode_failed; + } + } + + /* + * Ensure the new output state can be applied on + * its own and inform the client when it can not. + * + * Applying the changes may still fail later when + * getting mixed with wlr_output->pending which + * may contain further unrelated changes. + */ + struct wlr_output_state output_state; + wlr_output_state_init(&output_state); + wlr_output_head_v1_state_apply(&head->state, &output_state); + + if (!wlr_output_test_state(head->state.output, &output_state)) { + wlr_output_state_finish(&output_state); + return false; + } + wlr_output_state_finish(&output_state); + } + return true; + +custom_mode_failed: + assert(err_msg); + wlr_log(WLR_INFO, "%s (%s: %dx%d@%d)", + err_msg, + head->state.output->name, + head->state.custom_mode.width, + head->state.custom_mode.height, + head->state.custom_mode.refresh); + return false; } static void