mirror of
https://github.com/brl/mutter.git
synced 2024-11-21 15:40:41 -05:00
x11: Support the CTM (color transform matrix) RandR property
When supported, this property allows the window system to apply a 3x3 color correction matrix in order to transform colors from the window system's native color space to the measured color space of a display device. Query for this property and set the 'supports-color-transform' property in the GetResource reply. Add support for the SetOutputCTM DBus method and plumb that through to the server's CTM property. Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1048>
This commit is contained in:
parent
bd15cfc94b
commit
e88467f9d7
@ -5,6 +5,7 @@
|
|||||||
* Copyright (C) 2003 Rob Adams
|
* Copyright (C) 2003 Rob Adams
|
||||||
* Copyright (C) 2004-2006 Elijah Newren
|
* Copyright (C) 2004-2006 Elijah Newren
|
||||||
* Copyright (C) 2013 Red Hat Inc.
|
* Copyright (C) 2013 Red Hat Inc.
|
||||||
|
* Copyright (C) 2020 NVIDIA CORPORATION
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or
|
* This program is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU General Public License as
|
* modify it under the terms of the GNU General Public License as
|
||||||
@ -92,6 +93,17 @@ struct _MetaOutputAssignment
|
|||||||
gboolean is_underscanning;
|
gboolean is_underscanning;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* MetaOutputCtm:
|
||||||
|
*
|
||||||
|
* A 3x3 color transform matrix in the fixed-point S31.32 sign-magnitude format
|
||||||
|
* used by DRM.
|
||||||
|
*/
|
||||||
|
typedef struct _MetaOutputCtm
|
||||||
|
{
|
||||||
|
uint64_t matrix[9];
|
||||||
|
} MetaOutputCtm;
|
||||||
|
|
||||||
#define META_TYPE_MONITOR_MANAGER (meta_monitor_manager_get_type ())
|
#define META_TYPE_MONITOR_MANAGER (meta_monitor_manager_get_type ())
|
||||||
#define META_MONITOR_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_MONITOR_MANAGER, MetaMonitorManager))
|
#define META_MONITOR_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_MONITOR_MANAGER, MetaMonitorManager))
|
||||||
#define META_MONITOR_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_MONITOR_MANAGER, MetaMonitorManagerClass))
|
#define META_MONITOR_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_MONITOR_MANAGER, MetaMonitorManagerClass))
|
||||||
@ -179,6 +191,7 @@ struct _MetaMonitorManager
|
|||||||
* @get_capabilities: vfunc for meta_monitor_manager_get_capabilities().
|
* @get_capabilities: vfunc for meta_monitor_manager_get_capabilities().
|
||||||
* @get_max_screen_size: vfunc for meta_monitor_manager_get_max_screen_size().
|
* @get_max_screen_size: vfunc for meta_monitor_manager_get_max_screen_size().
|
||||||
* @get_default_layout_mode: vfunc for meta_monitor_manager_get_default_layout_mode().
|
* @get_default_layout_mode: vfunc for meta_monitor_manager_get_default_layout_mode().
|
||||||
|
* @set_output_ctm: vfunc for meta_monitor_manager_output_set_ctm()
|
||||||
*
|
*
|
||||||
* The base class for a #MetaMonitorManager.
|
* The base class for a #MetaMonitorManager.
|
||||||
*/
|
*/
|
||||||
@ -245,6 +258,9 @@ struct _MetaMonitorManagerClass
|
|||||||
int *);
|
int *);
|
||||||
|
|
||||||
MetaLogicalMonitorLayoutMode (*get_default_layout_mode) (MetaMonitorManager *);
|
MetaLogicalMonitorLayoutMode (*get_default_layout_mode) (MetaMonitorManager *);
|
||||||
|
|
||||||
|
void (*set_output_ctm) (MetaOutput *,
|
||||||
|
const MetaOutputCtm *);
|
||||||
};
|
};
|
||||||
|
|
||||||
META_EXPORT_TEST
|
META_EXPORT_TEST
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
* Copyright (C) 2003 Rob Adams
|
* Copyright (C) 2003 Rob Adams
|
||||||
* Copyright (C) 2004-2006 Elijah Newren
|
* Copyright (C) 2004-2006 Elijah Newren
|
||||||
* Copyright (C) 2013 Red Hat Inc.
|
* Copyright (C) 2013 Red Hat Inc.
|
||||||
|
* Copyright (C) 2020 NVIDIA CORPORATION
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or
|
* This program is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU General Public License as
|
* modify it under the terms of the GNU General Public License as
|
||||||
@ -1190,6 +1191,7 @@ meta_monitor_manager_handle_get_resources (MetaDBusDisplayConfig *skeleton,
|
|||||||
const char * connector_type_name;
|
const char * connector_type_name;
|
||||||
gboolean is_underscanning;
|
gboolean is_underscanning;
|
||||||
gboolean supports_underscanning;
|
gboolean supports_underscanning;
|
||||||
|
gboolean supports_color_transform;
|
||||||
|
|
||||||
g_variant_builder_init (&crtcs, G_VARIANT_TYPE ("au"));
|
g_variant_builder_init (&crtcs, G_VARIANT_TYPE ("au"));
|
||||||
for (j = 0; j < output_info->n_possible_crtcs; j++)
|
for (j = 0; j < output_info->n_possible_crtcs; j++)
|
||||||
@ -1230,6 +1232,7 @@ meta_monitor_manager_handle_get_resources (MetaDBusDisplayConfig *skeleton,
|
|||||||
is_underscanning = meta_output_is_underscanning (output);
|
is_underscanning = meta_output_is_underscanning (output);
|
||||||
connector_type_name = get_connector_type_name (output_info->connector_type);
|
connector_type_name = get_connector_type_name (output_info->connector_type);
|
||||||
supports_underscanning = output_info->supports_underscanning;
|
supports_underscanning = output_info->supports_underscanning;
|
||||||
|
supports_color_transform = output_info->supports_color_transform;
|
||||||
|
|
||||||
g_variant_builder_init (&properties, G_VARIANT_TYPE ("a{sv}"));
|
g_variant_builder_init (&properties, G_VARIANT_TYPE ("a{sv}"));
|
||||||
g_variant_builder_add (&properties, "{sv}", "vendor",
|
g_variant_builder_add (&properties, "{sv}", "vendor",
|
||||||
@ -1258,6 +1261,8 @@ meta_monitor_manager_handle_get_resources (MetaDBusDisplayConfig *skeleton,
|
|||||||
g_variant_new_boolean (is_underscanning));
|
g_variant_new_boolean (is_underscanning));
|
||||||
g_variant_builder_add (&properties, "{sv}", "supports-underscanning",
|
g_variant_builder_add (&properties, "{sv}", "supports-underscanning",
|
||||||
g_variant_new_boolean (supports_underscanning));
|
g_variant_new_boolean (supports_underscanning));
|
||||||
|
g_variant_builder_add (&properties, "{sv}", "supports-color-transform",
|
||||||
|
g_variant_new_boolean (supports_color_transform));
|
||||||
|
|
||||||
edid = manager_class->read_edid (manager, output);
|
edid = manager_class->read_edid (manager, output);
|
||||||
if (edid)
|
if (edid)
|
||||||
@ -2423,6 +2428,65 @@ meta_monitor_manager_handle_set_crtc_gamma (MetaDBusDisplayConfig *skeleton,
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
meta_monitor_manager_handle_set_output_ctm (MetaDBusDisplayConfig *skeleton,
|
||||||
|
GDBusMethodInvocation *invocation,
|
||||||
|
guint serial,
|
||||||
|
guint output_id,
|
||||||
|
GVariant *ctm_var,
|
||||||
|
MetaMonitorManager *manager)
|
||||||
|
{
|
||||||
|
MetaMonitorManagerClass *klass;
|
||||||
|
GList *combined_outputs;
|
||||||
|
MetaOutput *output;
|
||||||
|
MetaOutputCtm ctm;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (serial != manager->serial)
|
||||||
|
{
|
||||||
|
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
||||||
|
G_DBUS_ERROR_ACCESS_DENIED,
|
||||||
|
"The requested configuration is based on stale information");
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
combined_outputs = combine_gpu_lists (manager, meta_gpu_get_outputs);
|
||||||
|
|
||||||
|
if (output_id >= g_list_length (combined_outputs))
|
||||||
|
{
|
||||||
|
g_list_free (combined_outputs);
|
||||||
|
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
||||||
|
G_DBUS_ERROR_INVALID_ARGS,
|
||||||
|
"Invalid output id");
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
output = g_list_nth_data (combined_outputs, output_id);
|
||||||
|
g_list_free (combined_outputs);
|
||||||
|
|
||||||
|
if (g_variant_n_children (ctm_var) != 9)
|
||||||
|
{
|
||||||
|
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
||||||
|
G_DBUS_ERROR_INVALID_ARGS,
|
||||||
|
"Unexpected color transform matrix variant length");
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < 9; i++)
|
||||||
|
{
|
||||||
|
GVariant *tmp = g_variant_get_child_value (ctm_var, i);
|
||||||
|
ctm.matrix[i] = g_variant_get_uint64 (tmp);
|
||||||
|
g_variant_unref (tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
klass = META_MONITOR_MANAGER_GET_CLASS (manager);
|
||||||
|
if (klass->set_output_ctm)
|
||||||
|
klass->set_output_ctm (output, &ctm);
|
||||||
|
meta_dbus_display_config_complete_set_output_ctm (skeleton, invocation);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
monitor_manager_setup_dbus_config_handlers (MetaMonitorManager *manager)
|
monitor_manager_setup_dbus_config_handlers (MetaMonitorManager *manager)
|
||||||
{
|
{
|
||||||
@ -2444,6 +2508,9 @@ monitor_manager_setup_dbus_config_handlers (MetaMonitorManager *manager)
|
|||||||
g_signal_connect_object (manager->display_config, "handle-apply-monitors-config",
|
g_signal_connect_object (manager->display_config, "handle-apply-monitors-config",
|
||||||
G_CALLBACK (meta_monitor_manager_handle_apply_monitors_config),
|
G_CALLBACK (meta_monitor_manager_handle_apply_monitors_config),
|
||||||
manager, 0);
|
manager, 0);
|
||||||
|
g_signal_connect_object (manager->display_config, "handle-set-output-ctm",
|
||||||
|
G_CALLBACK (meta_monitor_manager_handle_set_output_ctm),
|
||||||
|
manager, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2017 Red Hat
|
* Copyright (C) 2017 Red Hat
|
||||||
|
* Copyright (C) 2020 NVIDIA CORPORATION
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or
|
* This program is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU General Public License as
|
* modify it under the terms of the GNU General Public License as
|
||||||
@ -89,6 +90,7 @@ typedef struct _MetaOutputInfo
|
|||||||
int backlight_max;
|
int backlight_max;
|
||||||
|
|
||||||
gboolean supports_underscanning;
|
gboolean supports_underscanning;
|
||||||
|
gboolean supports_color_transform;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get a new preferred mode on hotplug events, to handle dynamic guest
|
* Get a new preferred mode on hotplug events, to handle dynamic guest
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
* Copyright (C) 2003 Rob Adams
|
* Copyright (C) 2003 Rob Adams
|
||||||
* Copyright (C) 2004-2006 Elijah Newren
|
* Copyright (C) 2004-2006 Elijah Newren
|
||||||
* Copyright (C) 2013 Red Hat Inc.
|
* Copyright (C) 2013 Red Hat Inc.
|
||||||
|
* Copyright (C) 2020 NVIDIA CORPORATION
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or
|
* This program is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU General Public License as
|
* modify it under the terms of the GNU General Public License as
|
||||||
@ -1001,6 +1002,13 @@ meta_monitor_manager_xrandr_get_default_layout_mode (MetaMonitorManager *manager
|
|||||||
return META_LOGICAL_MONITOR_LAYOUT_MODE_PHYSICAL;
|
return META_LOGICAL_MONITOR_LAYOUT_MODE_PHYSICAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_monitor_manager_xrandr_set_output_ctm (MetaOutput *output,
|
||||||
|
const MetaOutputCtm *ctm)
|
||||||
|
{
|
||||||
|
meta_output_xrandr_set_ctm (META_OUTPUT_XRANDR (output), ctm);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
meta_monitor_manager_xrandr_constructed (GObject *object)
|
meta_monitor_manager_xrandr_constructed (GObject *object)
|
||||||
{
|
{
|
||||||
@ -1086,6 +1094,7 @@ meta_monitor_manager_xrandr_class_init (MetaMonitorManagerXrandrClass *klass)
|
|||||||
manager_class->get_capabilities = meta_monitor_manager_xrandr_get_capabilities;
|
manager_class->get_capabilities = meta_monitor_manager_xrandr_get_capabilities;
|
||||||
manager_class->get_max_screen_size = meta_monitor_manager_xrandr_get_max_screen_size;
|
manager_class->get_max_screen_size = meta_monitor_manager_xrandr_get_max_screen_size;
|
||||||
manager_class->get_default_layout_mode = meta_monitor_manager_xrandr_get_default_layout_mode;
|
manager_class->get_default_layout_mode = meta_monitor_manager_xrandr_get_default_layout_mode;
|
||||||
|
manager_class->set_output_ctm = meta_monitor_manager_xrandr_set_output_ctm;
|
||||||
|
|
||||||
quark_meta_monitor_xrandr_data =
|
quark_meta_monitor_xrandr_data =
|
||||||
g_quark_from_static_string ("-meta-monitor-xrandr-data");
|
g_quark_from_static_string ("-meta-monitor-xrandr-data");
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
* Copyright (C) 2003 Rob Adams
|
* Copyright (C) 2003 Rob Adams
|
||||||
* Copyright (C) 2004-2006 Elijah Newren
|
* Copyright (C) 2004-2006 Elijah Newren
|
||||||
* Copyright (C) 2013-2017 Red Hat Inc.
|
* Copyright (C) 2013-2017 Red Hat Inc.
|
||||||
|
* Copyright (C) 2020 NVIDIA CORPORATION
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or
|
* This program is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU General Public License as
|
* modify it under the terms of the GNU General Public License as
|
||||||
@ -197,6 +198,21 @@ meta_output_xrandr_change_backlight (MetaOutputXrandr *output_xrandr,
|
|||||||
meta_output_set_backlight (output, normalize_backlight (output, hw_value));
|
meta_output_set_backlight (output, normalize_backlight (output, hw_value));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
meta_output_xrandr_set_ctm (MetaOutputXrandr *output_xrandr,
|
||||||
|
const MetaOutputCtm *ctm)
|
||||||
|
{
|
||||||
|
MetaOutput *output = META_OUTPUT (output_xrandr);
|
||||||
|
Display *xdisplay = xdisplay_from_output (output);
|
||||||
|
Atom atom = XInternAtom (xdisplay, "CTM", False);
|
||||||
|
|
||||||
|
xcb_randr_change_output_property (XGetXCBConnection (xdisplay),
|
||||||
|
(XID) meta_output_get_id (output),
|
||||||
|
atom, XCB_ATOM_INTEGER, 32,
|
||||||
|
XCB_PROP_MODE_REPLACE,
|
||||||
|
18, &ctm->matrix);
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
output_get_integer_property (Display *xdisplay,
|
output_get_integer_property (Display *xdisplay,
|
||||||
RROutput output_id,
|
RROutput output_id,
|
||||||
@ -351,6 +367,32 @@ output_get_supports_underscanning_xrandr (Display *xdisplay,
|
|||||||
return supports_underscanning;
|
return supports_underscanning;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
output_get_supports_color_transform_xrandr (Display *xdisplay,
|
||||||
|
RROutput output_id)
|
||||||
|
{
|
||||||
|
Atom atom, actual_type;
|
||||||
|
int actual_format;
|
||||||
|
unsigned long nitems, bytes_after;
|
||||||
|
g_autofree unsigned char *buffer = NULL;
|
||||||
|
|
||||||
|
atom = XInternAtom (xdisplay, "CTM", False);
|
||||||
|
XRRGetOutputProperty (xdisplay,
|
||||||
|
(XID) output_id,
|
||||||
|
atom,
|
||||||
|
0, G_MAXLONG, False, False, XA_INTEGER,
|
||||||
|
&actual_type, &actual_format,
|
||||||
|
&nitems, &bytes_after, &buffer);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* X's CTM property is 9 64-bit integers represented as an array of 18 32-bit
|
||||||
|
* integers.
|
||||||
|
*/
|
||||||
|
return (actual_type == XA_INTEGER &&
|
||||||
|
actual_format == 32 &&
|
||||||
|
nitems == 18);
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
output_get_backlight_xrandr (MetaOutput *output)
|
output_get_backlight_xrandr (MetaOutput *output)
|
||||||
{
|
{
|
||||||
@ -868,6 +910,8 @@ meta_output_xrandr_new (MetaGpuXrandr *gpu_xrandr,
|
|||||||
|
|
||||||
output_info->supports_underscanning =
|
output_info->supports_underscanning =
|
||||||
output_get_supports_underscanning_xrandr (xdisplay, output_id);
|
output_get_supports_underscanning_xrandr (xdisplay, output_id);
|
||||||
|
output_info->supports_color_transform =
|
||||||
|
output_get_supports_color_transform_xrandr (xdisplay, output_id);
|
||||||
output_info_init_backlight_limits_xrandr (output_info, xdisplay, output_id);
|
output_info_init_backlight_limits_xrandr (output_info, xdisplay, output_id);
|
||||||
|
|
||||||
output = g_object_new (META_TYPE_OUTPUT_XRANDR,
|
output = g_object_new (META_TYPE_OUTPUT_XRANDR,
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2017 Red Hat
|
* Copyright (C) 2017 Red Hat
|
||||||
|
* Copyright (C) 2020 NVIDIA CORPORATION
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or
|
* This program is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU General Public License as
|
* modify it under the terms of the GNU General Public License as
|
||||||
@ -38,6 +39,9 @@ void meta_output_xrandr_apply_mode (MetaOutputXrandr *output_xrandr);
|
|||||||
void meta_output_xrandr_change_backlight (MetaOutputXrandr *output_xrandr,
|
void meta_output_xrandr_change_backlight (MetaOutputXrandr *output_xrandr,
|
||||||
int value);
|
int value);
|
||||||
|
|
||||||
|
void meta_output_xrandr_set_ctm (MetaOutputXrandr *output_xrandr,
|
||||||
|
const MetaOutputCtm *ctm);
|
||||||
|
|
||||||
GBytes * meta_output_xrandr_read_edid (MetaOutput *output_xrandr);
|
GBytes * meta_output_xrandr_read_edid (MetaOutput *output_xrandr);
|
||||||
|
|
||||||
MetaOutputXrandr * meta_output_xrandr_new (MetaGpuXrandr *gpu_xrandr,
|
MetaOutputXrandr * meta_output_xrandr_new (MetaGpuXrandr *gpu_xrandr,
|
||||||
|
@ -455,5 +455,19 @@
|
|||||||
<arg name="logical_monitors" direction="in" type="a(iiduba(ssa{sv}))" />
|
<arg name="logical_monitors" direction="in" type="a(iiduba(ssa{sv}))" />
|
||||||
<arg name="properties" direction="in" type="a{sv}" />
|
<arg name="properties" direction="in" type="a{sv}" />
|
||||||
</method>
|
</method>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
SetOutputCTM:
|
||||||
|
@serial: configuration serial
|
||||||
|
@output: API id of the output
|
||||||
|
@ctm: 3x3 matrix in fixed-point sign-magnitude S31.32
|
||||||
|
|
||||||
|
Changes the color transform matrix of @output
|
||||||
|
-->
|
||||||
|
<method name="SetOutputCTM">
|
||||||
|
<arg name="serial" direction="in" type="u" />
|
||||||
|
<arg name="output" direction="in" type="u" />
|
||||||
|
<arg name="ctm" direction="in" type="(ttttttttt)" />
|
||||||
|
</method>
|
||||||
</interface>
|
</interface>
|
||||||
</node>
|
</node>
|
||||||
|
Loading…
Reference in New Issue
Block a user