aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/wlr/types/wlr_output.h2
-rw-r--r--types/output/output.c65
2 files changed, 41 insertions, 26 deletions
diff --git a/include/wlr/types/wlr_output.h b/include/wlr/types/wlr_output.h
index 05275156..68f85ebb 100644
--- a/include/wlr/types/wlr_output.h
+++ b/include/wlr/types/wlr_output.h
@@ -428,6 +428,8 @@ bool wlr_output_commit(struct wlr_output *output);
void wlr_output_rollback(struct wlr_output *output);
bool wlr_output_test_state(struct wlr_output *output,
const struct wlr_output_state *state);
+bool wlr_output_commit_state(struct wlr_output *output,
+ const struct wlr_output_state *state);
/**
* Manually schedules a `frame` event. If a `frame` event is already pending,
* it is a no-op.
diff --git a/types/output/output.c b/types/output/output.c
index cdfb48ff..6bcb2b87 100644
--- a/types/output/output.c
+++ b/types/output/output.c
@@ -397,6 +397,12 @@ static void output_state_finish(struct wlr_output_state *state) {
free(state->gamma_lut);
}
+static void output_state_move(struct wlr_output_state *dst,
+ struct wlr_output_state *src) {
+ *dst = *src;
+ output_state_init(src);
+}
+
void wlr_output_init(struct wlr_output *output, struct wlr_backend *backend,
const struct wlr_output_impl *impl, struct wl_display *display) {
assert(impl->commit);
@@ -673,7 +679,7 @@ bool wlr_output_test_state(struct wlr_output *output,
const struct wlr_output_state *state) {
bool had_buffer = state->committed & WLR_OUTPUT_STATE_BUFFER;
- // Duplicate the satte because we might mutate it in output_ensure_buffer
+ // Duplicate the state because we might mutate it in output_ensure_buffer
struct wlr_output_state pending = *state;
if (!output_basic_test(output, &pending)) {
return false;
@@ -696,17 +702,20 @@ bool wlr_output_test(struct wlr_output *output) {
return wlr_output_test_state(output, &output->pending);
}
-bool wlr_output_commit(struct wlr_output *output) {
- if (!output_basic_test(output, &output->pending)) {
+bool wlr_output_commit_state(struct wlr_output *output,
+ const struct wlr_output_state *state) {
+ if (!output_basic_test(output, state)) {
wlr_log(WLR_ERROR, "Basic output test failed for %s", output->name);
return false;
}
- if (!output_ensure_buffer(output, &output->pending)) {
+ // Duplicate the state because we might mutate it in output_ensure_buffer
+ struct wlr_output_state pending = *state;
+ if (!output_ensure_buffer(output, &pending)) {
return false;
}
- if ((output->pending.committed & WLR_OUTPUT_STATE_BUFFER) &&
+ if ((pending.committed & WLR_OUTPUT_STATE_BUFFER) &&
output->idle_frame != NULL) {
wl_event_source_remove(output->idle_frame);
output->idle_frame = NULL;
@@ -718,7 +727,7 @@ bool wlr_output_commit(struct wlr_output *output) {
struct wlr_output_event_precommit pre_event = {
.output = output,
.when = &now,
- .state = &output->pending,
+ .state = &pending,
};
wlr_signal_emit_safe(&output->events.precommit, &pre_event);
@@ -727,19 +736,18 @@ bool wlr_output_commit(struct wlr_output *output) {
// 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) &&
+ if ((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, &output->pending)) {
+ if (!output->impl->commit(output, &pending)) {
wlr_buffer_unlock(back_buffer);
- output_state_clear(&output->pending);
return false;
}
- if (output->pending.committed & WLR_OUTPUT_STATE_BUFFER) {
+ if (pending.committed & WLR_OUTPUT_STATE_BUFFER) {
struct wlr_output_cursor *cursor;
wl_list_for_each(cursor, &output->cursors, link) {
if (!cursor->enabled || !cursor->visible || cursor->surface == NULL) {
@@ -749,27 +757,27 @@ bool wlr_output_commit(struct wlr_output *output) {
}
}
- if (output->pending.committed & WLR_OUTPUT_STATE_RENDER_FORMAT) {
- output->render_format = output->pending.render_format;
+ if (pending.committed & WLR_OUTPUT_STATE_RENDER_FORMAT) {
+ output->render_format = pending.render_format;
}
- if (output->pending.committed & WLR_OUTPUT_STATE_SUBPIXEL) {
- output->subpixel = output->pending.subpixel;
+ if (pending.committed & WLR_OUTPUT_STATE_SUBPIXEL) {
+ output->subpixel = pending.subpixel;
}
output->commit_seq++;
- bool scale_updated = output->pending.committed & WLR_OUTPUT_STATE_SCALE;
+ bool scale_updated = pending.committed & WLR_OUTPUT_STATE_SCALE;
if (scale_updated) {
- output->scale = output->pending.scale;
+ output->scale = pending.scale;
}
- if (output->pending.committed & WLR_OUTPUT_STATE_TRANSFORM) {
- output->transform = output->pending.transform;
+ if (pending.committed & WLR_OUTPUT_STATE_TRANSFORM) {
+ output->transform = pending.transform;
output_update_matrix(output);
}
- bool geometry_updated = output->pending.committed &
+ bool geometry_updated = pending.committed &
(WLR_OUTPUT_STATE_MODE | WLR_OUTPUT_STATE_TRANSFORM |
WLR_OUTPUT_STATE_SUBPIXEL);
if (geometry_updated || scale_updated) {
@@ -786,15 +794,14 @@ bool wlr_output_commit(struct wlr_output *output) {
}
// Destroy the swapchains when an output is disabled
- if ((output->pending.committed & WLR_OUTPUT_STATE_ENABLED) &&
- !output->pending.enabled) {
+ if ((pending.committed & WLR_OUTPUT_STATE_ENABLED) && !pending.enabled) {
wlr_swapchain_destroy(output->swapchain);
output->swapchain = NULL;
wlr_swapchain_destroy(output->cursor_swapchain);
output->cursor_swapchain = NULL;
}
- if (output->pending.committed & WLR_OUTPUT_STATE_BUFFER) {
+ if (pending.committed & WLR_OUTPUT_STATE_BUFFER) {
output->frame_pending = true;
output->needs_frame = false;
}
@@ -803,12 +810,9 @@ bool wlr_output_commit(struct wlr_output *output) {
wlr_swapchain_set_buffer_submitted(output->swapchain, back_buffer);
}
- uint32_t committed = output->pending.committed;
- output_state_clear(&output->pending);
-
struct wlr_output_event_commit event = {
.output = output,
- .committed = committed,
+ .committed = pending.committed,
.when = &now,
.buffer = back_buffer,
};
@@ -821,6 +825,15 @@ bool wlr_output_commit(struct wlr_output *output) {
return true;
}
+bool wlr_output_commit(struct wlr_output *output) {
+ // Make sure the pending state is cleared before the output is committed
+ struct wlr_output_state state = {0};
+ output_state_move(&state, &output->pending);
+ bool ok = wlr_output_commit_state(output, &state);
+ output_state_finish(&state);
+ return ok;
+}
+
void wlr_output_rollback(struct wlr_output *output) {
output_clear_back_buffer(output);
output_state_clear(&output->pending);