From 0ed829488136dd7d3487aaf0f9e442bac0d8e34e Mon Sep 17 00:00:00 2001 From: Leandro Ribeiro Date: Tue, 5 Nov 2024 11:56:17 -0300 Subject: [PATCH] color: add weston_color_profile_param_builder_set_primary_luminance() This follows a recent change in the CM&HDR protocol (more specifically, v4 of the experimental version). Now users of the API can set luminance parameters for the primary color volume. Signed-off-by: Leandro Ribeiro --- include/libweston/libweston.h | 4 + libweston/color-lcms/color-profile.c | 6 +- libweston/color-profile-param-builder.c | 112 +++++++++++++++++++++++- libweston/color.h | 6 ++ 4 files changed, 123 insertions(+), 5 deletions(-) diff --git a/include/libweston/libweston.h b/include/libweston/libweston.h index dc4fd231c..b5a015c60 100644 --- a/include/libweston/libweston.h +++ b/include/libweston/libweston.h @@ -393,6 +393,10 @@ bool weston_color_profile_param_builder_set_tf_power_exponent(struct weston_color_profile_param_builder *builder, float power_exponent); +bool +weston_color_profile_param_builder_set_primary_luminance(struct weston_color_profile_param_builder *builder, + float ref_lum, float min_lum, float max_lum); + bool weston_color_profile_param_builder_set_target_primaries(struct weston_color_profile_param_builder *builder, const struct weston_color_gamut *target_primaries); diff --git a/libweston/color-lcms/color-profile.c b/libweston/color-lcms/color-profile.c index 8ad4c141a..a45184fe6 100644 --- a/libweston/color-lcms/color-profile.c +++ b/libweston/color-lcms/color-profile.c @@ -389,10 +389,14 @@ cmlcms_find_color_profile_by_params(const struct weston_color_manager_lcms *cm, sizeof(params->primaries_info) + sizeof(params->tf_info) + sizeof(params->tf_params) + + sizeof(params->min_luminance) + + sizeof(params->max_luminance) + + sizeof(params->reference_white_luminance) + sizeof(params->target_min_luminance) + sizeof(params->target_max_luminance) + sizeof(params->maxCLL) + - sizeof(params->maxFALL), + sizeof(params->maxFALL) + + sizeof(params->padding), "struct weston_color_profile_params must not contain implicit padding"); wl_list_for_each(cprof, &cm->color_profile_list, link) { diff --git a/libweston/color-profile-param-builder.c b/libweston/color-profile-param-builder.c index 49e7c9377..6926bdebe 100644 --- a/libweston/color-profile-param-builder.c +++ b/libweston/color-profile-param-builder.c @@ -36,10 +36,11 @@ enum weston_color_profile_params_set { WESTON_COLOR_PROFILE_PARAMS_PRIMARIES = 0x01, WESTON_COLOR_PROFILE_PARAMS_TF = 0x02, - WESTON_COLOR_PROFILE_PARAMS_TARGET_PRIMARIES = 0x04, - WESTON_COLOR_PROFILE_PARAMS_TARGET_LUMINANCE = 0x08, - WESTON_COLOR_PROFILE_PARAMS_MAXCLL = 0x10, - WESTON_COLOR_PROFILE_PARAMS_MAXFALL = 0x20, + WESTON_COLOR_PROFILE_PARAMS_PRIMARY_LUMINANCE = 0x04, + WESTON_COLOR_PROFILE_PARAMS_TARGET_PRIMARIES = 0x08, + WESTON_COLOR_PROFILE_PARAMS_TARGET_LUMINANCE = 0x10, + WESTON_COLOR_PROFILE_PARAMS_MAXCLL = 0x20, + WESTON_COLOR_PROFILE_PARAMS_MAXFALL = 0x40, }; /** Builder object to create color profiles with parameters. */ @@ -375,6 +376,73 @@ weston_color_profile_param_builder_set_tf_power_exponent(struct weston_color_pro return true; } +/** + * Sets primary luminance for struct weston_color_profile_param_builder object. + * + * If the primary luminance is already set, this should fail. Setting a + * parameter twice is forbidden. + * + * If this fails, users can call weston_color_profile_param_builder_get_error() + * to get the error details. + * + * \param builder The builder object whose parameters will be set. + * \param ref_lum The white point reference luminance. + * \param min_lum The minimum luminance. + * \param max_lum The maximum luminance. + * \return true on success, false otherwise. + */ +bool +weston_color_profile_param_builder_set_primary_luminance(struct weston_color_profile_param_builder *builder, + float ref_lum, float min_lum, float max_lum) +{ + struct weston_color_manager *cm = builder->compositor->color_manager; + bool success = true; + + if (!((cm->supported_color_features >> WESTON_COLOR_FEATURE_SET_LUMINANCES) & 1)) { + store_error(builder, WESTON_COLOR_PROFILE_PARAM_BUILDER_ERROR_UNSUPPORTED, + "set_primary_luminance not supported by the color manager"); + success = false; + } + + if (builder->group_mask & WESTON_COLOR_PROFILE_PARAMS_PRIMARY_LUMINANCE) { + store_error(builder, WESTON_COLOR_PROFILE_PARAM_BUILDER_ERROR_ALREADY_SET, + "primary luminance was already set"); + success = false; + } + + if (max_lum < ref_lum) { + store_error(builder, WESTON_COLOR_PROFILE_PARAM_BUILDER_ERROR_INVALID_LUMINANCE, + "primary reference luminance %f shouldn't be greater than max %f", + ref_lum, max_lum); + success = false; + } + + if (min_lum >= ref_lum) { + store_error(builder, WESTON_COLOR_PROFILE_PARAM_BUILDER_ERROR_INVALID_LUMINANCE, + "primary reference luminance %f shouldn't be lesser than or equal to min %f", + ref_lum, min_lum); + success = false; + } + + if (min_lum >= max_lum) { + store_error(builder, WESTON_COLOR_PROFILE_PARAM_BUILDER_ERROR_INVALID_LUMINANCE, + "primary min luminance %f shouldn't be greater than or equal to max %f", + min_lum, max_lum); + success = false; + } + + if (!success) + return false; + + builder->params.reference_white_luminance = ref_lum; + builder->params.min_luminance = min_lum; + builder->params.max_luminance = max_lum; + + builder->group_mask |= WESTON_COLOR_PROFILE_PARAMS_PRIMARY_LUMINANCE; + + return true; +} + /** * Sets target primaries for struct weston_color_profile_param_builder object * using raw values. @@ -667,6 +735,42 @@ builder_complete_params(struct weston_color_profile_param_builder *builder) if (!(builder->group_mask & WESTON_COLOR_PROFILE_PARAMS_TARGET_PRIMARIES)) builder->params.target_primaries = builder->params.primaries; + if (!(builder->group_mask & WESTON_COLOR_PROFILE_PARAMS_PRIMARY_LUMINANCE)) { + /* If primary luminance is not set, set it to default values. + * These values comes from the CM&HDR protocol. */ + builder->params.reference_white_luminance = 80.0; + builder->params.min_luminance = 0.2; + builder->params.max_luminance = 80.0; + + /* Some TF's override the default. Values comes from the CM&HDR + * protocol as well. */ + if (builder->group_mask & WESTON_COLOR_PROFILE_PARAMS_TF) { + switch(builder->params.tf_info->tf) { + case WESTON_TF_ST2084_PQ: + builder->params.reference_white_luminance = 203.0; + builder->params.min_luminance = 0.0; + builder->params.max_luminance = 10000.0; + break; + case WESTON_TF_HLG: + builder->params.reference_white_luminance = 203.0; + builder->params.min_luminance = 0.005; + builder->params.max_luminance = 1000.0; + break; + default: + break; + } + } + } else { + /* Primary luminance is set, but PQ TF override them anyway + * (except reference white level). Also part of the CM&HDR + * protocol. */ + if ((builder->group_mask & WESTON_COLOR_PROFILE_PARAMS_TF) && + builder->params.tf_info->tf == WESTON_TF_ST2084_PQ) { + builder->params.min_luminance = 0.0; + builder->params.max_luminance = 10000.0; + } + } + /* * If target luminance is not set, set it to negative. Same applies to * maxCLL and maxFALL. diff --git a/libweston/color.h b/libweston/color.h index 965c60707..0fa15b67f 100644 --- a/libweston/color.h +++ b/libweston/color.h @@ -141,12 +141,18 @@ struct weston_color_profile_params { /* Transfer characteristic's parameters; depends on tf_info. */ float tf_params[10]; + /* Primary color volume luminance parameters cd/m²; always set. */ + float min_luminance, max_luminance; + float reference_white_luminance; + /* Target color volume; always set. */ struct weston_color_gamut target_primaries; /* Target luminance parameters cd/m²; negative when not set */ float target_min_luminance, target_max_luminance; float maxCLL, maxFALL; + + char padding[4]; }; /** Type or formula for a curve */