[gnome-flashback] backends: split out CRTC/output management to GfGpu



commit 853edf459354548ce08147a0c34053aa261cb120
Author: Alberts Muktupāvels <alberts muktupavels gmail com>
Date:   Sun Jul 7 19:34:41 2019 +0300

    backends: split out CRTC/output management to GfGpu
    
    Based on mutter commit:
    https://gitlab.gnome.org/GNOME/mutter/commit/c1683073f174406242ea

 backends/Makefile.am                         |   4 +
 backends/gf-crtc-private.h                   |   8 +-
 backends/gf-crtc-xrandr-private.h            |   4 +-
 backends/gf-crtc-xrandr.c                    |  17 +-
 backends/gf-crtc.c                           |   8 +-
 backends/gf-gpu-private.h                    |  63 ++++++
 backends/gf-gpu-xrandr-private.h             |  43 ++++
 backends/gf-gpu-xrandr.c                     | 301 +++++++++++++++++++++++++++
 backends/gf-gpu.c                            | 261 +++++++++++++++++++++++
 backends/gf-monitor-manager-dummy.c          |   8 +-
 backends/gf-monitor-manager-kms.c            |   6 -
 backends/gf-monitor-manager-private.h        |  17 +-
 backends/gf-monitor-manager-types-private.h  |   4 +-
 backends/gf-monitor-manager-xrandr-private.h |  10 +-
 backends/gf-monitor-manager-xrandr.c         | 232 +++------------------
 backends/gf-monitor-manager.c                | 155 +++++++++-----
 backends/gf-monitor-normal-private.h         |   4 +-
 backends/gf-monitor-normal.c                 |   6 +-
 backends/gf-monitor-private.h                |   4 +-
 backends/gf-monitor-tiled-private.h          |   6 +-
 backends/gf-monitor-tiled.c                  |  20 +-
 backends/gf-monitor.c                        |  47 +++--
 backends/gf-output-private.h                 |  14 +-
 backends/gf-output-xrandr-private.h          |  18 +-
 backends/gf-output-xrandr.c                  |  44 ++--
 backends/gf-output.c                         |   8 +-
 26 files changed, 934 insertions(+), 378 deletions(-)
---
diff --git a/backends/Makefile.am b/backends/Makefile.am
index e6b9fc4..bb022ef 100644
--- a/backends/Makefile.am
+++ b/backends/Makefile.am
@@ -38,6 +38,10 @@ libbackends_la_SOURCES = \
        gf-display-config-shared.h \
        gf-edid-parse.c \
        gf-edid-private.h \
+       gf-gpu-private.h \
+       gf-gpu-xrandr-private.h \
+       gf-gpu-xrandr.c \
+       gf-gpu.c \
        gf-logical-monitor-config-private.h \
        gf-logical-monitor-config.c \
        gf-logical-monitor-private.h \
diff --git a/backends/gf-crtc-private.h b/backends/gf-crtc-private.h
index 35d9e57..98d4a48 100644
--- a/backends/gf-crtc-private.h
+++ b/backends/gf-crtc-private.h
@@ -3,7 +3,7 @@
  * Copyright (C) 2003 Rob Adams
  * Copyright (C) 2004-2006 Elijah Newren
  * Copyright (C) 2013 Red Hat Inc.
- * Copyright (C) 2017 Alberts Muktupāvels
+ * Copyright (C) 2017-2019 Alberts Muktupāvels
  *
  * 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
@@ -27,9 +27,9 @@
 
 #include <glib-object.h>
 
+#include "gf-gpu-private.h"
 #include "gf-monitor-manager-enums-private.h"
 #include "gf-monitor-manager-types-private.h"
-#include "gf-monitor-manager.h"
 #include "gf-rectangle.h"
 
 G_BEGIN_DECLS
@@ -38,7 +38,7 @@ struct _GfCrtc
 {
   GObject             parent;
 
-  GfMonitorManager   *monitor_manager;
+  GfGpu              *gpu;
 
   glong               crtc_id;
   GfRectangle         rect;
@@ -91,7 +91,7 @@ G_DECLARE_FINAL_TYPE (GfCrtc, gf_crtc, GF, CRTC, GObject)
 #define GF_TYPE_CRTC_MODE (gf_crtc_mode_get_type ())
 G_DECLARE_FINAL_TYPE (GfCrtcMode, gf_crtc_mode, GF, CRTC_MODE, GObject)
 
-GfMonitorManager *gf_crtc_get_monitor_manager (GfCrtc *crtc);
+GfGpu *gf_crtc_get_gpu (GfCrtc *crtc);
 
 G_END_DECLS
 
diff --git a/backends/gf-crtc-xrandr-private.h b/backends/gf-crtc-xrandr-private.h
index 16ad70f..05a5bd4 100644
--- a/backends/gf-crtc-xrandr-private.h
+++ b/backends/gf-crtc-xrandr-private.h
@@ -26,11 +26,11 @@
 #include <xcb/randr.h>
 
 #include "gf-crtc-private.h"
-#include "gf-monitor-manager-xrandr-private.h"
+#include "gf-gpu-xrandr-private.h"
 
 G_BEGIN_DECLS
 
-GfCrtc   *gf_create_xrandr_crtc     (GfMonitorManager     *monitor_manager,
+GfCrtc   *gf_create_xrandr_crtc     (GfGpuXrandr          *gpu_xrandr,
                                      XRRCrtcInfo          *xrandr_crtc,
                                      RRCrtc                crtc_id,
                                      XRRScreenResources   *resources);
diff --git a/backends/gf-crtc-xrandr.c b/backends/gf-crtc-xrandr.c
index 14c8525..1a16bfc 100644
--- a/backends/gf-crtc-xrandr.c
+++ b/backends/gf-crtc-xrandr.c
@@ -103,7 +103,7 @@ gf_monitor_transform_from_xrandr_all (Rotation rotation)
 }
 
 GfCrtc *
-gf_create_xrandr_crtc (GfMonitorManager   *monitor_manager,
+gf_create_xrandr_crtc (GfGpuXrandr        *gpu_xrandr,
                        XRRCrtcInfo        *xrandr_crtc,
                        RRCrtc              crtc_id,
                        XRRScreenResources *resources)
@@ -111,10 +111,11 @@ gf_create_xrandr_crtc (GfMonitorManager   *monitor_manager,
 {
   GfCrtc *crtc;
   unsigned int i;
+  GList *modes;
 
   crtc = g_object_new (GF_TYPE_CRTC, NULL);
 
-  crtc->monitor_manager = monitor_manager;
+  crtc->gpu = GF_GPU (gpu_xrandr);
   crtc->crtc_id = crtc_id;
   crtc->rect.x = xrandr_crtc->x;
   crtc->rect.y = xrandr_crtc->y;
@@ -124,11 +125,12 @@ gf_create_xrandr_crtc (GfMonitorManager   *monitor_manager,
   crtc->transform = gf_monitor_transform_from_xrandr (xrandr_crtc->rotation);
   crtc->all_transforms = gf_monitor_transform_from_xrandr_all (xrandr_crtc->rotations);
 
+  modes = gf_gpu_get_modes (crtc->gpu);
   for (i = 0; i < (guint) resources->nmode; i++)
     {
       if (resources->modes[i].id == xrandr_crtc->mode)
         {
-          crtc->current_mode = g_list_nth_data (monitor_manager->modes, i);
+          crtc->current_mode = g_list_nth_data (modes, i);
           break;
         }
     }
@@ -148,6 +150,8 @@ gf_crtc_xrandr_set_config (GfCrtc               *crtc,
                            int                   n_outputs,
                            xcb_timestamp_t      *out_timestamp)
 {
+  GfGpu *gpu;
+  GfGpuXrandr *gpu_xrandr;
   GfMonitorManager *monitor_manager;
   GfMonitorManagerXrandr *monitor_manager_xrandr;
   Display *xdisplay;
@@ -158,11 +162,14 @@ gf_crtc_xrandr_set_config (GfCrtc               *crtc,
   xcb_randr_set_crtc_config_reply_t *reply;
   xcb_generic_error_t *xcb_error;
 
-  monitor_manager = gf_crtc_get_monitor_manager (crtc);
+  gpu = gf_crtc_get_gpu (crtc);
+  gpu_xrandr = GF_GPU_XRANDR (gpu);
+
+  monitor_manager = gf_gpu_get_monitor_manager (gpu);
   monitor_manager_xrandr = GF_MONITOR_MANAGER_XRANDR (monitor_manager);
 
   xdisplay = gf_monitor_manager_xrandr_get_xdisplay (monitor_manager_xrandr);
-  resources = gf_monitor_manager_xrandr_get_resources (monitor_manager_xrandr);
+  resources = gf_gpu_xrandr_get_resources (gpu_xrandr);
   xcb_conn = XGetXCBConnection (xdisplay);
 
   config_timestamp = resources->configTimestamp;
diff --git a/backends/gf-crtc.c b/backends/gf-crtc.c
index 4c27329..9ba8f27 100644
--- a/backends/gf-crtc.c
+++ b/backends/gf-crtc.c
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2017 Red Hat
- * Copyright (C) 2018 Alberts Muktupāvels
+ * Copyright (C) 2018-2019 Alberts Muktupāvels
  *
  * 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
@@ -49,8 +49,8 @@ gf_crtc_init (GfCrtc *crtc)
 {
 }
 
-GfMonitorManager *
-gf_crtc_get_monitor_manager (GfCrtc *crtc)
+GfGpu *
+gf_crtc_get_gpu (GfCrtc *crtc)
 {
-  return crtc->monitor_manager;
+  return crtc->gpu;
 }
diff --git a/backends/gf-gpu-private.h b/backends/gf-gpu-private.h
new file mode 100644
index 0000000..a7381f4
--- /dev/null
+++ b/backends/gf-gpu-private.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2017 Red Hat
+ * Copyright (C) 2019 Alberts Muktupāvels
+ *
+ * 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 3 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 GF_GPU_PRIVATE_H
+#define GF_GPU_PRIVATE_H
+
+#include <glib-object.h>
+
+#include "gf-monitor-manager-private.h"
+
+G_BEGIN_DECLS
+
+#define GF_TYPE_GPU (gf_gpu_get_type ())
+G_DECLARE_DERIVABLE_TYPE (GfGpu, gf_gpu, GF, GPU, GObject)
+
+struct _GfGpuClass
+{
+  GObjectClass parent_class;
+
+  gboolean (* read_current) (GfGpu   *gpu,
+                             GError **error);
+};
+
+gboolean          gf_gpu_read_current            (GfGpu   *gpu,
+                                                  GError **error);
+
+gboolean          gf_gpu_has_hotplug_mode_update (GfGpu   *gpu);
+
+GfMonitorManager *gf_gpu_get_monitor_manager     (GfGpu   *gpu);
+
+GList            *gf_gpu_get_outputs             (GfGpu   *gpu);
+
+GList            *gf_gpu_get_crtcs               (GfGpu   *gpu);
+
+GList            *gf_gpu_get_modes               (GfGpu   *gpu);
+
+void              gf_gpu_take_outputs            (GfGpu   *gpu,
+                                                  GList   *outputs);
+
+void              gf_gpu_take_crtcs              (GfGpu   *gpu,
+                                                  GList   *crtcs);
+
+void              gf_gpu_take_modes              (GfGpu   *gpu,
+                                                  GList   *modes);
+
+G_END_DECLS
+
+#endif
diff --git a/backends/gf-gpu-xrandr-private.h b/backends/gf-gpu-xrandr-private.h
new file mode 100644
index 0000000..31a5dea
--- /dev/null
+++ b/backends/gf-gpu-xrandr-private.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2017 Red Hat
+ * Copyright (C) 2019 Alberts Muktupāvels
+ *
+ * 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 3 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 GF_GPU_XRANDR_PRIVATE_H
+#define GF_GPU_XRANDR_PRIVATE_H
+
+#include <glib-object.h>
+#include <X11/extensions/Xrandr.h>
+
+#include "gf-gpu-private.h"
+#include "gf-monitor-manager-xrandr-private.h"
+
+G_BEGIN_DECLS
+
+#define GF_TYPE_GPU_XRANDR (gf_gpu_xrandr_get_type ())
+G_DECLARE_FINAL_TYPE (GfGpuXrandr, gf_gpu_xrandr, GF, GPU_XRANDR, GfGpu)
+
+GfGpuXrandr        *gf_gpu_xrandr_new                 (GfMonitorManagerXrandr *monitor_manager_xrandr);
+
+XRRScreenResources *gf_gpu_xrandr_get_resources       (GfGpuXrandr            *gpu_xrandr);
+
+void                gf_gpu_xrandr_get_max_screen_size (GfGpuXrandr            *gpu_xrandr,
+                                                       int                    *max_width,
+                                                       int                    *max_height);
+
+G_END_DECLS
+
+#endif
diff --git a/backends/gf-gpu-xrandr.c b/backends/gf-gpu-xrandr.c
new file mode 100644
index 0000000..ea6b3fd
--- /dev/null
+++ b/backends/gf-gpu-xrandr.c
@@ -0,0 +1,301 @@
+/*
+ * Copyright (C) 2001, 2002 Havoc Pennington
+ * Copyright (C) 2002, 2003 Red Hat Inc.
+ * Some ICCCM manager selection code derived from fvwm2,
+ * Copyright (C) 2001 Dominik Vogt, Matthias Clasen, and fvwm2 team
+ * Copyright (C) 2003 Rob Adams
+ * Copyright (C) 2004-2006 Elijah Newren
+ * Copyright (C) 2013-2017 Red Hat Inc.
+ * Copyright (C) 2019 Alberts Muktupāvels
+ *
+ * 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 3 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 "gf-gpu-xrandr-private.h"
+
+#include <X11/extensions/dpms.h>
+#include <X11/Xlibint.h>
+
+#include "gf-crtc-xrandr-private.h"
+#include "gf-monitor-manager-xrandr-private.h"
+#include "gf-output-private.h"
+#include "gf-output-xrandr-private.h"
+
+struct _GfGpuXrandr
+{
+  GfGpu               parent;
+
+  XRRScreenResources *resources;
+
+  int                 max_screen_width;
+  int                 max_screen_height;
+};
+
+G_DEFINE_TYPE (GfGpuXrandr, gf_gpu_xrandr, GF_TYPE_GPU)
+
+static gint
+compare_outputs (const void *one,
+                 const void *two)
+{
+  const GfOutput *o_one = one, *o_two = two;
+
+  return strcmp (o_one->name, o_two->name);
+}
+
+static char *
+get_xmode_name (XRRModeInfo *xmode)
+{
+  int width = xmode->width;
+  int height = xmode->height;
+
+  return g_strdup_printf ("%dx%d", width, height);
+}
+
+static void
+gf_gpu_xrandr_finalize (GObject *object)
+{
+  GfGpuXrandr *gpu_xrandr;
+
+  gpu_xrandr = GF_GPU_XRANDR (object);
+
+  g_clear_pointer (&gpu_xrandr->resources, XRRFreeScreenResources);
+
+  G_OBJECT_CLASS (gf_gpu_xrandr_parent_class)->finalize (object);
+}
+
+static gboolean
+gf_gpu_xrandr_read_current (GfGpu   *gpu,
+                            GError **error)
+{
+  GfGpuXrandr *gpu_xrandr;
+  GfMonitorManager *monitor_manager;
+  GfMonitorManagerXrandr *monitor_manager_xrandr;
+  Display *xdisplay;
+  XRRScreenResources *resources;
+  CARD16 dpms_state;
+  BOOL dpms_enabled;
+  gint min_width;
+  gint min_height;
+  Screen *screen;
+  GList *outputs;
+  GList *modes;
+  GList *crtcs;
+  guint i, j;
+  GList *l;
+  RROutput primary_output;
+
+  gpu_xrandr = GF_GPU_XRANDR (gpu);
+  monitor_manager = gf_gpu_get_monitor_manager (gpu);
+  monitor_manager_xrandr = GF_MONITOR_MANAGER_XRANDR (monitor_manager);
+  xdisplay = gf_monitor_manager_xrandr_get_xdisplay (monitor_manager_xrandr);
+
+  g_clear_pointer (&gpu_xrandr->resources, XRRFreeScreenResources);
+
+  if (DPMSCapable (xdisplay) &&
+      DPMSInfo (xdisplay, &dpms_state, &dpms_enabled) &&
+      dpms_enabled)
+    {
+      switch (dpms_state)
+        {
+          case DPMSModeOn:
+            monitor_manager->power_save_mode = GF_POWER_SAVE_ON;
+            break;
+
+          case DPMSModeStandby:
+            monitor_manager->power_save_mode = GF_POWER_SAVE_STANDBY;
+            break;
+
+          case DPMSModeSuspend:
+            monitor_manager->power_save_mode = GF_POWER_SAVE_SUSPEND;
+            break;
+
+          case DPMSModeOff:
+            monitor_manager->power_save_mode = GF_POWER_SAVE_OFF;
+            break;
+
+          default:
+            monitor_manager->power_save_mode = GF_POWER_SAVE_UNSUPPORTED;
+            break;
+        }
+    }
+  else
+    {
+      monitor_manager->power_save_mode = GF_POWER_SAVE_UNSUPPORTED;
+    }
+
+  XRRGetScreenSizeRange (xdisplay, DefaultRootWindow (xdisplay),
+                         &min_width, &min_height,
+                         &gpu_xrandr->max_screen_width,
+                         &gpu_xrandr->max_screen_height);
+
+  screen = ScreenOfDisplay (xdisplay, DefaultScreen (xdisplay));
+  /* This is updated because we called RRUpdateConfiguration below */
+  monitor_manager->screen_width = WidthOfScreen (screen);
+  monitor_manager->screen_height = HeightOfScreen (screen);
+
+  resources = XRRGetScreenResourcesCurrent (xdisplay, DefaultRootWindow (xdisplay));
+
+  if (!resources)
+    {
+      g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+                   "Failed to retrieve Xrandr screen resources");
+      return FALSE;
+    }
+
+  gpu_xrandr->resources = resources;
+
+  outputs = NULL;
+  modes = NULL;
+  crtcs = NULL;
+
+  for (i = 0; i < (guint) resources->nmode; i++)
+    {
+      XRRModeInfo *xmode;
+      GfCrtcMode *mode;
+
+      xmode = &resources->modes[i];
+      mode = g_object_new (GF_TYPE_CRTC_MODE, NULL);
+
+      mode->mode_id = xmode->id;
+      mode->width = xmode->width;
+      mode->height = xmode->height;
+      mode->refresh_rate = (xmode->dotClock / ((gfloat) xmode->hTotal * xmode->vTotal));
+      mode->flags = xmode->modeFlags;
+      mode->name = get_xmode_name (xmode);
+
+      modes = g_list_append (modes, mode);
+    }
+
+  gf_gpu_take_modes (gpu, modes);
+
+  for (i = 0; i < (guint) resources->ncrtc; i++)
+    {
+      XRRCrtcInfo *xrandr_crtc;
+      RRCrtc crtc_id;
+      GfCrtc *crtc;
+
+      crtc_id = resources->crtcs[i];
+      xrandr_crtc = XRRGetCrtcInfo (xdisplay, resources, crtc_id);
+      crtc = gf_create_xrandr_crtc (gpu_xrandr, xrandr_crtc, crtc_id, resources);
+
+      crtcs = g_list_append (crtcs, crtc);
+      XRRFreeCrtcInfo (xrandr_crtc);
+    }
+
+  gf_gpu_take_crtcs (gpu, crtcs);
+
+  primary_output = XRRGetOutputPrimary (xdisplay, DefaultRootWindow (xdisplay));
+
+  for (i = 0; i < (guint) resources->noutput; i++)
+    {
+      RROutput output_id;
+      XRROutputInfo *xrandr_output;
+
+      output_id = resources->outputs[i];
+      xrandr_output = XRRGetOutputInfo (xdisplay, resources, output_id);
+
+      if (!xrandr_output)
+        continue;
+
+      if (xrandr_output->connection != RR_Disconnected)
+        {
+          GfOutput *output;
+
+          output = gf_create_xrandr_output (gpu_xrandr,
+                                            xrandr_output,
+                                            output_id,
+                                            primary_output);
+
+          if (output)
+            outputs = g_list_prepend (outputs, output);
+        }
+
+      XRRFreeOutputInfo (xrandr_output);
+    }
+
+  /* Sort the outputs for easier handling in GfMonitorConfig */
+  outputs = g_list_sort (outputs, compare_outputs);
+
+  gf_gpu_take_outputs (gpu, outputs);
+
+  /* Now fix the clones */
+  for (l = outputs; l; l = l->next)
+    {
+      GfOutput *output;
+      GList *k;
+
+      output = l->data;
+
+      for (j = 0; j < output->n_possible_clones; j++)
+        {
+          RROutput clone = GPOINTER_TO_INT (output->possible_clones[j]);
+
+          for (k = outputs; k; k = k->next)
+            {
+              GfOutput *possible_clone = k->data;
+
+              if (clone == (XID) possible_clone->winsys_id)
+                {
+                  output->possible_clones[j] = possible_clone;
+                  break;
+                }
+            }
+        }
+    }
+
+  return TRUE;
+}
+
+static void
+gf_gpu_xrandr_class_init (GfGpuXrandrClass *gpu_xrandr_class)
+{
+  GObjectClass *object_class;
+  GfGpuClass *gpu_class;
+
+  object_class = G_OBJECT_CLASS (gpu_xrandr_class);
+  gpu_class = GF_GPU_CLASS (gpu_xrandr_class);
+
+  object_class->finalize = gf_gpu_xrandr_finalize;
+
+  gpu_class->read_current = gf_gpu_xrandr_read_current;
+}
+
+static void
+gf_gpu_xrandr_init (GfGpuXrandr *gpu_xrandr)
+{
+}
+
+GfGpuXrandr *
+gf_gpu_xrandr_new (GfMonitorManagerXrandr *monitor_manager_xrandr)
+{
+  return g_object_new (GF_TYPE_GPU_XRANDR,
+                       "monitor-manager", monitor_manager_xrandr,
+                       NULL);
+}
+
+XRRScreenResources *
+gf_gpu_xrandr_get_resources (GfGpuXrandr *gpu_xrandr)
+{
+  return gpu_xrandr->resources;
+}
+
+void
+gf_gpu_xrandr_get_max_screen_size (GfGpuXrandr *gpu_xrandr,
+                                   int         *max_width,
+                                   int         *max_height)
+{
+  *max_width = gpu_xrandr->max_screen_width;
+  *max_height = gpu_xrandr->max_screen_height;
+}
diff --git a/backends/gf-gpu.c b/backends/gf-gpu.c
new file mode 100644
index 0000000..e4d81e1
--- /dev/null
+++ b/backends/gf-gpu.c
@@ -0,0 +1,261 @@
+/*
+ * Copyright (C) 2017 Red Hat
+ * Copyright (C) 2019 Alberts Muktupāvels
+ *
+ * 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 3 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 "gf-gpu-private.h"
+
+#include "gf-output-private.h"
+
+typedef struct
+{
+  GfMonitorManager *monitor_manager;
+
+  GList            *outputs;
+  GList            *crtcs;
+  GList            *modes;
+} GfGpuPrivate;
+
+enum
+{
+  PROP_0,
+
+  PROP_MONITOR_MANAGER,
+
+  LAST_PROP
+};
+
+static GParamSpec *gpu_properties[LAST_PROP] = { NULL };
+
+G_DEFINE_TYPE_WITH_PRIVATE (GfGpu, gf_gpu, G_TYPE_OBJECT)
+
+static void
+gf_gpu_finalize (GObject *object)
+{
+  GfGpu *gpu;
+  GfGpuPrivate *priv;
+
+  gpu = GF_GPU (object);
+  priv = gf_gpu_get_instance_private (gpu);
+
+  g_list_free_full (priv->outputs, g_object_unref);
+  g_list_free_full (priv->modes, g_object_unref);
+  g_list_free_full (priv->crtcs, g_object_unref);
+
+  G_OBJECT_CLASS (gf_gpu_parent_class)->finalize (object);
+}
+
+static void
+gf_gpu_get_property (GObject    *object,
+                     guint       property_id,
+                     GValue     *value,
+                     GParamSpec *pspec)
+{
+  GfGpu *gpu;
+  GfGpuPrivate *priv;
+
+  gpu = GF_GPU (object);
+  priv = gf_gpu_get_instance_private (gpu);
+
+  switch (property_id)
+    {
+      case PROP_MONITOR_MANAGER:
+        g_value_set_object (value, priv->monitor_manager);
+        break;
+
+      default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+        break;
+    }
+}
+
+static void
+gf_gpu_set_property (GObject      *object,
+                     guint         property_id,
+                     const GValue *value,
+                     GParamSpec   *pspec)
+{
+  GfGpu *gpu;
+  GfGpuPrivate *priv;
+
+  gpu = GF_GPU (object);
+  priv = gf_gpu_get_instance_private (gpu);
+
+  switch (property_id)
+    {
+      case PROP_MONITOR_MANAGER:
+        priv->monitor_manager = g_value_get_object (value);
+        break;
+
+      default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+        break;
+    }
+}
+
+static void
+gf_gpu_install_properties (GObjectClass *object_class)
+{
+  gpu_properties[PROP_MONITOR_MANAGER] =
+    g_param_spec_object ("monitor-manager",
+                         "GfMonitorManager",
+                         "GfMonitorManager",
+                         GF_TYPE_MONITOR_MANAGER,
+                         G_PARAM_WRITABLE |
+                         G_PARAM_CONSTRUCT_ONLY |
+                         G_PARAM_STATIC_STRINGS);
+
+  g_object_class_install_properties (object_class, LAST_PROP,
+                                     gpu_properties);
+}
+
+static void
+gf_gpu_class_init (GfGpuClass *gpu_class)
+{
+  GObjectClass *object_class;
+
+  object_class = G_OBJECT_CLASS (gpu_class);
+
+  object_class->finalize = gf_gpu_finalize;
+  object_class->get_property = gf_gpu_get_property;
+  object_class->set_property = gf_gpu_set_property;
+
+  gf_gpu_install_properties (object_class);
+}
+
+static void
+gf_gpu_init (GfGpu *gpu)
+{
+}
+
+gboolean
+gf_gpu_read_current (GfGpu   *gpu,
+                     GError **error)
+{
+  GfGpuPrivate *priv;
+  gboolean ret;
+  GList *old_outputs;
+  GList *old_crtcs;
+  GList *old_modes;
+
+  priv = gf_gpu_get_instance_private (gpu);
+
+  /* TODO: Get rid of this when objects incref:s what they need instead. */
+  old_outputs = priv->outputs;
+  old_crtcs = priv->crtcs;
+  old_modes = priv->modes;
+
+  ret = GF_GPU_GET_CLASS (gpu)->read_current (gpu, error);
+
+  g_list_free_full (old_outputs, g_object_unref);
+  g_list_free_full (old_modes, g_object_unref);
+  g_list_free_full (old_crtcs, g_object_unref);
+
+  return ret;
+}
+
+gboolean
+gf_gpu_has_hotplug_mode_update (GfGpu *gpu)
+{
+  GfGpuPrivate *priv;
+  GList *l;
+
+  priv = gf_gpu_get_instance_private (gpu);
+
+  for (l = priv->outputs; l; l = l->next)
+    {
+      GfOutput *output = l->data;
+
+      if (output->hotplug_mode_update)
+        return TRUE;
+    }
+
+  return FALSE;
+}
+
+GfMonitorManager *
+gf_gpu_get_monitor_manager (GfGpu *gpu)
+{
+  GfGpuPrivate *priv;
+
+  priv = gf_gpu_get_instance_private (gpu);
+
+  return priv->monitor_manager;
+}
+
+GList *
+gf_gpu_get_outputs (GfGpu *gpu)
+{
+  GfGpuPrivate *priv;
+
+  priv = gf_gpu_get_instance_private (gpu);
+
+  return priv->outputs;
+}
+
+GList *
+gf_gpu_get_crtcs (GfGpu *gpu)
+{
+  GfGpuPrivate *priv;
+
+  priv = gf_gpu_get_instance_private (gpu);
+
+  return priv->crtcs;
+}
+
+GList *
+gf_gpu_get_modes (GfGpu *gpu)
+{
+  GfGpuPrivate *priv;
+
+  priv = gf_gpu_get_instance_private (gpu);
+
+  return priv->modes;
+}
+
+void
+gf_gpu_take_outputs (GfGpu *gpu,
+                     GList *outputs)
+{
+  GfGpuPrivate *priv;
+
+  priv = gf_gpu_get_instance_private (gpu);
+
+  priv->outputs = outputs;
+}
+
+void
+gf_gpu_take_crtcs (GfGpu *gpu,
+                   GList *crtcs)
+{
+  GfGpuPrivate *priv;
+
+  priv = gf_gpu_get_instance_private (gpu);
+
+  priv->crtcs = crtcs;
+}
+
+void
+gf_gpu_take_modes (GfGpu *gpu,
+                   GList *modes)
+{
+  GfGpuPrivate *priv;
+
+  priv = gf_gpu_get_instance_private (gpu);
+
+  priv->modes = modes;
+}
diff --git a/backends/gf-monitor-manager-dummy.c b/backends/gf-monitor-manager-dummy.c
index 8908d44..498caef 100644
--- a/backends/gf-monitor-manager-dummy.c
+++ b/backends/gf-monitor-manager-dummy.c
@@ -6,7 +6,7 @@
  * Copyright (C) 2003 Rob Adams
  * Copyright (C) 2004-2006 Elijah Newren
  * Copyright (C) 2013 Red Hat Inc.
- * Copyright (C) 2017 Alberts Muktupāvels
+ * Copyright (C) 2017-2019 Alberts Muktupāvels
  *
  * 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
@@ -35,11 +35,6 @@ struct _GfMonitorManagerDummy
 
 G_DEFINE_TYPE (GfMonitorManagerDummy, gf_monitor_manager_dummy, GF_TYPE_MONITOR_MANAGER)
 
-static void
-gf_monitor_manager_dummy_read_current (GfMonitorManager *manager)
-{
-}
-
 static void
 gf_monitor_manager_dummy_ensure_initial_config (GfMonitorManager *manager)
 {
@@ -110,7 +105,6 @@ gf_monitor_manager_dummy_class_init (GfMonitorManagerDummyClass *dummy_class)
 
   manager_class = GF_MONITOR_MANAGER_CLASS (dummy_class);
 
-  manager_class->read_current = gf_monitor_manager_dummy_read_current;
   manager_class->ensure_initial_config = gf_monitor_manager_dummy_ensure_initial_config;
   manager_class->apply_monitors_config = gf_monitor_manager_dummy_apply_monitors_config;
   manager_class->is_transform_handled = gf_monitor_manager_dummy_is_transform_handled;
diff --git a/backends/gf-monitor-manager-kms.c b/backends/gf-monitor-manager-kms.c
index 93db53e..add74ec 100644
--- a/backends/gf-monitor-manager-kms.c
+++ b/backends/gf-monitor-manager-kms.c
@@ -53,11 +53,6 @@ initable_iface_init (GInitableIface *initable_iface)
   initable_iface->init = gf_monitor_manager_kms_initable_init;
 }
 
-static void
-gf_monitor_manager_kms_read_current (GfMonitorManager *manager)
-{
-}
-
 static GBytes *
 gf_monitor_manager_kms_read_edid (GfMonitorManager *manager,
                                   GfOutput         *output)
@@ -160,7 +155,6 @@ gf_monitor_manager_kms_class_init (GfMonitorManagerKmsClass *kms_class)
 
   manager_class = GF_MONITOR_MANAGER_CLASS (kms_class);
 
-  manager_class->read_current = gf_monitor_manager_kms_read_current;
   manager_class->read_edid = gf_monitor_manager_kms_read_edid;
   manager_class->ensure_initial_config = gf_monitor_manager_kms_ensure_initial_config;
   manager_class->apply_monitors_config = gf_monitor_manager_kms_apply_monitors_config;
diff --git a/backends/gf-monitor-manager-private.h b/backends/gf-monitor-manager-private.h
index 8f54436..5a3cb89 100644
--- a/backends/gf-monitor-manager-private.h
+++ b/backends/gf-monitor-manager-private.h
@@ -59,14 +59,7 @@ struct _GfMonitorManager
   gint                         screen_width;
   gint                         screen_height;
 
-  /* Outputs refer to physical screens,
-   * CRTCs refer to stuff that can drive outputs
-   * (like encoders, but less tied to the HW),
-   * while logical_monitors refer to logical ones.
-   */
-  GList                       *outputs;
-  GList                       *crtcs;
-  GList                       *modes;
+  GList                       *gpus;
 
   GList                       *monitors;
 
@@ -85,8 +78,6 @@ typedef struct
 {
   GfDBusDisplayConfigSkeletonClass parent_class;
 
-  void                         (* read_current)                 (GfMonitorManager            *manager);
-
   gchar                      * (* get_edid_file)                (GfMonitorManager            *manager,
                                                                  GfOutput                    *output);
 
@@ -174,9 +165,11 @@ GList                      *gf_monitor_manager_get_monitors                 (GfM
 
 GfLogicalMonitor           *gf_monitor_manager_get_primary_logical_monitor  (GfMonitorManager            
*manager);
 
-GList                      *gf_monitor_manager_get_outputs                  (GfMonitorManager            
*manager);
+void                        gf_monitor_manager_add_gpu                      (GfMonitorManager            
*manager,
+                                                                             GfGpu                       
*gpu);
+
+GList                      *gf_monitor_manager_get_gpus                     (GfMonitorManager            
*manager);
 
-GList                      *gf_monitor_manager_get_crtcs                    (GfMonitorManager            
*manager);
 
 gboolean                    gf_monitor_manager_has_hotplug_mode_update      (GfMonitorManager            
*manager);
 void                        gf_monitor_manager_read_current_state           (GfMonitorManager            
*manager);
diff --git a/backends/gf-monitor-manager-types-private.h b/backends/gf-monitor-manager-types-private.h
index 8014bc4..384a54c 100644
--- a/backends/gf-monitor-manager-types-private.h
+++ b/backends/gf-monitor-manager-types-private.h
@@ -3,7 +3,7 @@
  * Copyright (C) 2003 Rob Adams
  * Copyright (C) 2004-2006 Elijah Newren
  * Copyright (C) 2013 Red Hat Inc.
- * Copyright (C) 2017 Alberts Muktupāvels
+ * Copyright (C) 2017-2019 Alberts Muktupāvels
  *
  * 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
@@ -39,6 +39,8 @@ typedef struct _GfLogicalMonitor GfLogicalMonitor;
 
 typedef struct _GfMonitorMode GfMonitorMode;
 
+typedef struct _GfGpu GfGpu;
+
 typedef struct _GfCrtc GfCrtc;
 typedef struct _GfOutput GfOutput;
 typedef struct _GfCrtcMode GfCrtcMode;
diff --git a/backends/gf-monitor-manager-xrandr-private.h b/backends/gf-monitor-manager-xrandr-private.h
index d439083..9bbd622 100644
--- a/backends/gf-monitor-manager-xrandr-private.h
+++ b/backends/gf-monitor-manager-xrandr-private.h
@@ -36,14 +36,12 @@ G_BEGIN_DECLS
 G_DECLARE_FINAL_TYPE (GfMonitorManagerXrandr, gf_monitor_manager_xrandr,
                       GF, MONITOR_MANAGER_XRANDR, GfMonitorManager)
 
-Display            *gf_monitor_manager_xrandr_get_xdisplay  (GfMonitorManagerXrandr *xrandr);
+Display  *gf_monitor_manager_xrandr_get_xdisplay  (GfMonitorManagerXrandr *xrandr);
 
-gboolean            gf_monitor_manager_xrandr_has_randr15   (GfMonitorManagerXrandr *xrandr);
+gboolean  gf_monitor_manager_xrandr_has_randr15   (GfMonitorManagerXrandr *xrandr);
 
-XRRScreenResources *gf_monitor_manager_xrandr_get_resources (GfMonitorManagerXrandr *xrandr);
-
-gboolean            gf_monitor_manager_xrandr_handle_xevent (GfMonitorManagerXrandr *xrandr,
-                                                             XEvent                 *event);
+gboolean  gf_monitor_manager_xrandr_handle_xevent (GfMonitorManagerXrandr *xrandr,
+                                                   XEvent                 *event);
 
 G_END_DECLS
 
diff --git a/backends/gf-monitor-manager-xrandr.c b/backends/gf-monitor-manager-xrandr.c
index d221354..37e85ee 100644
--- a/backends/gf-monitor-manager-xrandr.c
+++ b/backends/gf-monitor-manager-xrandr.c
@@ -37,6 +37,7 @@
 
 #include "gf-backend-x11-private.h"
 #include "gf-crtc-xrandr-private.h"
+#include "gf-gpu-xrandr-private.h"
 #include "gf-monitor-config-manager-private.h"
 #include "gf-monitor-manager-xrandr-private.h"
 #include "gf-monitor-private.h"
@@ -51,26 +52,28 @@
 
 struct _GfMonitorManagerXrandr
 {
-  GfMonitorManager    parent;
+  GfMonitorManager  parent;
 
-  Display            *xdisplay;
-  Window              xroot;
+  Display          *xdisplay;
+  Window            xroot;
 
-  gint                rr_event_base;
-  gint                rr_error_base;
+  gint              rr_event_base;
+  gint              rr_error_base;
 
-  gboolean            has_randr15;
-  GHashTable         *tiled_monitor_atoms;
+  gboolean          has_randr15;
+  GHashTable       *tiled_monitor_atoms;
 
-  XRRScreenResources *resources;
-
-  Time                last_xrandr_set_timestamp;
+  /*
+   * The X server deals with multiple GPUs for us, soe just see what the X
+   * server gives us as one single GPU, even though it may actually be backed
+   * by multiple.
+   */
+  GfGpu            *gpu;
 
-  gint                max_screen_width;
-  gint                max_screen_height;
+  Time              last_xrandr_set_timestamp;
 
-  gfloat             *supported_scales;
-  gint                n_supported_scales;
+  gfloat           *supported_scales;
+  gint              n_supported_scales;
 };
 
 typedef struct
@@ -298,9 +301,12 @@ is_assignments_changed (GfMonitorManager  *manager,
                         GfOutputInfo     **output_infos,
                         guint              n_output_infos)
 {
+  GfMonitorManagerXrandr *manager_xrandr;
   GList *l;
 
-  for (l = manager->crtcs; l; l = l->next)
+  manager_xrandr = GF_MONITOR_MANAGER_XRANDR (manager);
+
+  for (l = gf_gpu_get_crtcs (manager_xrandr->gpu); l; l = l->next)
     {
       GfCrtc *crtc = l->data;
 
@@ -308,7 +314,7 @@ is_assignments_changed (GfMonitorManager  *manager,
         return TRUE;
     }
 
-  for (l = manager->outputs; l; l = l->next)
+  for (l = gf_gpu_get_outputs (manager_xrandr->gpu); l; l = l->next)
     {
       GfOutput *output = l->data;
 
@@ -372,15 +378,6 @@ gf_monitor_transform_to_xrandr (GfMonitorTransform transform)
   return rotation;
 }
 
-static gint
-compare_outputs (const void *one,
-                 const void *two)
-{
-  const GfOutput *o_one = one, *o_two = two;
-
-  return strcmp (o_one->name, o_two->name);
-}
-
 static void
 apply_crtc_assignments (GfMonitorManager  *manager,
                         gboolean           save_timestamp,
@@ -454,7 +451,7 @@ apply_crtc_assignments (GfMonitorManager  *manager,
     }
 
   /* Disable CRTCs not mentioned in the list */
-  for (l = manager->crtcs; l; l = l->next)
+  for (l = gf_gpu_get_crtcs (xrandr->gpu); l; l = l->next)
     {
       GfCrtc *crtc = l->data;
 
@@ -579,7 +576,7 @@ apply_crtc_assignments (GfMonitorManager  *manager,
     }
 
   /* Disable outputs not mentioned in the list */
-  for (l = manager->outputs; l; l = l->next)
+  for (l = gf_gpu_get_outputs (xrandr->gpu); l; l = l->next)
     {
       GfOutput *output = l->data;
 
@@ -704,6 +701,9 @@ gf_monitor_manager_xrandr_constructed (GObject *object)
   xrandr->xdisplay = gf_backend_x11_get_xdisplay (GF_BACKEND_X11 (backend));
   xrandr->xroot = DefaultRootWindow (xrandr->xdisplay);
 
+  xrandr->gpu = GF_GPU (gf_gpu_xrandr_new (xrandr));
+  gf_monitor_manager_add_gpu (GF_MONITOR_MANAGER (xrandr), xrandr->gpu);
+
   if (XRRQueryExtension (xrandr->xdisplay, &rr_event_base, &rr_error_base))
     {
       gint major_version;
@@ -754,172 +754,12 @@ gf_monitor_manager_xrandr_finalize (GObject *object)
 
   xrandr = GF_MONITOR_MANAGER_XRANDR (object);
 
-  g_clear_pointer (&xrandr->resources, XRRFreeScreenResources);
+  g_clear_object (&xrandr->gpu);
   g_clear_pointer (&xrandr->supported_scales, g_free);
 
   G_OBJECT_CLASS (gf_monitor_manager_xrandr_parent_class)->finalize (object);
 }
 
-static void
-gf_monitor_manager_xrandr_read_current (GfMonitorManager *manager)
-{
-  GfMonitorManagerXrandr *xrandr;
-  XRRScreenResources *resources;
-  CARD16 dpms_state;
-  BOOL dpms_enabled;
-  gint min_width;
-  gint min_height;
-  Screen *screen;
-  guint i, j;
-  GList *l;
-  RROutput primary_output;
-
-  xrandr = GF_MONITOR_MANAGER_XRANDR (manager);
-
-  if (DPMSCapable (xrandr->xdisplay) &&
-      DPMSInfo (xrandr->xdisplay, &dpms_state, &dpms_enabled) &&
-      dpms_enabled)
-    {
-      switch (dpms_state)
-        {
-          case DPMSModeOn:
-            manager->power_save_mode = GF_POWER_SAVE_ON;
-            break;
-
-          case DPMSModeStandby:
-            manager->power_save_mode = GF_POWER_SAVE_STANDBY;
-            break;
-
-          case DPMSModeSuspend:
-            manager->power_save_mode = GF_POWER_SAVE_SUSPEND;
-            break;
-
-          case DPMSModeOff:
-            manager->power_save_mode = GF_POWER_SAVE_OFF;
-            break;
-
-          default:
-            manager->power_save_mode = GF_POWER_SAVE_UNSUPPORTED;
-            break;
-        }
-    }
-  else
-    {
-      manager->power_save_mode = GF_POWER_SAVE_UNSUPPORTED;
-    }
-
-  XRRGetScreenSizeRange (xrandr->xdisplay, xrandr->xroot,
-                         &min_width, &min_height,
-                         &xrandr->max_screen_width,
-                         &xrandr->max_screen_height);
-
-  /* This is updated because we called RRUpdateConfiguration below */
-  screen = ScreenOfDisplay (xrandr->xdisplay, DefaultScreen (xrandr->xdisplay));
-  manager->screen_width = WidthOfScreen (screen);
-  manager->screen_height = HeightOfScreen (screen);
-
-  g_clear_pointer (&xrandr->resources, XRRFreeScreenResources);
-  resources = XRRGetScreenResourcesCurrent (xrandr->xdisplay, xrandr->xroot);
-
-  if (!resources)
-    return;
-
-  xrandr->resources = resources;
-  manager->outputs = NULL;
-  manager->modes = NULL;
-  manager->crtcs = NULL;
-
-  for (i = 0; i < (guint) resources->nmode; i++)
-    {
-      XRRModeInfo *xmode;
-      GfCrtcMode *mode;
-
-      xmode = &resources->modes[i];
-      mode = g_object_new (GF_TYPE_CRTC_MODE, NULL);
-
-      mode->mode_id = xmode->id;
-      mode->width = xmode->width;
-      mode->height = xmode->height;
-      mode->refresh_rate = (xmode->dotClock / ((gfloat) xmode->hTotal * xmode->vTotal));
-      mode->flags = xmode->modeFlags;
-      mode->name = g_strdup_printf ("%dx%d", xmode->width, xmode->height);
-
-      manager->modes = g_list_append (manager->modes, mode);
-    }
-
-  for (i = 0; i < (guint) resources->ncrtc; i++)
-    {
-      XRRCrtcInfo *xrandr_crtc;
-      RRCrtc crtc_id;
-      GfCrtc *crtc;
-
-      crtc_id = resources->crtcs[i];
-      xrandr_crtc = XRRGetCrtcInfo (xrandr->xdisplay, resources, crtc_id);
-      crtc = gf_create_xrandr_crtc (manager, xrandr_crtc, crtc_id, resources);
-
-      manager->crtcs = g_list_append (manager->crtcs, crtc);
-      XRRFreeCrtcInfo (xrandr_crtc);
-    }
-
-  primary_output = XRRGetOutputPrimary (xrandr->xdisplay, xrandr->xroot);
-
-  for (i = 0; i < (guint) resources->noutput; i++)
-    {
-      RROutput output_id;
-      XRROutputInfo *xrandr_output;
-
-      output_id = resources->outputs[i];
-      xrandr_output = XRRGetOutputInfo (xrandr->xdisplay, resources,
-                                        output_id);
-
-      if (!xrandr_output)
-        continue;
-
-      if (xrandr_output->connection != RR_Disconnected)
-        {
-          GfOutput *output;
-
-          output = gf_create_xrandr_output (manager,
-                                            xrandr_output,
-                                            output_id,
-                                            primary_output);
-
-          if (output)
-            manager->outputs = g_list_prepend (manager->outputs, output);
-        }
-
-      XRRFreeOutputInfo (xrandr_output);
-    }
-
-  /* Sort the outputs for easier handling in GfMonitorConfig */
-  manager->outputs = g_list_sort (manager->outputs, compare_outputs);
-
-  /* Now fix the clones */
-  for (l = manager->outputs; l; l = l->next)
-    {
-      GfOutput *output;
-      GList *k;
-
-      output = l->data;
-
-      for (j = 0; j < output->n_possible_clones; j++)
-        {
-          RROutput clone = GPOINTER_TO_INT (output->possible_clones[j]);
-
-          for (k = manager->outputs; k; k = k->next)
-            {
-              GfOutput *possible_clone = k->data;
-
-              if (clone == (XID) possible_clone->winsys_id)
-                {
-                  output->possible_clones[j] = possible_clone;
-                  break;
-                }
-            }
-        }
-    }
-}
-
 static GBytes *
 gf_monitor_manager_xrandr_read_edid (GfMonitorManager *manager,
                                      GfOutput         *output)
@@ -1226,8 +1066,8 @@ gf_monitor_manager_xrandr_get_max_screen_size (GfMonitorManager *manager,
 
   xrandr = GF_MONITOR_MANAGER_XRANDR (manager);
 
-  *max_width = xrandr->max_screen_width;
-  *max_height = xrandr->max_screen_height;
+  gf_gpu_xrandr_get_max_screen_size (GF_GPU_XRANDR (xrandr->gpu),
+                                     max_width, max_height);
 
   return TRUE;
 }
@@ -1251,7 +1091,6 @@ gf_monitor_manager_xrandr_class_init (GfMonitorManagerXrandrClass *xrandr_class)
   object_class->dispose = gf_monitor_manager_xrandr_dispose;
   object_class->finalize = gf_monitor_manager_xrandr_finalize;
 
-  manager_class->read_current = gf_monitor_manager_xrandr_read_current;
   manager_class->read_edid = gf_monitor_manager_xrandr_read_edid;
   manager_class->ensure_initial_config = gf_monitor_manager_xrandr_ensure_initial_config;
   manager_class->apply_monitors_config = gf_monitor_manager_xrandr_apply_monitors_config;
@@ -1286,17 +1125,12 @@ gf_monitor_manager_xrandr_has_randr15 (GfMonitorManagerXrandr *xrandr)
   return xrandr->has_randr15;
 }
 
-XRRScreenResources *
-gf_monitor_manager_xrandr_get_resources (GfMonitorManagerXrandr *xrandr)
-{
-  return xrandr->resources;
-}
-
 gboolean
 gf_monitor_manager_xrandr_handle_xevent (GfMonitorManagerXrandr *xrandr,
                                          XEvent                 *event)
 {
   GfMonitorManager *manager;
+  GfGpuXrandr *gpu_xrandr;
   XRRScreenResources *resources;
 
   manager = GF_MONITOR_MANAGER (xrandr);
@@ -1307,7 +1141,9 @@ gf_monitor_manager_xrandr_handle_xevent (GfMonitorManagerXrandr *xrandr,
   XRRUpdateConfiguration (event);
   gf_monitor_manager_read_current_state (manager);
 
-  resources = xrandr->resources;
+  gpu_xrandr = GF_GPU_XRANDR (xrandr->gpu);
+  resources = gf_gpu_xrandr_get_resources (gpu_xrandr);
+
   if (!resources)
     return TRUE;
 
diff --git a/backends/gf-monitor-manager.c b/backends/gf-monitor-manager.c
index e422350..a577277 100644
--- a/backends/gf-monitor-manager.c
+++ b/backends/gf-monitor-manager.c
@@ -1067,36 +1067,62 @@ rebuild_monitors (GfMonitorManager *manager)
       manager->monitors = NULL;
     }
 
-  for (l = manager->outputs; l; l = l->next)
+  for (l = manager->gpus; l; l = l->next)
     {
-      GfOutput *output = l->data;
+      GfGpu *gpu = l->data;
+      GList *k;
 
-      if (output->tile_info.group_id)
+      for (k = gf_gpu_get_outputs (gpu); k; k = k->next)
         {
-          if (is_main_tiled_monitor_output (output))
+          GfOutput *output = k->data;
+
+          if (output->tile_info.group_id)
             {
-              GfMonitorTiled *monitor_tiled;
+              if (is_main_tiled_monitor_output (output))
+                {
+                  GfMonitorTiled *monitor_tiled;
 
-              monitor_tiled = gf_monitor_tiled_new (manager, output);
-              manager->monitors = g_list_append (manager->monitors, monitor_tiled);
+                  monitor_tiled = gf_monitor_tiled_new (gpu, output);
+                  manager->monitors = g_list_append (manager->monitors, monitor_tiled);
+                }
             }
-        }
-      else
-        {
-          GfMonitorNormal *monitor_normal;
+          else
+            {
+              GfMonitorNormal *monitor_normal;
 
-          monitor_normal = gf_monitor_normal_new (manager, output);
-          manager->monitors = g_list_append (manager->monitors, monitor_normal);
+              monitor_normal = gf_monitor_normal_new (gpu, output);
+              manager->monitors = g_list_append (manager->monitors, monitor_normal);
+            }
         }
     }
 }
 
+static GList *
+combine_gpu_lists (GfMonitorManager *manager,
+                   GList            * (*list_getter) (GfGpu *gpu))
+{
+  GList *list = NULL;
+  GList *l;
+
+  for (l = manager->gpus; l; l = l->next)
+    {
+      GfGpu *gpu = l->data;
+
+      list = g_list_concat (list, g_list_copy (list_getter (gpu)));
+    }
+
+  return list;
+}
+
 static gboolean
 gf_monitor_manager_handle_get_resources (GfDBusDisplayConfig   *skeleton,
                                          GDBusMethodInvocation *invocation)
 {
   GfMonitorManager *manager;
   GfMonitorManagerClass *manager_class;
+  GList *combined_modes;
+  GList *combined_outputs;
+  GList *combined_crtcs;
   GVariantBuilder crtc_builder;
   GVariantBuilder output_builder;
   GVariantBuilder mode_builder;
@@ -1108,11 +1134,15 @@ gf_monitor_manager_handle_get_resources (GfDBusDisplayConfig   *skeleton,
   manager = GF_MONITOR_MANAGER (skeleton);
   manager_class = GF_MONITOR_MANAGER_GET_CLASS (skeleton);
 
+  combined_modes = combine_gpu_lists (manager, gf_gpu_get_modes);
+  combined_outputs = combine_gpu_lists (manager, gf_gpu_get_outputs);
+  combined_crtcs = combine_gpu_lists (manager, gf_gpu_get_crtcs);
+
   g_variant_builder_init (&crtc_builder, G_VARIANT_TYPE ("a(uxiiiiiuaua{sv})"));
   g_variant_builder_init (&output_builder, G_VARIANT_TYPE ("a(uxiausauaua{sv})"));
   g_variant_builder_init (&mode_builder, G_VARIANT_TYPE ("a(uxuudu)"));
 
-  for (l = manager->crtcs, i = 0; l; l = l->next, i++)
+  for (l = combined_crtcs, i = 0; l; l = l->next, i++)
     {
       GfCrtc *crtc = l->data;
       GVariantBuilder transforms;
@@ -1124,7 +1154,7 @@ gf_monitor_manager_handle_get_resources (GfDBusDisplayConfig   *skeleton,
           g_variant_builder_add (&transforms, "u", j);
 
       if (crtc->current_mode)
-        current_mode_index = g_list_index (manager->modes, crtc->current_mode);
+        current_mode_index = g_list_index (combined_modes, crtc->current_mode);
       else
         current_mode_index = -1;
 
@@ -1141,7 +1171,7 @@ gf_monitor_manager_handle_get_resources (GfDBusDisplayConfig   *skeleton,
                              NULL /* properties */);
     }
 
-  for (l = manager->outputs, i = 0; l; l = l->next, i++)
+  for (l = combined_outputs, i = 0; l; l = l->next, i++)
     {
       GfOutput *output = l->data;
       GVariantBuilder crtcs, modes, clones, properties;
@@ -1156,7 +1186,7 @@ gf_monitor_manager_handle_get_resources (GfDBusDisplayConfig   *skeleton,
           guint possible_crtc_index;
 
           possible_crtc = output->possible_crtcs[j];
-          possible_crtc_index = g_list_index (manager->crtcs, possible_crtc);
+          possible_crtc_index = g_list_index (combined_crtcs, possible_crtc);
 
           g_variant_builder_add (&crtcs, "u", possible_crtc_index);
         }
@@ -1166,7 +1196,7 @@ gf_monitor_manager_handle_get_resources (GfDBusDisplayConfig   *skeleton,
         {
           guint mode_index;
 
-          mode_index = g_list_index (manager->modes, output->modes[j]);
+          mode_index = g_list_index (combined_modes, output->modes[j]);
           g_variant_builder_add (&modes, "u", mode_index);
 
         }
@@ -1176,7 +1206,7 @@ gf_monitor_manager_handle_get_resources (GfDBusDisplayConfig   *skeleton,
         {
           guint possible_clone_index;
 
-          possible_clone_index = g_list_index (manager->outputs,
+          possible_clone_index = g_list_index (combined_outputs,
                                                output->possible_clones[j]);
 
           g_variant_builder_add (&clones, "u", possible_clone_index);
@@ -1244,7 +1274,7 @@ gf_monitor_manager_handle_get_resources (GfDBusDisplayConfig   *skeleton,
                                                 output->tile_info.tile_h));
         }
 
-      crtc_index = output->crtc ? g_list_index (manager->crtcs, output->crtc) : -1;
+      crtc_index = output->crtc ? g_list_index (combined_crtcs, output->crtc) : -1;
 
       g_variant_builder_add (&output_builder, "(uxiausauaua{sv})",
                              i, /* ID */
@@ -1257,7 +1287,7 @@ gf_monitor_manager_handle_get_resources (GfDBusDisplayConfig   *skeleton,
                              &properties);
     }
 
-  for (l = manager->modes, i = 0; l; l = l->next, i++)
+  for (l = combined_modes, i = 0; l; l = l->next, i++)
     {
       GfCrtcMode *mode = l->data;
 
@@ -1285,6 +1315,10 @@ gf_monitor_manager_handle_get_resources (GfDBusDisplayConfig   *skeleton,
                                                  g_variant_builder_end (&mode_builder),
                                                  max_screen_width, max_screen_height);
 
+  g_list_free (combined_modes);
+  g_list_free (combined_outputs);
+  g_list_free (combined_crtcs);
+
   return TRUE;
 }
 
@@ -1297,6 +1331,7 @@ gf_monitor_manager_handle_change_backlight (GfDBusDisplayConfig   *skeleton,
 {
   GfMonitorManager *manager;
   GfMonitorManagerClass *manager_class;
+  GList *combined_outputs;
   GfOutput *output;
 
   manager = GF_MONITOR_MANAGER (skeleton);
@@ -1310,15 +1345,20 @@ gf_monitor_manager_handle_change_backlight (GfDBusDisplayConfig   *skeleton,
       return TRUE;
     }
 
-  if (output_index >= g_list_length (manager->outputs))
+  combined_outputs = combine_gpu_lists (manager, gf_gpu_get_outputs);
+
+  if (output_index >= 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 (manager->outputs, output_index);
+  output = g_list_nth_data (combined_outputs, output_index);
+  g_list_free (combined_outputs);
 
   if (value < 0 || value > 100)
     {
@@ -1353,6 +1393,7 @@ gf_monitor_manager_handle_get_crtc_gamma (GfDBusDisplayConfig   *skeleton,
 {
   GfMonitorManager *manager;
   GfMonitorManagerClass *manager_class;
+  GList *combined_crtcs;
   GfCrtc *crtc;
   gsize size;
   gushort *red;
@@ -1376,15 +1417,19 @@ gf_monitor_manager_handle_get_crtc_gamma (GfDBusDisplayConfig   *skeleton,
       return TRUE;
     }
 
-  if (crtc_id >= g_list_length (manager->crtcs))
+  combined_crtcs = combine_gpu_lists (manager, gf_gpu_get_crtcs);
+
+  if (crtc_id >= g_list_length (combined_crtcs))
     {
+      g_list_free (combined_crtcs);
       g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
                                              G_DBUS_ERROR_INVALID_ARGS,
                                              "Invalid crtc id");
       return TRUE;
     }
 
-  crtc = g_list_nth_data (manager->crtcs, crtc_id);
+  crtc = g_list_nth_data (combined_crtcs, crtc_id);
+  g_list_free (combined_crtcs);
 
   if (manager_class->get_crtc_gamma)
     {
@@ -1425,6 +1470,7 @@ gf_monitor_manager_handle_set_crtc_gamma (GfDBusDisplayConfig   *skeleton,
 {
   GfMonitorManager *manager;
   GfMonitorManagerClass *manager_class;
+  GList *combined_crtcs;
   GfCrtc *crtc;
   GBytes *red_bytes;
   GBytes *green_bytes;
@@ -1445,15 +1491,19 @@ gf_monitor_manager_handle_set_crtc_gamma (GfDBusDisplayConfig   *skeleton,
       return TRUE;
     }
 
-  if (crtc_id >= g_list_length (manager->crtcs))
+  combined_crtcs = combine_gpu_lists (manager, gf_gpu_get_crtcs);
+
+  if (crtc_id >= g_list_length (combined_crtcs))
     {
+      g_list_free (combined_crtcs);
       g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
                                              G_DBUS_ERROR_INVALID_ARGS,
                                              "Invalid crtc id");
       return TRUE;
     }
 
-  crtc = g_list_nth_data (manager->crtcs, crtc_id);
+  crtc = g_list_nth_data (combined_crtcs, crtc_id);
+  g_list_free (combined_crtcs);
 
   red_bytes = g_variant_get_data_as_bytes (red_v);
   green_bytes = g_variant_get_data_as_bytes (green_v);
@@ -2012,10 +2062,7 @@ gf_monitor_manager_finalize (GObject *object)
 
   manager = GF_MONITOR_MANAGER (object);
 
-  g_list_free_full (manager->outputs, g_object_unref);
-  g_list_free_full (manager->modes, g_object_unref);
-  g_list_free_full (manager->crtcs, g_object_unref);
-
+  g_list_free_full (manager->gpus, g_object_unref);
   g_list_free_full (manager->logical_monitors, g_object_unref);
 
   G_OBJECT_CLASS (gf_monitor_manager_parent_class)->finalize (object);
@@ -2218,16 +2265,17 @@ gf_monitor_manager_get_primary_logical_monitor (GfMonitorManager *manager)
   return manager->primary_logical_monitor;
 }
 
-GList *
-gf_monitor_manager_get_outputs (GfMonitorManager *manager)
+void
+gf_monitor_manager_add_gpu (GfMonitorManager *manager,
+                            GfGpu            *gpu)
 {
-  return manager->outputs;
+  manager->gpus = g_list_append (manager->gpus, gpu);
 }
 
 GList *
-gf_monitor_manager_get_crtcs (GfMonitorManager *manager)
+gf_monitor_manager_get_gpus (GfMonitorManager *manager)
 {
-  return manager->crtcs;
+  return manager->gpus;
 }
 
 gboolean
@@ -2235,11 +2283,11 @@ gf_monitor_manager_has_hotplug_mode_update (GfMonitorManager *manager)
 {
   GList *l;
 
-  for (l = manager->outputs; l; l = l->next)
+  for (l = manager->gpus; l; l = l->next)
     {
-      GfOutput *output = l->data;
+      GfGpu *gpu = l->data;
 
-      if (output->hotplug_mode_update)
+      if (gf_gpu_has_hotplug_mode_update (gpu))
         return TRUE;
     }
 
@@ -2249,26 +2297,23 @@ gf_monitor_manager_has_hotplug_mode_update (GfMonitorManager *manager)
 void
 gf_monitor_manager_read_current_state (GfMonitorManager *manager)
 {
-  GList *old_outputs;
-  GList *old_crtcs;
-  GList *old_modes;
-
-  /* Some implementations of read_current use the existing information
-   * we have available, so don't free the old configuration until after
-   * read_current finishes.
-   */
-  old_outputs = manager->outputs;
-  old_crtcs = manager->crtcs;
-  old_modes = manager->modes;
+  GList *l;
 
   manager->serial++;
-  GF_MONITOR_MANAGER_GET_CLASS (manager)->read_current (manager);
 
-  rebuild_monitors (manager);
+  for (l = manager->gpus; l; l = l->next)
+    {
+      GfGpu *gpu = l->data;
+      GError *error = NULL;
+
+      if (!gf_gpu_read_current (gpu, &error))
+        {
+          g_warning ("Failed to read current KMS state: %s", error->message);
+          g_clear_error (&error);
+        }
+    }
 
-  g_list_free_full (old_outputs, g_object_unref);
-  g_list_free_full (old_modes, g_object_unref);
-  g_list_free_full (old_crtcs, g_object_unref);
+  rebuild_monitors (manager);
 }
 
 void
diff --git a/backends/gf-monitor-normal-private.h b/backends/gf-monitor-normal-private.h
index 0cec695..e0be600 100644
--- a/backends/gf-monitor-normal-private.h
+++ b/backends/gf-monitor-normal-private.h
@@ -30,8 +30,8 @@ G_BEGIN_DECLS
 G_DECLARE_FINAL_TYPE (GfMonitorNormal, gf_monitor_normal,
                       GF, MONITOR_NORMAL, GfMonitor)
 
-GfMonitorNormal *gf_monitor_normal_new (GfMonitorManager *monitor_manager,
-                                        GfOutput         *output);
+GfMonitorNormal *gf_monitor_normal_new (GfGpu    *gpu,
+                                        GfOutput *output);
 
 G_END_DECLS
 
diff --git a/backends/gf-monitor-normal.c b/backends/gf-monitor-normal.c
index b2cc170..9d46c98 100644
--- a/backends/gf-monitor-normal.c
+++ b/backends/gf-monitor-normal.c
@@ -161,14 +161,14 @@ gf_monitor_normal_init (GfMonitorNormal *normal)
 }
 
 GfMonitorNormal *
-gf_monitor_normal_new (GfMonitorManager *monitor_manager,
-                       GfOutput         *output)
+gf_monitor_normal_new (GfGpu    *gpu,
+                       GfOutput *output)
 {
   GfMonitorNormal *normal;
   GfMonitor *monitor;
 
   normal = g_object_new (GF_TYPE_MONITOR_NORMAL,
-                         "monitor-manager", monitor_manager,
+                         "gpu", gpu,
                          NULL);
 
   monitor = GF_MONITOR (normal);
diff --git a/backends/gf-monitor-private.h b/backends/gf-monitor-private.h
index 44538db..1e37a11 100644
--- a/backends/gf-monitor-private.h
+++ b/backends/gf-monitor-private.h
@@ -22,9 +22,9 @@
 #ifndef GF_MONITOR_PRIVATE_H
 #define GF_MONITOR_PRIVATE_H
 
+#include "gf-gpu-private.h"
 #include "gf-monitor-manager-enums-private.h"
 #include "gf-monitor-manager-types-private.h"
-#include "gf-monitor-manager.h"
 #include "gf-rectangle.h"
 
 G_BEGIN_DECLS
@@ -88,7 +88,7 @@ struct _GfMonitorClass
                                           gint               *height);
 };
 
-GfMonitorManager  *gf_monitor_get_monitor_manager        (GfMonitor                  *monitor);
+GfGpu             *gf_monitor_get_gpu                    (GfMonitor                  *monitor);
 
 gboolean           gf_monitor_is_mode_assigned           (GfMonitor                  *monitor,
                                                           GfMonitorMode              *mode);
diff --git a/backends/gf-monitor-tiled-private.h b/backends/gf-monitor-tiled-private.h
index b211ac6..de2bddb 100644
--- a/backends/gf-monitor-tiled-private.h
+++ b/backends/gf-monitor-tiled-private.h
@@ -31,10 +31,10 @@ G_BEGIN_DECLS
 G_DECLARE_FINAL_TYPE (GfMonitorTiled, gf_monitor_tiled,
                       GF, MONITOR_TILED, GfMonitor)
 
-GfMonitorTiled *gf_monitor_tiled_new               (GfMonitorManager *monitor_manager,
-                                                    GfOutput         *output);
+GfMonitorTiled *gf_monitor_tiled_new               (GfGpu          *gpu,
+                                                    GfOutput       *output);
 
-uint32_t        gf_monitor_tiled_get_tile_group_id (GfMonitorTiled   *monitor_tiled);
+uint32_t        gf_monitor_tiled_get_tile_group_id (GfMonitorTiled *monitor_tiled);
 
 G_END_DECLS
 
diff --git a/backends/gf-monitor-tiled.c b/backends/gf-monitor-tiled.c
index faf74b0..e2e0e7e 100644
--- a/backends/gf-monitor-tiled.c
+++ b/backends/gf-monitor-tiled.c
@@ -494,8 +494,8 @@ find_untiled_output (GfMonitorTiled *tiled)
 }
 
 static void
-add_tiled_monitor_outputs (GfMonitorManager *monitor_manager,
-                           GfMonitorTiled   *tiled)
+add_tiled_monitor_outputs (GfGpu          *gpu,
+                           GfMonitorTiled *tiled)
 {
   GfMonitor *monitor;
   GList *outputs;
@@ -503,7 +503,7 @@ add_tiled_monitor_outputs (GfMonitorManager *monitor_manager,
 
   monitor = GF_MONITOR (tiled);
 
-  outputs = monitor_manager->outputs;
+  outputs = gf_gpu_get_outputs (gpu);
   for (l = outputs; l; l = l->next)
     {
       GfOutput *output;
@@ -593,11 +593,13 @@ static void
 gf_monitor_tiled_finalize (GObject *object)
 {
   GfMonitor *monitor;
+  GfGpu *gpu;
   GfMonitorManager *monitor_manager;
 
   monitor = GF_MONITOR (object);
 
-  monitor_manager = gf_monitor_get_monitor_manager (monitor);
+  gpu = gf_monitor_get_gpu (monitor);
+  monitor_manager = gf_gpu_get_monitor_manager (gpu);
   gf_monitor_manager_tiled_monitor_removed (monitor_manager, monitor);
 
   G_OBJECT_CLASS (gf_monitor_tiled_parent_class)->finalize (object);
@@ -706,14 +708,15 @@ gf_monitor_tiled_init (GfMonitorTiled *tiled)
 }
 
 GfMonitorTiled *
-gf_monitor_tiled_new (GfMonitorManager *monitor_manager,
-                      GfOutput         *output)
+gf_monitor_tiled_new (GfGpu    *gpu,
+                      GfOutput *output)
 {
   GfMonitorTiled *tiled;
   GfMonitor *monitor;
+  GfMonitorManager *monitor_manager;
 
   tiled = g_object_new (GF_TYPE_MONITOR_TILED,
-                        "monitor-manager", monitor_manager,
+                        "gpu", gpu,
                         NULL);
 
   monitor = GF_MONITOR (tiled);
@@ -722,12 +725,13 @@ gf_monitor_tiled_new (GfMonitorManager *monitor_manager,
   gf_monitor_set_winsys_id (monitor, output->winsys_id);
 
   tiled->origin_output = output;
-  add_tiled_monitor_outputs (monitor_manager, tiled);
+  add_tiled_monitor_outputs (gpu, tiled);
 
   tiled->main_output = find_untiled_output (tiled);
 
   gf_monitor_generate_spec (monitor);
 
+  monitor_manager = gf_gpu_get_monitor_manager (gpu);
   gf_monitor_manager_tiled_monitor_added (monitor_manager, monitor);
   generate_modes (tiled);
 
diff --git a/backends/gf-monitor.c b/backends/gf-monitor.c
index b7154e1..72d770a 100644
--- a/backends/gf-monitor.c
+++ b/backends/gf-monitor.c
@@ -25,6 +25,7 @@
 #include <string.h>
 
 #include "gf-crtc-private.h"
+#include "gf-gpu-private.h"
 #include "gf-monitor-manager-private.h"
 #include "gf-monitor-private.h"
 #include "gf-monitor-spec-private.h"
@@ -52,16 +53,16 @@
 
 typedef struct
 {
-  GfMonitorManager *monitor_manager;
+  GfGpu         *gpu;
 
-  GList            *outputs;
-  GList            *modes;
-  GHashTable       *mode_ids;
+  GList         *outputs;
+  GList         *modes;
+  GHashTable    *mode_ids;
 
-  GfMonitorMode    *preferred_mode;
-  GfMonitorMode    *current_mode;
+  GfMonitorMode *preferred_mode;
+  GfMonitorMode *current_mode;
 
-  GfMonitorSpec    *spec;
+  GfMonitorSpec *spec;
 
   /*
    * The primary or first output for this monitor, 0 if we can't figure out.
@@ -72,14 +73,14 @@ typedef struct
    * (it's an attempt to keep windows on the same monitor, and preferably on
    * the primary one).
    */
-  glong             winsys_id;
+  glong          winsys_id;
 } GfMonitorPrivate;
 
 enum
 {
   PROP_0,
 
-  PROP_MONITOR_MANAGER,
+  PROP_GPU,
 
   LAST_PROP
 };
@@ -278,8 +279,8 @@ gf_monitor_get_property (GObject    *object,
 
   switch (property_id)
     {
-      case PROP_MONITOR_MANAGER:
-        g_value_set_object (value, priv->monitor_manager);
+      case PROP_GPU:
+        g_value_set_object (value, priv->gpu);
         break;
 
       default:
@@ -302,8 +303,8 @@ gf_monitor_set_property (GObject      *object,
 
   switch (property_id)
     {
-      case PROP_MONITOR_MANAGER:
-        priv->monitor_manager = g_value_get_object (value);
+      case PROP_GPU:
+        priv->gpu = g_value_get_object (value);
         break;
 
       default:
@@ -315,11 +316,11 @@ gf_monitor_set_property (GObject      *object,
 static void
 gf_monitor_install_properties (GObjectClass *object_class)
 {
-  monitor_properties[PROP_MONITOR_MANAGER] =
-    g_param_spec_object ("monitor-manager",
-                         "GfMonitorManager",
-                         "GfMonitorManager",
-                         GF_TYPE_MONITOR_MANAGER,
+  monitor_properties[PROP_GPU] =
+    g_param_spec_object ("gpu",
+                         "GfGpu",
+                         "GfGpu",
+                         GF_TYPE_GPU,
                          G_PARAM_READWRITE |
                          G_PARAM_STATIC_STRINGS |
                          G_PARAM_CONSTRUCT_ONLY);
@@ -352,14 +353,14 @@ gf_monitor_init (GfMonitor *monitor)
   priv->mode_ids = g_hash_table_new (g_str_hash, g_str_equal);
 }
 
-GfMonitorManager *
-gf_monitor_get_monitor_manager (GfMonitor *monitor)
+GfGpu *
+gf_monitor_get_gpu (GfMonitor *monitor)
 {
   GfMonitorPrivate *priv;
 
   priv = gf_monitor_get_instance_private (monitor);
 
-  return priv->monitor_manager;
+  return priv->gpu;
 }
 
 gboolean
@@ -809,12 +810,14 @@ gf_monitor_calculate_mode_scale (GfMonitor     *monitor,
                                  GfMonitorMode *monitor_mode)
 {
   GfMonitorPrivate *priv;
+  GfMonitorManager *monitor_manager;
   GfBackend *backend;
   GfSettings *settings;
   gint global_scaling_factor;
 
   priv = gf_monitor_get_instance_private (monitor);
-  backend = gf_monitor_manager_get_backend (priv->monitor_manager);
+  monitor_manager = gf_gpu_get_monitor_manager (priv->gpu);
+  backend = gf_monitor_manager_get_backend (monitor_manager);
   settings = gf_backend_get_settings (backend);
 
   if (gf_settings_get_global_scaling_factor (settings, &global_scaling_factor))
diff --git a/backends/gf-output-private.h b/backends/gf-output-private.h
index c26456b..a19b32d 100644
--- a/backends/gf-output-private.h
+++ b/backends/gf-output-private.h
@@ -3,7 +3,7 @@
  * Copyright (C) 2003 Rob Adams
  * Copyright (C) 2004-2006 Elijah Newren
  * Copyright (C) 2013 Red Hat Inc.
- * Copyright (C) 2017 Alberts Muktupāvels
+ * Copyright (C) 2017-2019 Alberts Muktupāvels
  *
  * 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
@@ -27,9 +27,9 @@
 
 #include <glib-object.h>
 
+#include "gf-gpu-private.h"
 #include "gf-monitor-manager-enums-private.h"
 #include "gf-monitor-manager-types-private.h"
-#include "gf-monitor-manager.h"
 
 G_BEGIN_DECLS
 
@@ -57,7 +57,7 @@ struct _GfOutput
 {
   GObject            parent;
 
-  GfMonitorManager  *monitor_manager;
+  GfGpu             *gpu;
 
   /* The CRTC driving this output, NULL if the output is not enabled */
   GfCrtc            *crtc;
@@ -112,13 +112,13 @@ struct _GfOutput
 #define GF_TYPE_OUTPUT (gf_output_get_type ())
 G_DECLARE_FINAL_TYPE (GfOutput, gf_output, GF, OUTPUT, GObject)
 
-GfMonitorManager *gf_output_get_monitor_manager (GfOutput *output);
+GfGpu    *gf_output_get_gpu    (GfOutput *output);
 
 
-void              gf_output_parse_edid          (GfOutput *output,
-                                                 GBytes   *edid);
+void      gf_output_parse_edid (GfOutput *output,
+                                GBytes   *edid);
 
-gboolean          gf_output_is_laptop           (GfOutput *output);
+gboolean  gf_output_is_laptop  (GfOutput *output);
 
 G_END_DECLS
 
diff --git a/backends/gf-output-xrandr-private.h b/backends/gf-output-xrandr-private.h
index 01e55b8..bedf591 100644
--- a/backends/gf-output-xrandr-private.h
+++ b/backends/gf-output-xrandr-private.h
@@ -21,22 +21,22 @@
 
 #include <X11/extensions/Xrandr.h>
 
-#include "gf-monitor-manager-xrandr-private.h"
+#include "gf-gpu-xrandr-private.h"
 #include "gf-output-private.h"
 
 G_BEGIN_DECLS
 
-GfOutput *gf_create_xrandr_output           (GfMonitorManager *monitor_manager,
-                                             XRROutputInfo    *xrandr_output,
-                                             RROutput          output_id,
-                                             RROutput          primary_output);
+GfOutput *gf_create_xrandr_output           (GfGpuXrandr   *gpu_xrandr,
+                                             XRROutputInfo *xrandr_output,
+                                             RROutput       output_id,
+                                             RROutput       primary_output);
 
-GBytes   *gf_output_xrandr_read_edid        (GfOutput         *output);
+GBytes   *gf_output_xrandr_read_edid        (GfOutput      *output);
 
-void      gf_output_xrandr_apply_mode       (GfOutput         *output);
+void      gf_output_xrandr_apply_mode       (GfOutput      *output);
 
-void      gf_output_xrandr_change_backlight (GfOutput         *output,
-                                             int               value);
+void      gf_output_xrandr_change_backlight (GfOutput      *output,
+                                             int            value);
 
 G_END_DECLS
 
diff --git a/backends/gf-output-xrandr.c b/backends/gf-output-xrandr.c
index c266644..e93a7ac 100644
--- a/backends/gf-output-xrandr.c
+++ b/backends/gf-output-xrandr.c
@@ -36,10 +36,12 @@
 static Display *
 xdisplay_from_output (GfOutput *output)
 {
+  GfGpu *gpu;
   GfMonitorManager *monitor_manager;
   GfMonitorManagerXrandr *monitor_manager_xrandr;
 
-  monitor_manager = gf_output_get_monitor_manager (output);
+  gpu = gf_output_get_gpu (output);
+  monitor_manager = gf_gpu_get_monitor_manager (gpu);
   monitor_manager_xrandr = GF_MONITOR_MANAGER_XRANDR (monitor_manager);
 
   return gf_monitor_manager_xrandr_get_xdisplay (monitor_manager_xrandr);
@@ -376,6 +378,7 @@ output_get_connector_type (GfOutput *output)
 static void
 output_get_tile_info (GfOutput *output)
 {
+  GfGpu *gpu;
   GfMonitorManager *monitor_manager;
   GfMonitorManagerXrandr *monitor_manager_xrandr;
   Display *xdisplay;
@@ -385,7 +388,8 @@ output_get_tile_info (GfOutput *output)
   gint actual_format;
   Atom actual_type;
 
-  monitor_manager = gf_output_get_monitor_manager (output);
+  gpu = gf_output_get_gpu (output);
+  monitor_manager = gf_gpu_get_monitor_manager (gpu);
   monitor_manager_xrandr = GF_MONITOR_MANAGER_XRANDR (monitor_manager);
 
   if (!gf_monitor_manager_xrandr_has_randr15 (monitor_manager_xrandr))
@@ -417,13 +421,15 @@ output_get_tile_info (GfOutput *output)
 }
 
 static void
-output_get_modes (GfMonitorManager *manager,
-                  GfOutput         *output,
-                  XRROutputInfo    *xrandr_output)
+output_get_modes (GfOutput      *output,
+                  XRROutputInfo *xrandr_output)
 {
+  GfGpu *gpu;
   guint j;
   guint n_actual_modes;
 
+  gpu = gf_output_get_gpu (output);
+
   output->modes = g_new0 (GfCrtcMode *, xrandr_output->nmode);
 
   n_actual_modes = 0;
@@ -431,7 +437,7 @@ output_get_modes (GfMonitorManager *manager,
     {
       GList *l;
 
-      for (l = manager->modes; l; l = l->next)
+      for (l = gf_gpu_get_modes (gpu); l; l = l->next)
         {
           GfCrtcMode *mode = l->data;
 
@@ -450,20 +456,22 @@ output_get_modes (GfMonitorManager *manager,
 }
 
 static void
-output_get_crtcs (GfMonitorManager *manager,
-                  GfOutput         *output,
-                  XRROutputInfo    *xrandr_output)
+output_get_crtcs (GfOutput      *output,
+                  XRROutputInfo *xrandr_output)
 {
+  GfGpu *gpu;
   guint j;
   guint n_actual_crtcs;
   GList *l;
 
+  gpu = gf_output_get_gpu (output);
+
   output->possible_crtcs = g_new0 (GfCrtc *, xrandr_output->ncrtc);
 
   n_actual_crtcs = 0;
   for (j = 0; j < (guint) xrandr_output->ncrtc; j++)
     {
-      for (l = manager->crtcs; l; l = l->next)
+      for (l = gf_gpu_get_crtcs (gpu); l; l = l->next)
         {
           GfCrtc *crtc = l->data;
 
@@ -478,7 +486,7 @@ output_get_crtcs (GfMonitorManager *manager,
   output->n_possible_crtcs = n_actual_crtcs;
 
   output->crtc = NULL;
-  for (l = manager->crtcs; l; l = l->next)
+  for (l = gf_gpu_get_crtcs (gpu); l; l = l->next)
     {
       GfCrtc *crtc = l->data;
 
@@ -694,17 +702,17 @@ output_get_backlight_limits_xrandr (GfOutput *output)
 }
 
 GfOutput *
-gf_create_xrandr_output (GfMonitorManager *monitor_manager,
-                         XRROutputInfo    *xrandr_output,
-                         RROutput          output_id,
-                         RROutput          primary_output)
+gf_create_xrandr_output (GfGpuXrandr   *gpu_xrandr,
+                         XRROutputInfo *xrandr_output,
+                         RROutput       output_id,
+                         RROutput       primary_output)
 {
   GfOutput *output;
   GBytes *edid;
   unsigned int i;
 
   output = g_object_new (GF_TYPE_OUTPUT, NULL);
-  output->monitor_manager = monitor_manager;
+  output->gpu = GF_GPU (gpu_xrandr);
 
   output->winsys_id = output_id;
   output->name = g_strdup (xrandr_output->name);
@@ -721,8 +729,8 @@ gf_create_xrandr_output (GfMonitorManager *monitor_manager,
   output->connector_type = output_get_connector_type (output);
 
   output_get_tile_info (output);
-  output_get_modes (monitor_manager, output, xrandr_output);
-  output_get_crtcs (monitor_manager, output, xrandr_output);
+  output_get_modes (output, xrandr_output);
+  output_get_crtcs (output, xrandr_output);
 
   output->n_possible_clones = xrandr_output->nclone;
   output->possible_clones = g_new0 (GfOutput *, output->n_possible_clones);
diff --git a/backends/gf-output.c b/backends/gf-output.c
index 2051259..c8724df 100644
--- a/backends/gf-output.c
+++ b/backends/gf-output.c
@@ -6,7 +6,7 @@
  * Copyright (C) 2003 Rob Adams
  * Copyright (C) 2004-2006 Elijah Newren
  * Copyright (C) 2013 Red Hat Inc.
- * Copyright (C) 2017 Alberts Muktupāvels
+ * Copyright (C) 2017-2019 Alberts Muktupāvels
  * Copyright (C) 2017 Red Hat
  *
  * This program is free software: you can redistribute it and/or modify
@@ -68,10 +68,10 @@ gf_output_init (GfOutput *output)
 {
 }
 
-GfMonitorManager *
-gf_output_get_monitor_manager (GfOutput *output)
+GfGpu *
+gf_output_get_gpu (GfOutput *output)
 {
-  return output->monitor_manager;
+  return output->gpu;
 }
 
 void


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