aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--types/wlr_output.c22
1 files changed, 16 insertions, 6 deletions
diff --git a/types/wlr_output.c b/types/wlr_output.c
index 325b0233..9089ea5c 100644
--- a/types/wlr_output.c
+++ b/types/wlr_output.c
@@ -736,8 +736,19 @@ bool wlr_output_commit(struct wlr_output *output) {
};
wlr_signal_emit_safe(&output->events.precommit, &pre_event);
- if (!output->impl->commit(output)) {
+ // output_clear_back_buffer detaches the buffer from the renderer. This is
+ // important to do before calling impl->commit(), because this marks an
+ // implicit rendering synchronization point. The backend needs it to avoid
+ // displaying a buffer when asynchronous GPU work isn't finished.
+ struct wlr_buffer *back_buffer = NULL;
+ if ((output->pending.committed & WLR_OUTPUT_STATE_BUFFER) &&
+ output->back_buffer != NULL) {
+ back_buffer = wlr_buffer_lock(output->back_buffer);
output_clear_back_buffer(output);
+ }
+
+ if (!output->impl->commit(output)) {
+ wlr_buffer_unlock(back_buffer);
output_state_clear(&output->pending);
return false;
}
@@ -782,12 +793,11 @@ bool wlr_output_commit(struct wlr_output *output) {
if (output->pending.committed & WLR_OUTPUT_STATE_BUFFER) {
output->frame_pending = true;
output->needs_frame = false;
+ }
- if (output->back_buffer != NULL) {
- wlr_swapchain_set_buffer_submitted(output->swapchain,
- output->back_buffer);
- output_clear_back_buffer(output);
- }
+ if (back_buffer != NULL) {
+ wlr_swapchain_set_buffer_submitted(output->swapchain, back_buffer);
+ wlr_buffer_unlock(back_buffer);
}
uint32_t committed = output->pending.committed;