weston/libweston/color-profile-param-builder.c

757 lines
25 KiB
C

/*
* Copyright 2024 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 "color.h"
#include "color-properties.h"
#include "shared/helpers.h"
#include "shared/string-helpers.h"
#include "shared/xalloc.h"
#include "shared/weston-assert.h"
/** Enum that helps keep track of what params have been set. */
enum weston_color_profile_params_set {
WESTON_COLOR_PROFILE_PARAMS_PRIMARIES = 0x01,
WESTON_COLOR_PROFILE_PARAMS_TF = 0x02,
WESTON_COLOR_PROFILE_PARAMS_TARGET_PRIMARIES = 0x04,
WESTON_COLOR_PROFILE_PARAMS_LUMINANCE = 0x08,
WESTON_COLOR_PROFILE_PARAMS_MAXCLL = 0x10,
WESTON_COLOR_PROFILE_PARAMS_MAXFALL = 0x20,
};
/** Builder object to create color profiles with parameters. */
struct weston_color_profile_param_builder {
struct weston_compositor *compositor;
struct weston_color_profile_params params;
/*
* Keeps track of what params have already been set.
*
* A bitmask of values from enum weston_color_profile_params_set.
*/
uint32_t group_mask;
/*
* Keeps track of errors.
*
* This API may produce errors, and we store all the error messages in
* the string below to help users to debug. Regarding error codes, we
* store only the first that occurs.
*
* Such errors can be queried with
* weston_color_profile_param_builder_get_error(). They are also
* return'ed when users of the API set all the params and call
* weston_color_profile_param_builder_create_color_profile().
*/
enum weston_color_profile_param_builder_error err;
bool has_errors;
FILE *err_fp;
char *err_msg;
size_t err_msg_size;
};
/**
* Creates struct weston_color_profile_param_builder object. It should be used
* to create color profiles from parameters.
*
* We expect it to be used by our frontend (to allow creating color profiles
* from .ini files or similar) and by the color-management protocol
* implementation (so that clients can create color profiles from parameters).
*
* It is invalid to set the same parameter twice using this object.
*
* After creating the color profile from this object, it will be automatically
* destroyed.
*
* \param compositor The weston compositor.
* \return The struct weston_color_profile_param_builder object created.
*/
struct weston_color_profile_param_builder *
weston_color_profile_param_builder_create(struct weston_compositor *compositor)
{
struct weston_color_profile_param_builder *builder;
builder = xzalloc(sizeof(*builder));
builder->compositor = compositor;
builder->err_fp = open_memstream(&builder->err_msg,
&builder->err_msg_size);
weston_assert_ptr(compositor, builder->err_fp);
return builder;
}
/**
* Destroys a struct weston_color_profile_param_builder object.
*
* \param builder The object that should be destroyed.
*/
void
weston_color_profile_param_builder_destroy(struct weston_color_profile_param_builder *builder)
{
fclose(builder->err_fp);
free(builder->err_msg);
free(builder);
}
static void __attribute__ ((format (printf, 3, 4)))
store_error(struct weston_color_profile_param_builder *builder,
enum weston_color_profile_param_builder_error err,
const char *fmt, ...)
{
va_list ap;
/* First error that we log. We also log the err code in such case. */
if (!builder->has_errors) {
builder->has_errors = true;
builder->err = err;
goto log_msg;
}
/* There are errors already, so add new line first. */
fprintf(builder->err_fp, "\n");
log_msg:
va_start(ap, fmt);
vfprintf(builder->err_fp, fmt, ap);
va_end(ap);
}
/**
* Returns the code for the first error generated and a string with all error
* messages that we caught.
*
* Function weston_color_profile_param_builder_create_color_profile() will also
* fail with the first error code (if there's any), but we still need this
* function because some users of the API may want to know about the error
* immediately after calling a setter.
*
* \param builder The builder object whose parameters will be set.
* \param err Set if there's an error, untouched otherwise. The first error code caught.
* \param err_msg Set if there's an error, untouched otherwise. Must be free()'d
* by the caller. Combination of all error messages caught. Not terminated with
* a new line character.
* \return true if there's an error, false otherwise.
*/
bool
weston_color_profile_param_builder_get_error(struct weston_color_profile_param_builder *builder,
enum weston_color_profile_param_builder_error *err,
char **err_msg)
{
if (!builder->has_errors)
return false;
*err = builder->err;
fflush(builder->err_fp);
*err_msg = strdup(builder->err_msg);
return true;
}
/**
* Sets primaries for struct weston_color_profile_param_builder object.
*
* See also weston_color_profile_param_builder_set_primaries_named(), which is
* another way of setting the primaries.
*
* If the primaries are already set (with this function or the one
* mentioned above), this should fail. Setting a parameter twice is forbidden.
*
* If this fails, users can call weston_color_profile_param_builder_get_error()
* to get the error details.
*
* \param builder The builder object whose parameters will be set.
* \param primaries The object containing the primaries.
* \return true on success, false otherwise.
*/
bool
weston_color_profile_param_builder_set_primaries(struct weston_color_profile_param_builder *builder,
const struct weston_color_gamut *primaries)
{
struct weston_color_manager *cm = builder->compositor->color_manager;
bool success = true;
if (!((cm->supported_color_features >> WESTON_COLOR_FEATURE_SET_PRIMARIES) & 1)) {
store_error(builder, WESTON_COLOR_PROFILE_PARAM_BUILDER_ERROR_INVALID_PRIMARIES,
"set_primaries not supported by the color manager");
success = false;
}
if (builder->group_mask & WESTON_COLOR_PROFILE_PARAMS_PRIMARIES) {
store_error(builder, WESTON_COLOR_PROFILE_PARAM_BUILDER_ERROR_ALREADY_SET,
"primaries were already set");
success = false;
}
if (!success)
return false;
builder->params.primaries = *primaries;
builder->group_mask |= WESTON_COLOR_PROFILE_PARAMS_PRIMARIES;
return true;
}
/**
* Sets primaries for struct weston_color_profile_param_builder object using a
* enum weston_color_primaries.
*
* See also weston_color_profile_param_builder_set_primaries(), which is another
* way of setting the primaries.
*
* If the primaries are already set (with this function or the one mentioned
* above), this should fail. Setting a parameter twice is forbidden.
*
* If this fails, users can call weston_color_profile_param_builder_get_error()
* to get the error details.
*
* \param builder The builder object whose parameters will be set.
* \param primaries The enum representing the primaries.
* \return true on success, false otherwise.
*/
bool
weston_color_profile_param_builder_set_primaries_named(struct weston_color_profile_param_builder *builder,
enum weston_color_primaries primaries)
{
struct weston_compositor *compositor = builder->compositor;
struct weston_color_manager *cm = compositor->color_manager;
bool success = true;
if (!((cm->supported_primaries_named >> primaries) & 1)) {
store_error(builder, WESTON_COLOR_PROFILE_PARAM_BUILDER_ERROR_INVALID_PRIMARIES,
"named primaries %u not supported by the color manager",
primaries);
success = false;
}
if (builder->group_mask & WESTON_COLOR_PROFILE_PARAMS_PRIMARIES) {
store_error(builder, WESTON_COLOR_PROFILE_PARAM_BUILDER_ERROR_ALREADY_SET,
"primaries were already set");
success = false;
}
if (!success)
return false;
builder->params.primaries_info =
weston_color_primaries_info_from(compositor, primaries);
builder->params.primaries = builder->params.primaries_info->color_gamut;
builder->group_mask |= WESTON_COLOR_PROFILE_PARAMS_PRIMARIES;
return true;
}
/**
* Sets transfer function for struct weston_color_profile_param_builder object
* using a enum weston_transfer_function.
*
* See also weston_color_profile_param_builder_set_tf_power_exponent(), which is
* another way of setting the transfer function.
*
* If the transfer function is already set (with this function or the one
* mentioned above), this should fail. Setting a parameter twice is forbidden.
*
* If this fails, users can call weston_color_profile_param_builder_get_error()
* to get the error details.
*
* \param builder The builder object whose parameters will be set.
* \param tf The enum representing the transfer function.
* \return true on success, false otherwise.
*/
bool
weston_color_profile_param_builder_set_tf_named(struct weston_color_profile_param_builder *builder,
enum weston_transfer_function tf)
{
struct weston_compositor *compositor = builder->compositor;
struct weston_color_manager *cm = compositor->color_manager;
bool success = true;
if (!((cm->supported_tf_named >> tf) & 1)) {
store_error(builder, WESTON_COLOR_PROFILE_PARAM_BUILDER_ERROR_INVALID_TF,
"named tf %u not supported by the color manager", tf);
success = false;
}
if (builder->group_mask & WESTON_COLOR_PROFILE_PARAMS_TF) {
store_error(builder, WESTON_COLOR_PROFILE_PARAM_BUILDER_ERROR_ALREADY_SET,
"tf was already set");
success = false;
}
if (!success)
return false;
builder->params.tf_info = weston_color_tf_info_from(compositor, tf);
weston_assert_false(builder->compositor,
builder->params.tf_info->has_parameters);
builder->group_mask |= WESTON_COLOR_PROFILE_PARAMS_TF;
return true;
}
/**
* Sets transfer function for struct weston_color_profile_param_builder object
* using a power law function exponent g. In such case, the transfer function is
* y = x ^ g. The valid range for the given exponent is [1.0, 10.0].
*
* See also weston_color_profile_param_builder_set_tf_named(), which is another
* way of setting the transfer function.
*
* If the transfer function is already set (with this function or the one
* mentioned above), this should fail. Setting a parameter twice is forbidden.
*
* If this fails, users can call weston_color_profile_param_builder_get_error()
* to get the error details.
*
* \param builder The builder object whose parameters will be set.
* \param power_exponent The power law function exponent.
* \return true on success, false otherwise.
*/
bool
weston_color_profile_param_builder_set_tf_power_exponent(struct weston_color_profile_param_builder *builder,
float power_exponent)
{
struct weston_compositor *compositor = builder->compositor;
struct weston_color_manager *cm = compositor->color_manager;
bool success = true;
if (!((cm->supported_color_features >> WESTON_COLOR_FEATURE_SET_TF_POWER) & 1)) {
store_error(builder, WESTON_COLOR_PROFILE_PARAM_BUILDER_ERROR_INVALID_TF,
"set_tf_power not supported by the color manager");
success = false;
}
if (builder->group_mask & WESTON_COLOR_PROFILE_PARAMS_TF) {
store_error(builder, WESTON_COLOR_PROFILE_PARAM_BUILDER_ERROR_ALREADY_SET,
"tf was already set");
success = false;
}
/* The exponent should be at least 1.0 and at most 10.0. */
if (!(power_exponent >= 1.0 && power_exponent <= 10.0)) {
store_error(builder, WESTON_COLOR_PROFILE_PARAM_BUILDER_ERROR_INVALID_TF,
"tf power exponent %f is not in the range [1.0, 10.0]",
power_exponent);
success = false;
}
if (!success)
return false;
builder->params.tf_info = weston_color_tf_info_from(compositor, WESTON_TF_POWER);
builder->params.tf_params[0] = power_exponent;
builder->group_mask |= WESTON_COLOR_PROFILE_PARAMS_TF;
return true;
}
/**
* Sets target primaries for struct weston_color_profile_param_builder object
* using raw values.
*
* If the target primaries are already set, this should fail. Setting a
* parameter twice is forbidden.
*
* If this fails, users can call weston_color_profile_param_builder_get_error()
* to get the error details.
*
* \param builder The builder object whose parameters will be set.
* \param target_primaries The object containing the target primaries.
* \return true on success, false otherwise.
*/
bool
weston_color_profile_param_builder_set_target_primaries(struct weston_color_profile_param_builder *builder,
const struct weston_color_gamut *target_primaries)
{
struct weston_color_manager *cm = builder->compositor->color_manager;
bool success = true;
if (!((cm->supported_color_features >> WESTON_COLOR_FEATURE_SET_MASTERING_DISPLAY_PRIMARIES) & 1)) {
store_error(builder, WESTON_COLOR_PROFILE_PARAM_BUILDER_ERROR_INVALID_TARGET_PRIMARIES,
"set_mastering_display_primaries not supported by " \
"the color manager");
success = false;
}
if (builder->group_mask & WESTON_COLOR_PROFILE_PARAMS_TARGET_PRIMARIES) {
store_error(builder, WESTON_COLOR_PROFILE_PARAM_BUILDER_ERROR_ALREADY_SET,
"target primaries were already set");
success = false;
}
if (!success)
return false;
builder->params.target_primaries = *target_primaries;
builder->group_mask |= WESTON_COLOR_PROFILE_PARAMS_TARGET_PRIMARIES;
return true;
}
/**
* Sets target luminance for struct weston_color_profile_param_builder object.
*
* If the target luminance is already set, this should fail. Setting a parameter
* twice is forbidden.
*
* If this fails, users can call weston_color_profile_param_builder_get_error()
* to get the error details.
*
* \param builder The builder object whose parameters will be set.
* \param min_luminance The minimum luminance.
* \param max_luminance The maximum luminance.
* \return true on success, false otherwise.
*/
bool
weston_color_profile_param_builder_set_target_luminance(struct weston_color_profile_param_builder *builder,
float min_luminance, float max_luminance)
{
bool success = true;
if (builder->group_mask & WESTON_COLOR_PROFILE_PARAMS_LUMINANCE) {
store_error(builder, WESTON_COLOR_PROFILE_PARAM_BUILDER_ERROR_ALREADY_SET,
"target luminance was already set");
success = false;
}
if (min_luminance >= max_luminance) {
store_error(builder, WESTON_COLOR_PROFILE_PARAM_BUILDER_ERROR_INVALID_LUMINANCE,
"min luminance %f shouldn't be greater than or equal to max %f",
min_luminance, max_luminance);
success = false;
}
if (!success)
return false;
builder->params.min_luminance = min_luminance;
builder->params.max_luminance = max_luminance;
builder->group_mask |= WESTON_COLOR_PROFILE_PARAMS_LUMINANCE;
return true;
}
/**
* Sets target maxFALL for struct weston_color_profile_param_builder object.
*
* If the target maxFALL is already set, this should fail. Setting a parameter
* twice is forbidden.
*
* If this fails, users can call weston_color_profile_param_builder_get_error()
* to get the error details.
*
* \param builder The builder object whose parameters will be set.
* \param maxFALL The maxFALL.
* \return true on success, false otherwise.
*/
bool
weston_color_profile_param_builder_set_maxFALL(struct weston_color_profile_param_builder *builder,
float maxFALL)
{
if (builder->group_mask & WESTON_COLOR_PROFILE_PARAMS_MAXFALL) {
store_error(builder, WESTON_COLOR_PROFILE_PARAM_BUILDER_ERROR_ALREADY_SET,
"max fall was already set");
return false;
}
builder->params.maxFALL = maxFALL;
builder->group_mask |= WESTON_COLOR_PROFILE_PARAMS_MAXFALL;
return true;
}
/**
* Sets target maxCLL for struct weston_color_profile_param_builder object.
*
* If the target maxCLL is already set, this should fail. Setting a parameter
* twice is forbidden.
*
* If this fails, users can call weston_color_profile_param_builder_get_error()
* to get the error details.
*
* \param builder The builder object whose parameters will be set.
* \param maxCLL The maxCLL.
* \return true on success, false otherwise.
*/
bool
weston_color_profile_param_builder_set_maxCLL(struct weston_color_profile_param_builder *builder,
float maxCLL)
{
if (builder->group_mask & WESTON_COLOR_PROFILE_PARAMS_MAXCLL) {
store_error(builder, WESTON_COLOR_PROFILE_PARAM_BUILDER_ERROR_ALREADY_SET,
"max cll was already set");
return false;
}
builder->params.maxCLL = maxCLL;
builder->group_mask |= WESTON_COLOR_PROFILE_PARAMS_MAXCLL;
return true;
}
static void
builder_validate_params_set(struct weston_color_profile_param_builder *builder)
{
/* Primaries are mandatory. */
if (!(builder->group_mask & WESTON_COLOR_PROFILE_PARAMS_PRIMARIES))
store_error(builder, WESTON_COLOR_PROFILE_PARAM_BUILDER_ERROR_INCOMPLETE_SET,
"primaries not set");
/* TF is mandatory. */
if (!(builder->group_mask & WESTON_COLOR_PROFILE_PARAMS_TF))
store_error(builder, WESTON_COLOR_PROFILE_PARAM_BUILDER_ERROR_INCOMPLETE_SET,
"transfer function not set");
/* If luminance values were given, tf must be PQ. */
if (builder->params.tf_info->tf != WESTON_TF_ST2084_PQ &&
(builder->group_mask & WESTON_COLOR_PROFILE_PARAMS_LUMINANCE ||
builder->group_mask & WESTON_COLOR_PROFILE_PARAMS_MAXCLL ||
builder->group_mask & WESTON_COLOR_PROFILE_PARAMS_MAXFALL))
store_error(builder, WESTON_COLOR_PROFILE_PARAM_BUILDER_ERROR_INCONSISTENT_SET,
"luminance values were given but transfer function " \
"is not Rec. ITU-R BT.2100-2 (PQ)");
}
static float
triangle_area(float x1, float y1, float x2, float y2, float x3, float y3)
{
/* Based on the shoelace formula, also known as Gauss's area formula. */
return fabs((x1 - x3) * (y2 - y1) - (x1 - x2) * (y3 - y1)) / 2.0f;
}
static bool
is_point_inside_triangle(float point_x, float point_y,
float x1, float y1, float x2, float y2, float x3, float y3)
{
float A1, A2, A3;
float A;
const float PRECISION = 1e-5;
A = triangle_area(x1, y1, x2, y2, x3, y3);
/* Bail out if something that is not a triangle was given. */
if (A <= PRECISION)
return false;
A1 = triangle_area(point_x, point_y, x1, y1, x2, y2);
A2 = triangle_area(point_x, point_y, x1, y1, x3, y3);
A3 = triangle_area(point_x, point_y, x2, y2, x3, y3);
if (fabs(A - (A1 + A2 + A3)) <= PRECISION)
return true;
return false;
}
static void
validate_color_gamut(struct weston_color_profile_param_builder *builder,
const struct weston_color_gamut *gamut,
const char *gamut_name)
{
/*
* We choose the legal range [-1.0, 2.0] for CIE xy values. It is
* probably more than we'd ever need, but tight enough to not cause
* mathematical issues. If wasn't for the ACES AP0 color space, we'd
* probably choose the range [0.0, 1.0].
*/
if (gamut->white_point.x < -1.0f || gamut->white_point.x > 2.0f ||
gamut->white_point.y < -1.0f || gamut->white_point.y > 2.0f ||
gamut->primary[0].x < -1.0f || gamut->primary[0].x > 2.0f ||
gamut->primary[0].y < -1.0f || gamut->primary[0].y > 2.0f ||
gamut->primary[1].x < -1.0f || gamut->primary[1].x > 2.0f ||
gamut->primary[1].y < -1.0f || gamut->primary[1].y > 2.0f ||
gamut->primary[2].x < -1.0f || gamut->primary[2].x > 2.0f ||
gamut->primary[2].y < -1.0f || gamut->primary[2].y > 2.0f) {
store_error(builder, WESTON_COLOR_PROFILE_PARAM_BUILDER_ERROR_CIE_XY_OUT_OF_RANGE,
"invalid %s", gamut_name);
return;
}
/*
* That is not sufficient. There are points inside the triangle that
* would not be valid white points. But for now that's good enough.
*/
if (!is_point_inside_triangle(gamut->white_point.x,
gamut->white_point.y,
gamut->primary[0].x,
gamut->primary[0].y,
gamut->primary[1].x,
gamut->primary[1].y,
gamut->primary[2].x,
gamut->primary[2].y))
store_error(builder, WESTON_COLOR_PROFILE_PARAM_BUILDER_ERROR_CIE_XY_OUT_OF_RANGE,
"white point out of %s volume", gamut_name);
}
static void
validate_maxcll(struct weston_color_profile_param_builder *builder)
{
if (!(builder->group_mask & WESTON_COLOR_PROFILE_PARAMS_LUMINANCE))
return;
if (builder->params.min_luminance >= builder->params.maxCLL)
store_error(builder, WESTON_COLOR_PROFILE_PARAM_BUILDER_ERROR_INCONSISTENT_LUMINANCES,
"maxCLL (%f) should be greater or equal to min luminance (%f)",
builder->params.maxCLL, builder->params.min_luminance);
if (builder->params.max_luminance < builder->params.maxCLL)
store_error(builder, WESTON_COLOR_PROFILE_PARAM_BUILDER_ERROR_INCONSISTENT_LUMINANCES,
"maxCLL (%f) should not be greater than max luminance (%f)",
builder->params.maxCLL, builder->params.max_luminance);
}
static void
validate_maxfall(struct weston_color_profile_param_builder *builder)
{
if (!(builder->group_mask & WESTON_COLOR_PROFILE_PARAMS_LUMINANCE))
return;
if (builder->params.min_luminance >= builder->params.maxFALL)
store_error(builder, WESTON_COLOR_PROFILE_PARAM_BUILDER_ERROR_INCONSISTENT_LUMINANCES,
"maxFALL (%f) should be greater or equal to min luminance (%f)",
builder->params.maxFALL, builder->params.min_luminance);
if (builder->params.max_luminance < builder->params.maxFALL)
store_error(builder, WESTON_COLOR_PROFILE_PARAM_BUILDER_ERROR_INCONSISTENT_LUMINANCES,
"maxFALL (%f) should not be greater than max luminance (%f)",
builder->params.maxFALL, builder->params.max_luminance);
}
static void
builder_validate_params(struct weston_color_profile_param_builder *builder)
{
if (builder->group_mask & WESTON_COLOR_PROFILE_PARAMS_PRIMARIES)
validate_color_gamut(builder, &builder->params.primaries,
"primaries");
if (builder->group_mask & WESTON_COLOR_PROFILE_PARAMS_TARGET_PRIMARIES)
validate_color_gamut(builder, &builder->params.target_primaries,
"target primaries");
if (builder->group_mask & WESTON_COLOR_PROFILE_PARAMS_MAXCLL)
validate_maxcll(builder);
if (builder->group_mask & WESTON_COLOR_PROFILE_PARAMS_MAXFALL)
validate_maxfall(builder);
}
static void
builder_complete_params(struct weston_color_profile_param_builder *builder)
{
/* If no target primaries were set, it matches the primaries. */
if (!(builder->group_mask & WESTON_COLOR_PROFILE_PARAMS_TARGET_PRIMARIES))
builder->params.target_primaries = builder->params.primaries;
/*
* If luminance is not set, set it to negative. Same applies to maxCLL
* and maxFALL.
*/
if (!(builder->group_mask & WESTON_COLOR_PROFILE_PARAMS_LUMINANCE)) {
builder->params.min_luminance = -1.0f;
builder->params.max_luminance = -1.0f;
}
if (!(builder->group_mask & WESTON_COLOR_PROFILE_PARAMS_MAXCLL))
builder->params.maxCLL = -1.0f;
if (!(builder->group_mask & WESTON_COLOR_PROFILE_PARAMS_MAXFALL))
builder->params.maxFALL = -1.0f;
}
/**
* Creates a color profile from a struct weston_color_profile_param_builder
* object.
*
* After creating the weston_color_profile_param_builder and setting the
* appropriate parameters, this function should be called to finally create the
* color profile. It checks if the parameters are consistent and, if so, call
* the color manager to create the color profile.
*
* Also, this is a destructor function. It destroys the builder object.
*
* \param builder The object that has the parameters set.
* \param name_part A string to be used in describing the profile.
* \param err Set if there's an error, untouched otherwise. The first error code caught.
* \param err_msg Set if there's an error, untouched otherwise. Must be free()'d
* by the caller. Combination of all error messages caught. Not terminated with
* a new line character.
* \return The color profile created, or NULL on failure.
*/
struct weston_color_profile *
weston_color_profile_param_builder_create_color_profile(struct weston_color_profile_param_builder *builder,
const char *name_part,
enum weston_color_profile_param_builder_error *err,
char **err_msg)
{
struct weston_color_manager *cm = builder->compositor->color_manager;
struct weston_color_profile_params *params = &builder->params;
struct weston_color_profile *cprof = NULL;
bool ret;
/*
* See struct weston_color_profile_params description. That struct has
* some rules that we need to fullfil (e.g. target primaries must be
* set, even if client does not pass anything). In this function we
* complete the param set in order to fullfil such rules.
*/
builder_complete_params(builder);
/* Ensure that params make sense together. */
builder_validate_params_set(builder);
/* Ensure that each param set is reasonable. */
builder_validate_params(builder);
/* Something went wrong, so error out. */
if (builder->has_errors) {
fflush(builder->err_fp);
*err_msg = strdup(builder->err_msg);
*err = builder->err;
goto out;
}
ret = cm->get_color_profile_from_params(cm, params, name_part,
&cprof, err_msg);
if (!ret)
*err = WESTON_COLOR_PROFILE_PARAM_BUILDER_ERROR_UNSUPPORTED;
out:
weston_color_profile_param_builder_destroy(builder);
return cprof;
}