output: Add color space and HDR metadata

The color space and HDR metadata are eventually sent as metadata to the
display. The color space informs the display of the colorimetry of the
frames we produce, the HDR metadata informs the display of the transfer
function and additional mastering display colorimetry and luminance to
guide tone and gamut mapping.

The only color spaces we support right now are the default color space
and Rec bt.2020 which is typically used for HDR content. Other supported
color spaces can be added when needed.

The default color space corresponds to whatever colorimetry the display
has when no further changes are made to the calibration of the display.
The colorimetry is communicated to sources via EDID/DisplayID.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2879>
This commit is contained in:
Sebastian Wick 2023-03-02 01:32:38 +01:00 committed by Marge Bot
parent 47fcb52435
commit fad0efa687
2 changed files with 142 additions and 0 deletions

View File

@ -38,6 +38,16 @@ enum
static GParamSpec *obj_props[N_PROPS];
enum
{
COLOR_SPACE_CHANGED,
HDR_METADATA_CHANGED,
N_SIGNALS
};
static guint signals[N_SIGNALS];
typedef struct _MetaOutputPrivate
{
uint64_t id;
@ -63,6 +73,9 @@ typedef struct _MetaOutputPrivate
MetaPrivacyScreenState privacy_screen_state;
gboolean is_privacy_screen_enabled;
MetaOutputHdrMetadata hdr_metadata;
MetaOutputColorspace color_space;
} MetaOutputPrivate;
G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (MetaOutput, meta_output, G_TYPE_OBJECT)
@ -515,12 +528,76 @@ meta_output_set_privacy_screen_enabled (MetaOutput *output,
return TRUE;
}
gboolean
meta_output_is_color_space_supported (MetaOutput *output,
MetaOutputColorspace color_space)
{
MetaOutputClass *output_class = META_OUTPUT_GET_CLASS (output);
uint64_t supported = 0;
if (output_class->get_supported_color_spaces)
supported = output_class->get_supported_color_spaces (output);
return supported & (1 << color_space);
}
void
meta_output_set_color_space (MetaOutput *output,
MetaOutputColorspace color_space)
{
MetaOutputPrivate *priv = meta_output_get_instance_private (output);
priv->color_space = color_space;
g_signal_emit (output, signals[COLOR_SPACE_CHANGED], 0);
}
MetaOutputColorspace
meta_output_peek_color_space (MetaOutput *output)
{
MetaOutputPrivate *priv = meta_output_get_instance_private (output);
return priv->color_space;
}
gboolean
meta_output_is_hdr_metadata_supported (MetaOutput *output)
{
MetaOutputClass *output_class = META_OUTPUT_GET_CLASS (output);
if (!output_class->is_hdr_metadata_supported)
return FALSE;
return output_class->is_hdr_metadata_supported (output);
}
void
meta_output_set_hdr_metadata (MetaOutput *output,
MetaOutputHdrMetadata *metadata)
{
MetaOutputPrivate *priv = meta_output_get_instance_private (output);
priv->hdr_metadata = *metadata;
g_signal_emit (output, signals[HDR_METADATA_CHANGED], 0);
}
MetaOutputHdrMetadata *
meta_output_peek_hdr_metadata (MetaOutput *output)
{
MetaOutputPrivate *priv = meta_output_get_instance_private (output);
return &priv->hdr_metadata;
}
static void
meta_output_init (MetaOutput *output)
{
MetaOutputPrivate *priv = meta_output_get_instance_private (output);
priv->backlight = -1;
priv->color_space = META_OUTPUT_COLORSPACE_UNKNOWN;
priv->hdr_metadata.active = FALSE;
}
static void
@ -565,6 +642,21 @@ meta_output_class_init (MetaOutputClass *klass)
G_PARAM_READWRITE |
G_PARAM_STATIC_STRINGS);
g_object_class_install_properties (object_class, N_PROPS, obj_props);
signals[COLOR_SPACE_CHANGED] =
g_signal_new ("color-space-changed",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
0,
NULL, NULL, NULL,
G_TYPE_NONE, 0);
signals[HDR_METADATA_CHANGED] =
g_signal_new ("hdr-metadata-changed",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
0,
NULL, NULL, NULL,
G_TYPE_NONE, 0);
}
gboolean

View File

@ -28,6 +28,39 @@
#include "backends/meta-gpu.h"
#include "core/util-private.h"
typedef enum _MetaOutputColorspace
{
META_OUTPUT_COLORSPACE_UNKNOWN = 0,
META_OUTPUT_COLORSPACE_DEFAULT,
META_OUTPUT_COLORSPACE_BT2020,
} MetaOutputColorspace;
typedef enum
{
META_OUTPUT_HDR_METADATA_EOTF_TRADITIONAL_GAMMA_SDR,
META_OUTPUT_HDR_METADATA_EOTF_TRADITIONAL_GAMMA_HDR,
META_OUTPUT_HDR_METADATA_EOTF_PQ,
META_OUTPUT_HDR_METADATA_EOTF_HLG,
} MetaOutputHdrMetadataEOTF;
typedef struct _MetaOutputHdrMetadata
{
gboolean active;
MetaOutputHdrMetadataEOTF eotf;
struct {
double x;
double y;
} mastering_display_primaries[3];
struct {
double x;
double y;
} mastering_display_white_point;
double mastering_display_max_luminance;
double mastering_display_min_luminance;
double max_cll;
double max_fall;
} MetaOutputHdrMetadata;
struct _MetaTileInfo
{
uint32_t group_id;
@ -165,6 +198,8 @@ struct _MetaOutputClass
gboolean (* set_privacy_screen_enabled) (MetaOutput *output,
gboolean enabled,
GError **error);
uint64_t (* get_supported_color_spaces) (MetaOutput *output);
gboolean (* is_hdr_metadata_supported) (MetaOutput *output);
};
META_EXPORT_TEST
@ -211,6 +246,21 @@ gboolean meta_output_set_privacy_screen_enabled (MetaOutput *output,
gboolean enabled,
GError **error);
gboolean meta_output_is_color_space_supported (MetaOutput *output,
MetaOutputColorspace color_space);
void meta_output_set_color_space (MetaOutput *output,
MetaOutputColorspace color_space);
MetaOutputColorspace meta_output_peek_color_space (MetaOutput *output);
gboolean meta_output_is_hdr_metadata_supported (MetaOutput *output);
void meta_output_set_hdr_metadata (MetaOutput *output,
MetaOutputHdrMetadata *metadata);
MetaOutputHdrMetadata * meta_output_peek_hdr_metadata (MetaOutput *output);
void meta_output_add_possible_clone (MetaOutput *output,
MetaOutput *possible_clone);