From 9ab2852c15837ab3450210c59fce052e4b56b3eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pedro=20C=C3=B4rte-Real?= Date: Tue, 18 May 2021 23:15:02 +0100 Subject: [PATCH] Avoid no-op output reconfiguring When an output command doesn't actually change anything in the output config the processing will still all be done and cause other changes. Notably if you run a command like: output * dpms on even if it does nothing it will still cause all the inputs to be reconfigured and very noticeable amounts of input latency to occur. To fix this save the current output config in the output data and on configure, if the config is the same just return without doing anything else. Fixes #6280 --- include/sway/config.h | 4 +++ include/sway/output.h | 2 ++ sway/config/output.c | 68 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 74 insertions(+) diff --git a/include/sway/config.h b/include/sway/config.h index 5ad240d34..7dd47500a 100644 --- a/include/sway/config.h +++ b/include/sway/config.h @@ -636,6 +636,10 @@ struct output_config *new_output_config(const char *name); void merge_output_config(struct output_config *dst, struct output_config *src); +struct output_config *duplicate_output_config(const struct output_config *src); + +bool compare_output_config(const struct output_config *dst, const struct output_config *src); + bool apply_output_config(struct output_config *oc, struct sway_output *output); bool test_output_config(struct output_config *oc, struct sway_output *output); diff --git a/include/sway/output.h b/include/sway/output.h index f27f6344a..b2d93a71f 100644 --- a/include/sway/output.h +++ b/include/sway/output.h @@ -57,6 +57,8 @@ struct sway_output { uint32_t refresh_nsec; int max_render_time; // In milliseconds struct wl_event_source *repaint_timer; + + struct output_config *current_config; }; struct sway_output *output_create(struct wlr_output *wlr_output); diff --git a/sway/config/output.c b/sway/config/output.c index b59cabd4e..10f46844f 100644 --- a/sway/config/output.c +++ b/sway/config/output.c @@ -14,6 +14,7 @@ #include "sway/tree/root.h" #include "log.h" #include "util.h" +#include "stringop.h" int output_name_cmp(const void *item, const void *data) { const struct output_config *output = item; @@ -125,6 +126,63 @@ void merge_output_config(struct output_config *dst, struct output_config *src) { } } +struct output_config *duplicate_output_config(const struct output_config *src) { + struct output_config *oc = calloc(1, sizeof(struct output_config)); + if (oc == NULL) { + return NULL; + } + oc->name = strdup(src->name); + if (oc->name == NULL) { + free(oc); + return NULL; + } + oc->enabled = src->enabled; + oc->width = src->width; + oc->height = src->height; + oc->refresh_rate = src->refresh_rate; + oc->custom_mode = src->custom_mode; + oc->x = src->x; + oc->y = src->y; + oc->scale = src->scale; + oc->scale_filter = src->scale_filter; + oc->transform = src->transform; + oc->subpixel = src->subpixel; + oc->max_render_time = src->max_render_time; + oc->adaptive_sync = src->adaptive_sync; + if (src->background) { + oc->background = strdup(src->background); + } + if (src->background_option) { + oc->background_option = strdup(src->background_option); + } + if (src->background_fallback) { + oc->background_fallback = strdup(src->background_fallback); + } + oc->dpms_state = src->dpms_state; + return oc; +} + +bool compare_output_config(const struct output_config *dst, const struct output_config *src) { + return dst && src && + dst->enabled == src->enabled && + dst->width == src->width && + dst->height == src->height && + dst->x == src->x && + dst->y == src->y && + dst->scale == src->scale && + dst->scale_filter == src->scale_filter && + dst->subpixel == src->subpixel && + dst->refresh_rate == src->refresh_rate && + dst->custom_mode == src->custom_mode && + dst->transform == src->transform && + dst->max_render_time == src->max_render_time && + dst->adaptive_sync == src->adaptive_sync && + !lenient_strcmp(dst->background, src->background) && + !lenient_strcmp(dst->background_option, src->background_option) && + !lenient_strcmp(dst->background_fallback, src->background_fallback) && + dst->dpms_state == src->dpms_state; +} + static void merge_wildcard_on_all(struct output_config *wildcard) { for (int i = 0; i < config->output_configs->length; i++) { struct output_config *oc = config->output_configs->items[i]; @@ -397,6 +455,16 @@ bool apply_output_config(struct output_config *oc, struct sway_output *output) { struct wlr_output *wlr_output = output->wlr_output; + if (oc && output->current_config && compare_output_config(oc, output->current_config)) { + // The output config is unchanged so bail out early + sway_log(SWAY_DEBUG, "Config for output %s is unchanged", wlr_output->name); + return true; + } + if (output->current_config) { + free_output_config(output->current_config); + } + output->current_config = duplicate_output_config(oc); + // Flag to prevent the output mode event handler from calling us output->enabling = (!oc || oc->enabled);