weston/libweston/color.h

643 lines
20 KiB
C

/*
* Copyright 2021 Collabora, Ltd.
* Copyright 2021 Advanced Micro Devices, Inc.
*
* 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.
*/
#ifndef WESTON_COLOR_H
#define WESTON_COLOR_H
#include <stdbool.h>
#include <stdint.h>
#include <libweston/libweston.h>
#include "backend-drm/drm-kms-enums.h"
enum weston_hdr_metadata_type1_groups {
/** weston_hdr_metadata_type1::primary is set */
WESTON_HDR_METADATA_TYPE1_GROUP_PRIMARIES = 0x01,
/** weston_hdr_metadata_type1::white is set */
WESTON_HDR_METADATA_TYPE1_GROUP_WHITE = 0x02,
/** weston_hdr_metadata_type1::maxDML is set */
WESTON_HDR_METADATA_TYPE1_GROUP_MAXDML = 0x04,
/** weston_hdr_metadata_type1::minDML is set */
WESTON_HDR_METADATA_TYPE1_GROUP_MINDML = 0x08,
/** weston_hdr_metadata_type1::maxCLL is set */
WESTON_HDR_METADATA_TYPE1_GROUP_MAXCLL = 0x10,
/** weston_hdr_metadata_type1::maxFALL is set */
WESTON_HDR_METADATA_TYPE1_GROUP_MAXFALL = 0x20,
/** all valid bits */
WESTON_HDR_METADATA_TYPE1_GROUP_ALL_MASK = 0x3f
};
/** HDR static metadata type 1
*
* The fields are defined by CTA-861-G except here they use float encoding.
*
* In Weston used only with HDR display modes.
*/
struct weston_hdr_metadata_type1 {
/** Which fields are valid
*
* A bitmask of values from enum weston_hdr_metadata_type1_groups.
*/
uint32_t group_mask;
/* EOTF is tracked externally with enum weston_eotf_mode */
/** Chromaticities of the primaries, in any order */
struct weston_CIExy primary[3];
/** White point chromaticity */
struct weston_CIExy white;
/** Maximum display mastering luminance, 1 - 65535 cd/m² */
float maxDML;
/** Minimum display mastering luminance, 0.0001 - 6.5535 cd/m² */
float minDML;
/** Maximum content light level, 1 - 65535 cd/m² */
float maxCLL;
/** Maximum frame-average light level, 1 - 65535 cd/m² */
float maxFALL;
};
/** Output properties derived from its color characteristics and profile
*
* These are constructed by a color manager.
*
* A weston_output_color_outcome owns (a reference to) everything it contains.
*
* \ingroup output
* \internal
*/
struct weston_output_color_outcome {
/** sRGB to output color space transformation */
struct weston_color_transform *from_sRGB_to_output;
/** sRGB to blending color space transformation */
struct weston_color_transform *from_sRGB_to_blend;
/** Blending to output color space transformation */
struct weston_color_transform *from_blend_to_output;
/** HDR Static Metadata Type 1 for WESTON_EOTF_MODE_ST2084 */
struct weston_hdr_metadata_type1 hdr_meta;
};
/**
* Represents a color profile description (an ICC color profile)
*
* Sub-classed by the color manager that created this.
*/
struct weston_color_profile {
struct weston_color_manager *cm;
int ref_count;
char *description;
/* Unique id to be used by the CM&HDR protocol extension. */
uint32_t id;
};
/** Parameters that define a parametric color profile */
struct weston_color_profile_params {
/* Primary color volume; always set. */
struct weston_color_gamut primaries;
/* Primary color volume by enumeration; optional, may be NULL. */
const struct weston_color_primaries_info *primaries_info;
/* Encoding transfer characteristic by enumeration; always set. */
const struct weston_color_tf_info *tf_info;
/* Transfer characteristic's parameters; depends on tf_info. */
float tf_params[10];
/* Target color volume; always set. */
struct weston_color_gamut target_primaries;
/* Luminance parameters cd/m²; negative when not set */
float min_luminance, max_luminance;
float maxCLL;
float maxFALL;
};
/** Type or formula for a curve */
enum weston_color_curve_type {
/** Identity function, no-op */
WESTON_COLOR_CURVE_TYPE_IDENTITY = 0,
/** Three-channel, one-dimensional look-up table */
WESTON_COLOR_CURVE_TYPE_LUT_3x1D,
/** Transfer function named LINPOW
*
* y = (a * x + b) ^ g | x >= d
* y = c * x | 0 <= x < d
*
* We gave it the name LINPOW because the first operation with the input
* x is a linear one, and then the result is raised to g.
*
* As all parametric curves, this one should be represented using struct
* weston_color_curve_parametric. For each color channel RGB we may have
* different params, see weston_color_curve_parametric::params.
*
* For LINPOW, the params g, a, b, c, and d are respectively
* params[channel][0], ... , params[channel][4].
*
* The input for all color channels may be clamped to [0.0, 1.0]. In
* such case, weston_color_curve_parametric::clamped_input is true.
* If the input is not clamped and LINPOW needs to evaluate a negative
* input value, it uses mirroring (i.e. -f(-x)).
*/
WESTON_COLOR_CURVE_TYPE_LINPOW,
/** Transfer function named POWLIN
*
* y = (a * (x ^ g)) + b | x >= d
* y = c * x | 0 <= x < d
*
* We gave it the name POWLIN because the first operation with the input
* x is an exponential one, and then the result is multiplied by a.
*
* As all parametric curves, this one should be represented using struct
* weston_color_curve_parametric. For each color channel RGB we may have
* different params, see weston_color_curve_parametric::params.
*
* For POWLIN, the params g, a, b, c, and d are respectively
* params[channel][0], ... , params[channel][4].
*
* The input for all color channels may be clamped to [0.0, 1.0]. In
* such case, weston_color_curve_parametric::clamped_input is true.
* If the input is not clamped and POWLIN needs to evaluate a negative
* input value, it uses mirroring (i.e. -f(-x)).
*/
WESTON_COLOR_CURVE_TYPE_POWLIN,
};
/** LUT_3x1D parameters */
struct weston_color_curve_lut_3x1d {
/**
* Approximate a color curve with three 1D LUTs
*
* A 1D LUT is a mapping from [0.0, 1.0] to arbitrary values. The first
* element in the LUT corresponds to input value 0.0, and the last
* element corresponds to input value 1.0. The step from one element
* to the next in input space is 1.0 / (len - 1). When input value is
* between two elements, linear interpolation should be used.
*
* This function fills in the given array with the LUT values.
*
* \param xform This color transformation object.
* \param len The number of elements in each 1D LUT.
* \param values Array of 3 x len elements. First R channel
* LUT, immediately followed by G channel LUT, and then B channel LUT.
*/
void
(*fill_in)(struct weston_color_transform *xform,
float *values, unsigned len);
/** Optimal 1D LUT length for storage vs. precision */
unsigned optimal_len;
};
/** Parametric color curve parameters */
struct weston_color_curve_parametric {
/* For each color channel we may have different curves. For each of
* them, we can have up to 10 params, depending on the curve type. The
* channels are in RGB order. */
float params[3][10];
/* The input of the curve should be clamped from 0.0 to 1.0? */
bool clamped_input;
};
/**
* A scalar function for color encoding and decoding
*
* This object can represent a one-dimensional function that is applied
* independently to each of the color channels. Depending on the type and
* parameterization of the curve, all color channels may use the
* same function or each may have separate parameters.
*
* This is usually used for EOTF or EOTF^-1 and to optimize a 3D LUT size
* without sacrificing precision, both in one step.
*/
struct weston_color_curve {
/** Which member of 'u' defines the curve. */
enum weston_color_curve_type type;
/** Parameters for the curve. */
union {
/* identity: no parameters */
struct weston_color_curve_lut_3x1d lut_3x1d;
struct weston_color_curve_parametric parametric;
} u;
};
/** Type or formula for a color mapping */
enum weston_color_mapping_type {
/** Identity function, no-op */
WESTON_COLOR_MAPPING_TYPE_IDENTITY = 0,
/** 3D-dimensional look-up table */
WESTON_COLOR_MAPPING_TYPE_3D_LUT,
/** matrix */
WESTON_COLOR_MAPPING_TYPE_MATRIX,
};
/**
* A three-dimensional look-up table
*
* A 3D LUT is a three-dimensional array where each element is an RGB triplet.
* A 3D LUT is usually an approximation of some arbitrary color mapping
* function that cannot be represented in any simpler form. The array contains
* samples from the approximated function, and values between samples are
* estimated by interpolation. The array is accessed with three indices, one
* for each input dimension (color channel).
*
* Color channel values in the range [0.0, 1.0] are mapped linearly to
* 3D LUT indices such that 0.0 maps exactly to the first element and 1.0 maps
* exactly to the last element in each dimension.
*
* This object represents a 3D LUT and offers an interface for realizing it
* as a data array with a custom size.
*/
struct weston_color_mapping_3dlut {
/**
* Create a 3D LUT data array
*
* \param xform This color transformation object.
* \param values Memory to hold the resulting data array.
* \param len The number of elements in each dimension.
*
* The array \c values must be at least 3 * len * len * len elements
* in size.
*
* Given the red index ri, green index gi and blue index bi, the
* corresponding array element index
*
* i = 3 * (len * len * bi + len * gi + ri) + c
*
* where
*
* c = 0 for red output value,
* c = 1 for green output value, and
* c = 2 for blue output value
*/
void
(*fill_in)(struct weston_color_transform *xform,
float *values, unsigned len);
/** Optimal 3D LUT size along each dimension */
unsigned optimal_len;
};
/**
* A 3x3 matrix and data is arranged as column major
*/
struct weston_color_mapping_matrix {
float matrix[9];
};
/**
* Color mapping function
*
* This object can represent a 3D LUT to do a color space conversion
*
*/
struct weston_color_mapping {
/** Which member of 'u' defines the color mapping type */
enum weston_color_mapping_type type;
/** Parameters for the color mapping function */
union {
/* identity: no parameters */
struct weston_color_mapping_3dlut lut3d;
struct weston_color_mapping_matrix mat;
} u;
};
/**
* Describes a color transformation formula
*
* Guaranteed unique, de-duplicated.
*
* Sub-classed by the color manager that created this.
*
* For a renderer to support WESTON_CAP_COLOR_OPS it must implement everything
* that this structure can represent.
*/
struct weston_color_transform {
struct weston_color_manager *cm;
int ref_count;
uint32_t id; /* For debug */
/* for renderer or backend to attach their own cached objects */
struct wl_signal destroy_signal;
/* Color transform is the series of steps: */
/** Step 1: color model change */
/* YCbCr→RGB conversion, but that is done elsewhere */
/** Step 2: color curve before color mapping */
struct weston_color_curve pre_curve;
/** Step 3: color mapping */
struct weston_color_mapping mapping;
/** Step 4: color curve after color mapping */
struct weston_color_curve post_curve;
};
/**
* How content color needs to be transformed
*
* This object is specific to the color properties of the weston_surface and
* weston_output it was created for. It is automatically destroyed if any
* relevant color properties change.
*
* Fundamentally this contains the color transformation from content color
* space to an output's blending color space. This is stored in field
* 'transform' with NULL value corresponding to identity transformation.
*
* For graphics pipeline optimization purposes, the field 'identity_pipeline'
* indicates whether the combination of 'transform' here and the output's
* blending color space to monitor color space transformation total to
* identity transformation. This helps detecting cases where renderer bypass
* (direct scanout) is possible.
*/
struct weston_surface_color_transform {
/** Transformation from source to blending space */
struct weston_color_transform *transform;
/** True, if source colorspace is identical to monitor color space */
bool identity_pipeline;
};
struct cm_image_desc_info;
struct weston_color_manager {
/** Identifies this CMS component */
const char *name;
/** This compositor instance */
struct weston_compositor *compositor;
/** Supports the Wayland CM&HDR protocol extension? */
bool supports_client_protocol;
/**
* Supported color features from Wayland CM&HDR protocol extension.
*
* If v (v being enum weston_color_feature v) is a supported color
* feature, the bit v of this will be set to 1.
*/
uint32_t supported_color_features;
/**
* Supported rendering intents from Wayland CM&HDR protocol extension.
*
* If v (v being enum weston_render_intent v) is a supported rendering
* intent, the bit v of this will be set to 1.
*/
uint32_t supported_rendering_intents;
/**
* Supported primaries named from Wayland CM&HDR protocol extension.
*
* If v (v being enum weston_color_primaries v) is a supported
* primaries named, the bit v of this will be set to 1.
*/
uint32_t supported_primaries_named;
/**
* Supported tf named from Wayland CM&HDR protocol extension.
*
* If v (v being enum weston_transfer_function v) is a supported
* tf named, the bit v of this will be set to 1.
*/
uint32_t supported_tf_named;
/** Initialize color manager */
bool
(*init)(struct weston_color_manager *cm);
/** Destroy color manager */
void
(*destroy)(struct weston_color_manager *cm);
/** Destroy a color profile after refcount fell to zero */
void
(*destroy_color_profile)(struct weston_color_profile *cprof);
/** Gets a new reference to the stock sRGB color profile
*
* \param cm The color manager.
* \return A new reference to the stock sRGB profile, never returns NULL.
*/
struct weston_color_profile *
(*ref_stock_sRGB_color_profile)(struct weston_color_manager *cm);
/** Create a color profile from ICC data
*
* \param cm The color manager.
* \param icc_data Pointer to the ICC binary data.
* \param icc_len Length of the ICC data in bytes.
* \param name_part A string to be used in describing the profile.
* \param cprof_out On success, the created object is returned here.
* On failure, untouched.
* \param errmsg On success, untouched. On failure, a pointer to a
* string describing the error is stored here. The string must be
* free()'d.
* \return True on success, false on failure.
*
* This may return a new reference to an existing color profile if
* that profile is identical to the one that would be created, apart
* from name_part.
*/
bool
(*get_color_profile_from_icc)(struct weston_color_manager *cm,
const void *icc_data,
size_t icc_len,
const char *name_part,
struct weston_color_profile **cprof_out,
char **errmsg);
/** Create a color profile from parameters
*
* \param cm The color manager.
* \param params The struct weston_color_profile_params with the params.
* \param name_part A string to be used in describing the profile.
* \param cprof_out On success, the created object is returned here.
* On failure, untouched.
* \param errmsg On success, untouched. On failure, a pointer to a
* string describing the error is stored here. The string must be
* free()'d.
* \return True on success, false on failure.
*
* This may return a new reference to an existing color profile if
* that profile is identical to the one that would be created, apart
* from name_part.
*/
bool
(*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);
/** Send image description to clients.
*
* \param cm_image_desc_info The image description info object
* \param cprof_base The color profile that backs the image description
* \return True on success, false on failure
*
* This should be used only by the CM&HDR protocol extension
* implementation.
*
* The color manager implementing this function should use the helpers
* from color-management.c (weston_cm_send_primaries(), etc) to send the
* information to clients.
*/
bool
(*send_image_desc_info)(struct cm_image_desc_info *cm_image_desc_info,
struct weston_color_profile *cprof_base);
/** Destroy a color transform after refcount fell to zero */
void
(*destroy_color_transform)(struct weston_color_transform *xform);
/** Get surface to output's blending space transformation
*
* \param cm The color manager.
* \param surface The surface for the source color space.
* \param output The output for the destination blending color space.
* \param surf_xform For storing the color transformation and
* additional information.
*
* The callee is responsible for increasing the reference count on the
* weston_color_transform it stores into surf_xform.
*/
bool
(*get_surface_color_transform)(struct weston_color_manager *cm,
struct weston_surface *surface,
struct weston_output *output,
struct weston_surface_color_transform *surf_xform);
/** Compute derived color properties for an output
*
* \param cm The color manager.
* \param output The output.
* \return A new color_outcome object on success, NULL on failure.
*
* The callee (color manager) must inspect the weston_output (color
* profile, EOTF mode, etc.) and create a fully populated
* weston_output_color_outcome object.
*/
struct weston_output_color_outcome *
(*create_output_color_outcome)(struct weston_color_manager *cm,
struct weston_output *output);
};
void
weston_color_profile_init(struct weston_color_profile *cprof,
struct weston_color_manager *cm);
struct weston_color_transform *
weston_color_transform_ref(struct weston_color_transform *xform);
void
weston_color_transform_unref(struct weston_color_transform *xform);
void
weston_color_transform_init(struct weston_color_transform *xform,
struct weston_color_manager *cm);
char *
weston_color_transform_string(const struct weston_color_transform *xform);
void
weston_surface_color_transform_copy(struct weston_surface_color_transform *dst,
const struct weston_surface_color_transform *src);
void
weston_surface_color_transform_fini(struct weston_surface_color_transform *surf_xform);
struct weston_paint_node;
void
weston_paint_node_ensure_color_transform(struct weston_paint_node *pnode);
struct weston_color_manager *
weston_color_manager_noop_create(struct weston_compositor *compositor);
/* DSO module entrypoint */
struct weston_color_manager *
weston_color_manager_create(struct weston_compositor *compositor);
const char *
weston_eotf_mode_to_str(enum weston_eotf_mode e);
char *
weston_eotf_mask_to_str(uint32_t eotf_mask);
struct weston_colorimetry_mode_info {
/** Primary key: the colorimetry mode */
enum weston_colorimetry_mode mode;
/** Its name as a string for logging. */
const char *name;
/** wdrm equivalent, or WDRM_COLORSPACE__COUNT if none */
enum wdrm_colorspace wdrm;
};
const struct weston_colorimetry_mode_info *
weston_colorimetry_mode_info_get(enum weston_colorimetry_mode c);
const struct weston_colorimetry_mode_info *
weston_colorimetry_mode_info_get_by_wdrm(enum wdrm_colorspace cs);
const char *
weston_colorimetry_mode_to_str(enum weston_colorimetry_mode c);
char *
weston_colorimetry_mask_to_str(uint32_t colorimetry_mask);
void
weston_output_color_outcome_destroy(struct weston_output_color_outcome **pco);
#endif /* WESTON_COLOR_H */