diff --git a/libweston/color-lcms/color-lcms.h b/libweston/color-lcms/color-lcms.h index b3dd79418..25309d130 100644 --- a/libweston/color-lcms/color-lcms.h +++ b/libweston/color-lcms/color-lcms.h @@ -201,9 +201,24 @@ struct color_transform_steps_mask { uint8_t steps; }; +enum cmlcms_color_transformer_elem { + CMLCMS_TRANSFORMER_CURVE1 = 1 << 0, + CMLCMS_TRANSFORMER_LIN1 = 1 << 1, + CMLCMS_TRANSFORMER_ICC_CHAIN = 1 << 2, + CMLCMS_TRANSFORMER_LIN2 = 1 << 3, + CMLCMS_TRANSFORMER_CURVE2 = 1 << 4, +}; + /** A complete color transformation to be computed on the CPU */ struct cmlcms_color_transformer { + /** Or'd together from enum cmlcms_color_transformer_elem */ + uint8_t element_mask; + + struct weston_color_curve curve1; + struct weston_color_mapping_matrix lin1; cmsHTRANSFORM icc_chain; + struct weston_color_mapping_matrix lin2; + struct weston_color_curve curve2; }; struct cmlcms_color_transform_recipe { diff --git a/libweston/color-lcms/color-transform.c b/libweston/color-lcms/color-transform.c index 45413fc18..9190eada8 100644 --- a/libweston/color-lcms/color-transform.c +++ b/libweston/color-lcms/color-transform.c @@ -1378,8 +1378,11 @@ init_icc_to_icc_chain(struct cmlcms_color_transform *xform) weston_assert_ptr_null(cm->base.compositor, xform->transformer.icc_chain); xform->transformer.icc_chain = xform_realize_icc_chain(xform, chain, chain_len, render_intent, allowed); + if (!xform->transformer.icc_chain) + return false; - return !!xform->transformer.icc_chain; + xform->transformer.element_mask |= CMLCMS_TRANSFORMER_ICC_CHAIN; + return true; } static void diff --git a/libweston/color-lcms/color-transformer.c b/libweston/color-lcms/color-transformer.c index d6bfd4c0f..da4f17b67 100644 --- a/libweston/color-lcms/color-transformer.c +++ b/libweston/color-lcms/color-transformer.c @@ -30,6 +30,8 @@ #include #include "color.h" +#include "color-operations.h" +#include "shared/weston-assert.h" #include "color-lcms.h" /** Release all transformer members. */ @@ -57,5 +59,40 @@ cmlcms_color_transformer_eval(struct weston_compositor *compositor, const struct weston_vec3f *src, size_t len) { - cmsDoTransform(t->icc_chain, src, dst, len); + const struct weston_vec3f *in = src; + struct weston_vec3f *end = dst + len; + struct weston_vec3f *out; + + weston_assert_u8_ne(compositor, t->element_mask, 0); + + if (t->element_mask & CMLCMS_TRANSFORMER_CURVE1) { + weston_color_curve_sample(compositor, &t->curve1, in, dst, len); + in = dst; + } + + if (t->element_mask & CMLCMS_TRANSFORMER_LIN1) { + for (out = dst; out < end; out++, in++) { + *out = weston_v3f_add_v3f(weston_m3f_mul_v3f(t->lin1.matrix, *in), + t->lin1.offset); + } + in = dst; + } + + if (t->element_mask & CMLCMS_TRANSFORMER_ICC_CHAIN) { + cmsDoTransform(t->icc_chain, in, dst, len); + in = dst; + } + + if (t->element_mask & CMLCMS_TRANSFORMER_LIN2) { + for (out = dst; out < end; out++, in++) { + *out = weston_v3f_add_v3f(weston_m3f_mul_v3f(t->lin2.matrix, *in), + t->lin2.offset); + } + in = dst; + } + + if (t->element_mask & CMLCMS_TRANSFORMER_CURVE2) { + weston_color_curve_sample(compositor, &t->curve2, in, dst, len); + in = dst; + } }