From 97b945beee1505b4844aaf8baaaa032b0cd42c5f Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Thu, 4 Jun 2026 16:00:12 +0200 Subject: [PATCH] output: add pre-blending color transform --- include/wlr/types/wlr_output.h | 11 +++++++++++ types/output/output.c | 15 +++++++++++++++ types/output/state.c | 16 ++++++++++++++++ 3 files changed, 42 insertions(+) diff --git a/include/wlr/types/wlr_output.h b/include/wlr/types/wlr_output.h index 103e57555..34310c543 100644 --- a/include/wlr/types/wlr_output.h +++ b/include/wlr/types/wlr_output.h @@ -78,6 +78,7 @@ enum wlr_output_state_field { WLR_OUTPUT_STATE_POST_COLOR_TRANSFORM = 1 << 12, WLR_OUTPUT_STATE_IMAGE_DESCRIPTION = 1 << 13, WLR_OUTPUT_STATE_COLOR_REPRESENTATION = 1 << 14, + WLR_OUTPUT_STATE_PRE_COLOR_TRANSFORM = 1 << 15, }; enum wlr_output_state_mode_type { @@ -162,6 +163,8 @@ struct wlr_output_state { struct wlr_drm_syncobj_timeline *signal_timeline; uint64_t signal_point; + // Pre-blending color transform + struct wlr_color_transform *pre_color_transform; // Post-blending color transform struct wlr_color_transform *post_color_transform; @@ -277,6 +280,7 @@ struct wlr_output { struct { struct wl_listener display_destroy; struct wlr_output_image_description image_description_value; + struct wlr_color_transform *pre_color_transform; struct wlr_color_transform *post_color_transform; struct wlr_color_primaries default_primaries_value; } WLR_PRIVATE; @@ -619,6 +623,13 @@ void wlr_output_state_set_wait_timeline(struct wlr_output_state *state, */ void wlr_output_state_set_signal_timeline(struct wlr_output_state *state, struct wlr_drm_syncobj_timeline *timeline, uint64_t dst_point); +/** + * Set the pre-blending color transform for an output. + * + * The color transform is applied before blending output layers. + */ +void wlr_output_state_set_pre_color_transform(struct wlr_output_state *state, + struct wlr_color_transform *tr); /** * Set the post-blending color transform for an output. * diff --git a/types/output/output.c b/types/output/output.c index 3f13eec2f..a3bd4a9af 100644 --- a/types/output/output.c +++ b/types/output/output.c @@ -252,6 +252,15 @@ static void output_apply_state(struct wlr_output *output, } } + if (state->committed & WLR_OUTPUT_STATE_PRE_COLOR_TRANSFORM) { + wlr_color_transform_unref(output->pre_color_transform); + if (state->pre_color_transform != NULL) { + output->pre_color_transform = wlr_color_transform_ref(state->pre_color_transform); + } else { + output->pre_color_transform = NULL; + } + } + if (state->committed & WLR_OUTPUT_STATE_POST_COLOR_TRANSFORM) { wlr_color_transform_unref(output->post_color_transform); if (state->post_color_transform != NULL) { @@ -426,6 +435,7 @@ void wlr_output_finish(struct wlr_output *output) { wlr_swapchain_destroy(output->cursor_swapchain); wlr_buffer_unlock(output->cursor_front_buffer); + wlr_color_transform_unref(output->pre_color_transform); wlr_color_transform_unref(output->post_color_transform); wlr_swapchain_destroy(output->swapchain); @@ -581,6 +591,10 @@ static uint32_t output_compare_state(struct wlr_output *output, output->subpixel == state->subpixel) { fields |= WLR_OUTPUT_STATE_SUBPIXEL; } + if ((state->committed & WLR_OUTPUT_STATE_PRE_COLOR_TRANSFORM) && + output->pre_color_transform == state->pre_color_transform) { + fields |= WLR_OUTPUT_STATE_PRE_COLOR_TRANSFORM; + } if ((state->committed & WLR_OUTPUT_STATE_POST_COLOR_TRANSFORM) && output->post_color_transform == state->post_color_transform) { fields |= WLR_OUTPUT_STATE_POST_COLOR_TRANSFORM; @@ -685,6 +699,7 @@ static bool output_basic_test(struct wlr_output *output, { WLR_OUTPUT_STATE_ADAPTIVE_SYNC_ENABLED, "adaptive sync" }, { WLR_OUTPUT_STATE_RENDER_FORMAT, "render format" }, { WLR_OUTPUT_STATE_SUBPIXEL, "subpixel" }, + { WLR_OUTPUT_STATE_PRE_COLOR_TRANSFORM, "pre color transform" }, { WLR_OUTPUT_STATE_POST_COLOR_TRANSFORM, "post color transform" }, { WLR_OUTPUT_STATE_IMAGE_DESCRIPTION, "image description" }, }; diff --git a/types/output/state.c b/types/output/state.c index 94764e69a..c1aeb3319 100644 --- a/types/output/state.c +++ b/types/output/state.c @@ -19,6 +19,7 @@ void wlr_output_state_finish(struct wlr_output_state *state) { pixman_region32_fini(&state->damage); wlr_drm_syncobj_timeline_unref(state->wait_timeline); wlr_drm_syncobj_timeline_unref(state->signal_timeline); + wlr_color_transform_unref(state->pre_color_transform); wlr_color_transform_unref(state->post_color_transform); free(state->image_description); } @@ -113,6 +114,17 @@ void wlr_output_state_set_signal_timeline(struct wlr_output_state *state, state->signal_point = dst_point; } +void wlr_output_state_set_pre_color_transform(struct wlr_output_state *state, + struct wlr_color_transform *tr) { + state->committed |= WLR_OUTPUT_STATE_PRE_COLOR_TRANSFORM; + wlr_color_transform_unref(state->pre_color_transform); + if (tr) { + state->pre_color_transform = wlr_color_transform_ref(tr); + } else { + state->pre_color_transform = NULL; + } +} + void wlr_output_state_set_post_color_transform(struct wlr_output_state *state, struct wlr_color_transform *tr) { state->committed |= WLR_OUTPUT_STATE_POST_COLOR_TRANSFORM; @@ -164,6 +176,7 @@ bool wlr_output_state_copy(struct wlr_output_state *dst, pixman_region32_init(©.damage); copy.wait_timeline = NULL; copy.signal_timeline = NULL; + copy.pre_color_transform = NULL; copy.post_color_transform = NULL; copy.image_description = NULL; @@ -186,6 +199,9 @@ bool wlr_output_state_copy(struct wlr_output_state *dst, src->signal_point); } + if (src->committed & WLR_OUTPUT_STATE_PRE_COLOR_TRANSFORM) { + wlr_output_state_set_pre_color_transform(©, src->pre_color_transform); + } if (src->committed & WLR_OUTPUT_STATE_POST_COLOR_TRANSFORM) { wlr_output_state_set_post_color_transform(©, src->post_color_transform); }