diff --git a/include/libweston/libweston.h b/include/libweston/libweston.h index c6877e95..58da3022 100644 --- a/include/libweston/libweston.h +++ b/include/libweston/libweston.h @@ -374,6 +374,7 @@ struct weston_output { bool enabled; /**< is in the output_list, not pending list */ int scale; + struct weston_color_profile *color_profile; struct weston_color_transform *from_sRGB_to_output; struct weston_color_transform *from_sRGB_to_blend; struct weston_color_transform *from_blend_to_output; @@ -2083,6 +2084,10 @@ void weston_output_set_transform(struct weston_output *output, uint32_t transform); +bool +weston_output_set_color_profile(struct weston_output *output, + struct weston_color_profile *cprof); + void weston_output_init(struct weston_output *output, struct weston_compositor *compositor, diff --git a/libweston/color-lcms/color-lcms.c b/libweston/color-lcms/color-lcms.c index 16e99812..18340a39 100644 --- a/libweston/color-lcms/color-lcms.c +++ b/libweston/color-lcms/color-lcms.c @@ -57,6 +57,10 @@ cmlcms_get_surface_color_transform(struct weston_color_manager *cm_base, }; struct cmlcms_color_transform *xform; + /* TODO: use output color profile */ + if (output->color_profile) + return false; + xform = cmlcms_color_transform_get(cm, ¶m); if (!xform) return false; @@ -82,6 +86,10 @@ cmlcms_get_output_color_transform(struct weston_color_manager *cm_base, }; struct cmlcms_color_transform *xform; + /* TODO: use output color profile */ + if (output->color_profile) + return false; + xform = cmlcms_color_transform_get(cm, ¶m); if (!xform) return false; @@ -96,6 +104,11 @@ cmlcms_get_sRGB_to_output_color_transform(struct weston_color_manager *cm_base, struct weston_color_transform **xform_out) { /* Assumes output color space is sRGB SDR */ + + /* TODO: use output color profile */ + if (output->color_profile) + return false; + /* Identity transform */ *xform_out = NULL; @@ -114,6 +127,10 @@ cmlcms_get_sRGB_to_blend_color_transform(struct weston_color_manager *cm_base, }; struct cmlcms_color_transform *xform; + /* TODO: use output color profile */ + if (output->color_profile) + return false; + xform = cmlcms_color_transform_get(cm, ¶m); if (!xform) return false; diff --git a/libweston/color-noop.c b/libweston/color-noop.c index 35d0fad9..4b0a0c38 100644 --- a/libweston/color-noop.c +++ b/libweston/color-noop.c @@ -72,7 +72,7 @@ cmnoop_get_surface_color_transform(struct weston_color_manager *cm_base, struct weston_surface_color_transform *surf_xform) { /* TODO: Assert surface has no colorspace set */ - /* TODO: Assert output has no colorspace set */ + assert(output->color_profile == NULL); /* Identity transform */ surf_xform->transform = NULL; @@ -86,7 +86,7 @@ cmnoop_get_output_color_transform(struct weston_color_manager *cm_base, struct weston_output *output, struct weston_color_transform **xform_out) { - /* TODO: Assert output has no colorspace set */ + assert(output->color_profile == NULL); /* Identity transform */ *xform_out = NULL; @@ -99,7 +99,7 @@ cmnoop_get_sRGB_to_output_color_transform(struct weston_color_manager *cm_base, struct weston_output *output, struct weston_color_transform **xform_out) { - /* TODO: Assert output has no colorspace set */ + assert(output->color_profile == NULL); /* Identity transform */ *xform_out = NULL; @@ -112,7 +112,7 @@ cmnoop_get_sRGB_to_blend_color_transform(struct weston_color_manager *cm_base, struct weston_output *output, struct weston_color_transform **xform_out) { - /* TODO: Assert output has no colorspace set */ + assert(output->color_profile == NULL); /* Identity transform */ *xform_out = NULL; diff --git a/libweston/color.c b/libweston/color.c index 3dd37c66..eb1d45eb 100644 --- a/libweston/color.c +++ b/libweston/color.c @@ -179,6 +179,8 @@ void weston_surface_color_transform_fini(struct weston_surface_color_transform *surf_xform) { weston_color_transform_unref(surf_xform->transform); + surf_xform->transform = NULL; + surf_xform->identity_pipeline = false; } /** diff --git a/libweston/compositor.c b/libweston/compositor.c index d747e31d..42984f98 100644 --- a/libweston/compositor.c +++ b/libweston/compositor.c @@ -6303,6 +6303,9 @@ weston_output_set_color_transforms(struct weston_output *output) output->from_sRGB_to_output = sRGB_to_output; output->from_sRGB_to_blend = sRGB_to_blend; + weston_log("Output '%s' using color profile: %s\n", output->name, + weston_color_profile_get_description(output->color_profile)); + return true; } @@ -6490,6 +6493,52 @@ weston_output_set_transform(struct weston_output *output, } } +/** Set output's color profile + * + * \param output The output to change. + * \param cprof The color profile to set. Can be NULL for default sRGB profile. + * \return True on success, or false on failure. + * + * Calling this function changes the color profile of the output. This causes + * all existing weston_color_transform objects related to this output via + * paint nodes to be unreferenced and later re-created on demand. + * + * This function may not be called from within weston_output_repaint(). + * + * On failure, nothing is changed. + * + * \ingroup output + */ +WL_EXPORT bool +weston_output_set_color_profile(struct weston_output *output, + struct weston_color_profile *cprof) +{ + struct weston_color_profile *old; + struct weston_paint_node *pnode; + + old = output->color_profile; + output->color_profile = weston_color_profile_ref(cprof); + + if (output->enabled) { + if (!weston_output_set_color_transforms(output)) { + /* Failed, roll back */ + weston_color_profile_unref(output->color_profile); + output->color_profile = old; + return false; + } + + /* Remove outdated cached color transformations */ + wl_list_for_each(pnode, &output->paint_node_list, output_link) { + weston_surface_color_transform_fini(&pnode->surf_xform); + pnode->surf_xform_valid = false; + } + } + + weston_color_profile_unref(old); + + return true; +} + /** Initializes a weston_output object with enough data so ** an output can be configured. * @@ -6848,6 +6897,8 @@ weston_output_release(struct weston_output *output) if (output->enabled) weston_compositor_remove_output(output); + weston_color_profile_unref(output->color_profile); + pixman_region32_fini(&output->region); wl_list_remove(&output->link);