monitor-manager: Make color space and HDR metadata accessible from lg

This adds a new 'experimental-hdr' string property to the MonitorManager
which can be changed from looking glass.

Currently when the string equals 'on', HDR (PQ, Rec2020) will be enabled
on all monitors which support it. In the future support for more
transfer functions and color spaces as well as HDR metadata can be
added.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2879>
This commit is contained in:
Sebastian Wick 2023-03-02 01:35:10 +01:00 committed by Marge Bot
parent fad0efa687
commit 48e759c443
3 changed files with 157 additions and 0 deletions

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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 */