You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
weston/libweston/color.h

264 lines
8.8 KiB

libweston: introduce CMS component architecture See: https://gitlab.freedesktop.org/wayland/weston/-/issues/467#note_814985 This starts building the framework required for implementing color management. The main new interface is struct weston_color_manager. This commit also adds a no-op color manager implementation, which is used if no other color manager is loaded. This no-op color manager simply provides identity color transforms for everything, so that Weston keeps running exactly like before. weston_color_manager interface is incomplete and will be extended later. Colorspace objects are not introduced in this commit. However, when client content colorspace and output colorspace definitions are combined, they will produce color transformations from client content to output blending space and from output blending space to output space. This commit introduces a placeholder struct for color transforms, weston_color_transform. Objects of this type are expected to be heavy to create and store, which is why they are designed to be shared as much as possible, ideally making their instances unique. As color transform description is intended to be generic in libweston core, renderers and backends are expected to derive their own state for each transform object as necessary. Creating and storing the derived state maybe be expensive as well, more the reason to re-use these objects as much as possible. E.g. GL-renderer might upload a 3D LUT into a texture and keep the texture around. DRM-backend might create a KMS blob for a LUT and keep that around. As a color transform depends on both the surface and the output, a transform object may need to be created for each unique pair of them. Therefore color transforms are referenced from weston_paint_node. As paint nodes exist for not just surface+output but surface+view+output triplets, the code ensures that all paint nodes (having different view) for the same surface+output have the same color transform state. As a special case, if weston_color_transform is NULL, it means identity transform. This short-circuits some checks and memory allocations, but it does mean we use a separate member on weston_paint_node to know if the color transform has been initialized or not. Color transformations are pre-created at the weston_output paint_node_z_order_list creation step. Currently the z order lists contain all views globally, which means we populate color transforms we may never need, e.g. a view is never shown on a particular output. This problem should get fixed naturally when z order lists are constructed "pruned" in the future: to contain only those paint nodes that actually contribute to the output's image. As nothing actually supports color transforms yet, both renderers and the DRM-backend assert that they only get identity transforms. This check has the side-effect that all surface-output pairs actually get a weston_surface_color_transform_ref even though it points to NULL weston_color_transform. This design is inspired by Sebastian Wick's Weston color management work. Co-authored-by: Sebastian Wick <sebastian@sebastianwick.net> Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
4 years ago
/*
* Copyright 2021 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.
*/
#ifndef WESTON_COLOR_H
#define WESTON_COLOR_H
#include <stdbool.h>
#include <libweston/libweston.h>
/** 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,
};
/** 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;
libweston: introduce CMS component architecture See: https://gitlab.freedesktop.org/wayland/weston/-/issues/467#note_814985 This starts building the framework required for implementing color management. The main new interface is struct weston_color_manager. This commit also adds a no-op color manager implementation, which is used if no other color manager is loaded. This no-op color manager simply provides identity color transforms for everything, so that Weston keeps running exactly like before. weston_color_manager interface is incomplete and will be extended later. Colorspace objects are not introduced in this commit. However, when client content colorspace and output colorspace definitions are combined, they will produce color transformations from client content to output blending space and from output blending space to output space. This commit introduces a placeholder struct for color transforms, weston_color_transform. Objects of this type are expected to be heavy to create and store, which is why they are designed to be shared as much as possible, ideally making their instances unique. As color transform description is intended to be generic in libweston core, renderers and backends are expected to derive their own state for each transform object as necessary. Creating and storing the derived state maybe be expensive as well, more the reason to re-use these objects as much as possible. E.g. GL-renderer might upload a 3D LUT into a texture and keep the texture around. DRM-backend might create a KMS blob for a LUT and keep that around. As a color transform depends on both the surface and the output, a transform object may need to be created for each unique pair of them. Therefore color transforms are referenced from weston_paint_node. As paint nodes exist for not just surface+output but surface+view+output triplets, the code ensures that all paint nodes (having different view) for the same surface+output have the same color transform state. As a special case, if weston_color_transform is NULL, it means identity transform. This short-circuits some checks and memory allocations, but it does mean we use a separate member on weston_paint_node to know if the color transform has been initialized or not. Color transformations are pre-created at the weston_output paint_node_z_order_list creation step. Currently the z order lists contain all views globally, which means we populate color transforms we may never need, e.g. a view is never shown on a particular output. This problem should get fixed naturally when z order lists are constructed "pruned" in the future: to contain only those paint nodes that actually contribute to the output's image. As nothing actually supports color transforms yet, both renderers and the DRM-backend assert that they only get identity transforms. This check has the side-effect that all surface-output pairs actually get a weston_surface_color_transform_ref even though it points to NULL weston_color_transform. This design is inspired by Sebastian Wick's Weston color management work. Co-authored-by: Sebastian Wick <sebastian@sebastianwick.net> Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
4 years ago
};
/**
* 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;
} 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;
/* 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 */
/* TBD: e.g. a 3D LUT or a matrix */
/** 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 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;
/** Initialize color manager */
bool
(*init)(struct weston_color_manager *cm);
/** Destroy color manager */
void
(*destroy)(struct weston_color_manager *cm);
/** 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);
/** Get output's blending space to output transformation
*
* \param cm The color manager.
* \param output The output for the destination color space.
* \param xform_out Pointer for storing the weston_color_transform.
* \return True on success, false on failure.
*
* The callee is responsible for increasing the reference count on the
* weston_color_transform it stores via xform_out. On failure, xform_out
* is untouched.
*/
bool
(*get_output_color_transform)(struct weston_color_manager *cm,
struct weston_output *output,
struct weston_color_transform **xform_out);
/** Get sRGB to output transformation
*
* \param cm The color manager.
* \param output The output for the destination color space.
* \param xform_out Pointer for storing the weston_color_transform.
* \return True on success, false on failure.
*
* The callee is responsible for increasing the reference count on the
* weston_color_transform it stores via xform_out. On failure, xform_out
* is untouched.
*/
bool
(*get_sRGB_to_output_color_transform)(struct weston_color_manager *cm,
struct weston_output *output,
struct weston_color_transform **xform_out);
/** Get sRGB to output's blending space transformation
*
* \param cm The color manager.
* \param output The output for the destination blending color space.
* \param xform_out Pointer for storing the weston_color_transform.
* \return True on success, false on failure.
*
* The callee is responsible for increasing the reference count on the
* weston_color_transform it stores via xform_out. On failure, xform_out
* is untouched.
*/
bool
(*get_sRGB_to_blend_color_transform)(struct weston_color_manager *cm,
struct weston_output *output,
struct weston_color_transform **xform_out);
libweston: introduce CMS component architecture See: https://gitlab.freedesktop.org/wayland/weston/-/issues/467#note_814985 This starts building the framework required for implementing color management. The main new interface is struct weston_color_manager. This commit also adds a no-op color manager implementation, which is used if no other color manager is loaded. This no-op color manager simply provides identity color transforms for everything, so that Weston keeps running exactly like before. weston_color_manager interface is incomplete and will be extended later. Colorspace objects are not introduced in this commit. However, when client content colorspace and output colorspace definitions are combined, they will produce color transformations from client content to output blending space and from output blending space to output space. This commit introduces a placeholder struct for color transforms, weston_color_transform. Objects of this type are expected to be heavy to create and store, which is why they are designed to be shared as much as possible, ideally making their instances unique. As color transform description is intended to be generic in libweston core, renderers and backends are expected to derive their own state for each transform object as necessary. Creating and storing the derived state maybe be expensive as well, more the reason to re-use these objects as much as possible. E.g. GL-renderer might upload a 3D LUT into a texture and keep the texture around. DRM-backend might create a KMS blob for a LUT and keep that around. As a color transform depends on both the surface and the output, a transform object may need to be created for each unique pair of them. Therefore color transforms are referenced from weston_paint_node. As paint nodes exist for not just surface+output but surface+view+output triplets, the code ensures that all paint nodes (having different view) for the same surface+output have the same color transform state. As a special case, if weston_color_transform is NULL, it means identity transform. This short-circuits some checks and memory allocations, but it does mean we use a separate member on weston_paint_node to know if the color transform has been initialized or not. Color transformations are pre-created at the weston_output paint_node_z_order_list creation step. Currently the z order lists contain all views globally, which means we populate color transforms we may never need, e.g. a view is never shown on a particular output. This problem should get fixed naturally when z order lists are constructed "pruned" in the future: to contain only those paint nodes that actually contribute to the output's image. As nothing actually supports color transforms yet, both renderers and the DRM-backend assert that they only get identity transforms. This check has the side-effect that all surface-output pairs actually get a weston_surface_color_transform_ref even though it points to NULL weston_color_transform. This design is inspired by Sebastian Wick's Weston color management work. Co-authored-by: Sebastian Wick <sebastian@sebastianwick.net> Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
4 years ago
};
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);
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);
libweston: introduce CMS component architecture See: https://gitlab.freedesktop.org/wayland/weston/-/issues/467#note_814985 This starts building the framework required for implementing color management. The main new interface is struct weston_color_manager. This commit also adds a no-op color manager implementation, which is used if no other color manager is loaded. This no-op color manager simply provides identity color transforms for everything, so that Weston keeps running exactly like before. weston_color_manager interface is incomplete and will be extended later. Colorspace objects are not introduced in this commit. However, when client content colorspace and output colorspace definitions are combined, they will produce color transformations from client content to output blending space and from output blending space to output space. This commit introduces a placeholder struct for color transforms, weston_color_transform. Objects of this type are expected to be heavy to create and store, which is why they are designed to be shared as much as possible, ideally making their instances unique. As color transform description is intended to be generic in libweston core, renderers and backends are expected to derive their own state for each transform object as necessary. Creating and storing the derived state maybe be expensive as well, more the reason to re-use these objects as much as possible. E.g. GL-renderer might upload a 3D LUT into a texture and keep the texture around. DRM-backend might create a KMS blob for a LUT and keep that around. As a color transform depends on both the surface and the output, a transform object may need to be created for each unique pair of them. Therefore color transforms are referenced from weston_paint_node. As paint nodes exist for not just surface+output but surface+view+output triplets, the code ensures that all paint nodes (having different view) for the same surface+output have the same color transform state. As a special case, if weston_color_transform is NULL, it means identity transform. This short-circuits some checks and memory allocations, but it does mean we use a separate member on weston_paint_node to know if the color transform has been initialized or not. Color transformations are pre-created at the weston_output paint_node_z_order_list creation step. Currently the z order lists contain all views globally, which means we populate color transforms we may never need, e.g. a view is never shown on a particular output. This problem should get fixed naturally when z order lists are constructed "pruned" in the future: to contain only those paint nodes that actually contribute to the output's image. As nothing actually supports color transforms yet, both renderers and the DRM-backend assert that they only get identity transforms. This check has the side-effect that all surface-output pairs actually get a weston_surface_color_transform_ref even though it points to NULL weston_color_transform. This design is inspired by Sebastian Wick's Weston color management work. Co-authored-by: Sebastian Wick <sebastian@sebastianwick.net> Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
4 years ago
#endif /* WESTON_COLOR_H */