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:
@@ -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",
|
||||
|
Reference in New Issue
Block a user