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