From 45b197b8a4e6da4e54c8db77be6ae64e8895f451 Mon Sep 17 00:00:00 2001 From: Consolatis <35009135+Consolatis@users.noreply.github.com> Date: Mon, 17 Jun 2024 16:36:07 +0200 Subject: [PATCH] magnifier: fix flickering on simultaneous gamma changes Gamma changes take another code path and thus did not render the magnifier. This patch consalidates both code paths and therefore also renders the magnifier on gamma changes. Fixes: #1905 --- include/common/scene-helpers.h | 4 +- src/common/scene-helpers.c | 16 ++++++-- src/magnifier.c | 6 +-- src/output.c | 72 ++++++++++++++++++++-------------- 4 files changed, 61 insertions(+), 37 deletions(-) diff --git a/include/common/scene-helpers.h b/include/common/scene-helpers.h index 11697a94..021d3b16 100644 --- a/include/common/scene-helpers.h +++ b/include/common/scene-helpers.h @@ -7,6 +7,7 @@ struct wlr_scene_node; struct wlr_surface; struct wlr_scene_output; +struct wlr_output_state; struct wlr_surface *lab_wlr_surface_from_node(struct wlr_scene_node *node); @@ -18,6 +19,7 @@ struct wlr_surface *lab_wlr_surface_from_node(struct wlr_scene_node *node); struct wlr_scene_node *lab_wlr_scene_get_prev_node(struct wlr_scene_node *node); /* A variant of wlr_scene_output_commit() that respects wlr_output->pending */ -bool lab_wlr_scene_output_commit(struct wlr_scene_output *scene_output); +bool lab_wlr_scene_output_commit(struct wlr_scene_output *scene_output, + struct wlr_output_state *output_state); #endif /* LABWC_SCENE_HELPERS_H */ diff --git a/src/common/scene-helpers.c b/src/common/scene-helpers.c index 755d65d4..3ed59726 100644 --- a/src/common/scene-helpers.c +++ b/src/common/scene-helpers.c @@ -40,11 +40,12 @@ lab_wlr_scene_get_prev_node(struct wlr_scene_node *node) * as it doesn't use the pending state at all. */ bool -lab_wlr_scene_output_commit(struct wlr_scene_output *scene_output) +lab_wlr_scene_output_commit(struct wlr_scene_output *scene_output, + struct wlr_output_state *state) { assert(scene_output); + assert(state); struct wlr_output *wlr_output = scene_output->output; - struct wlr_output_state *state = &wlr_output->pending; struct output *output = wlr_output->data; bool wants_magnification = output_wants_magnification(output); @@ -70,11 +71,18 @@ lab_wlr_scene_output_commit(struct wlr_scene_output *scene_output) magnify(output, state->buffer, &additional_damage); } - if (!wlr_output_commit(wlr_output)) { - wlr_log(WLR_INFO, "Failed to commit output %s", + if (state == &wlr_output->pending) { + if (!wlr_output_commit(wlr_output)) { + wlr_log(WLR_INFO, "Failed to commit output %s", + wlr_output->name); + return false; + } + } else if (!wlr_output_commit_state(wlr_output, state)) { + wlr_log(WLR_INFO, "Failed to commit state for output %s", wlr_output->name); return false; } + /* * FIXME: Remove the following line as soon as * https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/4253 diff --git a/src/magnifier.c b/src/magnifier.c index 327fd3e4..29b16154 100644 --- a/src/magnifier.c +++ b/src/magnifier.c @@ -96,7 +96,7 @@ magnify(struct output *output, struct wlr_buffer *output_buffer, struct wlr_box /* (Re)create the temporary buffer if required */ if (tmp_buffer && (tmp_buffer->width != width || tmp_buffer->height != height)) { - wlr_log(WLR_DEBUG, "tmp buffer size changed, dropping"); + wlr_log(WLR_DEBUG, "tmp magnifier buffer size changed, dropping"); assert(tmp_texture); wlr_texture_destroy(tmp_texture); wlr_buffer_drop(tmp_buffer); @@ -117,7 +117,7 @@ magnify(struct output *output, struct wlr_buffer *output_buffer, struct wlr_box tmp_texture = wlr_texture_from_buffer(server->renderer, tmp_buffer); } if (!tmp_texture) { - wlr_log(WLR_ERROR, "Failed to allocate temporary texture"); + wlr_log(WLR_ERROR, "Failed to allocate temporary magnifier texture"); wlr_buffer_drop(tmp_buffer); tmp_buffer = NULL; return; @@ -209,7 +209,7 @@ magnify(struct output *output, struct wlr_buffer *output_buffer, struct wlr_box }; wlr_render_pass_add_texture(tmp_render_pass, &opts); if (!wlr_render_pass_submit(tmp_render_pass)) { - wlr_log(WLR_ERROR, "Failed to submit render pass"); + wlr_log(WLR_ERROR, "Failed to submit magnifier render pass"); goto cleanup; } diff --git a/src/output.c b/src/output.c index bb2b9760..1bf01429 100644 --- a/src/output.c +++ b/src/output.c @@ -48,6 +48,36 @@ get_tearing_preference(struct output *output) return server->active_view->tearing_hint; } +static void +output_apply_gamma(struct output *output) +{ + assert(output); + assert(output->gamma_lut_changed); + + struct server *server = output->server; + struct wlr_scene_output *scene_output = output->scene_output; + + struct wlr_output_state pending; + wlr_output_state_init(&pending); + + output->gamma_lut_changed = false; + struct wlr_gamma_control_v1 *gamma_control = + wlr_gamma_control_manager_v1_get_control( + server->gamma_control_manager_v1, + output->wlr_output); + + if (!wlr_gamma_control_v1_apply(gamma_control, &pending)) { + wlr_output_state_finish(&pending); + return; + } + + if (!lab_wlr_scene_output_commit(scene_output, &pending)) { + wlr_gamma_control_v1_send_failed_and_destroy(gamma_control); + } + + wlr_output_state_finish(&pending); +} + static void output_frame_notify(struct wl_listener *listener, void *data) { @@ -71,39 +101,23 @@ output_frame_notify(struct wl_listener *listener, void *data) return; } - struct wlr_output *wlr_output = output->wlr_output; - struct server *server = output->server; - if (output->gamma_lut_changed) { - struct wlr_output_state pending; - wlr_output_state_init(&pending); - if (!wlr_scene_output_build_state(output->scene_output, &pending, NULL)) { - return; - } - output->gamma_lut_changed = false; - struct wlr_gamma_control_v1 *gamma_control = - wlr_gamma_control_manager_v1_get_control( - server->gamma_control_manager_v1, wlr_output); - if (!wlr_gamma_control_v1_apply(gamma_control, &pending)) { - wlr_output_state_finish(&pending); - return; - } + /* + * We are not mixing the gamma state with + * other pending output changes to make it + * easier to handle a failed output commit + * due to gamma without impacting other + * unrelated output changes. + */ + output_apply_gamma(output); + } else { + output->wlr_output->pending.tearing_page_flip = + get_tearing_preference(output); - if (!wlr_output_commit_state(output->wlr_output, &pending)) { - wlr_gamma_control_v1_send_failed_and_destroy(gamma_control); - wlr_output_state_finish(&pending); - return; - } - - wlr_damage_ring_rotate(&output->scene_output->damage_ring); - wlr_output_state_finish(&pending); - return; + lab_wlr_scene_output_commit(output->scene_output, + &output->wlr_output->pending); } - output->wlr_output->pending.tearing_page_flip = - get_tearing_preference(output); - lab_wlr_scene_output_commit(output->scene_output); - struct timespec now = { 0 }; clock_gettime(CLOCK_MONOTONIC, &now); wlr_scene_output_send_frame_done(output->scene_output, &now);