color-device: Pass calibration state separately when creating profile
This allows using two separate ICC profiles for one "color profile", which is necessary to properly support color transform calibration profiles from an EFI variable. These types of profiles are intended to be applied using the color transformation matrix (CTM) property on the output, which makes the presented output match sRGB. In order to avoid color profile aware clients making the wrong assumption, we must set the profile exposed externally to be what is the expected perceived result, i.e. sRGB, while still applying CTM from the real ICC profile. The separation is done by introducing a MetaColorCalibration struct, that is filled with relevant data. For profiles coming from EFI, a created profile is practically an sRGB one, but the calibration data comes from EFI, while for other profiles, the calibration data and the ICC profile itself come from the same source. Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2568>
This commit is contained in:
parent
5b251bd8a7
commit
9aa9cacb3d
@ -612,6 +612,8 @@ typedef struct
|
||||
char *file_path;
|
||||
GBytes *bytes;
|
||||
CdIcc *cd_icc;
|
||||
|
||||
MetaColorCalibration *color_calibration;
|
||||
} GenerateProfileData;
|
||||
|
||||
static void
|
||||
@ -620,6 +622,7 @@ generate_profile_data_free (GenerateProfileData *data)
|
||||
g_free (data->file_path);
|
||||
g_clear_object (&data->cd_icc);
|
||||
g_clear_pointer (&data->bytes, g_bytes_unref);
|
||||
g_clear_pointer (&data->color_calibration, meta_color_calibration_free);
|
||||
g_free (data);
|
||||
}
|
||||
|
||||
@ -655,7 +658,8 @@ on_profile_written (GObject *source_object,
|
||||
color_profile =
|
||||
meta_color_profile_new_from_icc (color_manager,
|
||||
g_steal_pointer (&data->cd_icc),
|
||||
g_steal_pointer (&data->bytes));
|
||||
g_steal_pointer (&data->bytes),
|
||||
g_steal_pointer (&data->color_calibration));
|
||||
g_task_return_pointer (task, color_profile, g_object_unref);
|
||||
}
|
||||
|
||||
@ -939,6 +943,8 @@ create_device_profile_from_edid (MetaColorDevice *color_device,
|
||||
cd_icc_add_metadata (cd_icc, CD_PROFILE_METADATA_FILE_CHECKSUM,
|
||||
file_md5_checksum);
|
||||
|
||||
data->color_calibration =
|
||||
meta_color_calibration_new (cd_icc, NULL);
|
||||
data->cd_icc = g_steal_pointer (&cd_icc);
|
||||
data->bytes = bytes;
|
||||
save_icc_profile (file_path, task);
|
||||
@ -951,6 +957,16 @@ create_device_profile_from_edid (MetaColorDevice *color_device,
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
set_icc_checksum (CdIcc *cd_icc,
|
||||
GBytes *bytes)
|
||||
{
|
||||
g_autofree char *md5_checksum = NULL;
|
||||
|
||||
md5_checksum = g_compute_checksum_for_bytes (G_CHECKSUM_MD5, bytes);
|
||||
cd_icc_add_metadata (cd_icc, CD_PROFILE_METADATA_FILE_CHECKSUM, md5_checksum);
|
||||
}
|
||||
|
||||
static void
|
||||
on_efi_panel_color_info_loaded (GObject *source_object,
|
||||
GAsyncResult *res,
|
||||
@ -970,37 +986,75 @@ on_efi_panel_color_info_loaded (GObject *source_object,
|
||||
NULL,
|
||||
&error))
|
||||
{
|
||||
g_autoptr (CdIcc) cd_icc = NULL;
|
||||
g_autoptr (CdIcc) calibration_cd_icc = NULL;
|
||||
g_autoptr (CdIcc) srgb_cd_icc = NULL;
|
||||
|
||||
meta_topic (META_DEBUG_COLOR,
|
||||
"Generating ICC profile for '%s' from EFI variable",
|
||||
meta_color_device_get_id (color_device));
|
||||
|
||||
cd_icc = cd_icc_new ();
|
||||
if (cd_icc_load_data (cd_icc,
|
||||
srgb_cd_icc = cd_icc_new ();
|
||||
if (!cd_icc_create_default_full (srgb_cd_icc,
|
||||
CD_ICC_LOAD_FLAGS_PRIMARIES,
|
||||
&error))
|
||||
{
|
||||
g_warning ("Failed to generate sRGB profile: %s",
|
||||
error->message);
|
||||
goto out;
|
||||
}
|
||||
|
||||
calibration_cd_icc = cd_icc_new ();
|
||||
if (cd_icc_load_data (calibration_cd_icc,
|
||||
(uint8_t *) contents,
|
||||
length,
|
||||
CD_ICC_LOAD_FLAGS_METADATA,
|
||||
(CD_ICC_LOAD_FLAGS_METADATA |
|
||||
CD_ICC_LOAD_FLAGS_PRIMARIES),
|
||||
&error))
|
||||
{
|
||||
GenerateProfileData *data = g_task_get_task_data (task);
|
||||
const char *file_path = data->file_path;
|
||||
g_autofree char *file_md5_checksum = NULL;
|
||||
GBytes *bytes;
|
||||
g_autoptr (GBytes) calibration_bytes = NULL;
|
||||
g_autoptr (GBytes) srgb_bytes = NULL;
|
||||
CdMat3x3 csc;
|
||||
|
||||
bytes = g_bytes_new_take (g_steal_pointer (&contents), length);
|
||||
srgb_bytes = cd_icc_save_data (srgb_cd_icc,
|
||||
CD_ICC_SAVE_FLAGS_NONE,
|
||||
&error);
|
||||
if (!srgb_bytes)
|
||||
{
|
||||
g_warning ("Failed to save sRGB profile: %s",
|
||||
error->message);
|
||||
goto out;
|
||||
}
|
||||
|
||||
calibration_bytes = g_bytes_new_take (g_steal_pointer (&contents), length);
|
||||
|
||||
/* Set metadata needed by colord */
|
||||
cd_icc_add_metadata (cd_icc, CD_PROFILE_PROPERTY_FILENAME,
|
||||
|
||||
cd_icc_add_metadata (calibration_cd_icc, CD_PROFILE_PROPERTY_FILENAME,
|
||||
"/dev/null");
|
||||
set_icc_checksum (calibration_cd_icc, calibration_bytes);
|
||||
|
||||
cd_icc_add_metadata (srgb_cd_icc, CD_PROFILE_PROPERTY_FILENAME,
|
||||
file_path);
|
||||
cd_icc_add_metadata (srgb_cd_icc, CD_PROFILE_PROPERTY_TITLE,
|
||||
"Factory calibrated (sRGB)");
|
||||
set_icc_checksum (srgb_cd_icc, srgb_bytes);
|
||||
|
||||
file_md5_checksum = g_compute_checksum_for_bytes (G_CHECKSUM_MD5,
|
||||
bytes);
|
||||
cd_icc_add_metadata (cd_icc, CD_PROFILE_METADATA_FILE_CHECKSUM,
|
||||
file_md5_checksum);
|
||||
if (!cd_icc_utils_get_adaptation_matrix (calibration_cd_icc,
|
||||
srgb_cd_icc,
|
||||
&csc,
|
||||
&error))
|
||||
{
|
||||
g_warning ("Failed to calculate adaption matrix: %s",
|
||||
error->message);
|
||||
goto out;
|
||||
}
|
||||
|
||||
data->cd_icc = g_steal_pointer (&cd_icc);
|
||||
data->bytes = bytes;
|
||||
data->color_calibration =
|
||||
meta_color_calibration_new (calibration_cd_icc, &csc);
|
||||
data->cd_icc = g_steal_pointer (&srgb_cd_icc);
|
||||
data->bytes = g_steal_pointer (&srgb_bytes);
|
||||
save_icc_profile (file_path, g_steal_pointer (&task));
|
||||
return;
|
||||
}
|
||||
@ -1022,6 +1076,7 @@ on_efi_panel_color_info_loaded (GObject *source_object,
|
||||
g_warning ("Failed to read EFI panel color info: %s", error->message);
|
||||
}
|
||||
|
||||
out:
|
||||
create_device_profile_from_edid (color_device, g_steal_pointer (&task));
|
||||
}
|
||||
|
||||
|
@ -24,7 +24,6 @@
|
||||
|
||||
#include <colord.h>
|
||||
#include <gio/gio.h>
|
||||
#include <lcms2.h>
|
||||
|
||||
#include "backends/meta-color-manager-private.h"
|
||||
|
||||
@ -45,6 +44,7 @@ struct _MetaColorProfile
|
||||
|
||||
CdIcc *cd_icc;
|
||||
GBytes *bytes;
|
||||
MetaColorCalibration *calibration;
|
||||
|
||||
char *cd_profile_id;
|
||||
gboolean is_owner;
|
||||
@ -146,6 +146,7 @@ meta_color_profile_finalize (GObject *object)
|
||||
g_clear_object (&color_profile->cd_icc);
|
||||
g_clear_pointer (&color_profile->bytes, g_bytes_unref);
|
||||
g_clear_object (&color_profile->cd_profile);
|
||||
g_clear_pointer (&color_profile->calibration, meta_color_calibration_free);
|
||||
|
||||
G_OBJECT_CLASS (meta_color_profile_parent_class)->finalize (object);
|
||||
}
|
||||
@ -263,9 +264,10 @@ create_cd_profile (MetaColorProfile *color_profile,
|
||||
}
|
||||
|
||||
MetaColorProfile *
|
||||
meta_color_profile_new_from_icc (MetaColorManager *color_manager,
|
||||
CdIcc *cd_icc,
|
||||
GBytes *raw_bytes)
|
||||
meta_color_profile_new_from_icc (MetaColorManager *color_manager,
|
||||
CdIcc *cd_icc,
|
||||
GBytes *raw_bytes,
|
||||
MetaColorCalibration *color_calibration)
|
||||
{
|
||||
MetaColorProfile *color_profile;
|
||||
const char *checksum;
|
||||
@ -277,6 +279,7 @@ meta_color_profile_new_from_icc (MetaColorManager *color_manager,
|
||||
color_profile->color_manager = color_manager;
|
||||
color_profile->cd_icc = cd_icc;
|
||||
color_profile->bytes = raw_bytes;
|
||||
color_profile->calibration = color_calibration;
|
||||
color_profile->cancellable = g_cancellable_new ();
|
||||
color_profile->is_owner = TRUE;
|
||||
|
||||
@ -300,10 +303,11 @@ notify_ready_idle (gpointer user_data)
|
||||
}
|
||||
|
||||
MetaColorProfile *
|
||||
meta_color_profile_new_from_cd_profile (MetaColorManager *color_manager,
|
||||
CdProfile *cd_profile,
|
||||
CdIcc *cd_icc,
|
||||
GBytes *raw_bytes)
|
||||
meta_color_profile_new_from_cd_profile (MetaColorManager *color_manager,
|
||||
CdProfile *cd_profile,
|
||||
CdIcc *cd_icc,
|
||||
GBytes *raw_bytes,
|
||||
MetaColorCalibration *color_calibration)
|
||||
{
|
||||
MetaColorProfile *color_profile;
|
||||
const char *checksum;
|
||||
@ -312,6 +316,7 @@ meta_color_profile_new_from_cd_profile (MetaColorManager *color_manager,
|
||||
color_profile->color_manager = color_manager;
|
||||
color_profile->cd_icc = cd_icc;
|
||||
color_profile->bytes = raw_bytes;
|
||||
color_profile->calibration = color_calibration;
|
||||
color_profile->cancellable = g_cancellable_new ();
|
||||
color_profile->is_owner = FALSE;
|
||||
|
||||
@ -378,8 +383,7 @@ meta_color_profile_get_file_path (MetaColorProfile *color_profile)
|
||||
const char *
|
||||
meta_color_profile_get_brightness_profile (MetaColorProfile *color_profile)
|
||||
{
|
||||
return cd_profile_get_metadata_item (color_profile->cd_profile,
|
||||
CD_PROFILE_METADATA_SCREEN_BRIGHTNESS);
|
||||
return color_profile->calibration->brightness_profile;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -405,10 +409,10 @@ set_blackbody_color_for_temperature (CdColorRGB *blackbody_color,
|
||||
}
|
||||
|
||||
static MetaGammaLut *
|
||||
generate_gamma_lut_from_vcgt (MetaColorProfile *color_profile,
|
||||
const cmsToneCurve **vcgt,
|
||||
unsigned int temperature,
|
||||
size_t lut_size)
|
||||
generate_gamma_lut_from_vcgt (MetaColorProfile *color_profile,
|
||||
cmsToneCurve **vcgt,
|
||||
unsigned int temperature,
|
||||
size_t lut_size)
|
||||
{
|
||||
CdColorRGB blackbody_color;
|
||||
MetaGammaLut *lut;
|
||||
@ -484,17 +488,12 @@ meta_color_profile_generate_gamma_lut (MetaColorProfile *color_profile,
|
||||
unsigned int temperature,
|
||||
size_t lut_size)
|
||||
{
|
||||
cmsHPROFILE lcms_profile;
|
||||
const cmsToneCurve **vcgt;
|
||||
|
||||
g_return_val_if_fail (lut_size > 0, NULL);
|
||||
|
||||
lcms_profile = cd_icc_get_handle (color_profile->cd_icc);
|
||||
vcgt = cmsReadTag (lcms_profile, cmsSigVcgtTag);
|
||||
|
||||
if (vcgt && *vcgt)
|
||||
if (color_profile->calibration->has_vcgt)
|
||||
{
|
||||
return generate_gamma_lut_from_vcgt (color_profile, vcgt,
|
||||
return generate_gamma_lut_from_vcgt (color_profile,
|
||||
color_profile->calibration->vcgt,
|
||||
temperature, lut_size);
|
||||
}
|
||||
else
|
||||
@ -502,3 +501,52 @@ meta_color_profile_generate_gamma_lut (MetaColorProfile *color_profile,
|
||||
return generate_gamma_lut (color_profile, temperature, lut_size);
|
||||
}
|
||||
}
|
||||
|
||||
const MetaColorCalibration *
|
||||
meta_color_profile_get_calibration (MetaColorProfile *color_profile)
|
||||
{
|
||||
return color_profile->calibration;
|
||||
}
|
||||
|
||||
MetaColorCalibration *
|
||||
meta_color_calibration_new (CdIcc *cd_icc,
|
||||
const CdMat3x3 *adaptation_matrix)
|
||||
{
|
||||
MetaColorCalibration *color_calibration;
|
||||
cmsHPROFILE lcms_profile;
|
||||
const cmsToneCurve **vcgt;
|
||||
const char *brightness_profile;
|
||||
|
||||
color_calibration = g_new0 (MetaColorCalibration, 1);
|
||||
|
||||
lcms_profile = cd_icc_get_handle (cd_icc);
|
||||
vcgt = cmsReadTag (lcms_profile, cmsSigVcgtTag);
|
||||
if (vcgt && vcgt[0])
|
||||
{
|
||||
color_calibration->has_vcgt = TRUE;
|
||||
color_calibration->vcgt[0] = cmsDupToneCurve (vcgt[0]);
|
||||
color_calibration->vcgt[1] = cmsDupToneCurve (vcgt[1]);
|
||||
color_calibration->vcgt[2] = cmsDupToneCurve (vcgt[2]);
|
||||
}
|
||||
|
||||
brightness_profile =
|
||||
cd_icc_get_metadata_item (cd_icc, CD_PROFILE_METADATA_SCREEN_BRIGHTNESS);
|
||||
if (brightness_profile)
|
||||
color_calibration->brightness_profile = g_strdup (brightness_profile);
|
||||
|
||||
if (adaptation_matrix)
|
||||
{
|
||||
color_calibration->has_adaptation_matrix = TRUE;
|
||||
color_calibration->adaptation_matrix = *adaptation_matrix;
|
||||
}
|
||||
|
||||
return color_calibration;
|
||||
}
|
||||
|
||||
void
|
||||
meta_color_calibration_free (MetaColorCalibration *color_calibration)
|
||||
{
|
||||
cmsFreeToneCurveTriple (color_calibration->vcgt);
|
||||
g_free (color_calibration->brightness_profile);
|
||||
g_free (color_calibration);
|
||||
}
|
||||
|
@ -20,24 +20,38 @@
|
||||
|
||||
#include <colord.h>
|
||||
#include <glib-object.h>
|
||||
#include <lcms2.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "backends/meta-backend-types.h"
|
||||
#include "core/util-private.h"
|
||||
|
||||
typedef struct _MetaColorCalibration
|
||||
{
|
||||
gboolean has_vcgt;
|
||||
cmsToneCurve *vcgt[3];
|
||||
|
||||
gboolean has_adaptation_matrix;
|
||||
CdMat3x3 adaptation_matrix;
|
||||
|
||||
char *brightness_profile;
|
||||
} MetaColorCalibration;
|
||||
|
||||
#define META_TYPE_COLOR_PROFILE (meta_color_profile_get_type ())
|
||||
G_DECLARE_FINAL_TYPE (MetaColorProfile, meta_color_profile,
|
||||
META, COLOR_PROFILE,
|
||||
GObject)
|
||||
|
||||
MetaColorProfile * meta_color_profile_new_from_icc (MetaColorManager *color_manager,
|
||||
CdIcc *icc,
|
||||
GBytes *raw_bytes);
|
||||
MetaColorProfile * meta_color_profile_new_from_icc (MetaColorManager *color_manager,
|
||||
CdIcc *cd_icc,
|
||||
GBytes *raw_bytes,
|
||||
MetaColorCalibration *color_calibration);
|
||||
|
||||
MetaColorProfile * meta_color_profile_new_from_cd_profile (MetaColorManager *color_manager,
|
||||
CdProfile *cd_profile,
|
||||
CdIcc *cd_icc,
|
||||
GBytes *raw_bytes);
|
||||
MetaColorProfile * meta_color_profile_new_from_cd_profile (MetaColorManager *color_manager,
|
||||
CdProfile *cd_profile,
|
||||
CdIcc *cd_icc,
|
||||
GBytes *raw_bytes,
|
||||
MetaColorCalibration *color_calibration);
|
||||
|
||||
gboolean meta_color_profile_equals_bytes (MetaColorProfile *color_profile,
|
||||
GBytes *bytes);
|
||||
@ -64,4 +78,12 @@ MetaGammaLut * meta_color_profile_generate_gamma_lut (MetaColorProfile *color_pr
|
||||
unsigned int temperature,
|
||||
size_t lut_size);
|
||||
|
||||
META_EXPORT_TEST
|
||||
const MetaColorCalibration * meta_color_profile_get_calibration (MetaColorProfile *color_profile);
|
||||
|
||||
MetaColorCalibration * meta_color_calibration_new (CdIcc *cd_icc,
|
||||
const CdMat3x3 *adaptation_matrix);
|
||||
|
||||
void meta_color_calibration_free (MetaColorCalibration *color_calibration);
|
||||
|
||||
#endif /* META_COLOR_PROFILE_H */
|
||||
|
@ -116,6 +116,7 @@ create_profile_from_contents (MetaColorStore *color_store,
|
||||
g_autoptr (GError) error = NULL;
|
||||
g_autoptr (GBytes) bytes = NULL;
|
||||
g_autofree char *file_md5_checksum = NULL;
|
||||
MetaColorCalibration *color_calibration;
|
||||
MetaColorProfile *color_profile;
|
||||
|
||||
cd_icc = cd_icc_new ();
|
||||
@ -139,10 +140,12 @@ create_profile_from_contents (MetaColorStore *color_store,
|
||||
bytes);
|
||||
cd_icc_add_metadata (cd_icc, CD_PROFILE_METADATA_FILE_CHECKSUM,
|
||||
file_md5_checksum);
|
||||
color_calibration = meta_color_calibration_new (cd_icc, NULL);
|
||||
color_profile =
|
||||
meta_color_profile_new_from_icc (color_store->color_manager,
|
||||
g_steal_pointer (&cd_icc),
|
||||
g_steal_pointer (&bytes));
|
||||
g_steal_pointer (&bytes),
|
||||
color_calibration);
|
||||
|
||||
g_signal_connect (color_profile, "ready",
|
||||
G_CALLBACK (on_directory_profile_ready),
|
||||
@ -598,6 +601,7 @@ on_cd_profile_contents_loaded (GObject *source_object,
|
||||
g_autoptr (CdIcc) cd_icc = NULL;
|
||||
g_autofree char *file_md5_checksum = NULL;
|
||||
GBytes *bytes;
|
||||
MetaColorCalibration *color_calibration;
|
||||
MetaColorProfile *color_profile;
|
||||
|
||||
if (!g_file_load_contents_finish (file, res,
|
||||
@ -631,11 +635,13 @@ on_cd_profile_contents_loaded (GObject *source_object,
|
||||
file_md5_checksum);
|
||||
|
||||
bytes = g_bytes_new_take (g_steal_pointer (&contents), length);
|
||||
color_calibration = meta_color_calibration_new (cd_icc, NULL);
|
||||
color_profile =
|
||||
meta_color_profile_new_from_cd_profile (color_manager,
|
||||
cd_profile,
|
||||
g_steal_pointer (&cd_icc),
|
||||
bytes);
|
||||
bytes,
|
||||
color_calibration);
|
||||
|
||||
g_hash_table_insert (color_store->profiles,
|
||||
g_strdup (meta_color_profile_get_id (color_profile)),
|
||||
|
@ -34,9 +34,6 @@
|
||||
struct _MetaColorManagerX11
|
||||
{
|
||||
MetaColorManager parent;
|
||||
|
||||
CdIcc *srgb_cd_icc;
|
||||
GBytes *srgb_icc_bytes;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (MetaColorManagerX11, meta_color_manager_x11,
|
||||
@ -46,57 +43,10 @@ G_DEFINE_TYPE (MetaColorManagerX11, meta_color_manager_x11,
|
||||
#define ICC_PROFILE_IN_X_VERSION_MAJOR 0
|
||||
#define ICC_PROFILE_IN_X_VERSION_MINOR 3
|
||||
|
||||
static CdIcc *
|
||||
ensure_srgb_profile (MetaColorManagerX11 *color_manager_x11)
|
||||
{
|
||||
CdIcc *srgb_cd_icc;
|
||||
g_autoptr (GError) error = NULL;
|
||||
|
||||
if (color_manager_x11->srgb_cd_icc)
|
||||
return color_manager_x11->srgb_cd_icc;
|
||||
|
||||
srgb_cd_icc = cd_icc_new ();
|
||||
if (!cd_icc_create_default_full (srgb_cd_icc,
|
||||
CD_ICC_LOAD_FLAGS_PRIMARIES,
|
||||
&error))
|
||||
{
|
||||
g_warning_once ("Failed to create sRGB ICC profile: %s", error->message);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
color_manager_x11->srgb_cd_icc = srgb_cd_icc;
|
||||
return srgb_cd_icc;
|
||||
}
|
||||
|
||||
static GBytes *
|
||||
ensure_srgb_profile_bytes (MetaColorManagerX11 *color_manager_x11)
|
||||
{
|
||||
CdIcc *srgb_cd_icc;
|
||||
g_autoptr (GError) error = NULL;
|
||||
GBytes *bytes;
|
||||
|
||||
srgb_cd_icc = ensure_srgb_profile (color_manager_x11);
|
||||
if (!srgb_cd_icc)
|
||||
return NULL;
|
||||
|
||||
bytes = cd_icc_save_data (srgb_cd_icc,
|
||||
CD_ICC_SAVE_FLAGS_NONE,
|
||||
&error);
|
||||
if (!bytes)
|
||||
{
|
||||
g_warning_once ("Failed to export sRGB ICC profile: %s", error->message);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
color_manager_x11->srgb_icc_bytes = bytes;
|
||||
return bytes;
|
||||
}
|
||||
|
||||
static void
|
||||
update_root_window_atom (MetaColorManagerX11 *color_manager_x11,
|
||||
MetaColorDevice *color_device)
|
||||
update_root_window_atom (MetaColorManager *color_manager,
|
||||
MetaColorDevice *color_device)
|
||||
{
|
||||
MetaColorManager *color_manager = META_COLOR_MANAGER (color_manager_x11);
|
||||
MetaBackend *backend = meta_color_manager_get_backend (color_manager);
|
||||
MetaBackendX11 *backend_x11 = META_BACKEND_X11 (backend);
|
||||
Display *xdisplay = meta_backend_x11_get_xdisplay (backend_x11);
|
||||
@ -104,6 +54,7 @@ update_root_window_atom (MetaColorManagerX11 *color_manager_x11,
|
||||
Atom icc_profile_atom;
|
||||
Atom icc_profile_version_atom;
|
||||
MetaMonitor *monitor;
|
||||
MetaColorProfile *color_profile;
|
||||
const uint8_t *profile_contents = NULL;
|
||||
size_t profile_size;
|
||||
|
||||
@ -111,32 +62,11 @@ update_root_window_atom (MetaColorManagerX11 *color_manager_x11,
|
||||
if (!meta_monitor_is_primary (monitor))
|
||||
return;
|
||||
|
||||
if (meta_monitor_supports_color_transform (monitor))
|
||||
color_profile = meta_color_device_get_assigned_profile (color_device);
|
||||
if (color_profile)
|
||||
{
|
||||
GBytes *profile_bytes;
|
||||
|
||||
/*
|
||||
* If the output supports color transforms, then
|
||||
* applications should use the standard sRGB color profile and
|
||||
* the window system will take care of converting colors to
|
||||
* match the output device's measured color profile.
|
||||
*/
|
||||
profile_bytes = ensure_srgb_profile_bytes (color_manager_x11);
|
||||
if (!profile_bytes)
|
||||
g_warning_once ("Failed to generate sRGB ICC profile");
|
||||
else
|
||||
profile_contents = g_bytes_get_data (profile_bytes, &profile_size);
|
||||
}
|
||||
else
|
||||
{
|
||||
MetaColorProfile *color_profile;
|
||||
|
||||
color_profile = meta_color_device_get_assigned_profile (color_device);
|
||||
if (color_profile)
|
||||
{
|
||||
profile_contents = meta_color_profile_get_data (color_profile);
|
||||
profile_size = meta_color_profile_get_data_size (color_profile);
|
||||
}
|
||||
profile_contents = meta_color_profile_get_data (color_profile);
|
||||
profile_size = meta_color_profile_get_data_size (color_profile);
|
||||
}
|
||||
|
||||
icc_profile_atom = XInternAtom (xdisplay, "_ICC_PROFILE", False);
|
||||
@ -187,7 +117,7 @@ double_to_ctmval (double value)
|
||||
}
|
||||
|
||||
static MetaOutputCtm
|
||||
mat33_to_ctm (CdMat3x3 matrix)
|
||||
mat33_to_ctm (const CdMat3x3 *matrix)
|
||||
{
|
||||
MetaOutputCtm ctm;
|
||||
|
||||
@ -195,29 +125,25 @@ mat33_to_ctm (CdMat3x3 matrix)
|
||||
* libcolord generates a matrix containing double values. RandR's CTM
|
||||
* property expects values in S31.32 fixed-point sign-magnitude format
|
||||
*/
|
||||
ctm.matrix[0] = double_to_ctmval (matrix.m00);
|
||||
ctm.matrix[1] = double_to_ctmval (matrix.m01);
|
||||
ctm.matrix[2] = double_to_ctmval (matrix.m02);
|
||||
ctm.matrix[3] = double_to_ctmval (matrix.m10);
|
||||
ctm.matrix[4] = double_to_ctmval (matrix.m11);
|
||||
ctm.matrix[5] = double_to_ctmval (matrix.m12);
|
||||
ctm.matrix[6] = double_to_ctmval (matrix.m20);
|
||||
ctm.matrix[7] = double_to_ctmval (matrix.m21);
|
||||
ctm.matrix[8] = double_to_ctmval (matrix.m22);
|
||||
ctm.matrix[0] = double_to_ctmval (matrix->m00);
|
||||
ctm.matrix[1] = double_to_ctmval (matrix->m01);
|
||||
ctm.matrix[2] = double_to_ctmval (matrix->m02);
|
||||
ctm.matrix[3] = double_to_ctmval (matrix->m10);
|
||||
ctm.matrix[4] = double_to_ctmval (matrix->m11);
|
||||
ctm.matrix[5] = double_to_ctmval (matrix->m12);
|
||||
ctm.matrix[6] = double_to_ctmval (matrix->m20);
|
||||
ctm.matrix[7] = double_to_ctmval (matrix->m21);
|
||||
ctm.matrix[8] = double_to_ctmval (matrix->m22);
|
||||
|
||||
return ctm;
|
||||
}
|
||||
|
||||
static void
|
||||
update_device_ctm (MetaColorManagerX11 *color_manager_x11,
|
||||
MetaColorDevice *color_device)
|
||||
update_device_ctm (MetaColorDevice *color_device)
|
||||
{
|
||||
MetaMonitor *monitor;
|
||||
MetaColorProfile *color_profile;
|
||||
CdIcc *srgb_cd_icc;
|
||||
g_autoptr (GError) error = NULL;
|
||||
CdIcc *cd_icc;
|
||||
CdMat3x3 csc;
|
||||
const MetaColorCalibration *color_calibration;
|
||||
MetaOutputCtm ctm;
|
||||
MetaOutput *output;
|
||||
MetaOutputXrandr *output_xrandr;
|
||||
@ -230,19 +156,12 @@ update_device_ctm (MetaColorManagerX11 *color_manager_x11,
|
||||
if (!color_profile)
|
||||
return;
|
||||
|
||||
srgb_cd_icc = ensure_srgb_profile (color_manager_x11);
|
||||
if (!srgb_cd_icc)
|
||||
color_calibration = meta_color_profile_get_calibration (color_profile);
|
||||
|
||||
if (!color_calibration->has_adaptation_matrix)
|
||||
return;
|
||||
|
||||
cd_icc = meta_color_profile_get_cd_icc (color_profile);
|
||||
if (!cd_icc_utils_get_adaptation_matrix (cd_icc, srgb_cd_icc, &csc, &error))
|
||||
{
|
||||
g_warning_once ("Failed to calculate adaption matrix: %s",
|
||||
error->message);
|
||||
return;
|
||||
}
|
||||
|
||||
ctm = mat33_to_ctm (csc);
|
||||
ctm = mat33_to_ctm (&color_calibration->adaptation_matrix);
|
||||
|
||||
output = meta_monitor_get_main_output (monitor);
|
||||
output_xrandr = META_OUTPUT_XRANDR (output);
|
||||
@ -253,11 +172,8 @@ static void
|
||||
on_color_device_updated (MetaColorManager *color_manager,
|
||||
MetaColorDevice *color_device)
|
||||
{
|
||||
MetaColorManagerX11 *color_manager_x11 =
|
||||
META_COLOR_MANAGER_X11 (color_manager);
|
||||
|
||||
update_root_window_atom (color_manager_x11, color_device);
|
||||
update_device_ctm (color_manager_x11, color_device);
|
||||
update_root_window_atom (color_manager, color_device);
|
||||
update_device_ctm (color_device);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -271,24 +187,12 @@ meta_color_manager_x11_constructed (GObject *object)
|
||||
G_OBJECT_CLASS (meta_color_manager_x11_parent_class)->constructed (object);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_color_manager_x11_finalize (GObject *object)
|
||||
{
|
||||
MetaColorManagerX11 *color_manager_x11 = META_COLOR_MANAGER_X11 (object);
|
||||
|
||||
g_clear_pointer (&color_manager_x11->srgb_icc_bytes, g_bytes_unref);
|
||||
g_clear_object (&color_manager_x11->srgb_cd_icc);
|
||||
|
||||
G_OBJECT_CLASS (meta_color_manager_x11_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_color_manager_x11_class_init (MetaColorManagerX11Class *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->constructed = meta_color_manager_x11_constructed;
|
||||
object_class->finalize = meta_color_manager_x11_finalize;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -20,6 +20,8 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <fcntl.h>
|
||||
|
||||
#include "backends/meta-color-device.h"
|
||||
#include "backends/meta-color-manager-private.h"
|
||||
#include "backends/meta-color-profile.h"
|
||||
@ -105,6 +107,22 @@ static MonitorTestCaseSetup base_monitor_setup = {
|
||||
.white_y = 0.329102, \
|
||||
})
|
||||
|
||||
#define assert_color_xyz_equal(color, expected_color) \
|
||||
g_assert_cmpfloat_with_epsilon (color->X, expected_color->X, \
|
||||
PRIMARY_EPSILON); \
|
||||
g_assert_cmpfloat_with_epsilon (color->Y, expected_color->Y, \
|
||||
PRIMARY_EPSILON); \
|
||||
g_assert_cmpfloat_with_epsilon (color->Z, expected_color->Z, \
|
||||
PRIMARY_EPSILON);
|
||||
|
||||
#define assert_color_yxy_equal(color, expected_color) \
|
||||
g_assert_cmpfloat_with_epsilon (color->x, expected_color->x, \
|
||||
PRIMARY_EPSILON); \
|
||||
g_assert_cmpfloat_with_epsilon (color->y, expected_color->y, \
|
||||
PRIMARY_EPSILON); \
|
||||
g_assert_cmpfloat_with_epsilon (color->Y, expected_color->Y, \
|
||||
PRIMARY_EPSILON);
|
||||
|
||||
static GDBusProxy *
|
||||
get_colord_mock_proxy (void)
|
||||
{
|
||||
@ -515,6 +533,155 @@ meta_test_color_management_profile_system (void)
|
||||
srgb_profile_id);
|
||||
}
|
||||
|
||||
static void
|
||||
generate_efi_test_profile (const char *path,
|
||||
double gamma,
|
||||
CdColorYxy *red,
|
||||
CdColorYxy *green,
|
||||
CdColorYxy *blue,
|
||||
CdColorYxy *white)
|
||||
{
|
||||
g_autoptr (GError) error = NULL;
|
||||
g_autoptr (CdIcc) cd_icc = NULL;
|
||||
g_autoptr (GFile) file = NULL;
|
||||
const CdColorXYZ *red_xyz;
|
||||
const CdColorXYZ *green_xyz;
|
||||
const CdColorXYZ *blue_xyz;
|
||||
const CdColorXYZ *white_xyz;
|
||||
|
||||
cd_icc = cd_icc_new ();
|
||||
|
||||
if (!cd_icc_create_from_edid (cd_icc, 2.2, red, green, blue, white, &error))
|
||||
g_error ("Failed to generate reference profile: %s", error->message);
|
||||
|
||||
file = g_file_new_for_path (path);
|
||||
if (!cd_icc_save_file (cd_icc, file, CD_ICC_SAVE_FLAGS_NONE,
|
||||
NULL, &error))
|
||||
g_error ("Failed to save reference profile: %s", error->message);
|
||||
|
||||
g_clear_object (&cd_icc);
|
||||
|
||||
cd_icc = cd_icc_new ();
|
||||
if (!cd_icc_load_file (cd_icc, file, CD_ICC_LOAD_FLAGS_PRIMARIES,
|
||||
NULL, &error))
|
||||
g_error ("Failed to load reference profile: %s", error->message);
|
||||
|
||||
red_xyz = cd_icc_get_red (cd_icc);
|
||||
green_xyz = cd_icc_get_green (cd_icc);
|
||||
blue_xyz = cd_icc_get_blue (cd_icc);
|
||||
white_xyz = cd_icc_get_white (cd_icc);
|
||||
cd_color_xyz_to_yxy (red_xyz, red);
|
||||
cd_color_xyz_to_yxy (green_xyz, green);
|
||||
cd_color_xyz_to_yxy (blue_xyz, blue);
|
||||
cd_color_xyz_to_yxy (white_xyz, white);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_test_color_management_profile_efivar (void)
|
||||
{
|
||||
MetaBackend *backend = meta_context_get_backend (test_context);
|
||||
MetaMonitorManager *monitor_manager =
|
||||
meta_backend_get_monitor_manager (backend);
|
||||
MetaMonitorManagerTest *monitor_manager_test =
|
||||
META_MONITOR_MANAGER_TEST (monitor_manager);
|
||||
MetaColorManager *color_manager =
|
||||
meta_backend_get_color_manager (backend);
|
||||
char efivar_path[] = "/tmp/efivar-test-profile-XXXXXX";
|
||||
int fd;
|
||||
CdColorYxy *reference_red_yxy;
|
||||
CdColorYxy *reference_green_yxy;
|
||||
CdColorYxy *reference_blue_yxy;
|
||||
CdColorYxy *reference_white_yxy;
|
||||
MetaEdidInfo edid_info;
|
||||
MonitorTestCaseSetup test_case_setup = base_monitor_setup;
|
||||
MetaMonitorTestSetup *test_setup;
|
||||
MetaMonitor *monitor;
|
||||
MetaColorDevice *color_device;
|
||||
MetaColorProfile *color_profile;
|
||||
CdIcc *cd_icc;
|
||||
g_autoptr (CdIcc) srgb_cd_icc = NULL;
|
||||
const CdColorXYZ *red_xyz;
|
||||
const CdColorXYZ *green_xyz;
|
||||
const CdColorXYZ *blue_xyz;
|
||||
const CdColorXYZ *white_xyz;
|
||||
const CdColorXYZ *srgb_red_xyz;
|
||||
const CdColorXYZ *srgb_green_xyz;
|
||||
const CdColorXYZ *srgb_blue_xyz;
|
||||
const CdColorXYZ *srgb_white_xyz;
|
||||
const MetaColorCalibration *color_calibration;
|
||||
|
||||
fd = mkostemp (efivar_path, O_CLOEXEC);
|
||||
g_assert_cmpint (fd, >=, 0);
|
||||
close (fd);
|
||||
|
||||
reference_red_yxy = cd_color_yxy_new ();
|
||||
reference_green_yxy = cd_color_yxy_new ();
|
||||
reference_blue_yxy = cd_color_yxy_new ();
|
||||
reference_white_yxy = cd_color_yxy_new ();
|
||||
|
||||
cd_color_yxy_set (reference_red_yxy, 0.0, 0.3, 0.6);
|
||||
cd_color_yxy_set (reference_green_yxy, 0.0, 0.7, 0.2);
|
||||
cd_color_yxy_set (reference_blue_yxy, 0.0, 0.1, 0.2);
|
||||
cd_color_yxy_set (reference_white_yxy, 1.0, 0.3, 0.3);
|
||||
|
||||
generate_efi_test_profile (efivar_path,
|
||||
2.2,
|
||||
reference_red_yxy,
|
||||
reference_green_yxy,
|
||||
reference_blue_yxy,
|
||||
reference_white_yxy);
|
||||
meta_set_color_efivar_test_path (efivar_path);
|
||||
|
||||
edid_info = ANCOR_VX239_EDID;
|
||||
test_case_setup.outputs[0].serial = __func__;
|
||||
test_case_setup.outputs[0].edid_info = edid_info;
|
||||
test_case_setup.outputs[0].has_edid_info = TRUE;
|
||||
test_case_setup.n_outputs = 1;
|
||||
test_setup = meta_create_monitor_test_setup (backend, &test_case_setup,
|
||||
MONITOR_TEST_FLAG_NO_STORED);
|
||||
meta_monitor_manager_test_emulate_hotplug (monitor_manager_test, test_setup);
|
||||
|
||||
monitor = meta_monitor_manager_get_monitors (monitor_manager)->data;
|
||||
color_device = meta_color_manager_get_color_device (color_manager, monitor);
|
||||
g_assert_nonnull (color_device);
|
||||
|
||||
while (!meta_color_device_is_ready (color_device))
|
||||
g_main_context_iteration (NULL, TRUE);
|
||||
|
||||
color_profile = meta_color_device_get_device_profile (color_device);
|
||||
g_assert_nonnull (color_profile);
|
||||
|
||||
cd_icc = meta_color_profile_get_cd_icc (color_profile);
|
||||
g_assert_nonnull (cd_icc);
|
||||
|
||||
red_xyz = cd_icc_get_red (cd_icc);
|
||||
green_xyz = cd_icc_get_green (cd_icc);
|
||||
blue_xyz = cd_icc_get_blue (cd_icc);
|
||||
white_xyz = cd_icc_get_white (cd_icc);
|
||||
|
||||
srgb_cd_icc = cd_icc_new ();
|
||||
g_assert_true (cd_icc_create_default_full (srgb_cd_icc,
|
||||
CD_ICC_LOAD_FLAGS_PRIMARIES,
|
||||
NULL));
|
||||
|
||||
srgb_red_xyz = cd_icc_get_red (srgb_cd_icc);
|
||||
srgb_green_xyz = cd_icc_get_green (srgb_cd_icc);
|
||||
srgb_blue_xyz = cd_icc_get_blue (srgb_cd_icc);
|
||||
srgb_white_xyz = cd_icc_get_white (srgb_cd_icc);
|
||||
|
||||
/* Make sure we the values from the sRGB profile. */
|
||||
assert_color_xyz_equal (red_xyz, srgb_red_xyz);
|
||||
assert_color_xyz_equal (green_xyz, srgb_green_xyz);
|
||||
assert_color_xyz_equal (blue_xyz, srgb_blue_xyz);
|
||||
assert_color_xyz_equal (white_xyz, srgb_white_xyz);
|
||||
|
||||
color_calibration = meta_color_profile_get_calibration (color_profile);
|
||||
g_assert_true (color_calibration->has_adaptation_matrix);
|
||||
|
||||
meta_set_color_efivar_test_path (NULL);
|
||||
unlink (efivar_path);
|
||||
}
|
||||
|
||||
static void
|
||||
wait_for_profile_assigned (MetaColorDevice *color_device,
|
||||
const char *profile_id)
|
||||
@ -1124,6 +1291,8 @@ init_tests (void)
|
||||
meta_test_color_management_profile_device);
|
||||
add_color_test ("/color-management/profile/system",
|
||||
meta_test_color_management_profile_system);
|
||||
add_color_test ("/color-management/profile/efivar",
|
||||
meta_test_color_management_profile_efivar);
|
||||
add_color_test ("/color-management/night-light/calibrated",
|
||||
meta_test_color_management_night_light_calibrated);
|
||||
add_color_test ("/color-management/night-light/uncalibrated",
|
||||
|
Loading…
Reference in New Issue
Block a user