diff --git a/include/render/color.h b/include/render/color.h index 128b345e1..111adb271 100644 --- a/include/render/color.h +++ b/include/render/color.h @@ -9,6 +9,7 @@ enum wlr_color_transform_type { COLOR_TRANSFORM_INVERSE_EOTF, COLOR_TRANSFORM_LCMS2, COLOR_TRANSFORM_LUT_3X1D, + COLOR_TRANSFORM_MATRIX, COLOR_TRANSFORM_PIPELINE, }; @@ -40,6 +41,12 @@ struct wlr_color_transform_lut_3x1d { size_t dim; }; +struct wlr_color_transform_matrix { + struct wlr_color_transform base; + + float matrix[9]; +}; + struct wlr_color_transform_pipeline { struct wlr_color_transform base; diff --git a/include/wlr/render/color.h b/include/wlr/render/color.h index 44bbedfb8..9d9363b0f 100644 --- a/include/wlr/render/color.h +++ b/include/wlr/render/color.h @@ -141,6 +141,12 @@ struct wlr_color_transform *wlr_color_transform_init_linear_to_inverse_eotf( struct wlr_color_transform *wlr_color_transform_init_lut_3x1d(size_t dim, const uint16_t *r, const uint16_t *g, const uint16_t *b); +/** + * Initialize a color transformation to apply a 3×3 matrix. Returns NULL on + * failure. + */ +struct wlr_color_transform *wlr_color_transform_init_matrix(const float matrix[static 9]); + /** * Initialize a color transformation to apply a sequence of color transforms * one after another. diff --git a/render/color.c b/render/color.c index 662c5b480..4286bc86d 100644 --- a/render/color.c +++ b/render/color.c @@ -62,6 +62,16 @@ struct wlr_color_transform *wlr_color_transform_init_lut_3x1d(size_t dim, return &tx->base; } +struct wlr_color_transform *wlr_color_transform_init_matrix(const float matrix[static 9]) { + struct wlr_color_transform_matrix *tx = calloc(1, sizeof(*tx)); + if (!tx) { + return NULL; + } + wlr_color_transform_init(&tx->base, COLOR_TRANSFORM_MATRIX); + memcpy(tx->matrix, matrix, sizeof(tx->matrix)); + return &tx->base; +} + struct wlr_color_transform *wlr_color_transform_init_pipeline( struct wlr_color_transform **transforms, size_t len) { assert(len > 0); @@ -92,6 +102,7 @@ struct wlr_color_transform *wlr_color_transform_init_pipeline( static void color_transform_destroy(struct wlr_color_transform *tr) { switch (tr->type) { case COLOR_TRANSFORM_INVERSE_EOTF: + case COLOR_TRANSFORM_MATRIX: break; case COLOR_TRANSFORM_LCMS2: color_transform_lcms2_finish(color_transform_lcms2_from_base(tr)); @@ -226,6 +237,8 @@ static void color_transform_lut_3x1d_eval(struct wlr_color_transform_lut_3x1d *t } } +static void multiply_matrix_vector(float out[static 3], float m[static 9], const float v[static 3]); + void wlr_color_transform_eval(struct wlr_color_transform *tr, float out[static 3], const float in[static 3]) { switch (tr->type) { @@ -238,6 +251,10 @@ void wlr_color_transform_eval(struct wlr_color_transform *tr, case COLOR_TRANSFORM_LUT_3X1D: color_transform_lut_3x1d_eval(color_transform_lut_3x1d_from_base(tr), out, in); break; + case COLOR_TRANSFORM_MATRIX:; + struct wlr_color_transform_matrix *matrix = wl_container_of(tr, matrix, base); + multiply_matrix_vector(out, matrix->matrix, in); + break; case COLOR_TRANSFORM_PIPELINE:; struct wlr_color_transform_pipeline *pipeline = wl_container_of(tr, pipeline, base); @@ -264,7 +281,7 @@ void wlr_color_primaries_from_named(struct wlr_color_primaries *out, abort(); } -static void multiply_matrix_vector(float out[static 3], float m[static 9], float v[static 3]) { +static void multiply_matrix_vector(float out[static 3], float m[static 9], const float v[static 3]) { float result[3] = { m[0] * v[0] + m[1] * v[1] + m[2] * v[2], m[3] * v[0] + m[4] * v[1] + m[5] * v[2],