From fad0efa687e560a4d104a4537fe5d287d72e18f7 Mon Sep 17 00:00:00 2001 From: Sebastian Wick Date: Thu, 2 Mar 2023 01:32:38 +0100 Subject: [PATCH] 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: --- src/backends/meta-output.c | 92 ++++++++++++++++++++++++++++++++++++++ src/backends/meta-output.h | 50 +++++++++++++++++++++ 2 files changed, 142 insertions(+) diff --git a/src/backends/meta-output.c b/src/backends/meta-output.c index b687a456a..0db3242d9 100644 --- a/src/backends/meta-output.c +++ b/src/backends/meta-output.c @@ -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 diff --git a/src/backends/meta-output.h b/src/backends/meta-output.h index 5fb81e443..e4f20475b 100644 --- a/src/backends/meta-output.h +++ b/src/backends/meta-output.h @@ -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);