diff --git a/include/libweston/libweston.h b/include/libweston/libweston.h index 6f053877bbc1d74cb7153fe8d58ae8463d35fbf4..d68f535a14665cb7198d1faea570eb338ffb92cc 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; @@ -2082,6 +2083,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 16e998126902885126a504f9271b6c69e4b45fca..18340a39316adf287c6414fa95c3d401ece4b3fb 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 557797dcec08b244f7a53a47602f15f2a7f79570..30a0762b2be5415978a4c458e34080110aa078df 100644 --- a/libweston/color-noop.c +++ b/libweston/color-noop.c @@ -73,7 +73,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; @@ -87,7 +87,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; @@ -100,7 +100,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; @@ -113,7 +113,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 90f332c5de990ca43c3e61ba690dc960811e94af..405e0965cdaf157e04cd6c39cf201e055ec8f2c4 100644 --- a/libweston/color.c +++ b/libweston/color.c @@ -181,6 +181,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 11bb820c8b21c34128b25694efc9b932d9cbf480..5e0f9165b75e3488c89eb3a8688518f8fb59522d 100644 --- a/libweston/compositor.c +++ b/libweston/compositor.c @@ -6310,6 +6310,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; } @@ -6497,6 +6500,62 @@ 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. + * + * The color profile must have WESTON_COLOR_PROFILE_KIND_OUTPUT bit, + * or it must be NULL. + * + * 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; + + if (cprof && (cprof->usage & WESTON_COLOR_PROFILE_KIND_OUTPUT) == 0) { + weston_log("Error setting color profile '%s' for output '%s': not an output profile\n", + weston_color_profile_get_description(cprof), + output->name); + return false; + } + + 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. * @@ -6852,6 +6911,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);