aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/wlr/types/wlr_output.h14
-rw-r--r--types/output/state.c36
2 files changed, 49 insertions, 1 deletions
diff --git a/include/wlr/types/wlr_output.h b/include/wlr/types/wlr_output.h
index 5ed29208..ad034982 100644
--- a/include/wlr/types/wlr_output.h
+++ b/include/wlr/types/wlr_output.h
@@ -690,12 +690,24 @@ void wlr_output_state_set_damage(struct wlr_output_state *state,
* advantage of backend features that may reduce the amount of things that
* need to be composited.
*
- * The array must be kept valid by the caller until wlr_output_state_finish().
+ * The array must be kept valid by the caller until wlr_output_state_finish()
+ * and all copies of the state have been finished as well.
* This state will be applied once wlr_output_commit_state() is called.
*/
void wlr_output_state_set_layers(struct wlr_output_state *state,
struct wlr_output_layer_state *layers, size_t layers_len);
+/**
+ * Copies the output state from src to dst. It is safe to then
+ * wlr_output_state_finish() src and have dst still be valid.
+ *
+ * Note: The lifetime of the output layers inside the state are not managed. It
+ * is the responsibility of the constructor of the output layers to make sure
+ * they remain valid for the output state and all copies made.
+ */
+bool wlr_output_state_copy(struct wlr_output_state *dst,
+ const struct wlr_output_state *src);
+
/**
* Re-configure the swapchain as required for the output's primary buffer.
diff --git a/types/output/state.c b/types/output/state.c
index 4633966c..7775fbb7 100644
--- a/types/output/state.c
+++ b/types/output/state.c
@@ -129,3 +129,39 @@ void wlr_output_state_set_layers(struct wlr_output_state *state,
state->layers = layers;
state->layers_len = layers_len;
}
+
+bool wlr_output_state_copy(struct wlr_output_state *dst,
+ const struct wlr_output_state *src) {
+ struct wlr_output_state copy = *src;
+ copy.committed &= ~(WLR_OUTPUT_STATE_BUFFER |
+ WLR_OUTPUT_STATE_DAMAGE |
+ WLR_OUTPUT_STATE_GAMMA_LUT);
+
+ if (src->committed & WLR_OUTPUT_STATE_BUFFER) {
+ wlr_output_state_set_buffer(&copy, src->buffer);
+ }
+
+ if (src->committed & WLR_OUTPUT_STATE_DAMAGE) {
+ wlr_output_state_set_damage(&copy, &src->damage);
+ }
+
+ if (src->committed & WLR_OUTPUT_STATE_GAMMA_LUT) {
+ size_t gamma_buffer_size = 3 * src->gamma_lut_size * sizeof(uint16_t);
+ copy.gamma_lut = malloc(gamma_buffer_size);
+ if (!copy.gamma_lut) {
+ wlr_log_errno(WLR_ERROR, "Allocation failed");
+ goto err;
+ }
+
+ copy.committed |= WLR_OUTPUT_STATE_GAMMA_LUT;
+ memcpy(copy.gamma_lut, src->gamma_lut, gamma_buffer_size);
+ copy.gamma_lut_size = src->gamma_lut_size;
+ }
+
+ wlr_output_state_finish(dst);
+ *dst = copy;
+ return true;
+err:
+ wlr_output_state_finish(&copy);
+ return false;
+}