Merge branch 'mr/parametric-srgb' into 'main'

Switch the default sRGB profile from ICC to parametric

See merge request wayland/weston!1954
This commit is contained in:
Pekka Paalanen 2026-03-20 11:11:17 +02:00
commit c427e4d258
12 changed files with 297 additions and 215 deletions

View file

@ -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)

View file

@ -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);
}

View file

@ -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)
{

View file

@ -429,19 +429,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 +514,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 +522,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 +539,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);

View file

@ -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

View file

@ -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 *

View file

@ -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

View file

@ -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.
*/

View file

@ -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 */

View file

@ -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:

View file

@ -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);

View file

@ -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));