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);