diff --git a/src/backends/meta-monitor-manager.c b/src/backends/meta-monitor-manager.c index 3a09782a1..19cbb263d 100644 --- a/src/backends/meta-monitor-manager.c +++ b/src/backends/meta-monitor-manager.c @@ -73,6 +73,7 @@ enum PROP_PANEL_ORIENTATION_MANAGED, PROP_HAS_BUILTIN_PANEL, PROP_NIGHT_LIGHT_SUPPORTED, + PROP_EXPERIMENTAL_HDR, PROP_LAST }; @@ -114,6 +115,7 @@ typedef struct _MetaMonitorManagerPrivate gboolean has_builtin_panel; gboolean night_light_supported; + const char *experimental_hdr; } MetaMonitorManagerPrivate; G_DEFINE_TYPE_WITH_PRIVATE (MetaMonitorManager, meta_monitor_manager, @@ -477,6 +479,71 @@ prepare_shutdown (MetaBackend *backend, priv->shutting_down = TRUE; } +static void +ensure_hdr_settings (MetaMonitorManager *manager) +{ + MetaMonitorManagerPrivate *priv = + meta_monitor_manager_get_instance_private (manager); + MetaOutputColorspace color_space; + MetaOutputHdrMetadata hdr_metadata; + GList *l; + + if (g_strcmp0 (priv->experimental_hdr, "on") == 0) + { + color_space = META_OUTPUT_COLORSPACE_BT2020; + hdr_metadata = (MetaOutputHdrMetadata) { + .active = TRUE, + .eotf = META_OUTPUT_HDR_METADATA_EOTF_PQ, + }; + } + else + { + color_space = META_OUTPUT_COLORSPACE_DEFAULT; + hdr_metadata = (MetaOutputHdrMetadata) { + .active = FALSE, + }; + } + + for (l = manager->monitors; l; l = l->next) + { + MetaMonitor *monitor = l->data; + g_autoptr (GError) error = NULL; + + if (!meta_monitor_set_color_space (monitor, color_space, &error)) + { + if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED)) + continue; + + g_warning ("Failed to set color space on monitor %s: %s", + meta_monitor_get_display_name (monitor), error->message); + + meta_monitor_set_color_space (monitor, + META_OUTPUT_COLORSPACE_UNKNOWN, + NULL); + + continue; + } + + if (!meta_monitor_set_hdr_metadata (monitor, &hdr_metadata, &error)) + { + if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED)) + continue; + + g_warning ("Failed to set HDR metadata on monitor %s: %s", + meta_monitor_get_display_name (monitor), error->message); + + meta_monitor_set_color_space (monitor, + META_OUTPUT_COLORSPACE_UNKNOWN, + NULL); + meta_monitor_set_hdr_metadata (monitor, &(MetaOutputHdrMetadata) { + .active = FALSE, + }, NULL); + + continue; + } + } +} + /** * meta_monitor_manager_is_headless: * @manager: A #MetaMonitorManager object @@ -1262,6 +1329,10 @@ meta_monitor_manager_constructed (GObject *object) G_CALLBACK (prepare_shutdown), manager); + g_signal_connect (manager, "notify::experimental-hdr", + G_CALLBACK (ensure_hdr_settings), + NULL); + manager->current_switch_config = META_MONITOR_SWITCH_CONFIG_UNKNOWN; initialize_dbus_interface (manager); @@ -1314,12 +1385,17 @@ meta_monitor_manager_set_property (GObject *object, GParamSpec *pspec) { MetaMonitorManager *manager = META_MONITOR_MANAGER (object); + MetaMonitorManagerPrivate *priv = + meta_monitor_manager_get_instance_private (manager); switch (prop_id) { case PROP_BACKEND: manager->backend = g_value_get_object (value); break; + case PROP_EXPERIMENTAL_HDR: + priv->experimental_hdr = g_value_dup_string (value); + break; case PROP_PANEL_ORIENTATION_MANAGED: case PROP_HAS_BUILTIN_PANEL: case PROP_NIGHT_LIGHT_SUPPORTED: @@ -1352,6 +1428,9 @@ meta_monitor_manager_get_property (GObject *object, case PROP_NIGHT_LIGHT_SUPPORTED: g_value_set_boolean (value, priv->night_light_supported); break; + case PROP_EXPERIMENTAL_HDR: + g_value_set_string (value, priv->experimental_hdr); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } @@ -1454,6 +1533,14 @@ meta_monitor_manager_class_init (MetaMonitorManagerClass *klass) G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS); + obj_props[PROP_EXPERIMENTAL_HDR] = + g_param_spec_string ("experimental-hdr", + "Experimental HDR", + "Experimental HDR settings string", + NULL, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS); + g_object_class_install_properties (object_class, PROP_LAST, obj_props); } @@ -3597,6 +3684,8 @@ meta_monitor_manager_rebuild (MetaMonitorManager *manager, ensure_privacy_screen_settings (manager); + ensure_hdr_settings (manager); + g_list_free_full (old_logical_monitors, g_object_unref); } diff --git a/src/backends/meta-monitor.c b/src/backends/meta-monitor.c index 289d0c620..c1315e84e 100644 --- a/src/backends/meta-monitor.c +++ b/src/backends/meta-monitor.c @@ -2242,3 +2242,63 @@ meta_monitor_set_privacy_screen_enabled (MetaMonitor *monitor, return meta_output_set_privacy_screen_enabled (output, enabled, error); } + +gboolean +meta_monitor_set_color_space (MetaMonitor *monitor, + MetaOutputColorspace color_space, + GError **error) +{ + MetaMonitorPrivate *priv = meta_monitor_get_instance_private (monitor); + GList *l; + + for (l = priv->outputs; l; l = l->next) + { + MetaOutput *output = l->data; + + if (!meta_output_is_color_space_supported (output, color_space)) + { + g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, + "The color space is not supported by this monitor"); + return FALSE; + } + } + + for (l = priv->outputs; l; l = l->next) + { + MetaOutput *output = l->data; + + meta_output_set_color_space (output, color_space); + } + + return TRUE; +} + +gboolean +meta_monitor_set_hdr_metadata (MetaMonitor *monitor, + MetaOutputHdrMetadata *metadata, + GError **error) +{ + MetaMonitorPrivate *priv = meta_monitor_get_instance_private (monitor); + GList *l; + + for (l = priv->outputs; l; l = l->next) + { + MetaOutput *output = l->data; + + if (!meta_output_is_hdr_metadata_supported (output)) + { + g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, + "HDR metadata is not supported by this monitor"); + return FALSE; + } + } + + for (l = priv->outputs; l; l = l->next) + { + MetaOutput *output = l->data; + + meta_output_set_hdr_metadata (output, metadata); + } + + return TRUE; +} diff --git a/src/backends/meta-monitor.h b/src/backends/meta-monitor.h index 3f98a58f6..bccfccbfa 100644 --- a/src/backends/meta-monitor.h +++ b/src/backends/meta-monitor.h @@ -310,4 +310,12 @@ size_t meta_monitor_get_gamma_lut_size (MetaMonitor *monitor); void meta_monitor_set_gamma_lut (MetaMonitor *monitor, const MetaGammaLut *lut); +gboolean meta_monitor_set_color_space (MetaMonitor *monitor, + MetaOutputColorspace color_space, + GError **error); + +gboolean meta_monitor_set_hdr_metadata (MetaMonitor *monitor, + MetaOutputHdrMetadata *metadata, + GError **error); + #endif /* META_MONITOR_H */