[mutter] x11: Add X11 color manager subclass



commit 17c99edfe0774ef2ce567d7e66b357e91003984f
Author: Jonas Ã…dahl <jadahl gmail com>
Date:   Mon Dec 6 11:47:00 2021 +0100

    x11: Add X11 color manager subclass
    
    This is used as part of the X11 backend to updated X11 root window
    properties according to the ICC Profiles in X Specification.
    
    Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2166>

 src/backends/meta-color-manager.h         |   1 +
 src/backends/x11/meta-backend-x11.c       |   3 +-
 src/backends/x11/meta-color-manager-x11.c | 207 ++++++++++++++++++++++++++++++
 src/backends/x11/meta-color-manager-x11.h |  30 +++++
 src/meson.build                           |   2 +
 src/tests/meta-backend-test.c             |  10 ++
 6 files changed, 252 insertions(+), 1 deletion(-)
---
diff --git a/src/backends/meta-color-manager.h b/src/backends/meta-color-manager.h
index 90369b8f73..2469222647 100644
--- a/src/backends/meta-color-manager.h
+++ b/src/backends/meta-color-manager.h
@@ -24,6 +24,7 @@
 #include "core/util-private.h"
 
 #define META_TYPE_COLOR_MANAGER (meta_color_manager_get_type ())
+META_EXPORT_TEST
 G_DECLARE_DERIVABLE_TYPE (MetaColorManager, meta_color_manager,
                           META, COLOR_MANAGER,
                           GObject)
diff --git a/src/backends/x11/meta-backend-x11.c b/src/backends/x11/meta-backend-x11.c
index 4d4a5da9c7..8d44305254 100644
--- a/src/backends/x11/meta-backend-x11.c
+++ b/src/backends/x11/meta-backend-x11.c
@@ -48,6 +48,7 @@
 #include "backends/meta-stage-private.h"
 #include "backends/x11/meta-barrier-x11.h"
 #include "backends/x11/meta-clutter-backend-x11.h"
+#include "backends/x11/meta-color-manager-x11.h"
 #include "backends/x11/meta-event-x11.h"
 #include "backends/x11/meta-seat-x11.h"
 #include "backends/x11/meta-stage-x11.h"
@@ -599,7 +600,7 @@ meta_backend_x11_create_clutter_backend (MetaBackend *backend)
 static MetaColorManager *
 meta_backend_x11_create_color_manager (MetaBackend *backend)
 {
-  return g_object_new (META_TYPE_COLOR_MANAGER,
+  return g_object_new (META_TYPE_COLOR_MANAGER_X11,
                        "backend", backend,
                        NULL);
 }
diff --git a/src/backends/x11/meta-color-manager-x11.c b/src/backends/x11/meta-color-manager-x11.c
new file mode 100644
index 0000000000..8f1e6370b0
--- /dev/null
+++ b/src/backends/x11/meta-color-manager-x11.c
@@ -0,0 +1,207 @@
+/*
+ * Copyright (C) 2007 William Jon McCann <mccann jhu edu>
+ * Copyright (C) 2011-2013 Richard Hughes <richard hughsie com>
+ * Copyright (C) 2020 NVIDIA CORPORATION
+ * Copyright (C) 2021 Red Hat Inc.
+ *
+ * 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 the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include "backends/x11/meta-color-manager-x11.h"
+
+#include <colord.h>
+#include <X11/Xatom.h>
+
+#include "backends/meta-color-device.h"
+#include "backends/meta-color-profile.h"
+#include "backends/meta-monitor.h"
+#include "backends/x11/meta-backend-x11.h"
+#include "backends/x11/meta-output-xrandr.h"
+
+struct _MetaColorManagerX11
+{
+  MetaColorManager parent;
+
+  CdIcc *srgb_cd_icc;
+  GBytes *srgb_icc_bytes;
+};
+
+G_DEFINE_TYPE (MetaColorManagerX11, meta_color_manager_x11,
+               META_TYPE_COLOR_MANAGER)
+
+/* see http://www.oyranos.org/wiki/index.php?title=ICC_Profiles_in_X_Specification_0.3 */
+#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
+on_color_device_updated (MetaColorManager *color_manager,
+                         MetaColorDevice  *color_device)
+{
+  MetaColorManagerX11 *color_manager_x11 =
+    META_COLOR_MANAGER_X11 (color_manager);
+  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);
+  Window xroot = meta_backend_x11_get_root_xwindow (backend_x11);
+  Atom icc_profile_atom;
+  Atom icc_profile_version_atom;
+  MetaMonitor *monitor;
+  const uint8_t *profile_contents = NULL;
+  size_t profile_size;
+
+  monitor = meta_color_device_get_monitor (color_device);
+  if (!meta_monitor_is_primary (monitor))
+    return;
+
+  if (meta_monitor_supports_color_transform (monitor))
+    {
+      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);
+        }
+    }
+
+  icc_profile_atom = XInternAtom (xdisplay, "_ICC_PROFILE", False);
+  icc_profile_version_atom = XInternAtom (xdisplay,
+                                          "_ICC_PROFILE_IN_X_VERSION", False);
+  if (profile_contents)
+    {
+      unsigned int version_data;
+
+      XChangeProperty (xdisplay, xroot,
+                       icc_profile_atom,
+                       XA_CARDINAL, 8,
+                       PropModeReplace,
+                       profile_contents, profile_size);
+
+      version_data =
+        ICC_PROFILE_IN_X_VERSION_MAJOR * 100 +
+        ICC_PROFILE_IN_X_VERSION_MINOR * 1;
+
+      XChangeProperty (xdisplay, xroot,
+                       icc_profile_version_atom,
+                       XA_CARDINAL, 8,
+                       PropModeReplace,
+                       (uint8_t *) &version_data, 1);
+    }
+  else
+    {
+      XDeleteProperty (xdisplay, xroot, icc_profile_atom);
+      XDeleteProperty (xdisplay, xroot, icc_profile_version_atom);
+    }
+}
+
+static void
+meta_color_manager_x11_constructed (GObject *object)
+{
+  MetaColorManager *color_manager = META_COLOR_MANAGER (object);
+
+  g_signal_connect (color_manager, "device-updated",
+                    G_CALLBACK (on_color_device_updated), NULL);
+
+  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
+meta_color_manager_x11_init (MetaColorManagerX11 *color_manager_x11)
+{
+}
diff --git a/src/backends/x11/meta-color-manager-x11.h b/src/backends/x11/meta-color-manager-x11.h
new file mode 100644
index 0000000000..cb178c0bc0
--- /dev/null
+++ b/src/backends/x11/meta-color-manager-x11.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2021 Red Hat Inc
+ *
+ * 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 the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef META_COLOR_MANAGER_X11_H
+#define META_COLOR_MANAGER_X11_H
+
+#include <glib-object.h>
+
+#include "backends/meta-color-manager-private.h"
+
+#define META_TYPE_COLOR_MANAGER_X11 (meta_color_manager_x11_get_type ())
+G_DECLARE_FINAL_TYPE (MetaColorManagerX11, meta_color_manager_x11,
+                      META, COLOR_MANAGER_X11,
+                      MetaColorManager)
+
+#endif /* META_COLOR_MANAGER_X11_H */
diff --git a/src/meson.build b/src/meson.build
index 4bc295057a..7b62379682 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -387,6 +387,8 @@ if have_x11
     'backends/x11/meta-barrier-x11.h',
     'backends/x11/meta-clutter-backend-x11.c',
     'backends/x11/meta-clutter-backend-x11.h',
+    'backends/x11/meta-color-manager-x11.c',
+    'backends/x11/meta-color-manager-x11.h',
     'backends/x11/meta-crtc-xrandr.c',
     'backends/x11/meta-crtc-xrandr.h',
     'backends/x11/meta-cursor-renderer-x11.c',
diff --git a/src/tests/meta-backend-test.c b/src/tests/meta-backend-test.c
index 6916994e4b..9101d8874b 100644
--- a/src/tests/meta-backend-test.c
+++ b/src/tests/meta-backend-test.c
@@ -21,6 +21,7 @@
 
 #include "tests/meta-backend-test.h"
 
+#include "backends/meta-color-manager.h"
 #include "tests/meta-gpu-test.h"
 #include "tests/meta-monitor-manager-test.h"
 
@@ -76,6 +77,14 @@ meta_backend_test_create_monitor_manager (MetaBackend *backend,
                        NULL);
 }
 
+static MetaColorManager *
+meta_backend_test_create_color_manager (MetaBackend *backend)
+{
+  return g_object_new (META_TYPE_COLOR_MANAGER,
+                       "backend", backend,
+                       NULL);
+}
+
 ClutterInputDevice *
 meta_backend_test_add_test_device (MetaBackendTest        *backend_test,
                                    const char             *name,
@@ -183,6 +192,7 @@ meta_backend_test_class_init (MetaBackendTestClass *klass)
     META_BACKEND_X11_NESTED_CLASS (klass);
 
   backend_class->create_monitor_manager = meta_backend_test_create_monitor_manager;
+  backend_class->create_color_manager = meta_backend_test_create_color_manager;
   backend_class->is_lid_closed = meta_backend_test_is_lid_closed;
 
   backend_x11_nested_class->init_gpus = meta_backend_test_init_gpus;


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]