color-manager/x11: Set color transformation matrix

As was done in gsd-color, set the "CTM" of the output. This is only done
in X11, as it was only ever implemented for X11.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2166>
This commit is contained in:
Jonas Ådahl 2021-12-06 15:56:51 +01:00
parent 17c99edfe0
commit 39e01d8700

View File

@ -93,11 +93,10 @@ ensure_srgb_profile_bytes (MetaColorManagerX11 *color_manager_x11)
}
static void
on_color_device_updated (MetaColorManager *color_manager,
update_root_window_atom (MetaColorManagerX11 *color_manager_x11,
MetaColorDevice *color_device)
{
MetaColorManagerX11 *color_manager_x11 =
META_COLOR_MANAGER_X11 (color_manager);
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);
@ -170,6 +169,97 @@ on_color_device_updated (MetaColorManager *color_manager,
}
}
static uint64_t
double_to_ctmval (double value)
{
uint64_t sign = value < 0;
double integer, fractional;
if (sign)
value = -value;
fractional = modf (value, &integer);
return
sign << 63 |
(uint64_t) integer << 32 |
(uint64_t) (fractional * 0xffffffffUL);
}
static MetaOutputCtm
mat33_to_ctm (CdMat3x3 matrix)
{
MetaOutputCtm ctm;
/*
* 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);
return ctm;
}
static void
update_device_ctm (MetaColorManagerX11 *color_manager_x11,
MetaColorDevice *color_device)
{
MetaMonitor *monitor;
MetaColorProfile *color_profile;
CdIcc *srgb_cd_icc;
g_autoptr (GError) error = NULL;
CdIcc *cd_icc;
CdMat3x3 csc;
MetaOutputCtm ctm;
MetaOutput *output;
MetaOutputXrandr *output_xrandr;
monitor = meta_color_device_get_monitor (color_device);
if (!meta_monitor_supports_color_transform (monitor))
return;
color_profile = meta_color_device_get_assigned_profile (color_device);
if (!color_profile)
return;
srgb_cd_icc = ensure_srgb_profile (color_manager_x11);
if (!srgb_cd_icc)
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);
output = meta_monitor_get_main_output (monitor);
output_xrandr = META_OUTPUT_XRANDR (output);
meta_output_xrandr_set_ctm (output_xrandr, &ctm);
}
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);
}
static void
meta_color_manager_x11_constructed (GObject *object)
{