From f654fe8edeefa17f2e63b9e21fd62aa7bb1ef122 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix=20Poisot?= Date: Thu, 30 Oct 2025 11:42:20 +0000 Subject: [PATCH] sway/config: apply output CT before initial commit Currently, config apply sets the output's image description before the initial commit, but sets the output's color transform after the commit. In the case of a config reload removing a color profile and enabling HDR, both the color transform and image description will be set, which trips an assert in wlroots --- sway/config/output.c | 51 +++++++++++++++++++++++++++++++++----------- 1 file changed, 39 insertions(+), 12 deletions(-) diff --git a/sway/config/output.c b/sway/config/output.c index ed8147b8b..b884a785d 100644 --- a/sway/config/output.c +++ b/sway/config/output.c @@ -562,8 +562,28 @@ static void queue_output_config(struct output_config *oc, set_hdr(wlr_output, pending, hdr); } +struct config_output_state { + struct wlr_color_transform *color_transform; +}; + +static void config_output_state_finish(struct config_output_state *state) { + wlr_color_transform_unref(state->color_transform); +} + +static struct wlr_color_transform *get_color_profile(struct wlr_output *output, + struct output_config *oc) { + if (oc && oc->set_color_transform) { + if (oc->color_transform) { + wlr_color_transform_ref(oc->color_transform); + } + return oc->color_transform; + } else { + return NULL; + } +} + static bool finalize_output_config(struct output_config *oc, struct sway_output *output, - const struct wlr_output_state *applied) { + const struct wlr_output_state *applied, const struct config_output_state *config_applied) { if (output == root->fallback_output) { return false; } @@ -609,16 +629,11 @@ static bool finalize_output_config(struct output_config *oc, struct sway_output output_enable(output); } - if (oc && oc->set_color_transform) { - if (oc->color_transform) { - wlr_color_transform_ref(oc->color_transform); - } - wlr_color_transform_unref(output->color_transform); - output->color_transform = oc->color_transform; - } else { - wlr_color_transform_unref(output->color_transform); - output->color_transform = NULL; + wlr_color_transform_unref(output->color_transform); + if (config_applied->color_transform != NULL) { + wlr_color_transform_ref(config_applied->color_transform); } + output->color_transform = config_applied->color_transform; output->max_render_time = oc && oc->max_render_time > 0 ? oc->max_render_time : 0; output->allow_tearing = oc && oc->allow_tearing > 0; @@ -935,17 +950,25 @@ static bool apply_resolved_output_configs(struct matched_output_config *configs, if (!states) { return false; } + struct config_output_state *config_states = calloc(configs_len, sizeof(*config_states)); + if (!config_states) { + free(states); + return false; + } sway_log(SWAY_DEBUG, "Committing %zd outputs", configs_len); for (size_t idx = 0; idx < configs_len; idx++) { struct matched_output_config *cfg = &configs[idx]; struct wlr_backend_output_state *backend_state = &states[idx]; + struct config_output_state *config_state = &config_states[idx]; backend_state->output = cfg->output->wlr_output; wlr_output_state_init(&backend_state->base); queue_output_config(cfg->config, cfg->output, &backend_state->base); dump_output_state(cfg->output->wlr_output, &backend_state->base); + + config_state->color_transform = get_color_profile(cfg->output->wlr_output, cfg->config); } struct wlr_output_swapchain_manager swapchain_mgr; @@ -975,11 +998,12 @@ static bool apply_resolved_output_configs(struct matched_output_config *configs, for (size_t idx = 0; idx < configs_len; idx++) { struct matched_output_config *cfg = &configs[idx]; struct wlr_backend_output_state *backend_state = &states[idx]; + struct config_output_state *config_state = &config_states[idx]; struct wlr_scene_output_state_options opts = { .swapchain = wlr_output_swapchain_manager_get_swapchain( &swapchain_mgr, backend_state->output), - .color_transform = cfg->output->color_transform, + .color_transform = config_state->color_transform, }; struct wlr_scene_output *scene_output = cfg->output->scene_output; struct wlr_output_state *state = &backend_state->base; @@ -1003,9 +1027,10 @@ static bool apply_resolved_output_configs(struct matched_output_config *configs, for (size_t idx = 0; idx < configs_len; idx++) { struct matched_output_config *cfg = &configs[idx]; struct wlr_backend_output_state *backend_state = &states[idx]; + struct config_output_state *config_state = &config_states[idx]; sway_log(SWAY_DEBUG, "Finalizing config for %s", cfg->output->wlr_output->name); - finalize_output_config(cfg->config, cfg->output, &backend_state->base); + finalize_output_config(cfg->config, cfg->output, &backend_state->base, config_state); } // Output layout being applied in finalize_output_config can shift outputs @@ -1026,8 +1051,10 @@ out: for (size_t idx = 0; idx < configs_len; idx++) { struct wlr_backend_output_state *backend_state = &states[idx]; wlr_output_state_finish(&backend_state->base); + config_output_state_finish(&config_states[idx]); } free(states); + free(config_states); // Reconfigure all devices, since input config may have been applied before // this output came online, and some config items (like map_to_output) are