[gnome-flashback] monitor-manager: support the CTM RandR property
- From: Alberts Muktupāvels <muktupavels src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-flashback] monitor-manager: support the CTM RandR property
- Date: Sat, 13 Aug 2022 20:32:06 +0000 (UTC)
commit 55c01885e92e9887038ab82584e428b587b72169
Author: Alberts Muktupāvels <alberts muktupavels gmail com>
Date: Sat Aug 13 13:08:07 2022 +0300
monitor-manager: support the CTM RandR property
Based on mutter commits:
https://gitlab.gnome.org/GNOME/mutter/-/commit/e88467f9d76bcacecf14
https://gitlab.gnome.org/GNOME/mutter/-/commit/aa498dc27a47a527558f
https://gitlab.gnome.org/GNOME/mutter/-/commit/cf8efb58274d9a81ec00
backends/gf-monitor-manager-private.h | 4 ++
backends/gf-monitor-manager-types-private.h | 1 +
backends/gf-monitor-manager-xrandr.c | 9 ++++
backends/gf-monitor-manager.c | 69 +++++++++++++++++++++++++
backends/gf-output-info-private.h | 2 +
backends/gf-output-private.h | 6 +++
backends/gf-output-xrandr-private.h | 4 ++
backends/gf-output-xrandr.c | 79 ++++++++++++++++++++++++++++-
backends/org.gnome.Mutter.DisplayConfig.xml | 15 ++++++
9 files changed, 188 insertions(+), 1 deletion(-)
---
diff --git a/backends/gf-monitor-manager-private.h b/backends/gf-monitor-manager-private.h
index fdcdde8..a05893e 100644
--- a/backends/gf-monitor-manager-private.h
+++ b/backends/gf-monitor-manager-private.h
@@ -4,6 +4,7 @@
* Copyright (C) 2004-2006 Elijah Newren
* Copyright (C) 2013 Red Hat Inc.
* Copyright (C) 2017-2019 Alberts Muktupāvels
+ * Copyright (C) 2020 NVIDIA CORPORATION
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -140,6 +141,9 @@ typedef struct
gint *max_height);
GfLogicalMonitorLayoutMode (* get_default_layout_mode) (GfMonitorManager *manager);
+
+ void (* set_output_ctm) (GfOutput *output,
+ const GfOutputCtm *ctm);
} GfMonitorManagerClass;
GType gf_monitor_manager_get_type (void);
diff --git a/backends/gf-monitor-manager-types-private.h b/backends/gf-monitor-manager-types-private.h
index 384a54c..15d7678 100644
--- a/backends/gf-monitor-manager-types-private.h
+++ b/backends/gf-monitor-manager-types-private.h
@@ -43,6 +43,7 @@ typedef struct _GfGpu GfGpu;
typedef struct _GfCrtc GfCrtc;
typedef struct _GfOutput GfOutput;
+typedef struct _GfOutputCtm GfOutputCtm;
typedef struct _GfCrtcMode GfCrtcMode;
G_END_DECLS
diff --git a/backends/gf-monitor-manager-xrandr.c b/backends/gf-monitor-manager-xrandr.c
index 178d48b..eece357 100644
--- a/backends/gf-monitor-manager-xrandr.c
+++ b/backends/gf-monitor-manager-xrandr.c
@@ -7,6 +7,7 @@
* Copyright (C) 2004-2006 Elijah Newren
* Copyright (C) 2013 Red Hat Inc.
* Copyright (C) 2017-2019 Alberts Muktupāvels
+ * Copyright (C) 2020 NVIDIA CORPORATION
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -1007,6 +1008,13 @@ gf_monitor_manager_xrandr_get_default_layout_mode (GfMonitorManager *manager)
return GF_LOGICAL_MONITOR_LAYOUT_MODE_PHYSICAL;
}
+static void
+gf_monitor_manager_xrandr_set_output_ctm (GfOutput *output,
+ const GfOutputCtm *ctm)
+{
+ gf_output_xrandr_set_ctm (GF_OUTPUT_XRANDR (output), ctm);
+}
+
static void
gf_monitor_manager_xrandr_class_init (GfMonitorManagerXrandrClass *xrandr_class)
{
@@ -1035,6 +1043,7 @@ gf_monitor_manager_xrandr_class_init (GfMonitorManagerXrandrClass *xrandr_class)
manager_class->get_capabilities = gf_monitor_manager_xrandr_get_capabilities;
manager_class->get_max_screen_size = gf_monitor_manager_xrandr_get_max_screen_size;
manager_class->get_default_layout_mode = gf_monitor_manager_xrandr_get_default_layout_mode;
+ manager_class->set_output_ctm = gf_monitor_manager_xrandr_set_output_ctm;
}
static void
diff --git a/backends/gf-monitor-manager.c b/backends/gf-monitor-manager.c
index 1e3289e..4e9d63c 100644
--- a/backends/gf-monitor-manager.c
+++ b/backends/gf-monitor-manager.c
@@ -7,6 +7,7 @@
* Copyright (C) 2004-2006 Elijah Newren
* Copyright (C) 2013 Red Hat Inc.
* Copyright (C) 2017-2019 Alberts Muktupāvels
+ * Copyright (C) 2020 NVIDIA CORPORATION
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -1373,6 +1374,7 @@ gf_monitor_manager_handle_get_resources (GfDBusDisplayConfig *skeleton,
const char *connector_type_name;
gboolean is_underscanning;
gboolean supports_underscanning;
+ gboolean supports_color_transform;
output = l->data;
output_info = gf_output_get_info (output);
@@ -1420,6 +1422,7 @@ gf_monitor_manager_handle_get_resources (GfDBusDisplayConfig *skeleton,
is_underscanning = gf_output_is_underscanning (output);
connector_type_name = get_connector_type_name (output_info->connector_type);
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_add (&properties, "{sv}", "vendor",
@@ -1448,6 +1451,8 @@ gf_monitor_manager_handle_get_resources (GfDBusDisplayConfig *skeleton,
g_variant_new_boolean (is_underscanning));
g_variant_builder_add (&properties, "{sv}", "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);
@@ -2133,6 +2138,67 @@ gf_monitor_manager_handle_apply_monitors_config (GfDBusDisplayConfig *skeleton
return TRUE;
}
+static gboolean
+gf_monitor_manager_handle_set_output_ctm (GfDBusDisplayConfig *skeleton,
+ GDBusMethodInvocation *invocation,
+ guint serial,
+ guint output_id,
+ GVariant *ctm_var,
+ GfMonitorManager *self)
+{
+ GfMonitorManagerClass *manager_class;
+ GList *combined_outputs;
+ GfOutput *output;
+ GfOutputCtm ctm;
+ int i;
+
+ if (serial != self->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 (self, gf_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);
+ }
+
+ manager_class = GF_MONITOR_MANAGER_GET_CLASS (self);
+
+ if (manager_class->set_output_ctm != NULL)
+ manager_class->set_output_ctm (output, &ctm);
+
+ gf_dbus_display_config_complete_set_output_ctm (skeleton, invocation);
+
+ return TRUE;
+}
+
static void
monitor_manager_setup_dbus_config_handlers (GfMonitorManager *manager)
{
@@ -2154,6 +2220,9 @@ monitor_manager_setup_dbus_config_handlers (GfMonitorManager *manager)
g_signal_connect_object (manager->display_config, "handle-apply-monitors-config",
G_CALLBACK (gf_monitor_manager_handle_apply_monitors_config),
manager, 0);
+ g_signal_connect_object (manager->display_config, "handle-set-output-ctm",
+ G_CALLBACK (gf_monitor_manager_handle_set_output_ctm),
+ manager, 0);
}
static void
diff --git a/backends/gf-output-info-private.h b/backends/gf-output-info-private.h
index 29db275..d37b19e 100644
--- a/backends/gf-output-info-private.h
+++ b/backends/gf-output-info-private.h
@@ -4,6 +4,7 @@
* Copyright (C) 2004-2006 Elijah Newren
* Copyright (C) 2013 Red Hat Inc.
* Copyright (C) 2017-2020 Alberts Muktupāvels
+ * Copyright (C) 2020 NVIDIA CORPORATION
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -71,6 +72,7 @@ typedef struct
int backlight_max;
gboolean supports_underscanning;
+ gboolean supports_color_transform;
/* Get a new preferred mode on hotplug events, to handle
* dynamic guest resizing
diff --git a/backends/gf-output-private.h b/backends/gf-output-private.h
index 1ac0d24..c7c45eb 100644
--- a/backends/gf-output-private.h
+++ b/backends/gf-output-private.h
@@ -4,6 +4,7 @@
* Copyright (C) 2004-2006 Elijah Newren
* Copyright (C) 2013 Red Hat Inc.
* Copyright (C) 2017-2019 Alberts Muktupāvels
+ * Copyright (C) 2020 NVIDIA CORPORATION
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -33,6 +34,11 @@
G_BEGIN_DECLS
+typedef struct _GfOutputCtm
+{
+ uint64_t matrix[9];
+} GfOutputCtm;
+
typedef struct
{
GfOutput *output;
diff --git a/backends/gf-output-xrandr-private.h b/backends/gf-output-xrandr-private.h
index c8a7d32..49f9300 100644
--- a/backends/gf-output-xrandr-private.h
+++ b/backends/gf-output-xrandr-private.h
@@ -1,6 +1,7 @@
/*
* Copyright (C) 2017 Red Hat
* Copyright (C) 2019 Alberts Muktupāvels
+ * Copyright (C) 2020 NVIDIA CORPORATION
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -42,6 +43,9 @@ void gf_output_xrandr_apply_mode (GfOutputXrandr *self);
void gf_output_xrandr_change_backlight (GfOutputXrandr *self,
int value);
+void gf_output_xrandr_set_ctm (GfOutputXrandr *self,
+ const GfOutputCtm *ctm);
+
G_END_DECLS
#endif
diff --git a/backends/gf-output-xrandr.c b/backends/gf-output-xrandr.c
index 230ec23..c9ebda6 100644
--- a/backends/gf-output-xrandr.c
+++ b/backends/gf-output-xrandr.c
@@ -7,6 +7,7 @@
* Copyright (C) 2004-2006 Elijah Newren
* Copyright (C) 2013-2017 Red Hat Inc.
* Copyright (C) 2017-2019 Alberts Muktupāvels
+ * Copyright (C) 2020 NVIDIA CORPORATION
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -36,11 +37,29 @@
struct _GfOutputXrandr
{
- GfOutput parent;
+ GfOutput parent;
+
+ gboolean ctm_initialized;
+ GfOutputCtm ctm;
};
G_DEFINE_TYPE (GfOutputXrandr, gf_output_xrandr, GF_TYPE_OUTPUT)
+static gboolean
+ctm_is_equal (const GfOutputCtm *ctm1,
+ const GfOutputCtm *ctm2)
+{
+ int i;
+
+ for (i = 0; i < 9; i++)
+ {
+ if (ctm1->matrix[i] != ctm2->matrix[i])
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
static Display *
xdisplay_from_gpu (GfGpu *gpu)
{
@@ -705,6 +724,35 @@ output_get_supports_underscanning_xrandr (Display *xdisplay,
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;
+ unsigned char *buffer;
+
+ atom = XInternAtom (xdisplay, "CTM", False);
+ buffer = NULL;
+
+ XRRGetOutputProperty (xdisplay,
+ (XID) output_id,
+ atom,
+ 0, G_MAXLONG, False, False, XA_INTEGER,
+ &actual_type, &actual_format,
+ &nitems, &bytes_after, &buffer);
+
+ XFree (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
normalize_backlight (GfOutput *output,
gint hw_value)
@@ -872,6 +920,9 @@ gf_output_xrandr_new (GfGpuXrandr *gpu_xrandr,
output_info->supports_underscanning = 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 = g_object_new (GF_TYPE_OUTPUT_XRANDR,
@@ -977,3 +1028,29 @@ gf_output_xrandr_change_backlight (GfOutputXrandr *self,
/* We're not selecting for property notifies, so update the value immediately */
gf_output_set_backlight (output, normalize_backlight (output, hw_value));
}
+
+void
+gf_output_xrandr_set_ctm (GfOutputXrandr *self,
+ const GfOutputCtm *ctm)
+{
+ if (!self->ctm_initialized || !ctm_is_equal (ctm, &self->ctm))
+ {
+ GfOutput *output;
+ Display *xdisplay;
+ Atom ctm_atom;
+
+ output = GF_OUTPUT (self);
+
+ xdisplay = xdisplay_from_output (output);
+ ctm_atom = XInternAtom (xdisplay, "CTM", False);
+
+ xcb_randr_change_output_property (XGetXCBConnection (xdisplay),
+ (XID) gf_output_get_id (output),
+ ctm_atom, XCB_ATOM_INTEGER, 32,
+ XCB_PROP_MODE_REPLACE,
+ 18, &ctm->matrix);
+
+ self->ctm_initialized = TRUE;
+ self->ctm = *ctm;
+ }
+}
diff --git a/backends/org.gnome.Mutter.DisplayConfig.xml b/backends/org.gnome.Mutter.DisplayConfig.xml
index d0afd23..33dcbd6 100644
--- a/backends/org.gnome.Mutter.DisplayConfig.xml
+++ b/backends/org.gnome.Mutter.DisplayConfig.xml
@@ -403,5 +403,20 @@
<arg name="logical_monitors" direction="in" type="a(iiduba(ssa{sv}))" />
<arg name="properties" direction="in" type="a{sv}" />
</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>
</node>
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]