color: introduce API to create color profile from parameters
Add API to create color profiles from parameters. It is a public API that should be used by the frontend and also by the color management protocol implementation. Currently our protocol implementation does not support clients that want to create color profiles from parameters, and this is a step towards supporting that. As warned in "color: add get_color_profile_from_params() to color managers", we still do not fully support creating color profiles from parameters. This just creates a boilerplate color profile that we're planning to extend later. Signed-off-by: Leandro Ribeiro <leandro.ribeiro@collabora.com>
This commit is contained in:
parent
141f466a03
commit
2c44a4ea4a
@ -73,6 +73,7 @@ struct weston_point2d_device_normalized {
|
||||
double y;
|
||||
};
|
||||
|
||||
struct weston_compositor;
|
||||
struct weston_surface;
|
||||
struct weston_buffer;
|
||||
struct shell_surface;
|
||||
@ -84,6 +85,7 @@ struct linux_dmabuf_buffer;
|
||||
struct weston_recorder;
|
||||
struct weston_pointer_constraint;
|
||||
struct ro_anonymous_file;
|
||||
struct weston_color_profile_param_builder;
|
||||
struct weston_color_profile;
|
||||
struct weston_color_transform;
|
||||
struct pixel_format_info;
|
||||
@ -350,6 +352,69 @@ enum weston_transfer_function {
|
||||
WESTON_TF_POWER,
|
||||
};
|
||||
|
||||
/** Error codes that the color profile parameters functions may return. */
|
||||
enum weston_color_profile_param_builder_error {
|
||||
WESTON_COLOR_PROFILE_PARAM_BUILDER_ERROR_INVALID_TF = 0,
|
||||
WESTON_COLOR_PROFILE_PARAM_BUILDER_ERROR_INVALID_PRIMARIES,
|
||||
WESTON_COLOR_PROFILE_PARAM_BUILDER_ERROR_INVALID_TARGET_PRIMARIES,
|
||||
WESTON_COLOR_PROFILE_PARAM_BUILDER_ERROR_CIE_XY_OUT_OF_RANGE,
|
||||
WESTON_COLOR_PROFILE_PARAM_BUILDER_ERROR_INVALID_LUMINANCE,
|
||||
WESTON_COLOR_PROFILE_PARAM_BUILDER_ERROR_INCONSISTENT_LUMINANCES,
|
||||
WESTON_COLOR_PROFILE_PARAM_BUILDER_ERROR_INCONSISTENT_SET,
|
||||
WESTON_COLOR_PROFILE_PARAM_BUILDER_ERROR_INCOMPLETE_SET,
|
||||
WESTON_COLOR_PROFILE_PARAM_BUILDER_ERROR_ALREADY_SET,
|
||||
WESTON_COLOR_PROFILE_PARAM_BUILDER_ERROR_UNSUPPORTED,
|
||||
};
|
||||
|
||||
struct weston_color_profile_param_builder *
|
||||
weston_color_profile_param_builder_create(struct weston_compositor *compositor);
|
||||
|
||||
void
|
||||
weston_color_profile_param_builder_destroy(struct weston_color_profile_param_builder *builder);
|
||||
|
||||
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);
|
||||
|
||||
bool
|
||||
weston_color_profile_param_builder_set_primaries(struct weston_color_profile_param_builder *builder,
|
||||
const struct weston_color_gamut *primaries);
|
||||
|
||||
bool
|
||||
weston_color_profile_param_builder_set_primaries_named(struct weston_color_profile_param_builder *builder,
|
||||
enum weston_color_primaries primaries);
|
||||
|
||||
bool
|
||||
weston_color_profile_param_builder_set_tf_named(struct weston_color_profile_param_builder *builder,
|
||||
enum weston_transfer_function tf);
|
||||
|
||||
bool
|
||||
weston_color_profile_param_builder_set_tf_power_exponent(struct weston_color_profile_param_builder *builder,
|
||||
float power_exponent);
|
||||
|
||||
bool
|
||||
weston_color_profile_param_builder_set_target_primaries(struct weston_color_profile_param_builder *builder,
|
||||
const struct weston_color_gamut *target_primaries);
|
||||
|
||||
bool
|
||||
weston_color_profile_param_builder_set_target_luminance(struct weston_color_profile_param_builder *builder,
|
||||
float min_luminance, float max_luminance);
|
||||
|
||||
bool
|
||||
weston_color_profile_param_builder_set_maxFALL(struct weston_color_profile_param_builder *builder,
|
||||
float maxFALL);
|
||||
|
||||
bool
|
||||
weston_color_profile_param_builder_set_maxCLL(struct weston_color_profile_param_builder *builder,
|
||||
float maxCLL);
|
||||
|
||||
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);
|
||||
|
||||
enum weston_color_characteristics_groups {
|
||||
/** weston_color_characteristics::primary is set */
|
||||
WESTON_COLOR_CHARACTERISTICS_GROUP_PRIMARIES = 0x01,
|
||||
|
756
libweston/color-profile-param-builder.c
Normal file
756
libweston/color-profile-param-builder.c
Normal file
@ -0,0 +1,756 @@
|
||||
/*
|
||||
* 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;
|
||||
}
|
@ -18,6 +18,7 @@ srcs_libweston = [
|
||||
'color-properties.c',
|
||||
'color-management.c',
|
||||
'color-noop.c',
|
||||
'color-profile-param-builder.c',
|
||||
'compositor.c',
|
||||
'content-protection.c',
|
||||
'data-device.c',
|
||||
|
Loading…
Reference in New Issue
Block a user