1
0
Fork 0

color-device: Apply HDR and colorspace calibration

The color device now updates the white point via a LUT and sets the
colorspace and HDR metadata properties on monitors to get into the
required configuration.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3904>
This commit is contained in:
Sebastian Wick 2024-07-25 17:01:09 +02:00
parent dc6632f19b
commit e3afa1a1d1
2 changed files with 135 additions and 133 deletions

View file

@ -29,6 +29,7 @@
#include "backends/meta-color-profile.h"
#include "backends/meta-color-store.h"
#include "backends/meta-monitor.h"
#include "core/meta-debug-control-private.h"
#define EFI_PANEL_COLOR_INFO_PATH \
"/sys/firmware/efi/efivars/INTERNAL_PANEL_COLOR_INFO-01e1ada1-79f2-46b3-8d3e-71fc0996ca6b"
@ -1348,6 +1349,127 @@ meta_color_device_get_assigned_profile (MetaColorDevice *color_device)
return color_device->assigned_profile;
}
static void
set_color_space_and_hdr_metadata (MetaMonitor *monitor,
gboolean enable,
MetaOutputColorspace *color_space,
MetaOutputHdrMetadata *hdr_metadata)
{
MetaBackend *backend = meta_monitor_get_backend (monitor);
ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend);
CoglContext *cogl_context = clutter_backend_get_cogl_context (clutter_backend);
if (enable &&
!cogl_context_has_feature (cogl_context, COGL_FEATURE_ID_TEXTURE_HALF_FLOAT))
{
g_warning ("Tried to enable HDR without half float rendering support, ignoring");
enable = FALSE;
}
if (enable)
{
*color_space = META_OUTPUT_COLORSPACE_BT2020;
*hdr_metadata = (MetaOutputHdrMetadata) {
.active = TRUE,
.eotf = META_OUTPUT_HDR_METADATA_EOTF_PQ,
};
meta_topic (META_DEBUG_COLOR,
"ColorDevice: Trying to enabling HDR mode "
"(Colorimetry: bt.2020, TF: PQ, HDR Metadata: Minimal):");
}
else
{
*color_space = META_OUTPUT_COLORSPACE_DEFAULT;
*hdr_metadata = (MetaOutputHdrMetadata) {
.active = FALSE,
};
meta_topic (META_DEBUG_COLOR,
"ColorDevice: Trying to enable default mode "
"(Colorimetry: default, TF: default, HDR Metadata: None):");
}
}
static UpdateResult
update_hdr (MetaColorDevice *color_device)
{
MetaMonitor *monitor = color_device->monitor;
MetaBackend *backend = meta_monitor_get_backend (monitor);
MetaContext *context = meta_backend_get_context (backend);
MetaDebugControl *debug_control = meta_context_get_debug_control (context);
MetaOutputColorspace color_space;
MetaOutputHdrMetadata hdr_metadata;
gboolean hdr_enabled;
g_autoptr (GError) error = NULL;
hdr_enabled = meta_debug_control_is_hdr_enabled (debug_control);
set_color_space_and_hdr_metadata (monitor, hdr_enabled,
&color_space, &hdr_metadata);
if (meta_monitor_get_color_space (monitor) == color_space &&
meta_output_hdr_metadata_equal (meta_monitor_get_hdr_metadata (monitor),
&hdr_metadata))
return 0;
if (!meta_monitor_set_color_space (monitor, color_space, &error))
{
meta_monitor_set_color_space (monitor,
META_OUTPUT_COLORSPACE_DEFAULT,
NULL);
meta_monitor_set_hdr_metadata (monitor, &(MetaOutputHdrMetadata) {
.active = FALSE,
}, NULL);
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED))
{
meta_topic (META_DEBUG_COLOR,
"ColorDevice: Colorimetry not supported "
"on monitor %s",
meta_monitor_get_display_name (monitor));
}
else
{
g_warning ("Failed to set color space on monitor %s: %s",
meta_monitor_get_display_name (monitor), error->message);
}
return 0;
}
if (!meta_monitor_set_hdr_metadata (monitor, &hdr_metadata, &error))
{
meta_monitor_set_color_space (monitor,
META_OUTPUT_COLORSPACE_DEFAULT,
NULL);
meta_monitor_set_hdr_metadata (monitor, &(MetaOutputHdrMetadata) {
.active = FALSE,
}, NULL);
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED))
{
meta_topic (META_DEBUG_COLOR,
"ColorDevice: HDR Metadata not supported "
"on monitor %s",
meta_monitor_get_display_name (monitor));
}
else
{
g_warning ("Failed to set HDR metadata on monitor %s: %s",
meta_monitor_get_display_name (monitor),
error->message);
}
return 0;
}
meta_topic (META_DEBUG_COLOR,
"ColorDevice: successfully set on monitor %s",
meta_monitor_get_display_name (monitor));
return UPDATE_RESULT_CALIBRATION;
}
static UpdateResult
update_white_point (MetaColorDevice *color_device)
{
@ -1414,6 +1536,7 @@ meta_color_device_update (MetaColorDevice *color_device)
if (!meta_monitor_is_active (monitor))
return;
result |= update_hdr (color_device);
result |= update_white_point (color_device);
result |= update_color_state (color_device);

View file

@ -55,7 +55,6 @@
#include "backends/meta-output.h"
#include "backends/meta-virtual-monitor.h"
#include "clutter/clutter.h"
#include "core/meta-debug-control-private.h"
#include "core/util-private.h"
#include "meta/main.h"
#include "meta/meta-enum-types.h"
@ -489,125 +488,6 @@ prepare_shutdown (MetaBackend *backend,
g_clear_handle_id (&priv->reload_monitor_manager_id, g_source_remove);
}
static void
set_color_space_and_hdr_metadata (MetaMonitorManager *manager,
gboolean enable,
MetaOutputColorspace *color_space,
MetaOutputHdrMetadata *hdr_metadata)
{
MetaBackend *backend = meta_monitor_manager_get_backend (manager);
ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend);
CoglContext *cogl_context = clutter_backend_get_cogl_context (clutter_backend);
if (enable &&
!cogl_context_has_feature (cogl_context, COGL_FEATURE_ID_TEXTURE_HALF_FLOAT))
{
g_warning ("Tried to enable HDR without half float rendering support, ignoring");
enable = FALSE;
}
if (enable)
{
*color_space = META_OUTPUT_COLORSPACE_BT2020;
*hdr_metadata = (MetaOutputHdrMetadata) {
.active = TRUE,
.eotf = META_OUTPUT_HDR_METADATA_EOTF_PQ,
};
meta_topic (META_DEBUG_COLOR,
"MonitorManager: Trying to enabling HDR mode "
"(Colorimetry: bt.2020, TF: PQ, HDR Metadata: Minimal):");
}
else
{
*color_space = META_OUTPUT_COLORSPACE_DEFAULT;
*hdr_metadata = (MetaOutputHdrMetadata) {
.active = FALSE,
};
meta_topic (META_DEBUG_COLOR,
"MonitorManager: Trying to enable default mode "
"(Colorimetry: default, TF: default, HDR Metadata: None):");
}
}
static void
ensure_hdr_settings (MetaMonitorManager *manager)
{
MetaBackend *backend = manager->backend;
MetaContext *context = meta_backend_get_context (backend);
MetaDebugControl *debug_control = meta_context_get_debug_control (context);
MetaOutputColorspace color_space;
MetaOutputHdrMetadata hdr_metadata;
GList *l;
set_color_space_and_hdr_metadata (manager,
meta_debug_control_is_hdr_enabled (debug_control),
&color_space,
&hdr_metadata);
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))
{
meta_monitor_set_color_space (monitor,
META_OUTPUT_COLORSPACE_DEFAULT,
NULL);
meta_monitor_set_hdr_metadata (monitor, &(MetaOutputHdrMetadata) {
.active = FALSE,
}, NULL);
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED))
{
meta_topic (META_DEBUG_COLOR,
"MonitorManager: Colorimetry not supported "
"on monitor %s",
meta_monitor_get_display_name (monitor));
}
else
{
g_warning ("Failed to set color space on monitor %s: %s",
meta_monitor_get_display_name (monitor), error->message);
}
continue;
}
if (!meta_monitor_set_hdr_metadata (monitor, &hdr_metadata, &error))
{
meta_monitor_set_color_space (monitor,
META_OUTPUT_COLORSPACE_DEFAULT,
NULL);
meta_monitor_set_hdr_metadata (monitor, &(MetaOutputHdrMetadata) {
.active = FALSE,
}, NULL);
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED))
{
meta_topic (META_DEBUG_COLOR,
"MonitorManager: HDR Metadata not supported "
"on monitor %s",
meta_monitor_get_display_name (monitor));
}
else
{
g_warning ("Failed to set HDR metadata on monitor %s: %s",
meta_monitor_get_display_name (monitor),
error->message);
}
continue;
}
meta_topic (META_DEBUG_COLOR,
"MonitorManager: successfully set on monitor %s",
meta_monitor_get_display_name (monitor));
}
}
/**
* meta_monitor_manager_is_headless:
* @manager: A #MetaMonitorManager object
@ -1323,6 +1203,17 @@ update_night_light_supported (MetaMonitorManager *manager)
night_light_supported);
}
static void
meta_monitor_manager_notify_monitors_changed (MetaMonitorManager *manager)
{
meta_backend_monitors_changed (manager->backend);
g_signal_emit (manager, signals[MONITORS_CHANGED_INTERNAL], 0);
g_signal_emit (manager, signals[MONITORS_CHANGED], 0);
meta_dbus_display_config_emit_monitors_changed (manager->display_config);
}
void
meta_monitor_manager_setup (MetaMonitorManager *manager)
{
@ -1350,7 +1241,7 @@ meta_monitor_manager_setup (MetaMonitorManager *manager)
if (privacy_screen_needs_update (manager))
manager->privacy_screen_change_state = META_PRIVACY_SCREEN_CHANGE_STATE_INIT;
ensure_hdr_settings (manager);
meta_monitor_manager_notify_monitors_changed (manager);
manager->in_init = FALSE;
}
@ -3688,17 +3579,6 @@ meta_monitor_manager_read_current_state (MetaMonitorManager *manager)
manager_class->read_current_state (manager);
}
static void
meta_monitor_manager_notify_monitors_changed (MetaMonitorManager *manager)
{
meta_backend_monitors_changed (manager->backend);
g_signal_emit (manager, signals[MONITORS_CHANGED_INTERNAL], 0);
g_signal_emit (manager, signals[MONITORS_CHANGED], 0);
meta_dbus_display_config_emit_monitors_changed (manager->display_config);
}
static void
set_logical_monitor_modes (MetaMonitorManager *manager,
MetaLogicalMonitorConfig *logical_monitor_config)
@ -3780,7 +3660,6 @@ meta_monitor_manager_rebuild (MetaMonitorManager *manager,
meta_monitor_manager_update_logical_state (manager, config);
ensure_privacy_screen_settings (manager);
ensure_hdr_settings (manager);
meta_monitor_manager_notify_monitors_changed (manager);