diff --git a/frontend/main.c b/frontend/main.c index adeededc6..30ac2b29c 100644 --- a/frontend/main.c +++ b/frontend/main.c @@ -2110,13 +2110,7 @@ wet_output_set_color_profile(struct weston_output *output, } else if (parent_winsys_profile) { cprof = weston_color_profile_ref(parent_winsys_profile); } else { - /* - * TODO: Once parametric color profiles are fully supported - * and interoperable with ICC profiles, the default profile - * would be created like this: - * cprof = wet_create_output_color_profile(output, wc, "auto:"); - */ - return 0; + cprof = wet_create_output_color_profile(output, wc, "auto:"); } if (!cprof) @@ -2254,156 +2248,6 @@ wet_output_set_colorimetry_mode(struct weston_output *output, return 0; } -struct wet_color_characteristics_keys { - const char *name; - enum weston_color_characteristics_groups group; - float minval; - float maxval; -}; - -#define COLOR_CHARAC_NAME "color_characteristics" - -static int -parse_color_characteristics(struct weston_color_characteristics *cc_out, - struct weston_config_section *section) -{ - static const struct wet_color_characteristics_keys keys[] = { - { "red_x", WESTON_COLOR_CHARACTERISTICS_GROUP_PRIMARIES, 0.0f, 1.0f }, - { "red_y", WESTON_COLOR_CHARACTERISTICS_GROUP_PRIMARIES, 0.0f, 1.0f }, - { "green_x", WESTON_COLOR_CHARACTERISTICS_GROUP_PRIMARIES, 0.0f, 1.0f }, - { "green_y", WESTON_COLOR_CHARACTERISTICS_GROUP_PRIMARIES, 0.0f, 1.0f }, - { "blue_x", WESTON_COLOR_CHARACTERISTICS_GROUP_PRIMARIES, 0.0f, 1.0f }, - { "blue_y", WESTON_COLOR_CHARACTERISTICS_GROUP_PRIMARIES, 0.0f, 1.0f }, - { "white_x", WESTON_COLOR_CHARACTERISTICS_GROUP_WHITE, 0.0f, 1.0f }, - { "white_y", WESTON_COLOR_CHARACTERISTICS_GROUP_WHITE, 0.0f, 1.0f }, - { "max_L", WESTON_COLOR_CHARACTERISTICS_GROUP_MAXL, 0.0f, 1e5f }, - { "min_L", WESTON_COLOR_CHARACTERISTICS_GROUP_MINL, 0.0f, 1e5f }, - { "maxFALL", WESTON_COLOR_CHARACTERISTICS_GROUP_MAXFALL, 0.0f, 1e5f }, - }; - static const char *msgpfx = "Config error in weston.ini [" COLOR_CHARAC_NAME "]"; - struct weston_color_characteristics cc = {}; - float *const keyvalp[ARRAY_LENGTH(keys)] = { - /* These must be in the same order as keys[]. */ - &cc.primary[0].x, &cc.primary[0].y, - &cc.primary[1].x, &cc.primary[1].y, - &cc.primary[2].x, &cc.primary[2].y, - &cc.white.x, &cc.white.y, - &cc.max_luminance, - &cc.min_luminance, - &cc.maxFALL, - }; - bool found[ARRAY_LENGTH(keys)] = {}; - uint32_t missing_group_mask = 0; - unsigned i; - char *section_name; - int ret = 0; - - weston_config_section_get_string(section, "name", - §ion_name, ""); - if (strchr(section_name, ':') != NULL) { - ret = -1; - weston_log("%s name=%s is a reserved name. Do not use ':' character in the name.\n", - msgpfx, section_name); - } - - /* Parse keys if they exist */ - for (i = 0; i < ARRAY_LENGTH(keys); i++) { - double value; - - if (weston_config_section_get_double(section, keys[i].name, - &value, NAN) == 0) { - float f = value; - - found[i] = true; - - /* Range check, NaN shall not pass. */ - if (f >= keys[i].minval && f <= keys[i].maxval) { - /* Key found, parsed, and good value. */ - *keyvalp[i] = f; - continue; - } - - ret = -1; - weston_log("%s name=%s: %s value %f is outside of the range %f - %f.\n", - msgpfx, section_name, keys[i].name, value, - keys[i].minval, keys[i].maxval); - continue; - } - - if (errno == EINVAL) { - found[i] = true; - ret = -1; - weston_log("%s name=%s: failed to parse the value of key %s.\n", - msgpfx, section_name, keys[i].name); - } - } - - /* Collect set and unset groups */ - for (i = 0; i < ARRAY_LENGTH(keys); i++) { - uint32_t group = keys[i].group; - - if (found[i]) - cc.group_mask |= group; - else - missing_group_mask |= group; - } - - /* Ensure groups are given fully or not at all. */ - for (i = 0; i < ARRAY_LENGTH(keys); i++) { - uint32_t group = keys[i].group; - - if ((cc.group_mask & group) && (missing_group_mask & group)) { - ret = -1; - weston_log("%s name=%s: group %d key %s is %s. " - "You must set either none or all keys of a group.\n", - msgpfx, section_name, ffs(group), keys[i].name, - found[i] ? "set" : "missing"); - } - } - - free(section_name); - - if (ret == 0) - *cc_out = cc; - - return ret; -} - -WESTON_EXPORT_FOR_TESTS int -wet_output_set_color_characteristics(struct weston_output *output, - struct weston_config *wc, - struct weston_config_section *section) -{ - char *cc_name = NULL; - struct weston_config_section *cc_section; - struct weston_color_characteristics cc; - - weston_config_section_get_string(section, COLOR_CHARAC_NAME, - &cc_name, NULL); - if (!cc_name) - return 0; - - cc_section = weston_config_get_section(wc, COLOR_CHARAC_NAME, - "name", cc_name); - if (!cc_section) { - weston_log("Config error in weston.ini, output %s: " - "no [" COLOR_CHARAC_NAME "] section with 'name=%s' found.\n", - output->name, cc_name); - goto out_error; - } - - if (parse_color_characteristics(&cc, cc_section) < 0) - goto out_error; - - weston_output_set_color_characteristics(output, &cc); - free(cc_name); - return 0; - -out_error: - free(cc_name); - return -1; -} - static int wet_output_set_color_format(struct weston_output *output, struct weston_config_section *section) @@ -3207,10 +3051,6 @@ drm_backend_output_configure(struct weston_output *output, if (wet_output_set_color_format(output, section) < 0) return -1; - if (wet_output_set_color_characteristics(output, - wet->config, section) < 0) - return -1; - if (wet_output_set_vrr_mode(output, section) < 0) return -1; @@ -4289,9 +4129,6 @@ headless_backend_output_configure(struct weston_output *output) if (wet_output_set_colorimetry_mode(output, section, wet->use_color_manager) < 0) return -1; - if (wet_output_set_color_characteristics(output, wc, section) < 0) - return -1; - return wet_configure_windowed_output_from_config(output, &defaults, WESTON_WINDOWED_OUTPUT_HEADLESS); } diff --git a/frontend/weston-private.h b/frontend/weston-private.h index f82d66b79..f91daa26d 100644 --- a/frontend/weston-private.h +++ b/frontend/weston-private.h @@ -36,11 +36,6 @@ bool get_renderer_from_string(const char *name, enum weston_renderer_type *renderer); -int -wet_output_set_color_characteristics(struct weston_output *output, - struct weston_config *wc, - struct weston_config_section *section); - int wet_output_set_eotf_mode(struct weston_output *output, struct weston_config_section *section, diff --git a/include/libweston/colorimetry.h b/include/libweston/colorimetry.h index 5bc5ccc32..357d733dd 100644 --- a/include/libweston/colorimetry.h +++ b/include/libweston/colorimetry.h @@ -293,57 +293,6 @@ weston_color_profile_param_builder_create_color_profile(struct weston_color_prof enum weston_color_profile_param_builder_error *err, char **err_msg); -enum weston_color_characteristics_groups { - /** weston_color_characteristics::primary is set */ - WESTON_COLOR_CHARACTERISTICS_GROUP_PRIMARIES = 0x01, - - /** weston_color_characteristics::white is set */ - WESTON_COLOR_CHARACTERISTICS_GROUP_WHITE = 0x02, - - /** weston_color_characteristics::max_luminance is set */ - WESTON_COLOR_CHARACTERISTICS_GROUP_MAXL = 0x04, - - /** weston_color_characteristics::min_luminance is set */ - WESTON_COLOR_CHARACTERISTICS_GROUP_MINL = 0x08, - - /** weston_color_characteristics::maxFALL is set */ - WESTON_COLOR_CHARACTERISTICS_GROUP_MAXFALL = 0x10, - - /** all valid bits */ - WESTON_COLOR_CHARACTERISTICS_GROUP_ALL_MASK = 0x1f -}; - -/** Basic display color characteristics - * - * This is a simple description of a display or output (monitor) color - * characteristics. The parameters can be found in EDID, with caveats. They - * are particularly useful with HDR monitors. - */ -struct weston_color_characteristics { - /** Which fields are valid - * - * A bitmask of values from enum weston_color_characteristics_groups. - */ - uint32_t group_mask; - - /* EOTF is tracked externally with enum weston_eotf_mode */ - - /** Chromaticities of the primaries */ - struct weston_CIExy primary[3]; - - /** White point chromaticity */ - struct weston_CIExy white; - - /** Display's desired maximum content peak luminance, cd/m² */ - float max_luminance; - - /** Display's desired minimum content luminance, cd/m² */ - float min_luminance; - - /** Display's desired maximum frame-average light level, cd/m² */ - float maxFALL; -}; - struct weston_color_profile * weston_color_profile_ref(struct weston_color_profile *cprof); diff --git a/include/libweston/libweston.h b/include/libweston/libweston.h index ef3bcf0a6..dc21bdeb7 100644 --- a/include/libweston/libweston.h +++ b/include/libweston/libweston.h @@ -520,7 +520,6 @@ struct weston_output { bool from_blend_to_output_by_backend; enum weston_eotf_mode eotf_mode; enum weston_colorimetry_mode colorimetry_mode; - struct weston_color_characteristics color_characteristics; struct weston_output_color_outcome *color_outcome; uint64_t color_outcome_serial; @@ -2715,13 +2714,6 @@ weston_output_set_colorimetry_mode(struct weston_output *output, enum weston_colorimetry_mode weston_output_get_colorimetry_mode(const struct weston_output *output); -void -weston_output_set_color_characteristics(struct weston_output *output, - const struct weston_color_characteristics *cc); - -const struct weston_color_characteristics * -weston_output_get_color_characteristics(struct weston_output *output); - void weston_output_init(struct weston_output *output, struct weston_compositor *compositor, diff --git a/libweston/color-lcms/color-curve-segments.c b/libweston/color-lcms/color-curve-segments.c index 14f61dcd3..95e30f6ed 100644 --- a/libweston/color-lcms/color-curve-segments.c +++ b/libweston/color-lcms/color-curve-segments.c @@ -531,7 +531,7 @@ join_powerlaw_curvesets(cmsContext context_id, ret = cmsStageAllocToneCurves(context_id, ARRAY_LENGTH(arr), arr); abort_oom_if_null(ret); cmsFreeToneCurveTriple(arr); - return ret; + return ret; } void @@ -573,6 +573,56 @@ curveset_print(cmsStage *stage, struct weston_log_scope *scope) } } +static const cmsCurveSegment * +get_defining_curve_segment(cmsToneCurve *from, bool *clamped_input) +{ + const cmsCurveSegment *seg0, *seg1, *seg2; + + /* We handle curves with 1 or 3 segments. No more, no less. */ + seg0 = cmsGetToneCurveSegment(0, from); + seg1 = cmsGetToneCurveSegment(1, from); + seg2 = cmsGetToneCurveSegment(2, from); + if (seg0 && !seg1) { + /* Case 1: we have a single segment (seg0). */ + + /* If the domain is (-inf, inf), the curve is unbounded. */ + if (are_segment_breaks_equal(seg0->x0, -INFINITY) && + are_segment_breaks_equal(seg0->x1, INFINITY)) { + *clamped_input = false; + return seg0; + } + + /* If the domain is [0.0, 1.0], the curve is bounded. */ + if (are_segment_breaks_equal(seg0->x0, 0.0) && + are_segment_breaks_equal(seg0->x1, 1.0)) { + *clamped_input = true; + return seg0; + } + + /* We don't handle anything else. */ + return NULL; + } else if (seg0 && seg1 && seg2) { + /* Case 2: we have three segments. Clamped input. + * + * Ensure that the domain breaks are (-inf, 0.0], + * (0.0, 1.0] and (1.0, inf]. + */ + if (!are_segment_breaks_equal(seg0->x0, -INFINITY) || + !are_segment_breaks_equal(seg0->x1, 0.0) || + !are_segment_breaks_equal(seg1->x0, 0.0) || + !are_segment_breaks_equal(seg1->x1, 1.0) || + !are_segment_breaks_equal(seg2->x0, 1.0) || + !are_segment_breaks_equal(seg2->x1, INFINITY)) + return NULL; + *clamped_input = true; + return seg1; + } else { + /* Neither 1 or 3 segments. So we don't define the + * curveset as parametric. */ + return NULL; + } +} + bool get_parametric_curveset_params(struct weston_compositor *compositor, _cmsStageToneCurvesData *trc_data, @@ -580,7 +630,7 @@ get_parametric_curveset_params(struct weston_compositor *compositor, float curveset_params[3][MAX_PARAMS_LCMS_PARAM_CURVE], bool *clamped_input) { - const cmsCurveSegment *seg, *seg0, *seg1, *seg2; + const cmsCurveSegment *seg; cmsInt32Number curve_types[3]; unsigned int i, j; @@ -596,44 +646,18 @@ get_parametric_curveset_params(struct weston_compositor *compositor, *clamped_input = false; for (i = 0; i < 3; i++) { - /* We handle curves with 1 or 3 segments. No more, no less. */ - seg0 = cmsGetToneCurveSegment(0, trc_data->TheCurves[i]); - seg1 = cmsGetToneCurveSegment(1, trc_data->TheCurves[i]); - seg2 = cmsGetToneCurveSegment(2, trc_data->TheCurves[i]); + bool clamp_this; - if (seg0 && !seg1) { - /* Case 1: we have a single segment (seg0). - * - * Ensure that the domain is (-inf, inf) and that the - * seg type is not 0 (the type of sampled segments). - */ - if (!are_segment_breaks_equal(seg0->x0, -INFINITY) || - !are_segment_breaks_equal(seg0->x1, INFINITY) || - seg0->Type == 0) - return false; - seg = seg0; - } else if (seg0 && seg1 && seg2) { - /* Case 2: we have three segments. Clamped input. - * - * Ensure that the domain breaks are (-inf, 0.0], - * (0.0, 1.0] and (1.0, inf] and that the 2nd segment - * type is not 0 (the type of sampled segments). - */ - if (!are_segment_breaks_equal(seg0->x0, -INFINITY) || - !are_segment_breaks_equal(seg0->x1, 0.0) || - !are_segment_breaks_equal(seg1->x0, 0.0) || - !are_segment_breaks_equal(seg1->x1, 1.0) || - !are_segment_breaks_equal(seg2->x0, 1.0) || - !are_segment_breaks_equal(seg2->x1, INFINITY) || - seg1->Type == 0) - return false; - seg = seg1; - *clamped_input = true; - } else { - /* Neither 1 or 3 segments. So we don't define the - * curveset as parametric. */ + seg = get_defining_curve_segment(trc_data->TheCurves[i], &clamp_this); + if (!seg) return false; - } + + /* Reject tabulated (LUT) segments. */ + if (seg->Type == 0) + return false; + + if (clamp_this) + *clamped_input = true; /* Copy the type and params from the segment that matters. We * don't use memcpy because we need to cast each cmsFloat64Number @@ -652,3 +676,58 @@ get_parametric_curveset_params(struct weston_compositor *compositor, return true; } + +/** Create a matrix stage equivalent to the CurveSet stage. + * + * A tabulated curve segment with 2 samples is equivalent to a matrix + * (scaling and offset), ignoring possible input clamping and allowing + * extrapolation. + * + * \param context_id The matrix stage is created in this context. + * \param stage An arbitrary stage, can be NULL. + * \return A new matrix stage equivalent to the given (CurveSet) stage, or + * NULL otherwise. + */ +cmsStage * +lcms_matrix_stage_from_curve(cmsContext context_id, cmsStage *stage) +{ + const _cmsStageToneCurvesData *data; + cmsFloat64Number Matrix[3 * 3] = {}; /* row-major */ + cmsFloat64Number Offset[3]; + unsigned i; + + if (!stage || cmsStageType(stage) != cmsSigCurveSetElemType) + return NULL; + + data = cmsStageData(stage); + if (data->nCurves != 3) + return NULL; + + for (i = 0; i < 3; i++) { + const cmsCurveSegment *seg; + bool clamped_input; + double y0, y1, k; + + seg = get_defining_curve_segment(data->TheCurves[i], &clamped_input); + if (!seg) + return NULL; + + /* Type 0 is tabulated. */ + if (seg->Type != 0) + return NULL; + + if (seg->nGridPoints != 2) + return NULL; + + y0 = seg->SampledPoints[0]; + y1 = seg->SampledPoints[1]; + + /* y = k * x + Offset */ + + k = (y1 - y0) / (seg->x1 - seg->x0); + Offset[i] = y0 - k * seg->x0; + Matrix[3 * i + i] = k; + } + + return cmsStageAllocMatrix(context_id, 3, 3, Matrix, Offset); +} diff --git a/libweston/color-lcms/color-curve-segments.h b/libweston/color-lcms/color-curve-segments.h index adb20dab4..b761a3264 100644 --- a/libweston/color-lcms/color-curve-segments.h +++ b/libweston/color-lcms/color-curve-segments.h @@ -39,6 +39,9 @@ get_parametric_curveset_params(struct weston_compositor *compositor, float curveset_params[3][MAX_PARAMS_LCMS_PARAM_CURVE], bool *clamped_input); +cmsStage * +lcms_matrix_stage_from_curve(cmsContext context_id, cmsStage *stage); + void curveset_print(cmsStage *stage, struct weston_log_scope *scope); @@ -64,6 +67,12 @@ get_parametric_curveset_params(struct weston_compositor *compositor, return false; } +cmsStage * +lcms_matrix_stage_from_curve(cmsContext ContextID, cmsStage *stage) +{ + return NULL; +} + static inline void curveset_print(cmsStage *stage, struct weston_log_scope *scope) { diff --git a/libweston/color-lcms/color-lcms.c b/libweston/color-lcms/color-lcms.c index 8317febfd..605699a31 100644 --- a/libweston/color-lcms/color-lcms.c +++ b/libweston/color-lcms/color-lcms.c @@ -195,7 +195,7 @@ cmlcms_get_sRGB_to_blend_color_transform(struct weston_color_manager_lcms *cm, static float meta_clamp(float value, const char *valname, float min, float max, - struct weston_output *output) + const struct cmlcms_color_profile *cprof) { float ret = value; @@ -207,78 +207,71 @@ meta_clamp(float value, const char *valname, float min, float max, ret = max; if (ret != value) { - weston_log("output '%s' clamping %s value from %f to %f.\n", - output->name, valname, value, ret); + weston_log("Output profile p%u '%s': clamping %s value from %f to %f.\n", + cprof->base.id, cprof->base.description, valname, value, ret); } return ret; } -static bool -cmlcms_get_hdr_meta(struct weston_output *output, - struct weston_hdr_metadata_type1 *hdr_meta) +static void +cmlcms_get_hdr_meta(struct weston_hdr_metadata_type1 *hdr_meta, + const struct cmlcms_color_profile *cprof) { - const struct weston_color_characteristics *cc; - - /* TODO: get color characteristics from color profiles instead. */ + const struct weston_color_profile_params *cpp = NULL; + unsigned i; hdr_meta->group_mask = 0; - /* Only SMPTE ST 2084 mode uses HDR Static Metadata Type 1 */ - if (weston_output_get_eotf_mode(output) != WESTON_EOTF_MODE_ST2084) - return true; + switch (cprof->type) { + case CMLCMS_PROFILE_TYPE_ICC: + /* No HDR metadata */ + return; - cc = weston_output_get_color_characteristics(output); - - /* Target content chromaticity */ - if (cc->group_mask & WESTON_COLOR_CHARACTERISTICS_GROUP_PRIMARIES) { - unsigned i; - - for (i = 0; i < 3; i++) { - hdr_meta->primary[i].x = meta_clamp(cc->primary[i].x, - "primary", 0.0, 1.0, - output); - hdr_meta->primary[i].y = meta_clamp(cc->primary[i].y, - "primary", 0.0, 1.0, - output); - } - hdr_meta->group_mask |= WESTON_HDR_METADATA_TYPE1_GROUP_PRIMARIES; + case CMLCMS_PROFILE_TYPE_PARAMS: + cpp = cprof->params; + break; } + weston_assert_ptr_not_null(cprof->base.cm->compositor, cpp); - /* Target content white point */ - if (cc->group_mask & WESTON_COLOR_CHARACTERISTICS_GROUP_WHITE) { - hdr_meta->white.x = meta_clamp(cc->white.x, "white", - 0.0, 1.0, output); - hdr_meta->white.y = meta_clamp(cc->white.y, "white", - 0.0, 1.0, output); - hdr_meta->group_mask |= WESTON_HDR_METADATA_TYPE1_GROUP_WHITE; + + for (i = 0; i < 3; i++) { + hdr_meta->primary[i].x = meta_clamp(cpp->target_primaries.primary[i].x, + "primary", 0.0, 1.0, cprof); + hdr_meta->primary[i].y = meta_clamp(cpp->target_primaries.primary[i].y, + "primary", 0.0, 1.0, cprof); } + hdr_meta->group_mask |= WESTON_HDR_METADATA_TYPE1_GROUP_PRIMARIES; - /* Target content peak and max mastering luminance */ - if (cc->group_mask & WESTON_COLOR_CHARACTERISTICS_GROUP_MAXL) { - hdr_meta->maxDML = meta_clamp(cc->max_luminance, "maxDML", - 1.0, 65535.0, output); - hdr_meta->maxCLL = meta_clamp(cc->max_luminance, "maxCLL", - 1.0, 65535.0, output); + hdr_meta->white.x = meta_clamp(cpp->target_primaries.white_point.x, + "white", 0.0, 1.0, cprof); + hdr_meta->white.y = meta_clamp(cpp->target_primaries.white_point.y, + "white", 0.0, 1.0, cprof); + hdr_meta->group_mask |= WESTON_HDR_METADATA_TYPE1_GROUP_WHITE; + + if (cpp->target_max_luminance > 0.0f) { + hdr_meta->maxDML = meta_clamp(cpp->target_max_luminance, + "maxDML", 1.0, 65535.0, cprof); hdr_meta->group_mask |= WESTON_HDR_METADATA_TYPE1_GROUP_MAXDML; - hdr_meta->group_mask |= WESTON_HDR_METADATA_TYPE1_GROUP_MAXCLL; } - /* Target content min mastering luminance */ - if (cc->group_mask & WESTON_COLOR_CHARACTERISTICS_GROUP_MINL) { - hdr_meta->minDML = meta_clamp(cc->min_luminance, "minDML", - 0.0001, 6.5535, output); + if (cpp->target_min_luminance > 0.0f) { + hdr_meta->minDML = meta_clamp(cpp->target_min_luminance, + "minDML", 0.0001, 6.5535, cprof); hdr_meta->group_mask |= WESTON_HDR_METADATA_TYPE1_GROUP_MINDML; } - /* Target content max frame-average luminance */ - if (cc->group_mask & WESTON_COLOR_CHARACTERISTICS_GROUP_MAXFALL) { - hdr_meta->maxFALL = meta_clamp(cc->maxFALL, "maxFALL", - 1.0, 65535.0, output); + if (cpp->maxFALL > 0.0f) { + hdr_meta->maxFALL = meta_clamp(cpp->maxFALL, + "maxFALL", 1.0, 65535.0, cprof); hdr_meta->group_mask |= WESTON_HDR_METADATA_TYPE1_GROUP_MAXFALL; } - return true; + if (cpp->maxCLL > 0.0f) { + hdr_meta->maxCLL = meta_clamp(cpp->maxCLL, + "maxCLL", 1.0, 65535.0, cprof); + hdr_meta->group_mask |= WESTON_HDR_METADATA_TYPE1_GROUP_MAXCLL; + } } static struct weston_output_color_outcome * @@ -288,14 +281,13 @@ cmlcms_create_output_color_outcome(struct weston_color_manager *cm_base, struct weston_color_manager_lcms *cm = to_cmlcms(cm_base); struct weston_output_color_outcome *co; + weston_assert_ptr_not_null(cm->base.compositor, output->color_profile); + co = zalloc(sizeof *co); if (!co) return NULL; - if (!cmlcms_get_hdr_meta(output, &co->hdr_meta)) - goto out_fail; - - assert(output->color_profile); + cmlcms_get_hdr_meta(&co->hdr_meta, to_cmlcms_cprof(output->color_profile)); /* TODO: take container color space into account */ @@ -429,19 +421,13 @@ cmlcms_init(struct weston_color_manager *cm_base) cmsSetLogErrorHandlerTHR(cm->lcms_ctx, lcms_error_logger); - if (!cmlcms_create_stock_profile(cm)) { - weston_log("color-lcms: error: cmlcms_create_stock_profile failed\n"); - goto out_err; - } + cm->sRGB_profile = cmlcms_create_stock_profile(cm); + weston_log("LittleCMS %d initialized.\n", cmsGetEncodedCMMversion()); return true; out_err: - if (cm->lcms_ctx) - cmsDeleteContext(cm->lcms_ctx); - cm->lcms_ctx = NULL; - weston_log_scope_destroy(cm->transforms_scope); cm->transforms_scope = NULL; weston_log_scope_destroy(cm->optimizer_scope); @@ -520,7 +506,6 @@ weston_color_manager_create(struct weston_compositor *compositor) cm->base.get_surface_color_transform = cmlcms_get_surface_color_transform; cm->base.create_output_color_outcome = cmlcms_create_output_color_outcome; - /* We support all color features. */ cm->base.supported_color_features = (1 << WESTON_COLOR_FEATURE_ICC) | (1 << WESTON_COLOR_FEATURE_PARAMETRIC) | (1 << WESTON_COLOR_FEATURE_SET_PRIMARIES) | @@ -529,14 +514,12 @@ weston_color_manager_create(struct weston_compositor *compositor) (1 << WESTON_COLOR_FEATURE_SET_MASTERING_DISPLAY_PRIMARIES) | (1 << WESTON_COLOR_FEATURE_EXTENDED_TARGET_VOLUME); - /* We support all rendering intents. */ cm->base.supported_rendering_intents = (1 << WESTON_RENDER_INTENT_PERCEPTUAL) | - (1 << WESTON_RENDER_INTENT_SATURATION) | + /* (1 << WESTON_RENDER_INTENT_SATURATION) | */ (1 << WESTON_RENDER_INTENT_ABSOLUTE) | (1 << WESTON_RENDER_INTENT_RELATIVE) | (1 << WESTON_RENDER_INTENT_RELATIVE_BPC); - /* We support all primaries named. */ cm->base.supported_primaries_named = (1 << WESTON_PRIMARIES_CICP_SRGB) | (1 << WESTON_PRIMARIES_CICP_PAL_M) | (1 << WESTON_PRIMARIES_CICP_PAL) | @@ -548,18 +531,10 @@ weston_color_manager_create(struct weston_compositor *compositor) (1 << WESTON_PRIMARIES_CICP_DISPLAY_P3) | (1 << WESTON_PRIMARIES_ADOBE_RGB); - /** - * TODO: this is a lie just to make the color-management-parametric - * tests to work. Without this the tests would be much more limited. We - * actually need to implement such TF's. There's no problem doing that, - * as parametric color profiles themselves are still unsupported. - */ - - /* We need to implement each tf, and we support only a few of them. */ cm->base.supported_tf_named = (1 << WESTON_TF_GAMMA22) | (1 << WESTON_TF_GAMMA28) | - (1 << WESTON_TF_SRGB) | - (1 << WESTON_TF_ST2084_PQ); + (1 << WESTON_TF_ST2084_PQ) | + (1 << WESTON_TF_EXT_LINEAR); wl_list_init(&cm->color_transform_list); wl_list_init(&cm->color_profile_list); diff --git a/libweston/color-lcms/color-lcms.h b/libweston/color-lcms/color-lcms.h index 0c64c5f10..56fb4ad07 100644 --- a/libweston/color-lcms/color-lcms.h +++ b/libweston/color-lcms/color-lcms.h @@ -292,7 +292,7 @@ ref_cprof(struct cmlcms_color_profile *cprof); void unref_cprof(struct cmlcms_color_profile *cprof); -bool +struct cmlcms_color_profile * cmlcms_create_stock_profile(struct weston_color_manager_lcms *cm); void diff --git a/libweston/color-lcms/color-profile.c b/libweston/color-lcms/color-profile.c index c5751ba85..295b20bfa 100644 --- a/libweston/color-lcms/color-profile.c +++ b/libweston/color-lcms/color-profile.c @@ -558,57 +558,36 @@ make_icc_file_description(struct lcmsProfilePtr profile, * BT.709 primaries with gamma-2.2 transfer characteristic. This is the * expected sRGB display response. */ -bool +struct cmlcms_color_profile * cmlcms_create_stock_profile(struct weston_color_manager_lcms *cm) { - static const cmsCIExyY D65 = { 0.3127, 0.3290, 1.0 }; - static const cmsCIExyYTRIPLE bt709 = { - { 0.6400, 0.3300, 1.0 }, - { 0.3000, 0.6000, 1.0 }, - { 0.1500, 0.0600, 1.0 } - }; - cmsToneCurve *gamma22[3]; - struct lcmsProfilePtr profile = { NULL }; - struct cmlcms_md5_sum md5sum; + struct weston_compositor *compositor = cm->base.compositor; + struct weston_color_profile_params p = {}; + struct cmlcms_color_profile *stock; char *desc = NULL; - const char *err_msg = NULL; - gamma22[0] = gamma22[1] = gamma22[2] = cmsBuildGamma(cm->lcms_ctx, 2.2); - if (gamma22[0]) - profile.p = cmsCreateRGBProfileTHR(cm->lcms_ctx, &D65, &bt709, gamma22); - cmsFreeToneCurve(gamma22[0]); - if (!profile.p) { - weston_log("color-lcms: error: failed to create stock sRGB profile.\n"); - return false; - } - if (!cmsMD5computeID(profile.p)) { - weston_log("Failed to compute MD5 for stock sRGB profile.\n"); - goto err_close; - } + p.primaries_info = weston_color_primaries_info_from(compositor, + WESTON_PRIMARIES_CICP_SRGB); + p.primaries = p.primaries_info->color_gamut; + p.tf.info = weston_color_tf_info_from(compositor, WESTON_TF_GAMMA22); + p.reference_white_luminance = 80.0; + p.min_luminance = 0.2; + p.max_luminance = 80.0; + p.target_primaries = p.primaries; + p.target_min_luminance = p.min_luminance; + p.target_max_luminance = p.max_luminance; + p.maxCLL = -1.0f; + p.maxFALL = -1.0f; - cmsGetHeaderProfileID(profile.p, md5sum.bytes); - desc = make_icc_file_description(profile, &md5sum, "sRGB stock"); - if (!desc) - goto err_close; + str_printf(&desc, "default sRGB: %s primaries, %s transfer function", + p.primaries_info->desc, p.tf.info->desc); + abort_oom_if_null(desc); - cm->sRGB_profile = cmlcms_color_profile_alloc(cm, CMLCMS_PROFILE_TYPE_ICC, desc); - cm->sRGB_profile->icc.profile = profile; - cm->sRGB_profile->icc.md5sum = md5sum; + stock = cmlcms_color_profile_alloc(cm, CMLCMS_PROFILE_TYPE_PARAMS, desc); + *stock->params = p; + cmlcms_color_profile_register(stock); - if (!ensure_output_profile_extract(cm->sRGB_profile, cm->lcms_ctx, - cmlcms_reasonable_1D_points(), &err_msg)) - goto err_close; - - cmlcms_color_profile_register(cm->sRGB_profile); - - return true; - -err_close: - if (err_msg) - weston_log("%s\n", err_msg); - - cmlcms_color_profile_destroy(cm->sRGB_profile); - return false; + return stock; } struct weston_color_profile * @@ -719,84 +698,47 @@ cmlcms_get_color_profile_from_params(struct weston_color_manager *cm_base, return true; } +static bool +cmlcms_send_icc_info(struct cm_image_desc_info *cm_image_desc_info, + const struct cmlcms_color_profile *cprof) +{ + int32_t fd; + uint32_t len; + + /* ICC-based color profile, so just send the ICC file fd. If we + * get an error (negative fd), the helper will send the proper + * error to the client. */ + fd = os_ro_anonymous_file_get_fd(cprof->icc.prof_rofile, + RO_ANONYMOUS_FILE_MAPMODE_PRIVATE); + if (fd < 0) { + weston_cm_send_icc_file(cm_image_desc_info, -1, 0); + return false; + } + + len = os_ro_anonymous_file_size(cprof->icc.prof_rofile); + weston_assert_u32_gt(cprof->base.cm->compositor, len, 0); + + weston_cm_send_icc_file(cm_image_desc_info, fd, len); + + os_ro_anonymous_file_put_fd(fd); + return true; +} + bool cmlcms_send_image_desc_info(struct cm_image_desc_info *cm_image_desc_info, struct weston_color_profile *cprof_base) { - struct weston_color_manager_lcms *cm = to_cmlcms(cprof_base->cm); - struct weston_compositor *compositor = cm->base.compositor; struct cmlcms_color_profile *cprof = to_cmlcms_cprof(cprof_base); - const struct weston_color_primaries_info *primaries_info; - const struct weston_color_tf_info *tf_info; - int32_t fd; - uint32_t len; - /** - * TODO: when we convert the stock sRGB profile to a parametric profile - * instead of an ICC one, we'll be able to change the if/else below to - * a switch/case. - */ - - if (cprof->type == CMLCMS_PROFILE_TYPE_ICC && cprof != cm->sRGB_profile) { - /* ICC-based color profile, so just send the ICC file fd. If we - * get an error (negative fd), the helper will send the proper - * error to the client. */ - fd = os_ro_anonymous_file_get_fd(cprof->icc.prof_rofile, - RO_ANONYMOUS_FILE_MAPMODE_PRIVATE); - if (fd < 0) { - weston_cm_send_icc_file(cm_image_desc_info, -1, 0); - return false; - } - - len = os_ro_anonymous_file_size(cprof->icc.prof_rofile); - weston_assert_u32_gt(compositor, len, 0); - - weston_cm_send_icc_file(cm_image_desc_info, fd, len); - - os_ro_anonymous_file_put_fd(fd); - } else { - /* TODO: we still don't support parametric color profiles that - * are not the stock one. This should change when we start - * advertising parametric image description support in our - * color-management protocol implementation. */ - if (cprof != cm->sRGB_profile) - weston_assert_not_reached(compositor, "we don't support parametric " \ - "cprof's that are not the stock sRGB one"); - - /* Stock sRGB color profile. TODO: when we add support for - * parametric color profiles, the stock sRGB will be crafted - * using parameters, instead of cmsCreate_sRGBProfileTHR() - * (which we currently use). So we'll get the parameters - * directly from it, instead of hardcoding as we are doing here. - * We don't get the parameters from the stock sRGB color profile - * because it is not trivial to retrieve that from LittleCMS. */ - - /* Send the H.273 ColourPrimaries code point that matches the - * Rec709 primaries and the D65 white point. */ - primaries_info = weston_color_primaries_info_from(compositor, - WESTON_PRIMARIES_CICP_SRGB); - weston_cm_send_primaries_named(cm_image_desc_info, primaries_info); - - /* These are the Rec709 primaries and D65 white point. */ - weston_cm_send_primaries(cm_image_desc_info, - &primaries_info->color_gamut); - - /* Target primaries, equal to the primary primaries. */ - weston_cm_send_target_primaries(cm_image_desc_info, - &primaries_info->color_gamut); - - /* sRGB transfer function. */ - tf_info = weston_color_tf_info_from(compositor, WESTON_TF_GAMMA22); - weston_cm_send_tf_named(cm_image_desc_info, tf_info); - - /* Primary luminance, default values from the protocol. */ - weston_cm_send_luminances(cm_image_desc_info, 0.2, 80.0, 80.0); - - /* Target luminance, min/max equals primary luminance min/max. */ - weston_cm_send_target_luminances(cm_image_desc_info, 0.2, 80.0); + switch (cprof->type) { + case CMLCMS_PROFILE_TYPE_ICC: + return cmlcms_send_icc_info(cm_image_desc_info, cprof); + case CMLCMS_PROFILE_TYPE_PARAMS: + weston_cm_send_parametric_info(cm_image_desc_info, cprof->params); + return true; } - return true; + return false; } struct weston_color_profile * diff --git a/libweston/color-lcms/color-transform.c b/libweston/color-lcms/color-transform.c index 6f4ba3b8c..d3c20c048 100644 --- a/libweston/color-lcms/color-transform.c +++ b/libweston/color-lcms/color-transform.c @@ -387,6 +387,30 @@ merge_curvesets(cmsPipeline **lut, cmsContext context_id) return modified; } +static void +linear_curvesets_to_matrices(cmsPipeline **lut, cmsContext context_id) +{ + cmsPipeline *pipe; + cmsStage *elem; + cmsStage *matrix; + + pipe = cmsPipelineAlloc(context_id, 3, 3); + abort_oom_if_null(pipe); + + elem = cmsPipelineGetPtrToFirstStage(*lut); + for (; elem; elem = cmsStageNext(elem)) { + matrix = lcms_matrix_stage_from_curve(context_id, elem); + if (matrix) { + cmsPipelineInsertStage(pipe, cmsAT_END, matrix); + } else { + cmsPipelineInsertStage(pipe, cmsAT_END, cmsStageDup(elem)); + } + } + + cmsPipelineFree(*lut); + *lut = pipe; +} + static const struct weston_color_tf_info * lcms_curve_matches_any_tf(struct weston_compositor *compositor, uint32_t lcms_curve_type, bool clamped_input, @@ -1013,6 +1037,8 @@ lcms_optimize_pipeline(cmsPipeline **lut, cmsContext context_id) { bool cont_opt; + linear_curvesets_to_matrices(lut, context_id); + /** * This optimization loop will delete identity stages. Deleting * identity matrix stages is harmless, but deleting identity diff --git a/libweston/color-management.c b/libweston/color-management.c index 10cf7a305..fbf59caee 100644 --- a/libweston/color-management.c +++ b/libweston/color-management.c @@ -209,15 +209,34 @@ weston_cm_send_target_primaries(struct cm_image_desc_info *cm_image_desc_info, * This is a helper function that should be used by the color plugin * that owns the color profile and has information about it. * - * \param cm_image_desc_info The image description info object - * \param tf_info The tf_info object + * \param cm_image_desc_info The image description info object. + * \param tf The color transfer function to send. */ WL_EXPORT void -weston_cm_send_tf_named(struct cm_image_desc_info *cm_image_desc_info, - const struct weston_color_tf_info *tf_info) +weston_cm_send_tf(struct cm_image_desc_info *cm_image_desc_info, + const struct weston_color_tf *tf) { - wp_image_description_info_v1_send_tf_named(cm_image_desc_info->owner, - tf_info->protocol_tf); + switch (tf->info->tf) { + case WESTON_TF_BT1886: + case WESTON_TF_GAMMA22: + case WESTON_TF_GAMMA28: + case WESTON_TF_SRGB: + case WESTON_TF_EXT_SRGB: + case WESTON_TF_ST240: + case WESTON_TF_ST428: + case WESTON_TF_ST2084_PQ: + case WESTON_TF_EXT_LINEAR: + case WESTON_TF_LOG_100: + case WESTON_TF_LOG_316: + case WESTON_TF_XVYCC: + case WESTON_TF_HLG: + wp_image_description_info_v1_send_tf_named(cm_image_desc_info->owner, + tf->info->protocol_tf); + break; + case WESTON_TF_POWER: + wp_image_description_info_v1_send_tf_power(cm_image_desc_info->owner, + tf->params[0]); + } } /** @@ -261,6 +280,37 @@ weston_cm_send_target_luminances(struct cm_image_desc_info *cm_image_desc_info, max_lum); } +/** + * Send complete parametric image description information to the client. + */ +WL_EXPORT void +weston_cm_send_parametric_info(struct cm_image_desc_info *cm_image_desc_info, + const struct weston_color_profile_params *par) +{ + if (par->primaries_info) + weston_cm_send_primaries_named(cm_image_desc_info, par->primaries_info); + weston_cm_send_primaries(cm_image_desc_info, &par->primaries); + weston_cm_send_target_primaries(cm_image_desc_info, &par->target_primaries); + + weston_cm_send_tf(cm_image_desc_info, &par->tf); + + weston_cm_send_luminances(cm_image_desc_info, par->min_luminance, + par->max_luminance, par->reference_white_luminance); + weston_cm_send_target_luminances(cm_image_desc_info, + par->target_min_luminance, + par->target_max_luminance); + + if (par->maxCLL > 0.0f) { + wp_image_description_info_v1_send_target_max_cll(cm_image_desc_info->owner, + par->maxCLL); + } + + if (par->maxFALL > 0.0f) { + wp_image_description_info_v1_send_target_max_fall(cm_image_desc_info->owner, + par->maxFALL); + } +} + /** * Destroy an image description info object. */ diff --git a/libweston/color-management.h b/libweston/color-management.h index 5ae38198e..d83ed39c4 100644 --- a/libweston/color-management.h +++ b/libweston/color-management.h @@ -56,8 +56,8 @@ weston_cm_send_target_primaries(struct cm_image_desc_info *cm_image_desc_info, const struct weston_color_gamut *color_gamut); void -weston_cm_send_tf_named(struct cm_image_desc_info *cm_image_desc_info, - const struct weston_color_tf_info *tf_info); +weston_cm_send_tf(struct cm_image_desc_info *cm_image_desc_info, + const struct weston_color_tf *tf); void weston_cm_send_luminances(struct cm_image_desc_info *cm_image_desc_info, @@ -67,4 +67,8 @@ void weston_cm_send_target_luminances(struct cm_image_desc_info *cm_image_desc_info, float min_lum, float max_lum); +void +weston_cm_send_parametric_info(struct cm_image_desc_info *cm_image_desc_info, + const struct weston_color_profile_params *par); + #endif /* WESTON_COLOR_MANAGEMENT_H */ diff --git a/libweston/color.h b/libweston/color.h index 464aae333..e2afcfc47 100644 --- a/libweston/color.h +++ b/libweston/color.h @@ -90,7 +90,7 @@ struct weston_hdr_metadata_type1 { float maxFALL; }; -/** Output properties derived from its color characteristics and profile +/** Output properties derived from its color profile * * These are constructed by a color manager. * diff --git a/libweston/compositor.c b/libweston/compositor.c index b1bd4e8e7..cc34a72f5 100644 --- a/libweston/compositor.c +++ b/libweston/compositor.c @@ -8224,50 +8224,6 @@ weston_output_get_hdr_metadata_type1(const struct weston_output *output) return &output->color_outcome->hdr_meta; } -/** Set display or monitor basic color characteristics - * - * \param output The output to modify, must be in disabled state. - * \param cc The new characteristics to set, or NULL to unset everything. - * - * This sets the metadata that describes the color characteristics of the - * output in a very simple manner. If a non-NULL color profile is set for the - * output, that will always take precedence. - * - * The initial value has everything unset. - * - * This function is meant to be used by compositor frontends. - * - * \ingroup output - * \sa weston_output_set_color_profile - */ -WL_EXPORT void -weston_output_set_color_characteristics(struct weston_output *output, - const struct weston_color_characteristics *cc) -{ - assert(!output->enabled); - - if (cc) - output->color_characteristics = *cc; - else - output->color_characteristics.group_mask = 0; -} - -/** Get display or monitor basic color characteristics - * - * \param output The output to query. - * \return Pointer to the metadata stored in weston_output. - * - * This function is meant to be used by color manager modules. - * - * \ingroup output - * \sa weston_output_set_color_characteristics - */ -WL_EXPORT const struct weston_color_characteristics * -weston_output_get_color_characteristics(struct weston_output *output) -{ - return &output->color_characteristics; -} - WL_EXPORT void weston_output_set_single_mode(struct weston_output *output, struct weston_mode *target) diff --git a/man/weston.ini.man b/man/weston.ini.man index c7bd161e0..c92d63253 100644 --- a/man/weston.ini.man +++ b/man/weston.ini.man @@ -583,11 +583,6 @@ on DRM, headless, wayland, and x11 backends, and for remoting and pipewire outputs. .TP 7 .BI "color-profile=" name - -.B NOTE: -This feature is not fully implemented yet, and therefore it is not expected to -work. - Color profiles describe how the display is assumed to behave. Knowing the display color behavior, Weston can adapt window contents to produce the presumed appearance. The option @@ -605,7 +600,7 @@ section by referring to it by its value. Alternatively this key can use one of the special profile names that contain a colon (:). -The default, once implemented, will be +The default is .BR "color-profile=auto:" . The following special names are accepted: @@ -775,13 +770,6 @@ The mode can be one of the following strings: Defaults to .BR sdr ". Non-SDR modes require " "color-management=true" . .TP 7 -.BI "color_characteristics=" name -Sets the basic output color characteristics by loading the parameters from the -.B color_characteristics -section with the key -.BI "name=" name -\&. If an ICC profile is also set, the ICC profile takes precedence. -.TP 7 .BI "mirror-of=" ouput_name Makes the remote output overlap (mirror) the native output identified by the mirror-of value. This is useful for sharing or mirroring a native DRM output. @@ -891,69 +879,6 @@ parallel to Weston, so it does not have to immediately exit. Defaults to empty. If set to true, quit Weston after the auto-launched executable exits. Set to false by default. .\"--------------------------------------------------------------------- -.SH "COLOR_CHARACTERISTICS SECTION" -Each -.B color_characteristics -section records one set of basic display or monitor color characterisation -parameters. The parameters are defined in CTA-861-H specification as Static -Metadata Type 1, and they can also be found in EDID. The parameters are -divided into groups. Each group must be given either fully or not at all. -.PP -Each section should be named with -.B name -key by which it can be referenced from other sections. A metadata section is -just a collection of parameter values and does nothing on its own. It has an -effect only when referenced from elsewhere. -.PP -See -.BR output " section key " color_characteristics . -.TP 7 -.BI "name=" name -An arbitrary name for this section. You can choose any name you want as long as -it does not contain the colon -.RB ( : ) -character. Names with at least one colon are reserved. -.SS Primaries group -.TP 7 -.BI "red_x=" x -.TQ -.BI "red_y=" y -.TQ -.BI "green_x=" x -.TQ -.BI "green_y=" y -.TQ -.BI "blue_x=" x -.TQ -.BI "blue_y=" y -The CIE 1931 xy chromaticity coordinates of the display primaries. -These floating point values must reside between 0.0 and 1.0, inclusive. -.SS White point group -.TP 7 -.BI "white_x=" x -.TQ -.BI "white_y=" y -The CIE 1931 xy chromaticity coordinates of the display white point. -These floating point values must reside between 0.0 and 1.0, inclusive. -.SS Independent parameters -Each parameter listed here has its own group and therefore can be given -alone. -.TP 7 -.BI "max_L=" L -Display's desired maximum content luminance (peak) -.IR L \~cd/m², -a floating point value in the range 0.0\(en100000.0. -.TP 7 -.BI "min_L=" L -Display's desired minimum content luminance -.IR L \~cd/m², -a floating point value in the range 0.0\(en100000.0. -.TP 7 -.BI "maxFALL=" L -Display's desired maximum frame-average light level -.IR L \~cd/m², -a floating point value in the range 0.0\(en100000.0. -.\"--------------------------------------------------------------------- .SH "COLOR-PROFILE SECTION" Each .B color-profile diff --git a/tests/color-management-parametric-test.c b/tests/color-management-parametric-test.c index 9ad7f2384..4e2317044 100644 --- a/tests/color-management-parametric-test.c +++ b/tests/color-management-parametric-test.c @@ -95,10 +95,10 @@ static const struct test_case test_cases[] = { /******** Successful cases *******/ { - /* sRGB primaries with sRGB TF; succeeds. */ + /* sRGB primaries with gamma22; succeeds. */ .primaries_named = WP_COLOR_MANAGER_V1_PRIMARIES_SRGB, .primaries = NULL, - .tf_named = WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_SRGB, + .tf_named = WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_GAMMA22, .tf_power = NOT_SET, .primaries_min_lum = NOT_SET, .primaries_max_lum = NOT_SET, @@ -112,10 +112,10 @@ static const struct test_case test_cases[] = { .error_point = ERROR_POINT_NONE, }, { - /* Custom primaries with sRGB TF; succeeds. */ + /* Custom primaries with gamma22; succeeds. */ .primaries_named = NOT_SET, .primaries = &color_gamut_sRGB, - .tf_named = WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_SRGB, + .tf_named = WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_GAMMA22, .tf_power = NOT_SET, .primaries_min_lum = NOT_SET, .primaries_max_lum = NOT_SET, @@ -129,10 +129,10 @@ static const struct test_case test_cases[] = { .error_point = ERROR_POINT_NONE, }, { - /* sRGB primaries, sRGB TF and valid luminance values; succeeds. */ + /* sRGB primaries, gamma22 and valid luminance values; succeeds. */ .primaries_named = NOT_SET, .primaries = &color_gamut_sRGB, - .tf_named = WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_SRGB, + .tf_named = WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_GAMMA22, .tf_power = NOT_SET, .primaries_min_lum = 0.5, .primaries_max_lum = 2000, @@ -163,10 +163,10 @@ static const struct test_case test_cases[] = { .error_point = ERROR_POINT_NONE, }, { - /* sRGB primaries, sRGB TF and valid target primaries; succeeds. */ + /* sRGB primaries, gamma22 and valid target primaries; succeeds. */ .primaries_named = WP_COLOR_MANAGER_V1_PRIMARIES_SRGB, .primaries = NULL, - .tf_named = WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_SRGB, + .tf_named = WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_GAMMA22, .tf_power = NOT_SET, .primaries_min_lum = NOT_SET, .primaries_max_lum = NOT_SET, @@ -309,7 +309,7 @@ static const struct test_case test_cases[] = { * protocol error. */ .primaries_named = WP_COLOR_MANAGER_V1_PRIMARIES_SRGB, .primaries = NULL, - .tf_named = WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_SRGB, + .tf_named = WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_GAMMA22, .tf_power = NOT_SET, .primaries_min_lum = NOT_SET, .primaries_max_lum = NOT_SET, @@ -327,7 +327,7 @@ static const struct test_case test_cases[] = { * protocol error. */ .primaries_named = WP_COLOR_MANAGER_V1_PRIMARIES_SRGB, .primaries = NULL, - .tf_named = WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_SRGB, + .tf_named = WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_GAMMA22, .tf_power = NOT_SET, .primaries_min_lum = NOT_SET, .primaries_max_lum = NOT_SET, @@ -381,7 +381,7 @@ static const struct test_case test_cases[] = { * defined range); graceful failure. */ .primaries_named = WP_COLOR_MANAGER_V1_PRIMARIES_SRGB, .primaries = NULL, - .tf_named = WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_SRGB, + .tf_named = WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_GAMMA22, .tf_power = NOT_SET, .primaries_min_lum = NOT_SET, .primaries_max_lum = NOT_SET, @@ -399,7 +399,7 @@ static const struct test_case test_cases[] = { * graceful failure. */ .primaries_named = WP_COLOR_MANAGER_V1_PRIMARIES_SRGB, .primaries = NULL, - .tf_named = WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_SRGB, + .tf_named = WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_GAMMA22, .tf_power = NOT_SET, .primaries_min_lum = NOT_SET, .primaries_max_lum = NOT_SET, @@ -433,7 +433,7 @@ color_manager_get(struct client *client) test_assert_u32_eq(cm->supported_rendering_intents, (1 << WP_COLOR_MANAGER_V1_RENDER_INTENT_PERCEPTUAL) | (1 << WP_COLOR_MANAGER_V1_RENDER_INTENT_RELATIVE) | - (1 << WP_COLOR_MANAGER_V1_RENDER_INTENT_SATURATION) | + /* (1 << WP_COLOR_MANAGER_V1_RENDER_INTENT_SATURATION) | */ (1 << WP_COLOR_MANAGER_V1_RENDER_INTENT_ABSOLUTE) | (1 << WP_COLOR_MANAGER_V1_RENDER_INTENT_RELATIVE_BPC)); @@ -455,7 +455,7 @@ color_manager_get(struct client *client) test_assert_u32_eq(cm->supported_tf, (1 << WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_GAMMA22) | (1 << WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_GAMMA28) | - (1 << WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_SRGB) | + (1 << WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_EXT_LINEAR) | (1 << WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_ST2084_PQ)); test_assert_true(cm->init_done); @@ -736,10 +736,10 @@ TEST(set_tf_named_twice) image_desc_creator_param = color_manager_create_param(cm); wp_image_description_creator_params_v1_set_tf_named(image_desc_creator_param, - WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_SRGB); + WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_GAMMA22); client_roundtrip(client); /* make sure connection is still valid */ wp_image_description_creator_params_v1_set_tf_named(image_desc_creator_param, - WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_SRGB); + WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_GAMMA22); expect_protocol_error(client, &wp_image_description_creator_params_v1_interface, WP_IMAGE_DESCRIPTION_CREATOR_PARAMS_V1_ERROR_ALREADY_SET); wp_image_description_creator_params_v1_destroy(image_desc_creator_param); @@ -763,7 +763,7 @@ TEST(set_tf_power_then_tf_named) 2.4 * 10000); client_roundtrip(client); /* make sure connection is still valid */ wp_image_description_creator_params_v1_set_tf_named(image_desc_creator_param, - WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_SRGB); + WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_GAMMA22); expect_protocol_error(client, &wp_image_description_creator_params_v1_interface, WP_IMAGE_DESCRIPTION_CREATOR_PARAMS_V1_ERROR_ALREADY_SET); wp_image_description_creator_params_v1_destroy(image_desc_creator_param); @@ -784,7 +784,7 @@ TEST(set_tf_named_then_tf_power) image_desc_creator_param = color_manager_create_param(cm); wp_image_description_creator_params_v1_set_tf_named(image_desc_creator_param, - WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_SRGB); + WP_COLOR_MANAGER_V1_TRANSFER_FUNCTION_GAMMA22); client_roundtrip(client); /* make sure connection is still valid */ wp_image_description_creator_params_v1_set_tf_power(image_desc_creator_param, 2.4 * 10000); diff --git a/tests/color-management-test.c b/tests/color-management-test.c index f4bf46f09..fd18b32e3 100644 --- a/tests/color-management-test.c +++ b/tests/color-management-test.c @@ -73,7 +73,7 @@ color_manager_get(struct client *client) test_assert_u32_eq(cm->supported_rendering_intents, (1 << WP_COLOR_MANAGER_V1_RENDER_INTENT_PERCEPTUAL) | (1 << WP_COLOR_MANAGER_V1_RENDER_INTENT_RELATIVE) | - (1 << WP_COLOR_MANAGER_V1_RENDER_INTENT_SATURATION) | + /* (1 << WP_COLOR_MANAGER_V1_RENDER_INTENT_SATURATION) | */ (1 << WP_COLOR_MANAGER_V1_RENDER_INTENT_ABSOLUTE) | (1 << WP_COLOR_MANAGER_V1_RENDER_INTENT_RELATIVE_BPC)); diff --git a/tests/color-metadata-errors-test.c b/tests/color-metadata-errors-test.c deleted file mode 100644 index 7b91b78c3..000000000 --- a/tests/color-metadata-errors-test.c +++ /dev/null @@ -1,971 +0,0 @@ -/* - * Copyright 2022 Collabora, Ltd. - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial - * portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include "config.h" - -#include -#include - -#include "weston-test-client-helper.h" -#include "weston-test-fixture-compositor.h" -#include "weston-test-assert.h" - -#include "weston-private.h" -#include "libweston-internal.h" -#include "backend.h" -#include "color.h" -#include "id-number-allocator.h" -#include "shared/string-helpers.h" -#include "shared/xalloc.h" - -struct config_testcase { - bool has_characteristics_key; - const char *output_characteristics_name; - const char *characteristics_name; - const char *red_x; - const char *green_y; - const char *white_y; - const char *min_L; - int expected_retval; - const char *expected_error; -}; - -static const struct config_testcase config_cases[] = { - { - false, "fred", "fred", "red_x=0.9", "green_y=0.8", "white_y=0.323", "min_L=1e-4", 0, - "" - }, - { - true, "fred", "fred", "red_x=0.9", "green_y= 0.8 ", "white_y=0.323", "min_L=1e-4", 0, - "" - }, - { - true, "fred", "fred", "red_x=0.9", "green_y= 0.8 ", "white_y=0.323", "", 0, - "" - }, - { - true, "notexisting", "fred", "red_x=0.9", "green_y=0.8", "white_y=0.323", "min_L=1e-4", -1, - "Config error in weston.ini, output mockoutput: no [color_characteristics] section with 'name=notexisting' found.\n" - }, - { - true, "fr:ed", "fr:ed", "red_x=0.9", "green_y=0.8", "white_y=0.323", "min_L=1e-4", -1, - "Config error in weston.ini [color_characteristics] name=fr:ed is a reserved name. Do not use ':' character in the name.\n" - }, - { - true, "fred", "fred", "red_x=-5", "green_y=1.01", "white_y=0.323", "min_L=1e-4", -1, - "Config error in weston.ini [color_characteristics] name=fred: red_x value -5.000000 is outside of the range 0.000000 - 1.000000.\n" - "Config error in weston.ini [color_characteristics] name=fred: green_y value 1.010000 is outside of the range 0.000000 - 1.000000.\n" - }, - { - true, "fred", "fred", "red_x=haahaa", "green_y=-", "white_y=0.323", "min_L=1e-4", -1, - "Config error in weston.ini [color_characteristics] name=fred: failed to parse the value of key red_x.\n" - "Config error in weston.ini [color_characteristics] name=fred: failed to parse the value of key green_y.\n" - }, - { - true, "fred", "fred", "", "", "white_y=0.323", "min_L=1e-4", -1, - "Config error in weston.ini [color_characteristics] name=fred: group 1 key red_x is missing. You must set either none or all keys of a group.\n" - "Config error in weston.ini [color_characteristics] name=fred: group 1 key red_y is set. You must set either none or all keys of a group.\n" - "Config error in weston.ini [color_characteristics] name=fred: group 1 key green_x is set. You must set either none or all keys of a group.\n" - "Config error in weston.ini [color_characteristics] name=fred: group 1 key green_y is missing. You must set either none or all keys of a group.\n" - "Config error in weston.ini [color_characteristics] name=fred: group 1 key blue_x is set. You must set either none or all keys of a group.\n" - "Config error in weston.ini [color_characteristics] name=fred: group 1 key blue_y is set. You must set either none or all keys of a group.\n" - }, - { - true, "fred", "fred", "red_x=0.9", "green_y=0.8", "", "min_L=1e-4", -1, - "Config error in weston.ini [color_characteristics] name=fred: group 2 key white_x is set. You must set either none or all keys of a group.\n" - "Config error in weston.ini [color_characteristics] name=fred: group 2 key white_y is missing. You must set either none or all keys of a group.\n" - }, -}; - -static FILE *logfile; - -static int -logger(const char *fmt, va_list arg) -{ - return vfprintf(logfile, fmt, arg); -} - -static int -no_logger(const char *fmt, va_list arg) -{ - return 0; -} - -static struct weston_config * -create_config(const struct config_testcase *t) -{ - struct compositor_setup setup; - struct weston_config *wc; - - compositor_setup_defaults(&setup); - weston_ini_setup(&setup, - cfgln("[output]"), - cfgln("name=mockoutput"), - t->has_characteristics_key ? - cfgln("color_characteristics=%s", t->output_characteristics_name) : - cfgln(""), - cfgln("eotf-mode=st2084"), - - cfgln("[color_characteristics]"), - cfgln("name=%s", t->characteristics_name), - cfgln("maxFALL=1000"), - cfgln("%s", t->red_x), - cfgln("red_y=0.3"), - cfgln("blue_x=0.1"), - cfgln("blue_y=0.11"), - cfgln("green_x=0.1771"), - cfgln("%s", t->green_y), - cfgln("white_x=0.313"), - cfgln("%s", t->white_y), - cfgln("%s", t->min_L), - cfgln("max_L=65535.0"), - - cfgln("[core]"), - cfgln("color-management=true")); - - wc = weston_config_parse(setup.config_file); - free(setup.config_file); - - return wc; -} - -struct mock_color_manager { - struct weston_color_manager base; - struct weston_hdr_metadata_type1 *test_hdr_meta; -}; - -static struct weston_output_color_outcome * -mock_create_output_color_outcome(struct weston_color_manager *cm_base, - struct weston_output *output) -{ - struct mock_color_manager *cm = container_of(cm_base, typeof(*cm), base); - struct weston_output_color_outcome *co; - - co = xzalloc(sizeof *co); - - co->hdr_meta = *cm->test_hdr_meta; - - return co; -} - -static struct weston_color_profile * -mock_cm_ref_stock_sRGB_color_profile(struct weston_color_manager *mock_cm) -{ - struct weston_color_profile *mock_cprof; - - mock_cprof = xzalloc(sizeof(*mock_cprof)); - - weston_color_profile_init(mock_cprof, mock_cm); - str_printf(&mock_cprof->description, "mock cprof"); - - return mock_cprof; -} - -static bool -mock_cm_get_color_profile_from_params(struct weston_color_manager *cm, - const struct weston_color_profile_params *params, - const char *name_part, - struct weston_color_profile **cprof_out, - char **errmsg) -{ - test_assert_not_reached("This cannot be a valid parametric profile."); -} - -static void -mock_cm_destroy_color_profile(struct weston_color_profile *mock_cprof) -{ - free(mock_cprof->description); - free(mock_cprof); -} - -/* - * Manufacture various weston.ini and check what - * wet_output_set_color_characteristics() says. Tests for the return value and - * the error messages logged. - */ -TEST_P(color_characteristics_config_error, config_cases) -{ - const struct config_testcase *t = data; - struct weston_config *wc; - struct weston_config_section *section; - int retval; - char *logbuf; - size_t logsize; - struct mock_color_manager mock_cm = { - .base.create_output_color_outcome = mock_create_output_color_outcome, - .base.ref_stock_sRGB_color_profile = mock_cm_ref_stock_sRGB_color_profile, - .base.destroy_color_profile = mock_cm_destroy_color_profile, - }; - struct weston_compositor mock_compositor = { - .color_manager = &mock_cm.base, - .color_profile_id_generator = weston_idalloc_create(&mock_compositor), - }; - struct weston_output mock_output = {}; - - mock_cm.base.compositor = &mock_compositor; - - wl_list_init(&mock_compositor.plane_list); - weston_output_init(&mock_output, &mock_compositor, "mockoutput"); - - logfile = open_memstream(&logbuf, &logsize); - weston_log_set_handler(logger, logger); - - wc = create_config(t); - section = weston_config_get_section(wc, "output", "name", "mockoutput"); - test_assert_ptr_not_null(section); - - retval = wet_output_set_color_characteristics(&mock_output, wc, section); - - test_assert_int_eq(fclose(logfile), 0); - logfile = NULL; - - testlog("retval %d, logs:\n%s\n", retval, logbuf); - - test_assert_int_eq(retval, t->expected_retval); - test_assert_int_eq(strcmp(logbuf, t->expected_error), 0); - - weston_config_destroy(wc); - free(logbuf); - weston_output_release(&mock_output); - weston_idalloc_destroy(mock_compositor.color_profile_id_generator); - - return RESULT_OK; -} - -/* Setting NULL resets group_mask */ -TEST(weston_output_set_color_characteristics_null) -{ - struct mock_color_manager mock_cm = { - .base.create_output_color_outcome = mock_create_output_color_outcome, - .base.ref_stock_sRGB_color_profile = mock_cm_ref_stock_sRGB_color_profile, - .base.destroy_color_profile = mock_cm_destroy_color_profile, - }; - struct weston_compositor mock_compositor = { - .color_manager = &mock_cm.base, - .color_profile_id_generator = weston_idalloc_create(&mock_compositor), - }; - struct weston_output mock_output = {}; - - mock_cm.base.compositor = &mock_compositor; - - wl_list_init(&mock_compositor.plane_list); - weston_output_init(&mock_output, &mock_compositor, "mockoutput"); - - mock_output.color_characteristics.group_mask = 1; - weston_output_set_color_characteristics(&mock_output, NULL); - test_assert_u32_eq(mock_output.color_characteristics.group_mask, 0); - - weston_output_release(&mock_output); - weston_idalloc_destroy(mock_compositor.color_profile_id_generator); - - return RESULT_OK; -} - -struct value_testcase { - unsigned field_index; - float value; - bool retval; -}; - -static const struct value_testcase value_cases[] = { - { 0, 0.0, true }, - { 0, 1.0, true }, - { 0, -0.001, false }, - { 0, 1.01, false }, - { 0, NAN, false }, - { 0, HUGE_VALF, false }, - { 0, -HUGE_VALF, false }, - { 1, -1.0, false }, - { 2, 2.0, false }, - { 3, 2.0, false }, - { 4, 2.0, false }, - { 5, 2.0, false }, - { 6, 2.0, false }, - { 7, 2.0, false }, - { 8, 0.99, false }, - { 8, 65535.1, false }, - { 9, 0.000099, false }, - { 9, 6.55351, false }, - { 10, 0.99, false }, - { 10, 65535.1, false }, - { 11, 0.99, false }, - { 11, 65535.1, false }, -}; - -/* - * Modify one value in a known good metadata structure, and see how - * validation reacts to it. - */ -TEST_P(hdr_metadata_type1_errors, value_cases) -{ - struct value_testcase *t = data; - struct weston_hdr_metadata_type1 meta = { - .group_mask = WESTON_HDR_METADATA_TYPE1_GROUP_ALL_MASK, - .primary[0] = { 0.6650, 0.3261 }, - .primary[1] = { 0.2890, 0.6435 }, - .primary[2] = { 0.1491, 0.0507 }, - .white = { 0.3134, 0.3291 }, - .maxDML = 600.0, - .minDML = 0.0001, - .maxCLL = 600.0, - .maxFALL = 400.0, - }; - float *fields[] = { - &meta.primary[0].x, &meta.primary[0].y, - &meta.primary[1].x, &meta.primary[1].y, - &meta.primary[2].x, &meta.primary[2].y, - &meta.white.x, &meta.white.y, - &meta.maxDML, &meta.minDML, - &meta.maxCLL, &meta.maxFALL, - }; - struct mock_color_manager mock_cm = { - .base.create_output_color_outcome = mock_create_output_color_outcome, - .base.ref_stock_sRGB_color_profile = mock_cm_ref_stock_sRGB_color_profile, - .base.destroy_color_profile = mock_cm_destroy_color_profile, - .test_hdr_meta = &meta, - }; - struct weston_compositor mock_compositor = { - .color_manager = &mock_cm.base, - .color_profile_id_generator = weston_idalloc_create(&mock_compositor), - }; - struct weston_output mock_output = {}; - bool ret; - - weston_log_set_handler(no_logger, no_logger); - - mock_cm.base.compositor = &mock_compositor; - - wl_list_init(&mock_compositor.plane_list); - weston_output_init(&mock_output, &mock_compositor, "mockoutput"); - - test_assert_uint_lt(t->field_index, ARRAY_LENGTH(fields)); - *fields[t->field_index] = t->value; - ret = weston_output_set_color_outcome(&mock_output); - test_assert_int_eq(ret, t->retval); - - weston_output_color_outcome_destroy(&mock_output.color_outcome); - weston_output_release(&mock_output); - weston_idalloc_destroy(mock_compositor.color_profile_id_generator); - - return RESULT_OK; -} - -/* Unflagged members are ignored in validity check */ -TEST(hdr_metadata_type1_ignore_unflagged) -{ - /* All values invalid, but also empty mask so none actually used. */ - struct weston_hdr_metadata_type1 meta = { - .group_mask = 0, - .primary[0] = { -1.0, -1.0 }, - .primary[1] = { -1.0, -1.0 }, - .primary[2] = { -1.0, -1.0 }, - .white = { -1.0, -1.0 }, - .maxDML = -1.0, - .minDML = -1.0, - .maxCLL = -1.0, - .maxFALL = -1.0, - }; - struct mock_color_manager mock_cm = { - .base.create_output_color_outcome = mock_create_output_color_outcome, - .base.ref_stock_sRGB_color_profile = mock_cm_ref_stock_sRGB_color_profile, - .base.destroy_color_profile = mock_cm_destroy_color_profile, - .test_hdr_meta = &meta, - }; - struct weston_compositor mock_compositor = { - .color_manager = &mock_cm.base, - .color_profile_id_generator = weston_idalloc_create(&mock_compositor), - }; - struct weston_output mock_output = {}; - bool ret; - - mock_cm.base.compositor = &mock_compositor; - - wl_list_init(&mock_compositor.plane_list); - weston_log_set_handler(no_logger, no_logger); - - weston_output_init(&mock_output, &mock_compositor, "mockoutput"); - - ret = weston_output_set_color_outcome(&mock_output); - test_assert_true(ret); - - weston_output_color_outcome_destroy(&mock_output.color_outcome); - weston_output_release(&mock_output); - weston_idalloc_destroy(mock_compositor.color_profile_id_generator); - - return RESULT_OK; -} - -struct mode_testcase { - bool color_management; - uint32_t supported_eotf_mask; - uint32_t supported_colorimetry_mask; - const char *eotf_mode; - const char *colorimetry_mode; - enum weston_eotf_mode expected_eotf_mode; - enum weston_colorimetry_mode expected_colorimetry_mode; - int expected_retval; - const char *expected_error; -}; - -static const struct mode_testcase mode_config_cases[] = { - /* Defaults */ - { - false, WESTON_EOTF_MODE_SDR, WESTON_COLORIMETRY_MODE_DEFAULT, NULL, NULL, - WESTON_EOTF_MODE_SDR, WESTON_COLORIMETRY_MODE_DEFAULT, - 0, "" - }, - /* Color management off, EOTF modes */ - { - false, WESTON_EOTF_MODE_ALL_MASK, WESTON_COLORIMETRY_MODE_DEFAULT, "sdr", NULL, - WESTON_EOTF_MODE_SDR, WESTON_COLORIMETRY_MODE_DEFAULT, - 0, "" - }, - { - false, WESTON_EOTF_MODE_ALL_MASK, WESTON_COLORIMETRY_MODE_DEFAULT, "hdr-gamma", NULL, - WESTON_EOTF_MODE_SDR, WESTON_COLORIMETRY_MODE_DEFAULT, - -1, "Error: EOTF mode hdr-gamma on output 'mockoutput' requires color-management=true in weston.ini\n" - }, - { - false, WESTON_EOTF_MODE_ALL_MASK, WESTON_COLORIMETRY_MODE_DEFAULT, "st2084", NULL, - WESTON_EOTF_MODE_SDR, WESTON_COLORIMETRY_MODE_DEFAULT, - -1, "Error: EOTF mode st2084 on output 'mockoutput' requires color-management=true in weston.ini\n" - }, - { - false, WESTON_EOTF_MODE_ALL_MASK, WESTON_COLORIMETRY_MODE_DEFAULT, "hlg", NULL, - WESTON_EOTF_MODE_SDR, WESTON_COLORIMETRY_MODE_DEFAULT, - -1, "Error: EOTF mode hlg on output 'mockoutput' requires color-management=true in weston.ini\n" - }, - { - false, WESTON_EOTF_MODE_ALL_MASK, WESTON_COLORIMETRY_MODE_DEFAULT, "nonosense", NULL, - WESTON_EOTF_MODE_SDR, WESTON_COLORIMETRY_MODE_DEFAULT, - -1, "Error in config for output 'mockoutput': 'nonosense' is not a valid EOTF mode. Try one of: sdr hdr-gamma st2084 hlg\n" - }, - /* Color management on, EOTF modes */ - { - true, WESTON_EOTF_MODE_ALL_MASK, WESTON_COLORIMETRY_MODE_DEFAULT, "sdr", NULL, - WESTON_EOTF_MODE_SDR, WESTON_COLORIMETRY_MODE_DEFAULT, - 0, "" - }, - { - true, WESTON_EOTF_MODE_ALL_MASK, WESTON_COLORIMETRY_MODE_DEFAULT, "hdr-gamma", NULL, - WESTON_EOTF_MODE_TRADITIONAL_HDR, WESTON_COLORIMETRY_MODE_DEFAULT, - 0, "" - }, - { - true, WESTON_EOTF_MODE_ALL_MASK, WESTON_COLORIMETRY_MODE_DEFAULT, "st2084", NULL, - WESTON_EOTF_MODE_ST2084, WESTON_COLORIMETRY_MODE_DEFAULT, - 0, "" - }, - { - true, WESTON_EOTF_MODE_ALL_MASK, WESTON_COLORIMETRY_MODE_DEFAULT, "hlg", NULL, - WESTON_EOTF_MODE_HLG, WESTON_COLORIMETRY_MODE_DEFAULT, - 0, "" - }, - { - true, WESTON_EOTF_MODE_ALL_MASK, WESTON_COLORIMETRY_MODE_DEFAULT, "nonosense", NULL, - WESTON_EOTF_MODE_SDR, WESTON_COLORIMETRY_MODE_DEFAULT, - -1, "Error in config for output 'mockoutput': 'nonosense' is not a valid EOTF mode. Try one of: sdr hdr-gamma st2084 hlg\n" - }, - /* unsupported EOTF mode */ - { - true, - WESTON_EOTF_MODE_SDR | WESTON_EOTF_MODE_TRADITIONAL_HDR | WESTON_EOTF_MODE_ST2084, - WESTON_COLORIMETRY_MODE_DEFAULT, "hlg", NULL, - WESTON_EOTF_MODE_SDR, WESTON_COLORIMETRY_MODE_DEFAULT, - -1, "Error: output 'mockoutput' does not support EOTF mode hlg.\n" - }, - /* Color management off, colorimetry modes */ - { - false, WESTON_EOTF_MODE_SDR, WESTON_COLORIMETRY_MODE_ALL_MASK, NULL, "default", - WESTON_EOTF_MODE_SDR, WESTON_COLORIMETRY_MODE_DEFAULT, - 0, "" - }, - { - false, WESTON_EOTF_MODE_SDR, WESTON_COLORIMETRY_MODE_ALL_MASK, NULL, "bt2020cycc", - WESTON_EOTF_MODE_SDR, WESTON_COLORIMETRY_MODE_DEFAULT, - -1, "Error: Colorimetry mode bt2020cycc on output 'mockoutput' requires color-management=true in weston.ini\n" - }, - { - false, WESTON_EOTF_MODE_SDR, WESTON_COLORIMETRY_MODE_ALL_MASK, NULL, "bt2020ycc", - WESTON_EOTF_MODE_SDR, WESTON_COLORIMETRY_MODE_DEFAULT, - -1, "Error: Colorimetry mode bt2020ycc on output 'mockoutput' requires color-management=true in weston.ini\n" - }, - { - false, WESTON_EOTF_MODE_SDR, WESTON_COLORIMETRY_MODE_ALL_MASK, NULL, "bt2020rgb", - WESTON_EOTF_MODE_SDR, WESTON_COLORIMETRY_MODE_DEFAULT, - -1, "Error: Colorimetry mode bt2020rgb on output 'mockoutput' requires color-management=true in weston.ini\n" - }, - { - false, WESTON_EOTF_MODE_SDR, WESTON_COLORIMETRY_MODE_ALL_MASK, NULL, "p3d65", - WESTON_EOTF_MODE_SDR, WESTON_COLORIMETRY_MODE_DEFAULT, - -1, "Error: Colorimetry mode p3d65 on output 'mockoutput' requires color-management=true in weston.ini\n" - }, - { - false, WESTON_EOTF_MODE_SDR, WESTON_COLORIMETRY_MODE_ALL_MASK, NULL, "p3dci", - WESTON_EOTF_MODE_SDR, WESTON_COLORIMETRY_MODE_DEFAULT, - -1, "Error: Colorimetry mode p3dci on output 'mockoutput' requires color-management=true in weston.ini\n" - }, - { - false, WESTON_EOTF_MODE_SDR, WESTON_COLORIMETRY_MODE_ALL_MASK, NULL, "ictcp", - WESTON_EOTF_MODE_SDR, WESTON_COLORIMETRY_MODE_DEFAULT, - -1, "Error: Colorimetry mode ictcp on output 'mockoutput' requires color-management=true in weston.ini\n" - }, - { - false, WESTON_EOTF_MODE_SDR, WESTON_COLORIMETRY_MODE_ALL_MASK, NULL, "imagine that", - WESTON_EOTF_MODE_SDR, WESTON_COLORIMETRY_MODE_DEFAULT, - -1, "Error in config for output 'mockoutput': 'imagine that' is not a valid colorimetry mode. Try one of: default bt2020cycc bt2020ycc bt2020rgb p3d65 p3dci ictcp\n" - }, - /* Color management on, colorimetry modes */ - { - true, WESTON_EOTF_MODE_SDR, WESTON_COLORIMETRY_MODE_ALL_MASK, NULL, "default", - WESTON_EOTF_MODE_SDR, WESTON_COLORIMETRY_MODE_DEFAULT, - 0, "" - }, - { - true, WESTON_EOTF_MODE_SDR, WESTON_COLORIMETRY_MODE_ALL_MASK, NULL, "bt2020cycc", - WESTON_EOTF_MODE_SDR, WESTON_COLORIMETRY_MODE_BT2020_CYCC, - 0, "" - }, - { - true, WESTON_EOTF_MODE_SDR, WESTON_COLORIMETRY_MODE_ALL_MASK, NULL, "bt2020ycc", - WESTON_EOTF_MODE_SDR, WESTON_COLORIMETRY_MODE_BT2020_YCC, - 0, "" - }, - { - true, WESTON_EOTF_MODE_SDR, WESTON_COLORIMETRY_MODE_ALL_MASK, NULL, "bt2020rgb", - WESTON_EOTF_MODE_SDR, WESTON_COLORIMETRY_MODE_BT2020_RGB, - 0, "" - }, - { - true, WESTON_EOTF_MODE_SDR, WESTON_COLORIMETRY_MODE_ALL_MASK, NULL, "p3d65", - WESTON_EOTF_MODE_SDR, WESTON_COLORIMETRY_MODE_P3D65, - 0, "" - }, - { - true, WESTON_EOTF_MODE_SDR, WESTON_COLORIMETRY_MODE_ALL_MASK, NULL, "p3dci", - WESTON_EOTF_MODE_SDR, WESTON_COLORIMETRY_MODE_P3DCI, - 0, "" - }, - { - true, WESTON_EOTF_MODE_SDR, WESTON_COLORIMETRY_MODE_ALL_MASK, NULL, "ictcp", - WESTON_EOTF_MODE_SDR, WESTON_COLORIMETRY_MODE_ICTCP, - 0, "" - }, - { - true, WESTON_EOTF_MODE_SDR, WESTON_COLORIMETRY_MODE_ALL_MASK, NULL, "imagine that", - WESTON_EOTF_MODE_SDR, WESTON_COLORIMETRY_MODE_DEFAULT, - -1, "Error in config for output 'mockoutput': 'imagine that' is not a valid colorimetry mode. Try one of: default bt2020cycc bt2020ycc bt2020rgb p3d65 p3dci ictcp\n" - }, - /* Unsupported colorimetry mode */ - { - true, WESTON_EOTF_MODE_SDR, - WESTON_COLORIMETRY_MODE_DEFAULT | WESTON_COLORIMETRY_MODE_BT2020_RGB | WESTON_COLORIMETRY_MODE_BT2020_CYCC | WESTON_COLORIMETRY_MODE_P3D65, - NULL, "ictcp", - WESTON_EOTF_MODE_SDR, WESTON_COLORIMETRY_MODE_DEFAULT, - -1, "Error: output 'mockoutput' does not support colorimetry mode ictcp.\n" - }, -}; - -static struct weston_config * -create_mode_config(const struct mode_testcase *t) -{ - struct compositor_setup setup; - struct weston_config *wc; - - compositor_setup_defaults(&setup); - weston_ini_setup(&setup, - cfgln("[output]"), - cfgln("name=mockoutput"), - - t->eotf_mode ? - cfgln("eotf-mode=%s", t->eotf_mode) : - cfgln(""), - - t->colorimetry_mode ? - cfgln("colorimetry-mode=%s", t->colorimetry_mode) : - cfgln("") - ); - - wc = weston_config_parse(setup.config_file); - free(setup.config_file); - - return wc; -} - -/* - * Manufacture various weston.ini and check what - * wet_output_set_eotf_mode() and wet_output_set_colorimetry_mode() says. - * Tests for the return value and the error messages logged. - */ -TEST_P(mode_config_error, mode_config_cases) -{ - const struct mode_testcase *t = data; - struct mock_color_manager mock_cm = { - .base.create_output_color_outcome = mock_create_output_color_outcome, - .base.ref_stock_sRGB_color_profile = mock_cm_ref_stock_sRGB_color_profile, - .base.destroy_color_profile = mock_cm_destroy_color_profile, - }; - struct weston_compositor mock_compositor = { - .color_manager = &mock_cm.base, - .color_profile_id_generator = weston_idalloc_create(&mock_compositor), - }; - - struct weston_config *wc; - struct weston_config_section *section; - int retval; - int attached; - char *logbuf; - size_t logsize; - struct weston_head mock_head = {}; - struct weston_output mock_output = {}; - - mock_cm.base.compositor = &mock_compositor; - - wl_list_init(&mock_compositor.plane_list); - - weston_output_init(&mock_output, &mock_compositor, "mockoutput"); - weston_head_init(&mock_head, "mockhead"); - weston_head_set_supported_eotf_mask(&mock_head, t->supported_eotf_mask); - weston_head_set_supported_colorimetry_mask(&mock_head, t->supported_colorimetry_mask); - attached = weston_output_attach_head(&mock_output, &mock_head); - test_assert_int_eq(attached, 0); - - logfile = open_memstream(&logbuf, &logsize); - weston_log_set_handler(logger, logger); - - wc = create_mode_config(t); - section = weston_config_get_section(wc, "output", "name", "mockoutput"); - test_assert_ptr_not_null(section); - - retval = wet_output_set_eotf_mode(&mock_output, section, t->color_management); - if (retval == 0) { - retval = wet_output_set_colorimetry_mode(&mock_output, section, - t->color_management); - } - - test_assert_int_eq(fclose(logfile), 0); - logfile = NULL; - - testlog("retval %d, logs:\n%s\n", retval, logbuf); - - test_assert_int_eq(retval, t->expected_retval); - test_assert_int_eq(strcmp(logbuf, t->expected_error), 0); - test_assert_enum(weston_output_get_eotf_mode(&mock_output), t->expected_eotf_mode); - test_assert_enum(weston_output_get_colorimetry_mode(&mock_output), t->expected_colorimetry_mode); - - weston_config_destroy(wc); - free(logbuf); - weston_output_release(&mock_output); - weston_head_release(&mock_head); - weston_idalloc_destroy(mock_compositor.color_profile_id_generator); - - return RESULT_OK; -} - -static void -test_creating_output_color_profile(struct weston_config *wc, - const char *profile_name, - uint32_t supported_color_features, - uint32_t supported_primaries_named, - uint32_t supported_tf_named, - const char *expected_error) -{ - struct weston_color_profile *cprof; - char *logbuf; - size_t logsize; - struct mock_color_manager mock_cm = { - .base.ref_stock_sRGB_color_profile = mock_cm_ref_stock_sRGB_color_profile, - .base.get_color_profile_from_params = mock_cm_get_color_profile_from_params, - .base.destroy_color_profile = mock_cm_destroy_color_profile, - .base.supported_color_features = supported_color_features, - .base.supported_primaries_named = supported_primaries_named, - .base.supported_tf_named = supported_tf_named, - }; - struct weston_compositor mock_compositor = { - .color_manager = &mock_cm.base, - .color_profile_id_generator = weston_idalloc_create(&mock_compositor), - }; - struct weston_output mock_output = {}; - - mock_cm.base.compositor = &mock_compositor; - - wl_list_init(&mock_compositor.plane_list); - - logfile = open_memstream(&logbuf, &logsize); - weston_log_set_handler(logger, logger); - - weston_output_init(&mock_output, &mock_compositor, "mockoutput"); - - cprof = wet_create_output_color_profile(&mock_output, wc, profile_name); - test_assert_ptr_null(cprof); - - test_assert_int_eq(fclose(logfile), 0); - logfile = NULL; - - testlog("logs:\n%s\n------\n", logbuf); - - test_assert_str_eq(logbuf, expected_error); - - free(logbuf); - weston_output_release(&mock_output); - weston_idalloc_destroy(mock_compositor.color_profile_id_generator); -} - -struct color_profile_name_testcase { - const char *profile_name; - const char *expected_error; -}; - -static const struct color_profile_name_testcase color_profile_name_cases[] = { - { - "notexists", - "Config error in weston.ini, output mockoutput: no [color-profile] section with 'name=notexists' found.\n", - }, - { - "boo:faa", - "Config error in weston.ini, output mockoutput, color-profile=boo:faa is illegal. The ':' character is legal only for 'srgb:' and 'auto:'.\n", - }, - { - "auto:kek", - "Config error in weston.ini, output mockoutput, key color-profile=auto: invalid flag 'kek'.\n", - }, -}; - -/* - * Manufacture various weston.ini and check the error messages that - * wet_create_output_color_profile() generates for bad color-profile names. - */ -TEST_P(parametric_color_profile_name_errors, color_profile_name_cases) -{ - const struct color_profile_name_testcase *t = data; - - test_creating_output_color_profile(NULL, t->profile_name, - 0xffffffff, 0xffffffff, 0xffffffff, - t->expected_error); - - return RESULT_OK; -} - -struct parameters_testcase { - const char *profile_string; - const char *expected_error; -}; - -static const struct parameters_testcase param_config_cases[] = { - { - "", - "Config error in weston.ini [color-profile] name=mydisp, invalid parameter set:\n" - " primaries not set\n" - " transfer function not set\n", - }, - { - "tf_named=gamma22\n", - "Config error in weston.ini [color-profile] name=mydisp, invalid parameter set:\n" - " primaries not set\n" - }, - { - "prim_named=srgb\n", - "Config error in weston.ini [color-profile] name=mydisp, invalid parameter set:\n" - " transfer function not set\n", - }, - { - "tf_named=kukkuu\n" - "prim_named=jeejee\n", - "Config error in weston.ini [color-profile] name=mydisp, prim_named has unknown value 'jeejee'.\n" - "Config error in weston.ini [color-profile] name=mydisp, tf_named has unknown value 'kukkuu'.\n", - }, - { - "prim_named=pal\n" - "tf_named=gamma28\n" - "tf_power=2.4\n", - "Config error in weston.ini [color-profile] name=mydisp, invalid parameter set:\n" - " tf was already set\n", - }, - { - "prim_named=pal_m\n" - "prim_red=0.67 0.33\n" - "prim_green=0.21 0.71\n" - "prim_blue=0.14 0.08\n" - "prim_white=0.31 0.32\n" - "tf_power=2.4\n", - "Config error in weston.ini [color-profile] name=mydisp, invalid parameter set:\n" - " primaries were already set\n", - }, - { - "prim_red=0.6 0.3\n" - "prim_blue=0.1 0.05\n" - "min_lum=0\n" - "target_white=0.33 0.33\n" - "target_max_lum=1200\n", - "Config error in weston.ini [color-profile] name=mydisp:\n" - " group: signaling primaries\n" - " prim_red is set.\n" - " prim_green is missing.\n" - " prim_blue is set.\n" - " prim_white is missing.\n" - " group: signaling luminances\n" - " min_lum is set.\n" - " max_lum is missing.\n" - " ref_lum is missing.\n" - " group: target primaries\n" - " target_red is missing.\n" - " target_green is missing.\n" - " target_blue is missing.\n" - " target_white is set.\n" - " group: target luminances\n" - " target_min_lum is missing.\n" - " target_max_lum is set.\n" - "You must set either none or all keys of a group.\n", - }, - { - "prim_red=0.67 0.33 0.4\n" - "prim_green=0.21\n" - "prim_blue=0,14 k\n" - "prim_white=\n" - "tf_power=xx\n", - "Config error in weston.ini [color-profile] name=mydisp, parsing prim_red: Needed exactly 2 numbers separated by whitespace, got 3.\n" - "Config error in weston.ini [color-profile] name=mydisp, parsing prim_green: Needed exactly 2 numbers separated by whitespace, got 1.\n" - "Config error in weston.ini [color-profile] name=mydisp, parsing prim_blue: '0,14' is not a number.\n" - "Config error in weston.ini [color-profile] name=mydisp, parsing prim_white: Needed exactly 2 numbers separated by whitespace, got 0.\n" - "Config error in weston.ini [color-profile] name=mydisp, parsing tf_power: 'xx' is not a number.\n", - }, - { - "tf_power=50\n", - "Config error in weston.ini [color-profile] name=mydisp, invalid parameter set:\n" - " tf power exponent 50.000000 is not in the range [1.0, 10.0]\n" - " primaries not set\n" - " transfer function not set\n", - }, - { - "prim_red=Inf 0.33\n" - "prim_green=0.21 7\n" - "prim_blue=-1 NaN\n" - "prim_white=0 -2\n" - "tf_power=3\n", - "Config error in weston.ini [color-profile] name=mydisp, invalid parameter set:\n" - " invalid primary color volume, the red primary CIE x value inf is out of range [-1.0, 2.0]\n" - " invalid primary color volume, the green primary CIE y value 7.000000 is out of range [-1.0, 2.0]\n" - " invalid primary color volume, the blue primary CIE y value nan is out of range [-1.0, 2.0]\n" - " invalid primary color volume, the white point CIE y value -2.000000 is out of range [-1.0, 2.0]\n" - " white point out of primary volume\n" - }, - { - "prim_named=bt2020\n" - "tf_named=bt1886\n" - "min_lum=10\n" - "ref_lum=5\n" - "max_lum=2\n" - "target_min_lum=55\n" - "target_max_lum=1\n" - "max_fall=-7\n" - "max_cll=0\n", - "Config error in weston.ini [color-profile] name=mydisp, invalid parameter set:\n" - " reference luminance (5.000000) must be greater than primary minimum luminance (10.000000)\n" - " primary minimum luminance (10.000000) must be less than primary maximum luminance (2.000000)\n" - " target min luminance (55.000000) must be less than target max luminance (1.000000)\n" - " maxCLL (0.000000) must be in the range (0.0, 1e+6]\n" - " maxCLL (0.000000) should be greater than target min luminance (0.010000)\n" - " maxFALL (-7.000000) must be in the range (0.0, 1e+6]\n" - " maxFALL (-7.000000) must be greater than min luminance (0.010000)\n", - }, -}; - -/* - * Manufacture various weston.ini and check the error messages that - * wet_create_output_color_profile() generates for invalid - * color-profile sections. - */ -TEST_P(parametric_color_profile_parsing_errors, param_config_cases) -{ - const struct parameters_testcase *t = data; - struct compositor_setup setup; - struct weston_config *wc; - - compositor_setup_defaults(&setup); - weston_ini_setup(&setup, - cfgln("[color-profile]"), - cfgln("name=mydisp"), - cfgln("%s", t->profile_string)); - - wc = weston_config_parse(setup.config_file); - test_assert_ptr_not_null(wc); - free(setup.config_file); - - test_creating_output_color_profile(wc, "mydisp", - 0xffffffff, 0xffffffff, 0xffffffff, - t->expected_error); - weston_config_destroy(wc); - - return RESULT_OK; -} - -static const struct parameters_testcase param_unsupported_cases[] = { - { - "prim_named=ntsc\n" - "tf_named=log100\n", - "Config error in weston.ini [color-profile] name=mydisp, invalid parameter set:\n" - " primaries named NTSC (BT.601) not supported by the color manager\n" - " logarithmic 100:1 not supported by the color manager\n" - " primaries not set\n" - " transfer function not set\n", - }, - { - "prim_named=srgb\n" - "tf_power=2.3\n", - "Config error in weston.ini [color-profile] name=mydisp, invalid parameter set:\n" - " set_tf_power not supported by the color manager\n" - " transfer function not set\n", - }, -}; - -/* - * Manufacture various weston.ini and check the error messages that - * wet_create_output_color_profile() generates for valid - * color-profile sections that use things the color manager does not - * support. - */ -TEST_P(parametric_color_profile_parsing_unsupported, param_unsupported_cases) -{ - const struct parameters_testcase *t = data; - struct compositor_setup setup; - struct weston_config *wc; - - compositor_setup_defaults(&setup); - weston_ini_setup(&setup, - cfgln("[color-profile]"), - cfgln("name=mydisp"), - cfgln("%s", t->profile_string)); - - wc = weston_config_parse(setup.config_file); - test_assert_ptr_not_null(wc); - free(setup.config_file); - - test_creating_output_color_profile(wc, "mydisp", - 0, (1u << WESTON_PRIMARIES_CICP_SRGB), 0, - t->expected_error); - weston_config_destroy(wc); - - return RESULT_OK; -} diff --git a/tests/color-metadata-parsing-test.c b/tests/color-metadata-parsing-test.c deleted file mode 100644 index 94112e73e..000000000 --- a/tests/color-metadata-parsing-test.c +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright 2022 Collabora, Ltd. - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial - * portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include "config.h" - -#include - -#include "weston-test-client-helper.h" -#include "weston-test-fixture-compositor.h" -#include "weston-test-assert.h" -#include "backend.h" -#include "color.h" - -static enum test_result_code -fixture_setup(struct weston_test_harness *harness) -{ - struct compositor_setup setup; - - compositor_setup_defaults(&setup); - setup.renderer = WESTON_RENDERER_GL; - setup.shell = SHELL_TEST_DESKTOP; - - weston_ini_setup(&setup, - cfgln("[output]"), - cfgln("name=headless"), - cfgln("color_characteristics=my-awesome-color"), - cfgln("colorimetry-mode=bt2020rgb"), - cfgln("eotf-mode=st2084"), - - cfgln("[color_characteristics]"), - cfgln("name=my-awesome-color"), - cfgln("maxFALL=1000"), - cfgln("red_x=0.9999"), - cfgln("red_y=0.3"), - cfgln("blue_x=0.1"), - cfgln("blue_y=0.11"), - cfgln("green_x=0.1771"), - cfgln("green_y=0.80001"), - cfgln("white_x=0.313"), - cfgln("white_y=0.323"), - cfgln("min_L=0.0001"), - cfgln("max_L=65535.0"), - - cfgln("[core]"), - cfgln("color-management=true")); - - return weston_test_harness_execute_as_plugin(harness, &setup); -} -DECLARE_FIXTURE_SETUP(fixture_setup); - -PLUGIN_TEST(color_characteristics_from_weston_ini) -{ - struct weston_output *output = NULL; - struct weston_output *it; - enum weston_eotf_mode mode; - enum weston_colorimetry_mode colorimetry_mode; - const struct weston_color_characteristics *cc; - const struct weston_hdr_metadata_type1 *hdr_meta; - - wl_list_for_each(it, &compositor->output_list, link) { - if (strcmp(it->name, "headless") == 0) { - output = it; - break; - } - } - - test_assert_ptr_not_null(output); - - mode = weston_output_get_eotf_mode(output); - test_assert_enum(mode, WESTON_EOTF_MODE_ST2084); - - colorimetry_mode = weston_output_get_colorimetry_mode(output); - test_assert_enum(colorimetry_mode, WESTON_COLORIMETRY_MODE_BT2020_RGB); - - cc = weston_output_get_color_characteristics(output); - test_assert_enum(cc->group_mask, WESTON_COLOR_CHARACTERISTICS_GROUP_ALL_MASK); - test_assert_f32_eq(cc->primary[0].x, 0.9999f); - test_assert_f32_eq(cc->primary[0].y, 0.3f); - test_assert_f32_eq(cc->primary[1].x, 0.1771f); - test_assert_f32_eq(cc->primary[1].y, 0.80001f); - test_assert_f32_eq(cc->primary[2].x, 0.1f); - test_assert_f32_eq(cc->primary[2].y, 0.11f); - test_assert_f32_eq(cc->white.x, 0.313f); - test_assert_f32_eq(cc->white.y, 0.323f); - test_assert_f32_eq(cc->min_luminance, 0.0001f); - test_assert_f32_eq(cc->max_luminance, 65535.0f); - test_assert_f32_eq(cc->maxFALL, 1000.0f); - - /* The below is color manager policy. */ - hdr_meta = weston_output_get_hdr_metadata_type1(output); - test_assert_enum(hdr_meta->group_mask, WESTON_HDR_METADATA_TYPE1_GROUP_ALL_MASK); - test_assert_f32_eq(hdr_meta->primary[0].x, 0.9999f); - test_assert_f32_eq(hdr_meta->primary[0].y, 0.3f); - test_assert_f32_eq(hdr_meta->primary[1].x, 0.1771f); - test_assert_f32_eq(hdr_meta->primary[1].y, 0.80001f); - test_assert_f32_eq(hdr_meta->primary[2].x, 0.1f); - test_assert_f32_eq(hdr_meta->primary[2].y, 0.11f); - test_assert_f32_eq(hdr_meta->white.x, 0.313f); - test_assert_f32_eq(hdr_meta->white.y, 0.323f); - test_assert_f32_eq(hdr_meta->minDML, 0.0001f); - test_assert_f32_eq(hdr_meta->maxDML, 65535.0f); - test_assert_f32_eq(hdr_meta->maxCLL, 65535.0f); - test_assert_f32_eq(hdr_meta->maxFALL, 1000.0f); - - return RESULT_OK; -} diff --git a/tests/meson.build b/tests/meson.build index 264e56f0a..cca0df0a3 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -20,10 +20,6 @@ tests = [ 'dep_objs': dep_libm, }, { 'name': 'color-effects', }, - { - 'name': 'color-metadata-errors', - 'dep_objs': dep_libexec_weston, - }, { 'name': 'color-output-parsing', 'dep_objs': [ @@ -205,7 +201,6 @@ if get_option('color-management-lcms') color_management_v1_protocol_c, ], }, - { 'name': 'color-metadata-parsing' }, { 'name': 'lcms-util', 'dep_objs': [ dep_lcms_util ]