[mutter] renderer-native: Draw stage separately per CRTC



commit 1c98f01a65a7b1ad980dbe1bb5129d36aec999e3
Author: Jonas Ådahl <jadahl gmail com>
Date:   Fri Jan 17 21:08:02 2020 +0100

    renderer-native: Draw stage separately per CRTC
    
    Prior to this commit the stage was drawn separately for each logical
    monitor. This allowed to draw different parts of the stage with
    different transformations, e.g. with a different viewport to implement
    HiDPI support.
    
    Go even further and have one view per CRTC. This causes the stage to
    e.g. draw two mirrored monitors twice, instead of using the same
    framebuffer on both. This enables us to do two things: one is to support
    tiled monitors and monitor mirroring using the EGLStreams backend; the
    other is that it'll enable us to tie rendering directly to the CRTC it
    will render for. It is also a requirement for rendering being affected
    by CRTC state, such as gamma.
    
    It'll be possible to still inhibit re-drawing of the same content
    twice, but it should be implemented differently, so that it will still
    be possible to implement features requiring the CRTC split.
    
    https://gitlab.gnome.org/GNOME/mutter/merge_requests/1042

 clutter/clutter/clutter-stage.c                    |  47 +-
 src/backends/meta-renderer-view.c                  |  21 -
 src/backends/meta-renderer-view.h                  |   2 -
 src/backends/meta-renderer.c                       |  48 +-
 src/backends/meta-renderer.h                       |   7 +-
 src/backends/meta-screen-cast-monitor-stream-src.c | 109 ++--
 src/backends/native/meta-crtc-kms.c                |  15 +-
 src/backends/native/meta-crtc-kms.h                |   2 -
 src/backends/native/meta-renderer-native.c         | 637 +++++----------------
 src/backends/x11/nested/meta-renderer-x11-nested.c |  32 +-
 src/backends/x11/nested/meta-stage-x11-nested.c    | 147 +----
 11 files changed, 305 insertions(+), 762 deletions(-)
---
diff --git a/clutter/clutter/clutter-stage.c b/clutter/clutter/clutter-stage.c
index 57ffc78c8..25735c264 100644
--- a/clutter/clutter/clutter-stage.c
+++ b/clutter/clutter/clutter-stage.c
@@ -4476,49 +4476,42 @@ capture_view_into (ClutterStage          *stage,
   cogl_object_unref (bitmap);
 }
 
-static ClutterStageView *
-get_view_at_rect (ClutterStage          *stage,
-                  cairo_rectangle_int_t *rect)
+void
+clutter_stage_capture_into (ClutterStage          *stage,
+                            gboolean               paint,
+                            cairo_rectangle_int_t *rect,
+                            uint8_t               *data)
 {
   ClutterStagePrivate *priv = stage->priv;
-  GList *views = _clutter_stage_window_get_views (priv->impl);
   GList *l;
+  int bpp = 4;
+  int stride;
 
-  for (l = views; l; l = l->next)
+  stride = rect->width * 4;
+
+  for (l = _clutter_stage_window_get_views (priv->impl); l; l = l->next)
     {
       ClutterStageView *view = l->data;
       cairo_rectangle_int_t view_layout;
       cairo_region_t *region;
-      cairo_rectangle_int_t view_capture_rect;
+      cairo_rectangle_int_t capture_rect;
+      int x_offset, y_offset;
 
       clutter_stage_view_get_layout (view, &view_layout);
       region = cairo_region_create_rectangle (&view_layout);
       cairo_region_intersect_rectangle (region, rect);
-      cairo_region_get_extents (region, &view_capture_rect);
+
+      cairo_region_get_extents (region, &capture_rect);
       cairo_region_destroy (region);
 
-      if (view_capture_rect.width == 0 || view_capture_rect.height == 0)
-        continue;
+      x_offset = capture_rect.x - rect->x;
+      y_offset = capture_rect.y - rect->y;
 
-      g_assert (view_capture_rect.width == rect->width &&
-                view_capture_rect.height == rect->height);
-      return view;
+      capture_view_into (stage, paint, view,
+                         &capture_rect,
+                         data + (x_offset * bpp) + (y_offset * stride),
+                         stride);
     }
-
-  return NULL;
-}
-
-void
-clutter_stage_capture_into (ClutterStage          *stage,
-                            gboolean               paint,
-                            cairo_rectangle_int_t *rect,
-                            uint8_t               *data)
-{
-  ClutterStageView *view;
-  int bpp = 4;
-
-  view = get_view_at_rect (stage, rect);
-  capture_view_into (stage, paint, view, rect, data, rect->width * bpp);
 }
 
 /**
diff --git a/src/backends/meta-renderer-view.c b/src/backends/meta-renderer-view.c
index cab1f5f48..ae771f2de 100644
--- a/src/backends/meta-renderer-view.c
+++ b/src/backends/meta-renderer-view.c
@@ -39,7 +39,6 @@ enum
 {
   PROP_0,
 
-  PROP_MONITOR_INFO,
   PROP_TRANSFORM,
 
   PROP_LAST
@@ -52,18 +51,11 @@ struct _MetaRendererView
   ClutterStageViewCogl parent;
 
   MetaMonitorTransform transform;
-  MetaLogicalMonitor *logical_monitor;
 };
 
 G_DEFINE_TYPE (MetaRendererView, meta_renderer_view,
                CLUTTER_TYPE_STAGE_VIEW_COGL)
 
-MetaLogicalMonitor *
-meta_renderer_view_get_logical_monitor (MetaRendererView *view)
-{
-  return view->logical_monitor;
-}
-
 MetaMonitorTransform
 meta_renderer_view_get_transform (MetaRendererView *view)
 {
@@ -146,9 +138,6 @@ meta_renderer_view_get_property (GObject    *object,
 
   switch (prop_id)
     {
-    case PROP_MONITOR_INFO:
-      g_value_set_pointer (value, view->logical_monitor);
-      break;
     case PROP_TRANSFORM:
       g_value_set_uint (value, view->transform);
       break;
@@ -168,9 +157,6 @@ meta_renderer_view_set_property (GObject      *object,
 
   switch (prop_id)
     {
-    case PROP_MONITOR_INFO:
-      view->logical_monitor = g_value_get_pointer (value);
-      break;
     case PROP_TRANSFORM:
       meta_renderer_view_set_transform (view, g_value_get_uint (value));
       break;
@@ -199,13 +185,6 @@ meta_renderer_view_class_init (MetaRendererViewClass *klass)
   object_class->get_property = meta_renderer_view_get_property;
   object_class->set_property = meta_renderer_view_set_property;
 
-  obj_props[PROP_MONITOR_INFO] =
-    g_param_spec_pointer ("logical-monitor",
-                          "MetaLogicalMonitor",
-                          "The logical monitor of the view",
-                          G_PARAM_READWRITE |
-                          G_PARAM_STATIC_STRINGS |
-                          G_PARAM_CONSTRUCT_ONLY);
   obj_props[PROP_TRANSFORM] =
     g_param_spec_uint ("transform",
                        "Transform",
diff --git a/src/backends/meta-renderer-view.h b/src/backends/meta-renderer-view.h
index 650341479..f601de534 100644
--- a/src/backends/meta-renderer-view.h
+++ b/src/backends/meta-renderer-view.h
@@ -26,8 +26,6 @@ G_DECLARE_FINAL_TYPE (MetaRendererView, meta_renderer_view,
                       META, RENDERER_VIEW,
                       ClutterStageViewCogl)
 
-MetaLogicalMonitor *meta_renderer_view_get_logical_monitor (MetaRendererView *view);
-
 MetaMonitorTransform meta_renderer_view_get_transform (MetaRendererView *view);
 
 #endif /* META_RENDERER_VIEW_H */
diff --git a/src/backends/meta-renderer.c b/src/backends/meta-renderer.c
index 24688577c..3846bde7d 100644
--- a/src/backends/meta-renderer.c
+++ b/src/backends/meta-renderer.c
@@ -47,6 +47,7 @@
 #include <glib-object.h>
 
 #include "backends/meta-backend-private.h"
+#include "backends/meta-logical-monitor.h"
 
 enum
 {
@@ -93,10 +94,14 @@ meta_renderer_create_cogl_renderer (MetaRenderer *renderer)
 
 static MetaRendererView *
 meta_renderer_create_view (MetaRenderer       *renderer,
-                           MetaLogicalMonitor *logical_monitor)
+                           MetaLogicalMonitor *logical_monitor,
+                           MetaOutput         *output,
+                           MetaCrtc           *crtc)
 {
   return META_RENDERER_GET_CLASS (renderer)->create_view (renderer,
-                                                          logical_monitor);
+                                                          logical_monitor,
+                                                          output,
+                                                          crtc);
 }
 
 /**
@@ -114,6 +119,21 @@ meta_renderer_rebuild_views (MetaRenderer *renderer)
   return META_RENDERER_GET_CLASS (renderer)->rebuild_views (renderer);
 }
 
+static void
+create_crtc_view (MetaLogicalMonitor *logical_monitor,
+                  MetaMonitor        *monitor,
+                  MetaOutput         *output,
+                  MetaCrtc           *crtc,
+                  gpointer            user_data)
+{
+  MetaRenderer *renderer = user_data;
+  MetaRendererPrivate *priv = meta_renderer_get_instance_private (renderer);
+  MetaRendererView *view;
+
+  view = meta_renderer_create_view (renderer, logical_monitor, output, crtc);
+  priv->views = g_list_append (priv->views, view);
+}
+
 static void
 meta_renderer_real_rebuild_views (MetaRenderer *renderer)
 {
@@ -132,10 +152,10 @@ meta_renderer_real_rebuild_views (MetaRenderer *renderer)
   for (l = logical_monitors; l; l = l->next)
     {
       MetaLogicalMonitor *logical_monitor = l->data;
-      MetaRendererView *view;
 
-      view = meta_renderer_create_view (renderer, logical_monitor);
-      priv->views = g_list_append (priv->views, view);
+      meta_logical_monitor_foreach_crtc (logical_monitor,
+                                         create_crtc_view,
+                                         renderer);
     }
 }
 
@@ -168,24 +188,6 @@ meta_renderer_get_views (MetaRenderer *renderer)
   return priv->views;
 }
 
-MetaRendererView *
-meta_renderer_get_view_from_logical_monitor (MetaRenderer       *renderer,
-                                             MetaLogicalMonitor *logical_monitor)
-{
-  GList *l;
-
-  for (l = meta_renderer_get_views (renderer); l; l = l->next)
-    {
-      MetaRendererView *view = l->data;
-
-      if (meta_renderer_view_get_logical_monitor (view) ==
-          logical_monitor)
-        return view;
-    }
-
-  return NULL;
-}
-
 gboolean
 meta_renderer_is_hardware_accelerated (MetaRenderer *renderer)
 {
diff --git a/src/backends/meta-renderer.h b/src/backends/meta-renderer.h
index f5182e0eb..e6160922a 100644
--- a/src/backends/meta-renderer.h
+++ b/src/backends/meta-renderer.h
@@ -42,7 +42,9 @@ struct _MetaRendererClass
 
   CoglRenderer * (* create_cogl_renderer) (MetaRenderer *renderer);
   MetaRendererView * (* create_view) (MetaRenderer       *renderer,
-                                      MetaLogicalMonitor *logical_monitor);
+                                      MetaLogicalMonitor *logical_monitor,
+                                      MetaOutput         *output,
+                                      MetaCrtc           *crtc);
   void (* rebuild_views) (MetaRenderer *renderer);
 };
 
@@ -58,9 +60,6 @@ void meta_renderer_set_legacy_view (MetaRenderer     *renderer,
 META_EXPORT_TEST
 GList * meta_renderer_get_views (MetaRenderer *renderer);
 
-MetaRendererView * meta_renderer_get_view_from_logical_monitor (MetaRenderer       *renderer,
-                                                                MetaLogicalMonitor *logical_monitor);
-
 gboolean meta_renderer_is_hardware_accelerated (MetaRenderer *renderer);
 
 #endif /* META_RENDERER_H */
diff --git a/src/backends/meta-screen-cast-monitor-stream-src.c 
b/src/backends/meta-screen-cast-monitor-stream-src.c
index 5d9dadc8c..902ae545b 100644
--- a/src/backends/meta-screen-cast-monitor-stream-src.c
+++ b/src/backends/meta-screen-cast-monitor-stream-src.c
@@ -42,9 +42,9 @@ struct _MetaScreenCastMonitorStreamSrc
   MetaScreenCastStreamSrc parent;
 
   gboolean cursor_bitmap_invalid;
+  gboolean hw_cursor_inhibited;
 
-  MetaStageWatch *paint_watch;
-  MetaStageWatch *after_paint_watch;
+  GList *watches;
 
   gulong cursor_moved_handler_id;
   gulong cursor_changed_handler_id;
@@ -226,9 +226,13 @@ inhibit_hw_cursor (MetaScreenCastMonitorStreamSrc *monitor_src)
   MetaCursorRenderer *cursor_renderer;
   MetaHwCursorInhibitor *inhibitor;
 
+  g_return_if_fail (!monitor_src->hw_cursor_inhibited);
+
   cursor_renderer = get_cursor_renderer (monitor_src);
   inhibitor = META_HW_CURSOR_INHIBITOR (monitor_src);
   meta_cursor_renderer_add_hw_cursor_inhibitor (cursor_renderer, inhibitor);
+
+  monitor_src->hw_cursor_inhibited = TRUE;
 }
 
 static void
@@ -237,39 +241,67 @@ uninhibit_hw_cursor (MetaScreenCastMonitorStreamSrc *monitor_src)
   MetaCursorRenderer *cursor_renderer;
   MetaHwCursorInhibitor *inhibitor;
 
+  g_return_if_fail (monitor_src->hw_cursor_inhibited);
+
   cursor_renderer = get_cursor_renderer (monitor_src);
   inhibitor = META_HW_CURSOR_INHIBITOR (monitor_src);
   meta_cursor_renderer_remove_hw_cursor_inhibitor (cursor_renderer, inhibitor);
+
+  monitor_src->hw_cursor_inhibited = FALSE;
 }
 
 static void
-meta_screen_cast_monitor_stream_src_enable (MetaScreenCastStreamSrc *src)
+add_view_painted_watches (MetaScreenCastMonitorStreamSrc *monitor_src,
+                          MetaStageWatchPhase             watch_phase)
 {
-  MetaScreenCastMonitorStreamSrc *monitor_src =
-    META_SCREEN_CAST_MONITOR_STREAM_SRC (src);
   MetaBackend *backend = get_backend (monitor_src);
   MetaRenderer *renderer = meta_backend_get_renderer (backend);
-  MetaCursorTracker *cursor_tracker = meta_backend_get_cursor_tracker (backend);
-  MetaRendererView *view;
+  ClutterStage *stage;
+  MetaStage *meta_stage;
   MetaMonitor *monitor;
   MetaLogicalMonitor *logical_monitor;
-  MetaStage *meta_stage;
-  ClutterStageView *stage_view;
-  ClutterStage *stage;
-  MetaScreenCastStream *stream;
+  MetaRectangle logical_monitor_layout;
+  GList *l;
 
-  stream = meta_screen_cast_stream_src_get_stream (src);
   stage = get_stage (monitor_src);
   meta_stage = META_STAGE (stage);
   monitor = get_monitor (monitor_src);
   logical_monitor = meta_monitor_get_logical_monitor (monitor);
-  view = meta_renderer_get_view_from_logical_monitor (renderer,
-                                                      logical_monitor);
+  logical_monitor_layout = meta_logical_monitor_get_layout (logical_monitor);
 
-  if (view)
-    stage_view = CLUTTER_STAGE_VIEW (view);
-  else
-    stage_view = NULL;
+  for (l = meta_renderer_get_views (renderer); l; l = l->next)
+    {
+      MetaRendererView *view = l->data;
+      MetaRectangle view_layout;
+
+      clutter_stage_view_get_layout (CLUTTER_STAGE_VIEW (view), &view_layout);
+      if (meta_rectangle_overlap (&logical_monitor_layout, &view_layout))
+        {
+          MetaStageWatch *watch;
+
+          watch = meta_stage_watch_view (meta_stage,
+                                         CLUTTER_STAGE_VIEW (view),
+                                         watch_phase,
+                                         stage_painted,
+                                         monitor_src);
+
+          monitor_src->watches = g_list_prepend (monitor_src->watches, watch);
+        }
+    }
+}
+
+static void
+meta_screen_cast_monitor_stream_src_enable (MetaScreenCastStreamSrc *src)
+{
+  MetaScreenCastMonitorStreamSrc *monitor_src =
+    META_SCREEN_CAST_MONITOR_STREAM_SRC (src);
+  MetaBackend *backend = get_backend (monitor_src);
+  MetaCursorTracker *cursor_tracker = meta_backend_get_cursor_tracker (backend);
+  ClutterStage *stage;
+  MetaScreenCastStream *stream;
+
+  stream = meta_screen_cast_stream_src_get_stream (src);
+  stage = get_stage (monitor_src);
 
   switch (meta_screen_cast_stream_get_cursor_mode (stream))
     {
@@ -284,21 +316,13 @@ meta_screen_cast_monitor_stream_src_enable (MetaScreenCastStreamSrc *src)
                                 monitor_src);
       G_GNUC_FALLTHROUGH;
     case META_SCREEN_CAST_CURSOR_MODE_HIDDEN:
-      monitor_src->paint_watch =
-        meta_stage_watch_view (meta_stage,
-                               stage_view,
-                               META_STAGE_WATCH_AFTER_ACTOR_PAINT,
-                               stage_painted,
-                               monitor_src);
+      add_view_painted_watches (monitor_src,
+                                META_STAGE_WATCH_AFTER_ACTOR_PAINT);
       break;
     case META_SCREEN_CAST_CURSOR_MODE_EMBEDDED:
       inhibit_hw_cursor (monitor_src);
-      monitor_src->after_paint_watch =
-        meta_stage_watch_view (meta_stage,
-                               stage_view,
-                               META_STAGE_WATCH_AFTER_PAINT,
-                               stage_painted,
-                               monitor_src);
+      add_view_painted_watches (monitor_src,
+                                META_STAGE_WATCH_AFTER_PAINT);
       break;
     }
 
@@ -314,22 +338,21 @@ meta_screen_cast_monitor_stream_src_disable (MetaScreenCastStreamSrc *src)
   MetaCursorTracker *cursor_tracker = meta_backend_get_cursor_tracker (backend);
   ClutterStage *stage;
   MetaStage *meta_stage;
+  GList *l;
 
   stage = get_stage (monitor_src);
   meta_stage = META_STAGE (stage);
 
-  if (monitor_src->paint_watch)
+  for (l = monitor_src->watches; l; l = l->next)
     {
-      meta_stage_remove_watch (meta_stage, monitor_src->paint_watch);
-      monitor_src->paint_watch = NULL;
-    }
+      MetaStageWatch *watch = l->data;
 
-  if (monitor_src->after_paint_watch)
-    {
-      meta_stage_remove_watch (meta_stage, monitor_src->after_paint_watch);
-      monitor_src->after_paint_watch = NULL;
-      uninhibit_hw_cursor (monitor_src);
+      meta_stage_remove_watch (meta_stage, watch);
     }
+  g_clear_pointer (&monitor_src->watches, g_list_free);
+
+  if (monitor_src->hw_cursor_inhibited)
+    uninhibit_hw_cursor (monitor_src);
 
   g_clear_signal_handler (&monitor_src->cursor_moved_handler_id,
                           cursor_tracker);
@@ -367,13 +390,11 @@ meta_screen_cast_monitor_stream_src_set_cursor_metadata (MetaScreenCastStreamSrc
   MetaBackend *backend = get_backend (monitor_src);
   MetaCursorRenderer *cursor_renderer =
     meta_backend_get_cursor_renderer (backend);
-  MetaRenderer *renderer = meta_backend_get_renderer (backend);
   MetaCursorSprite *cursor_sprite;
   MetaMonitor *monitor;
   MetaLogicalMonitor *logical_monitor;
   MetaRectangle logical_monitor_layout;
   graphene_rect_t logical_monitor_rect;
-  MetaRendererView *view;
   float view_scale;
   graphene_point_t cursor_position;
   int x, y;
@@ -393,10 +414,8 @@ meta_screen_cast_monitor_stream_src_set_cursor_metadata (MetaScreenCastStreamSrc
   logical_monitor_rect =
     meta_rectangle_to_graphene_rect (&logical_monitor_layout);
 
-  view = meta_renderer_get_view_from_logical_monitor (renderer,
-                                                      logical_monitor);
-  if (view)
-    view_scale = clutter_stage_view_get_scale (CLUTTER_STAGE_VIEW (view));
+  if (meta_is_stage_views_scaled ())
+    view_scale = meta_logical_monitor_get_scale (logical_monitor);
   else
     view_scale = 1.0;
 
diff --git a/src/backends/native/meta-crtc-kms.c b/src/backends/native/meta-crtc-kms.c
index 1ec6654f8..2d570b2de 100644
--- a/src/backends/native/meta-crtc-kms.c
+++ b/src/backends/native/meta-crtc-kms.c
@@ -76,14 +76,10 @@ meta_crtc_kms_apply_transform (MetaCrtc               *crtc,
 
 void
 meta_crtc_kms_assign_primary_plane (MetaCrtc      *crtc,
-                                    MetaMonitor   *monitor,
-                                    MetaOutput    *output,
                                     uint32_t       fb_id,
                                     MetaKmsUpdate *kms_update)
 {
-  MetaMonitorMode *monitor_mode;
   MetaCrtcConfig *crtc_config;
-  int crtc_x, crtc_y;
   MetaFixed16Rectangle src_rect;
   MetaFixed16Rectangle dst_rect;
   MetaKmsAssignPlaneFlag flags;
@@ -94,17 +90,10 @@ meta_crtc_kms_assign_primary_plane (MetaCrtc      *crtc,
 
   crtc_config = crtc->config;
 
-  monitor_mode = meta_monitor_get_current_mode (monitor);
-  meta_monitor_calculate_crtc_pos (monitor,
-                                   monitor_mode,
-                                   output,
-                                   crtc_config->transform,
-                                   &crtc_x,
-                                   &crtc_y);
 
   src_rect = (MetaFixed16Rectangle) {
-    .x = meta_fixed_16_from_int (crtc_x),
-    .y = meta_fixed_16_from_int (crtc_y),
+    .x = meta_fixed_16_from_int (0),
+    .y = meta_fixed_16_from_int (0),
     .width = meta_fixed_16_from_int (crtc_config->mode->width),
     .height = meta_fixed_16_from_int (crtc_config->mode->height),
   };
diff --git a/src/backends/native/meta-crtc-kms.h b/src/backends/native/meta-crtc-kms.h
index 4b2df3cfa..898622478 100644
--- a/src/backends/native/meta-crtc-kms.h
+++ b/src/backends/native/meta-crtc-kms.h
@@ -38,8 +38,6 @@ void meta_crtc_kms_apply_transform (MetaCrtc               *crtc,
                                     MetaKmsPlaneAssignment *kms_plane_assignment);
 
 void meta_crtc_kms_assign_primary_plane (MetaCrtc      *crtc,
-                                         MetaMonitor   *monitor,
-                                         MetaOutput    *output,
                                          uint32_t       fb_id,
                                          MetaKmsUpdate *kms_update);
 
diff --git a/src/backends/native/meta-renderer-native.c b/src/backends/native/meta-renderer-native.c
index 0de4ea3dc..19786b196 100644
--- a/src/backends/native/meta-renderer-native.c
+++ b/src/backends/native/meta-renderer-native.c
@@ -181,9 +181,10 @@ typedef struct _MetaOnscreenNative
 {
   MetaRendererNative *renderer_native;
   MetaGpuKms *render_gpu;
-  MetaLogicalMonitor *logical_monitor;
+  MetaOutput *output;
+  MetaCrtc *crtc;
 
-  GHashTable *secondary_gpu_states;
+  MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state;
 
   struct {
     struct gbm_surface *surface;
@@ -263,8 +264,7 @@ static MetaEgl *
 meta_renderer_native_get_egl (MetaRendererNative *renderer_native);
 
 static void
-free_current_secondary_bo (MetaGpuKms                          *gpu_kms,
-                           MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state);
+free_current_secondary_bo (CoglOnscreen *onscreen);
 
 static gboolean
 cogl_pixel_format_from_drm_format (uint32_t               drm_format,
@@ -320,24 +320,6 @@ meta_create_renderer_native_gpu_data (MetaGpuKms *gpu_kms)
   return g_new0 (MetaRendererNativeGpuData, 1);
 }
 
-static MetaOnscreenNativeSecondaryGpuState *
-meta_onscreen_native_get_secondary_gpu_state (MetaOnscreenNative *onscreen_native,
-                                              MetaGpuKms         *gpu_kms)
-{
-  return g_hash_table_lookup (onscreen_native->secondary_gpu_states, gpu_kms);
-}
-
-static MetaOnscreenNativeSecondaryGpuState *
-get_secondary_gpu_state (CoglOnscreen *onscreen,
-                         MetaGpuKms   *gpu_kms)
-{
-  CoglOnscreenEGL *onscreen_egl = onscreen->winsys;
-  MetaOnscreenNative *onscreen_native = onscreen_egl->platform;
-
-  return meta_onscreen_native_get_secondary_gpu_state (onscreen_native,
-                                                       gpu_kms);
-}
-
 static MetaEgl *
 meta_renderer_native_get_egl (MetaRendererNative *renderer_native)
 {
@@ -353,138 +335,56 @@ meta_onscreen_native_get_egl (MetaOnscreenNative *onscreen_native)
 }
 
 static GArray *
-get_supported_kms_modifiers (CoglOnscreen *onscreen,
-                             MetaGpu      *gpu,
-                             uint32_t      format)
+get_supported_kms_modifiers (MetaCrtc *crtc,
+                             uint32_t  format)
 {
-  CoglOnscreenEGL *onscreen_egl = onscreen->winsys;
-  MetaOnscreenNative *onscreen_native = onscreen_egl->platform;
-  MetaLogicalMonitor *logical_monitor = onscreen_native->logical_monitor;
   GArray *modifiers;
-  GArray *base_mods;
-  GList *l_crtc;
-  MetaCrtc *base_crtc = NULL;
-  GList *other_crtcs = NULL;
+  GArray *crtc_mods;
   unsigned int i;
 
-  if (!logical_monitor)
+  crtc_mods = meta_crtc_kms_get_modifiers (crtc, format);
+  if (!crtc_mods)
     return NULL;
 
-  /* Find our base CRTC to intersect against. */
-  for (l_crtc = meta_gpu_get_crtcs (gpu); l_crtc; l_crtc = l_crtc->next)
-    {
-      MetaCrtc *crtc = l_crtc->data;
-
-      if (crtc->logical_monitor != logical_monitor)
-        continue;
-
-      if (!base_crtc)
-        base_crtc = crtc;
-      else if (crtc == base_crtc)
-        continue;
-      else if (g_list_index (other_crtcs, crtc) == -1)
-        other_crtcs = g_list_append (other_crtcs, crtc);
-    }
-
-  if (!base_crtc)
-    goto out;
-
-  base_mods = meta_crtc_kms_get_modifiers (base_crtc, format);
-  if (!base_mods)
-    goto out;
-
-  /*
-   * If this is the only CRTC we have, we don't need to intersect the sets of
-   * modifiers.
-   */
-  if (other_crtcs == NULL)
-    {
-      modifiers = g_array_sized_new (FALSE, FALSE, sizeof (uint64_t),
-                                     base_mods->len);
-      g_array_append_vals (modifiers, base_mods->data, base_mods->len);
-      return modifiers;
-    }
-
   modifiers = g_array_new (FALSE, FALSE, sizeof (uint64_t));
 
   /*
    * For each modifier from base_crtc, check if it's available on all other
    * CRTCs.
    */
-  for (i = 0; i < base_mods->len; i++)
+  for (i = 0; i < crtc_mods->len; i++)
     {
-      uint64_t modifier = g_array_index (base_mods, uint64_t, i);
-      gboolean found_everywhere = TRUE;
-      GList *k;
+      uint64_t modifier = g_array_index (crtc_mods, uint64_t, i);
 
-      /* Check if we have the same modifier available for all CRTCs. */
-      for (k = other_crtcs; k; k = k->next)
-        {
-          MetaCrtc *crtc = k->data;
-          GArray *crtc_mods;
-          unsigned int m;
-          gboolean found_here = FALSE;
-
-          if (crtc->logical_monitor != logical_monitor)
-            continue;
-
-          crtc_mods = meta_crtc_kms_get_modifiers (crtc, format);
-          if (!crtc_mods)
-            {
-              g_array_free (modifiers, TRUE);
-              goto out;
-            }
-
-          for (m = 0; m < crtc_mods->len; m++)
-            {
-              uint64_t local_mod = g_array_index (crtc_mods, uint64_t, m);
-
-              if (local_mod == modifier)
-                {
-                  found_here = TRUE;
-                  break;
-                }
-            }
-
-          if (!found_here)
-            {
-              found_everywhere = FALSE;
-              break;
-            }
-        }
-
-      if (found_everywhere)
-        g_array_append_val (modifiers, modifier);
+      g_array_append_val (modifiers, modifier);
     }
 
   if (modifiers->len == 0)
     {
       g_array_free (modifiers, TRUE);
-      goto out;
+      return NULL;
     }
 
   return modifiers;
-
-out:
-  g_list_free (other_crtcs);
-  return NULL;
 }
 
 static GArray *
 get_supported_egl_modifiers (CoglOnscreen *onscreen,
-                             MetaGpu      *gpu,
+                             MetaCrtc     *crtc,
                              uint32_t      format)
 {
   CoglOnscreenEGL *onscreen_egl = onscreen->winsys;
   MetaOnscreenNative *onscreen_native = onscreen_egl->platform;
   MetaRendererNative *renderer_native = onscreen_native->renderer_native;
   MetaEgl *egl = meta_onscreen_native_get_egl (onscreen_native);
+  MetaGpu *gpu;
   MetaRendererNativeGpuData *renderer_gpu_data;
   EGLint num_modifiers;
   GArray *modifiers;
   GError *error = NULL;
   gboolean ret;
 
+  gpu = meta_crtc_get_gpu (crtc);
   renderer_gpu_data = meta_renderer_native_get_gpu_data (renderer_native,
                                                          META_GPU_KMS (gpu));
 
@@ -523,149 +423,33 @@ get_supported_modifiers (CoglOnscreen *onscreen,
 {
   CoglOnscreenEGL *onscreen_egl = onscreen->winsys;
   MetaOnscreenNative *onscreen_native = onscreen_egl->platform;
-  MetaLogicalMonitor *logical_monitor = onscreen_native->logical_monitor;
-  GArray *modifiers = NULL;
-  GArray *gpu_mods;
-  GList *l_monitor;
-  unsigned int i;
-
-  if (!logical_monitor)
-    return NULL;
-
-  /* Find our base CRTC to intersect against. */
-  for (l_monitor = meta_logical_monitor_get_monitors (logical_monitor);
-       l_monitor;
-       l_monitor = l_monitor->next)
-    {
-      MetaMonitor *monitor = l_monitor->data;
-      MetaGpu *gpu = meta_monitor_get_gpu (monitor);
-
-      if (gpu == META_GPU (onscreen_native->render_gpu))
-        gpu_mods = get_supported_kms_modifiers (onscreen, gpu, format);
-      else
-        gpu_mods = get_supported_egl_modifiers (onscreen, gpu, format);
-
-      if (!gpu_mods)
-        {
-          g_array_free (modifiers, TRUE);
-          return NULL;
-        }
-
-      if (!modifiers)
-        {
-          modifiers = gpu_mods;
-          continue;
-        }
-
-      for (i = 0; i < modifiers->len; i++)
-        {
-          uint64_t modifier = g_array_index (modifiers, uint64_t, i);
-          gboolean found = FALSE;
-          unsigned int m;
-
-          for (m = 0; m < gpu_mods->len; m++)
-            {
-              uint64_t gpu_mod = g_array_index (gpu_mods, uint64_t, m);
-
-              if (gpu_mod == modifier)
-                {
-                  found = TRUE;
-                  break;
-                }
-            }
-
-          if (!found)
-            {
-              g_array_remove_index_fast (modifiers, i);
-              i--;
-            }
-        }
-
-      g_array_free (gpu_mods, TRUE);
-    }
-
-  if (modifiers && modifiers->len == 0)
-    {
-      g_array_free (modifiers, TRUE);
-      return NULL;
-    }
-
-  return modifiers;
-}
-
-typedef struct _GetSupportedKmsFormatsData
-{
-  GArray *formats;
+  MetaCrtc *crtc = onscreen_native->crtc;
   MetaGpu *gpu;
-} GetSupportedKmsFormatsData;
-
-static void
-get_supported_kms_formats_crtc_func (MetaLogicalMonitor *logical_monitor,
-                                     MetaMonitor        *monitor,
-                                     MetaOutput         *output,
-                                     MetaCrtc           *crtc,
-                                     gpointer            user_data)
-{
-  GetSupportedKmsFormatsData *data = user_data;
-  gboolean supported = TRUE;
-  unsigned int i;
-
-  if (crtc->gpu != data->gpu)
-    return;
-
-  if (!data->formats)
-    {
-      /* MetaCrtcKms guarantees a non-empty list. */
-      data->formats = meta_crtc_kms_copy_drm_format_list (crtc);
-
-      return;
-    }
-
-  /* formats must be supported by all other CRTCs too */
-  for (i = 0; i < data->formats->len; i++)
-    {
-      uint32_t drm_format = g_array_index (data->formats, uint32_t, i);
+  g_autoptr (GArray) modifiers = NULL;
 
-      if (!meta_crtc_kms_supports_format (crtc, drm_format))
-        {
-          supported = FALSE;
-          break;
-        }
-    }
+  gpu = meta_crtc_get_gpu (crtc);
+  if (gpu == META_GPU (onscreen_native->render_gpu))
+    modifiers = get_supported_kms_modifiers (crtc, format);
+  else
+    modifiers = get_supported_egl_modifiers (onscreen, crtc, format);
 
-  if (!supported)
-    g_array_remove_index_fast (data->formats, i--);
+  return g_steal_pointer (&modifiers);
 }
 
 static GArray *
-get_supported_kms_formats (CoglOnscreen *onscreen,
-                           MetaGpu      *gpu)
+get_supported_kms_formats (CoglOnscreen *onscreen)
 {
   CoglOnscreenEGL *onscreen_egl = onscreen->winsys;
   MetaOnscreenNative *onscreen_native = onscreen_egl->platform;
-  MetaLogicalMonitor *logical_monitor = onscreen_native->logical_monitor;
-  GetSupportedKmsFormatsData data = {
-    .formats = NULL,
-    .gpu = gpu
-  };
-
-  meta_logical_monitor_foreach_crtc (logical_monitor,
-                                     get_supported_kms_formats_crtc_func,
-                                     &data);
-  if (data.formats->len == 0)
-    {
-      g_array_free (data.formats, TRUE);
-      data.formats = NULL;
-    }
+  MetaCrtc *crtc = onscreen_native->crtc;
 
-  return data.formats;
+  return meta_crtc_kms_copy_drm_format_list (crtc);
 }
 
 static gboolean
 init_secondary_gpu_state_gpu_copy_mode (MetaRendererNative         *renderer_native,
                                         CoglOnscreen               *onscreen,
                                         MetaRendererNativeGpuData  *renderer_gpu_data,
-                                        MetaGpuKms                 *gpu_kms,
                                         GError                    **error)
 {
   CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
@@ -677,6 +461,7 @@ init_secondary_gpu_state_gpu_copy_mode (MetaRendererNative         *renderer_nat
   struct gbm_surface *gbm_surface;
   EGLSurface egl_surface;
   MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state;
+  MetaGpuKms *gpu_kms;
 
   width = cogl_framebuffer_get_width (framebuffer);
   height = cogl_framebuffer_get_height (framebuffer);
@@ -708,13 +493,13 @@ init_secondary_gpu_state_gpu_copy_mode (MetaRendererNative         *renderer_nat
 
   secondary_gpu_state = g_new0 (MetaOnscreenNativeSecondaryGpuState, 1);
 
+  gpu_kms = META_GPU_KMS (meta_crtc_get_gpu (onscreen_native->crtc));
   secondary_gpu_state->gpu_kms = gpu_kms;
   secondary_gpu_state->renderer_gpu_data = renderer_gpu_data;
   secondary_gpu_state->gbm.surface = gbm_surface;
   secondary_gpu_state->egl_surface = egl_surface;
 
-  g_hash_table_insert (onscreen_native->secondary_gpu_states,
-                       gpu_kms, secondary_gpu_state);
+  onscreen_native->secondary_gpu_state = secondary_gpu_state;
 
   return TRUE;
 }
@@ -734,7 +519,6 @@ secondary_gpu_state_free (MetaOnscreenNativeSecondaryGpuState *secondary_gpu_sta
 {
   MetaBackend *backend = meta_get_backend ();
   MetaEgl *egl = meta_backend_get_egl (backend);
-  MetaGpuKms *gpu_kms = secondary_gpu_state->gpu_kms;
 
   if (secondary_gpu_state->egl_surface != EGL_NO_SURFACE)
     {
@@ -747,7 +531,7 @@ secondary_gpu_state_free (MetaOnscreenNativeSecondaryGpuState *secondary_gpu_sta
                                 NULL);
     }
 
-  free_current_secondary_bo (gpu_kms, secondary_gpu_state);
+  g_clear_object (&secondary_gpu_state->gbm.current_fb);
   g_clear_object (&secondary_gpu_state->gbm.next_fb);
   g_clear_pointer (&secondary_gpu_state->gbm.surface, gbm_surface_destroy);
 
@@ -757,8 +541,7 @@ secondary_gpu_state_free (MetaOnscreenNativeSecondaryGpuState *secondary_gpu_sta
 }
 
 static uint32_t
-pick_secondary_gpu_framebuffer_format_for_cpu (CoglOnscreen *onscreen,
-                                               MetaGpu      *gpu)
+pick_secondary_gpu_framebuffer_format_for_cpu (CoglOnscreen *onscreen)
 {
   /*
    * cogl_framebuffer_read_pixels_into_bitmap () supported formats in
@@ -784,7 +567,7 @@ pick_secondary_gpu_framebuffer_format_for_cpu (CoglOnscreen *onscreen,
   unsigned int i;
   uint32_t drm_format;
 
-  formats = get_supported_kms_formats (onscreen, gpu);
+  formats = get_supported_kms_formats (onscreen);
 
   /* Check if any of our preferred formats are supported. */
   for (k = 0; k < G_N_ELEMENTS (preferred_formats); k++)
@@ -822,20 +605,19 @@ static gboolean
 init_secondary_gpu_state_cpu_copy_mode (MetaRendererNative         *renderer_native,
                                         CoglOnscreen               *onscreen,
                                         MetaRendererNativeGpuData  *renderer_gpu_data,
-                                        MetaGpuKms                 *gpu_kms,
                                         GError                    **error)
 {
   CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
   CoglOnscreenEGL *onscreen_egl = onscreen->winsys;
   MetaOnscreenNative *onscreen_native = onscreen_egl->platform;
   MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state;
+  MetaGpuKms *gpu_kms;
   int width, height;
   unsigned int i;
   uint32_t drm_format;
   MetaDrmFormatBuf tmp;
 
-  drm_format = pick_secondary_gpu_framebuffer_format_for_cpu (onscreen,
-                                                              META_GPU (gpu_kms));
+  drm_format = pick_secondary_gpu_framebuffer_format_for_cpu (onscreen);
   if (drm_format == DRM_FORMAT_INVALID)
     {
       g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
@@ -846,6 +628,7 @@ init_secondary_gpu_state_cpu_copy_mode (MetaRendererNative         *renderer_nat
   width = cogl_framebuffer_get_width (framebuffer);
   height = cogl_framebuffer_get_height (framebuffer);
 
+  gpu_kms = META_GPU_KMS (meta_crtc_get_gpu (onscreen_native->crtc));
   g_debug ("Secondary GPU %s using DRM format '%s' (0x%x) for a %dx%d output.",
            meta_gpu_kms_get_file_path (gpu_kms),
            meta_drm_format_to_string (&tmp, drm_format),
@@ -879,8 +662,7 @@ init_secondary_gpu_state_cpu_copy_mode (MetaRendererNative         *renderer_nat
   secondary_gpu_state->import_status =
     META_SHARED_FRAMEBUFFER_IMPORT_STATUS_NONE;
 
-  g_hash_table_insert (onscreen_native->secondary_gpu_states,
-                       gpu_kms, secondary_gpu_state);
+  onscreen_native->secondary_gpu_state = secondary_gpu_state;
 
   return TRUE;
 }
@@ -888,13 +670,15 @@ init_secondary_gpu_state_cpu_copy_mode (MetaRendererNative         *renderer_nat
 static gboolean
 init_secondary_gpu_state (MetaRendererNative  *renderer_native,
                           CoglOnscreen        *onscreen,
-                          MetaGpuKms          *gpu_kms,
                           GError             **error)
 {
+  CoglOnscreenEGL *onscreen_egl = onscreen->winsys;
+  MetaOnscreenNative *onscreen_native = onscreen_egl->platform;
+  MetaGpu *gpu = meta_crtc_get_gpu (onscreen_native->crtc);
   MetaRendererNativeGpuData *renderer_gpu_data;
 
   renderer_gpu_data = meta_renderer_native_get_gpu_data (renderer_native,
-                                                         gpu_kms);
+                                                         META_GPU_KMS (gpu));
 
   switch (renderer_gpu_data->secondary.copy_mode)
     {
@@ -902,7 +686,6 @@ init_secondary_gpu_state (MetaRendererNative  *renderer_native,
       if (!init_secondary_gpu_state_gpu_copy_mode (renderer_native,
                                                    onscreen,
                                                    renderer_gpu_data,
-                                                   gpu_kms,
                                                    error))
         return FALSE;
       break;
@@ -917,7 +700,6 @@ init_secondary_gpu_state (MetaRendererNative  *renderer_native,
       if (!init_secondary_gpu_state_cpu_copy_mode (renderer_native,
                                                    onscreen,
                                                    renderer_gpu_data,
-                                                   gpu_kms,
                                                    error))
         return FALSE;
       break;
@@ -989,9 +771,16 @@ flush_pending_swap_notify_idle (void *user_data)
 }
 
 static void
-free_current_secondary_bo (MetaGpuKms                          *gpu_kms,
-                           MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state)
+free_current_secondary_bo (CoglOnscreen *onscreen)
 {
+  CoglOnscreenEGL *onscreen_egl =  onscreen->winsys;
+  MetaOnscreenNative *onscreen_native = onscreen_egl->platform;
+  MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state;
+
+  secondary_gpu_state = onscreen_native->secondary_gpu_state;
+  if (!secondary_gpu_state)
+    return;
+
   g_clear_object (&secondary_gpu_state->gbm.current_fb);
 }
 
@@ -1002,10 +791,7 @@ free_current_bo (CoglOnscreen *onscreen)
   MetaOnscreenNative *onscreen_native = onscreen_egl->platform;
 
   g_clear_object (&onscreen_native->gbm.current_fb);
-
-  g_hash_table_foreach (onscreen_native->secondary_gpu_states,
-                        (GHFunc) free_current_secondary_bo,
-                        NULL);
+  free_current_secondary_bo (onscreen);
 }
 
 static void
@@ -1292,9 +1078,16 @@ meta_renderer_native_egl_cleanup_context (CoglDisplay *cogl_display)
 }
 
 static void
-swap_secondary_drm_fb (MetaGpuKms                          *gpu_kms,
-                       MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state)
+swap_secondary_drm_fb (CoglOnscreen *onscreen)
 {
+  CoglOnscreenEGL *onscreen_egl =  onscreen->winsys;
+  MetaOnscreenNative *onscreen_native = onscreen_egl->platform;
+  MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state;
+
+  secondary_gpu_state = onscreen_native->secondary_gpu_state;
+  if (!secondary_gpu_state)
+    return;
+
   g_set_object (&secondary_gpu_state->gbm.current_fb,
                 secondary_gpu_state->gbm.next_fb);
   g_clear_object (&secondary_gpu_state->gbm.next_fb);
@@ -1311,9 +1104,7 @@ meta_onscreen_native_swap_drm_fb (CoglOnscreen *onscreen)
   g_set_object (&onscreen_native->gbm.current_fb, onscreen_native->gbm.next_fb);
   g_clear_object (&onscreen_native->gbm.next_fb);
 
-  g_hash_table_foreach (onscreen_native->secondary_gpu_states,
-                        (GHFunc) swap_secondary_drm_fb,
-                        NULL);
+  swap_secondary_drm_fb (onscreen);
 }
 
 static void
@@ -1354,9 +1145,9 @@ notify_view_crtc_presented (MetaRendererView *view,
   gpu_kms = META_GPU_KMS (meta_crtc_get_gpu (crtc));
   if (gpu_kms != render_gpu)
     {
-      MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state;
+      MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state =
+        onscreen_native->secondary_gpu_state;
 
-      secondary_gpu_state = get_secondary_gpu_state (onscreen, gpu_kms);
       secondary_gpu_state->pending_flips--;
     }
 
@@ -1555,8 +1346,6 @@ queue_dummy_power_save_page_flip (CoglOnscreen *onscreen)
 static void
 meta_onscreen_native_flip_crtc (CoglOnscreen     *onscreen,
                                 MetaRendererView *view,
-                                MetaMonitor      *monitor,
-                                MetaOutput       *output,
                                 MetaCrtc         *crtc,
                                 MetaKmsUpdate    *kms_update)
 {
@@ -1584,12 +1373,11 @@ meta_onscreen_native_flip_crtc (CoglOnscreen     *onscreen,
         }
       else
         {
-          secondary_gpu_state = get_secondary_gpu_state (onscreen, gpu_kms);
+          secondary_gpu_state = onscreen_native->secondary_gpu_state;
           fb_id = meta_drm_buffer_get_fb_id (secondary_gpu_state->gbm.next_fb);
         }
 
-      meta_crtc_kms_assign_primary_plane (crtc, monitor, output,
-                                          fb_id, kms_update);
+      meta_crtc_kms_assign_primary_plane (crtc, fb_id, kms_update);
       meta_crtc_kms_page_flip (crtc,
                                &page_flip_feedback,
                                g_object_ref (view),
@@ -1614,23 +1402,18 @@ meta_onscreen_native_flip_crtc (CoglOnscreen     *onscreen,
     }
 }
 
-typedef struct _SetCrtcModeData
-{
-  MetaRendererNativeGpuData *renderer_gpu_data;
-  MetaOnscreenNative *onscreen_native;
-  MetaKmsUpdate *kms_update;
-} SetCrtcModeData;
-
 static void
-set_crtc_mode (MetaLogicalMonitor *logical_monitor,
-               MetaMonitor        *monitor,
-               MetaOutput         *output,
-               MetaCrtc           *crtc,
-               gpointer            user_data)
+meta_onscreen_native_set_crtc_mode (CoglOnscreen              *onscreen,
+                                    MetaRendererNativeGpuData *renderer_gpu_data,
+                                    MetaKmsUpdate             *kms_update)
 {
-  SetCrtcModeData *data = user_data;
+  CoglOnscreenEGL *onscreen_egl = onscreen->winsys;
+  MetaOnscreenNative *onscreen_native = onscreen_egl->platform;
 
-  switch (data->renderer_gpu_data->mode)
+  COGL_TRACE_BEGIN_SCOPED (MetaOnscreenNativeSetCrtcModes,
+                           "Onscreen (set CRTC modes)");
+
+  switch (renderer_gpu_data->mode)
     {
     case META_RENDERER_NATIVE_MODE_GBM:
       break;
@@ -1639,63 +1422,16 @@ set_crtc_mode (MetaLogicalMonitor *logical_monitor,
       {
         uint32_t fb_id;
 
-        fb_id = data->onscreen_native->egl.dumb_fb.fb_id;
-        meta_crtc_kms_assign_primary_plane (crtc, monitor, output,
-                                            fb_id, data->kms_update);
+        fb_id = onscreen_native->egl.dumb_fb.fb_id;
+        meta_crtc_kms_assign_primary_plane (onscreen_native->crtc,
+                                            fb_id, kms_update);
         break;
       }
 #endif
     }
 
-  meta_crtc_kms_set_mode (crtc, data->kms_update);
-  meta_output_kms_set_underscan (output, data->kms_update);
-}
-
-static void
-meta_onscreen_native_set_crtc_modes (CoglOnscreen              *onscreen,
-                                     MetaRendererNativeGpuData *renderer_gpu_data,
-                                     MetaKmsUpdate             *kms_update)
-{
-  CoglOnscreenEGL *onscreen_egl = onscreen->winsys;
-  MetaOnscreenNative *onscreen_native = onscreen_egl->platform;
-  MetaRendererView *view = onscreen_native->view;
-  MetaLogicalMonitor *logical_monitor;
-  SetCrtcModeData data;
-
-  COGL_TRACE_BEGIN_SCOPED (MetaOnscreenNativeSetCrtcModes,
-                           "Onscreen (set CRTC modes)");
-
-  logical_monitor = meta_renderer_view_get_logical_monitor (view);
-  data = (SetCrtcModeData) {
-    .renderer_gpu_data = renderer_gpu_data,
-    .onscreen_native = onscreen_native,
-    .kms_update = kms_update,
-  };
-  meta_logical_monitor_foreach_crtc (logical_monitor, set_crtc_mode, &data);
-}
-
-typedef struct _FlipCrtcData
-{
-  MetaRendererView *view;
-  CoglOnscreen *onscreen;
-  MetaKmsUpdate *kms_update;
-} FlipCrtcData;
-
-static void
-flip_crtc (MetaLogicalMonitor *logical_monitor,
-           MetaMonitor        *monitor,
-           MetaOutput         *output,
-           MetaCrtc           *crtc,
-           gpointer            user_data)
-{
-  FlipCrtcData *data = user_data;
-
-  meta_onscreen_native_flip_crtc (data->onscreen,
-                                  data->view,
-                                  monitor,
-                                  output,
-                                  crtc,
-                                  data->kms_update);
+  meta_crtc_kms_set_mode (onscreen_native->crtc, kms_update);
+  meta_output_kms_set_underscan (onscreen_native->output, kms_update);
 }
 
 static void
@@ -1710,7 +1446,6 @@ meta_onscreen_native_flip_crtcs (CoglOnscreen  *onscreen,
   MetaMonitorManager *monitor_manager =
     meta_backend_get_monitor_manager (meta_renderer_get_backend (renderer));
   MetaPowerSave power_save_mode;
-  MetaLogicalMonitor *logical_monitor;
 
   COGL_TRACE_BEGIN_SCOPED (MetaOnscreenNativeFlipCrtcs,
                            "Onscreen (flip CRTCs)");
@@ -1718,13 +1453,8 @@ meta_onscreen_native_flip_crtcs (CoglOnscreen  *onscreen,
   power_save_mode = meta_monitor_manager_get_power_save_mode (monitor_manager);
   if (power_save_mode == META_POWER_SAVE_ON)
     {
-      FlipCrtcData data = {
-        .onscreen = onscreen,
-        .view = view,
-        .kms_update = kms_update,
-      };
-      logical_monitor = meta_renderer_view_get_logical_monitor (view);
-      meta_logical_monitor_foreach_crtc (logical_monitor, flip_crtc, &data);
+      meta_onscreen_native_flip_crtc (onscreen, view, onscreen_native->crtc,
+                                      kms_update);
     }
   else
     {
@@ -1738,13 +1468,10 @@ wait_for_pending_flips (CoglOnscreen *onscreen)
   CoglOnscreenEGL *onscreen_egl = onscreen->winsys;
   MetaOnscreenNative *onscreen_native = onscreen_egl->platform;
   MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state;
-  GHashTableIter iter;
   GError *error = NULL;
 
-  g_hash_table_iter_init (&iter, onscreen_native->secondary_gpu_states);
-  while (g_hash_table_iter_next (&iter,
-                                 NULL,
-                                 (gpointer *) &secondary_gpu_state))
+  secondary_gpu_state = onscreen_native->secondary_gpu_state;
+  if (secondary_gpu_state)
     {
       while (secondary_gpu_state->pending_flips)
         {
@@ -2159,16 +1886,13 @@ update_secondary_gpu_state_pre_swap_buffers (CoglOnscreen *onscreen)
 {
   CoglOnscreenEGL *onscreen_egl = onscreen->winsys;
   MetaOnscreenNative *onscreen_native = onscreen_egl->platform;
-  GHashTableIter iter;
   MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state;
 
   COGL_TRACE_BEGIN_SCOPED (MetaRendererNativeGpuStatePreSwapBuffers,
                            "Onscreen (secondary gpu pre-swap-buffers)");
 
-  g_hash_table_iter_init (&iter, onscreen_native->secondary_gpu_states);
-  while (g_hash_table_iter_next (&iter,
-                                 NULL,
-                                 (gpointer *) &secondary_gpu_state))
+  secondary_gpu_state = onscreen_native->secondary_gpu_state;
+  if (secondary_gpu_state)
     {
       MetaRendererNativeGpuData *renderer_gpu_data;
 
@@ -2218,16 +1942,13 @@ update_secondary_gpu_state_post_swap_buffers (CoglOnscreen *onscreen,
   CoglOnscreenEGL *onscreen_egl = onscreen->winsys;
   MetaOnscreenNative *onscreen_native = onscreen_egl->platform;
   MetaRendererNative *renderer_native = onscreen_native->renderer_native;
-  GHashTableIter iter;
   MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state;
 
   COGL_TRACE_BEGIN_SCOPED (MetaRendererNativeGpuStatePostSwapBuffers,
                            "Onscreen (secondary gpu post-swap-buffers)");
 
-  g_hash_table_iter_init (&iter, onscreen_native->secondary_gpu_states);
-  while (g_hash_table_iter_next (&iter,
-                                 NULL,
-                                 (gpointer *) &secondary_gpu_state))
+  secondary_gpu_state = onscreen_native->secondary_gpu_state;
+  if (secondary_gpu_state)
     {
       MetaRendererNativeGpuData *renderer_gpu_data;
 
@@ -2343,9 +2064,9 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen *onscreen,
   if (onscreen_native->pending_set_crtc &&
       power_save_mode == META_POWER_SAVE_ON)
     {
-      meta_onscreen_native_set_crtc_modes (onscreen,
-                                           renderer_gpu_data,
-                                           kms_update);
+      meta_onscreen_native_set_crtc_mode (onscreen,
+                                          renderer_gpu_data,
+                                          kms_update);
       onscreen_native->pending_set_crtc = FALSE;
     }
 
@@ -2420,29 +2141,12 @@ should_surface_be_sharable (CoglOnscreen *onscreen)
 {
   CoglOnscreenEGL *onscreen_egl = onscreen->winsys;
   MetaOnscreenNative *onscreen_native = onscreen_egl->platform;
-  MetaRendererNative *renderer_native = onscreen_native->renderer_native;
-  CoglContext *cogl_context = COGL_FRAMEBUFFER (onscreen)->context;
-  CoglRenderer *cogl_renderer = cogl_context->display->renderer;
-  CoglRendererEGL *cogl_renderer_egl = cogl_renderer->winsys;
-  MetaRendererNativeGpuData *renderer_gpu_data = cogl_renderer_egl->platform;
-  GList *l;
 
-  if (!onscreen_native->logical_monitor)
+  if (META_GPU_KMS (meta_crtc_get_gpu (onscreen_native->crtc)) ==
+      onscreen_native->render_gpu)
     return FALSE;
-
-  for (l = meta_logical_monitor_get_monitors (onscreen_native->logical_monitor);
-       l;
-       l = l->next)
-    {
-      MetaMonitor *monitor = l->data;
-      MetaGpuKms *gpu_kms = META_GPU_KMS (meta_monitor_get_gpu (monitor));
-
-      if (renderer_gpu_data != meta_renderer_native_get_gpu_data (renderer_native,
-                                                                  gpu_kms))
-        return TRUE;
-    }
-
-  return FALSE;
+  else
+    return TRUE;
 }
 
 static gboolean
@@ -2532,15 +2236,16 @@ meta_renderer_native_create_surface_gbm (CoglOnscreen        *onscreen,
 
 #ifdef HAVE_EGL_DEVICE
 static gboolean
-meta_renderer_native_create_surface_egl_device (CoglOnscreen       *onscreen,
-                                                MetaLogicalMonitor *logical_monitor,
-                                                int                 width,
-                                                int                 height,
-                                                EGLStreamKHR       *out_egl_stream,
-                                                EGLSurface         *out_egl_surface,
-                                                GError            **error)
+meta_renderer_native_create_surface_egl_device (CoglOnscreen  *onscreen,
+                                                int            width,
+                                                int            height,
+                                                EGLStreamKHR  *out_egl_stream,
+                                                EGLSurface    *out_egl_surface,
+                                                GError       **error)
 {
   CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
+  CoglOnscreenEGL *onscreen_egl = onscreen->winsys;
+  MetaOnscreenNative *onscreen_native = onscreen_egl->platform;
   CoglContext *cogl_context = framebuffer->context;
   CoglDisplay *cogl_display = cogl_context->display;
   CoglDisplayEGL *cogl_display_egl = cogl_display->winsys;
@@ -2550,9 +2255,6 @@ meta_renderer_native_create_surface_egl_device (CoglOnscreen       *onscreen,
   MetaEgl *egl =
     meta_renderer_native_get_egl (renderer_gpu_data->renderer_native);
   EGLDisplay egl_display = renderer_gpu_data->egl_display;
-  MetaMonitor *monitor;
-  MetaOutput *output;
-  MetaCrtc *crtc;
   EGLConfig egl_config;
   EGLStreamKHR egl_stream;
   EGLSurface egl_surface;
@@ -2574,17 +2276,8 @@ meta_renderer_native_create_surface_egl_device (CoglOnscreen       *onscreen,
   if (egl_stream == EGL_NO_STREAM_KHR)
     return FALSE;
 
-  monitor = meta_logical_monitor_get_monitors (logical_monitor)->data;
-  output = meta_monitor_get_main_output (monitor);
-  crtc = meta_output_get_assigned_crtc (output);
-
-  /*
-   * An "logical_monitor" may have multiple outputs/crtcs in case its tiled,
-   * but as far as I can tell, EGL only allows you to pass one crtc_id, so
-   * lets pass the first one.
-   */
   output_attribs[0] = EGL_DRM_CRTC_EXT;
-  output_attribs[1] = crtc->crtc_id;
+  output_attribs[1] = onscreen_native->crtc->crtc_id;
   output_attribs[2] = EGL_NONE;
 
   if (!meta_egl_get_output_layers (egl, egl_display,
@@ -2826,8 +2519,6 @@ meta_onscreen_native_allocate (CoglOnscreen *onscreen,
   int width;
   int height;
 #ifdef HAVE_EGL_DEVICE
-  MetaRendererView *view;
-  MetaLogicalMonitor *logical_monitor;
   EGLStreamKHR egl_stream;
 #endif
 
@@ -2868,10 +2559,7 @@ meta_onscreen_native_allocate (CoglOnscreen *onscreen,
                          error))
         return FALSE;
 
-      view = onscreen_native->view;
-      logical_monitor = meta_renderer_view_get_logical_monitor (view);
       if (!meta_renderer_native_create_surface_egl_device (onscreen,
-                                                           logical_monitor,
                                                            width, height,
                                                            &egl_stream,
                                                            &egl_surface,
@@ -2982,7 +2670,8 @@ meta_renderer_native_release_onscreen (CoglOnscreen *onscreen)
 #endif /* HAVE_EGL_DEVICE */
     }
 
-  g_hash_table_destroy (onscreen_native->secondary_gpu_states);
+  g_clear_pointer (&onscreen_native->secondary_gpu_state,
+                   secondary_gpu_state_free);
 
   g_slice_free (MetaOnscreenNative, onscreen_native);
   g_slice_free (CoglOnscreenEGL, onscreen->winsys);
@@ -3052,29 +2741,16 @@ meta_renderer_native_queue_modes_reset (MetaRendererNative *renderer_native)
 static CoglOnscreen *
 meta_renderer_native_create_onscreen (MetaRendererNative   *renderer_native,
                                       MetaGpuKms           *render_gpu,
-                                      MetaLogicalMonitor   *logical_monitor,
+                                      MetaOutput           *output,
+                                      MetaCrtc             *crtc,
                                       CoglContext          *context,
-                                      MetaMonitorTransform  transform,
-                                      gint                  view_width,
-                                      gint                  view_height,
+                                      int                   width,
+                                      int                   height,
                                       GError              **error)
 {
   CoglOnscreen *onscreen;
   CoglOnscreenEGL *onscreen_egl;
   MetaOnscreenNative *onscreen_native;
-  gint width, height;
-  GList *l;
-
-  if (meta_monitor_transform_is_rotated (transform))
-    {
-      width = view_height;
-      height = view_width;
-    }
-  else
-    {
-      width = view_width;
-      height = view_height;
-    }
 
   onscreen = cogl_onscreen_new (context, width, height);
 
@@ -3088,24 +2764,12 @@ meta_renderer_native_create_onscreen (MetaRendererNative   *renderer_native,
   onscreen_native = onscreen_egl->platform;
   onscreen_native->renderer_native = renderer_native;
   onscreen_native->render_gpu = render_gpu;
-  onscreen_native->logical_monitor = logical_monitor;
-  onscreen_native->secondary_gpu_states =
-    g_hash_table_new_full (NULL, NULL,
-                           NULL,
-                           (GDestroyNotify) secondary_gpu_state_free);
+  onscreen_native->output = output;
+  onscreen_native->crtc = crtc;
 
-  for (l = meta_logical_monitor_get_monitors (logical_monitor); l; l = l->next)
+  if (META_GPU_KMS (meta_crtc_get_gpu (crtc)) != render_gpu)
     {
-      MetaMonitor *monitor = l->data;
-      MetaGpuKms *gpu_kms = META_GPU_KMS (meta_monitor_get_gpu (monitor));
-
-      if (gpu_kms == render_gpu)
-        continue;
-
-      if (get_secondary_gpu_state (onscreen, gpu_kms))
-        continue;
-
-      if (!init_secondary_gpu_state (renderer_native, onscreen, gpu_kms, error))
+      if (!init_secondary_gpu_state (renderer_native, onscreen, error))
         {
           cogl_object_unref (onscreen);
           return NULL;
@@ -3225,24 +2889,15 @@ meta_onscreen_native_set_view (CoglOnscreen     *onscreen,
 
 static MetaMonitorTransform
 calculate_view_transform (MetaMonitorManager *monitor_manager,
-                          MetaLogicalMonitor *logical_monitor)
+                          MetaLogicalMonitor *logical_monitor,
+                          MetaOutput         *output,
+                          MetaCrtc           *crtc)
 {
-  MetaMonitor *main_monitor;
-  MetaOutput *main_output;
-  MetaCrtc *crtc;
   MetaMonitorTransform crtc_transform;
 
-  main_monitor = meta_logical_monitor_get_monitors (logical_monitor)->data;
-  main_output = meta_monitor_get_main_output (main_monitor);
-  crtc = meta_output_get_assigned_crtc (main_output);
+  crtc = meta_output_get_assigned_crtc (output);
   crtc_transform =
-    meta_monitor_logical_to_crtc_transform (main_monitor,
-                                            logical_monitor->transform);
-
-  /*
-   * Pick any monitor and output and check; all CRTCs of a logical monitor will
-   * always have the same transform assigned to them.
-   */
+    meta_output_logical_to_crtc_transform (output, logical_monitor->transform);
 
   if (meta_monitor_manager_is_transform_handled (monitor_manager,
                                                  crtc,
@@ -3295,7 +2950,9 @@ should_force_shadow_fb (MetaRendererNative *renderer_native,
 
 static MetaRendererView *
 meta_renderer_native_create_view (MetaRenderer       *renderer,
-                                  MetaLogicalMonitor *logical_monitor)
+                                  MetaLogicalMonitor *logical_monitor,
+                                  MetaOutput         *output,
+                                  MetaCrtc           *crtc)
 {
   MetaRendererNative *renderer_native = META_RENDERER_NATIVE (renderer);
   MetaBackend *backend = meta_renderer_get_backend (renderer);
@@ -3306,42 +2963,56 @@ meta_renderer_native_create_view (MetaRenderer       *renderer,
   CoglDisplay *cogl_display = cogl_context_get_display (cogl_context);
   CoglDisplayEGL *cogl_display_egl;
   CoglOnscreenEGL *onscreen_egl;
+  MetaCrtcConfig *crtc_config;
   MetaMonitorTransform view_transform;
   CoglOnscreen *onscreen = NULL;
   CoglOffscreen *offscreen = NULL;
   CoglOffscreen *shadowfb = NULL;
   float scale;
-  int width, height;
+  int onscreen_width;
+  int onscreen_height;
   MetaRendererView *view;
   GError *error = NULL;
 
-  view_transform = calculate_view_transform (monitor_manager, logical_monitor);
-
-  if (meta_is_stage_views_scaled ())
-    scale = meta_logical_monitor_get_scale (logical_monitor);
-  else
-    scale = 1.0;
-
-  width = roundf (logical_monitor->rect.width * scale);
-  height = roundf (logical_monitor->rect.height * scale);
+  crtc_config = crtc->config;
+  onscreen_width = crtc_config->mode->width;
+  onscreen_height = crtc_config->mode->height;
 
   onscreen = meta_renderer_native_create_onscreen (renderer_native,
                                                    renderer_native->primary_gpu_kms,
-                                                   logical_monitor,
+                                                   output,
+                                                   crtc,
                                                    cogl_context,
-                                                   view_transform,
-                                                   width,
-                                                   height,
+                                                   onscreen_width,
+                                                   onscreen_height,
                                                    &error);
   if (!onscreen)
     g_error ("Failed to allocate onscreen framebuffer: %s", error->message);
 
+  view_transform = calculate_view_transform (monitor_manager,
+                                             logical_monitor,
+                                             output,
+                                             crtc);
   if (view_transform != META_MONITOR_TRANSFORM_NORMAL)
     {
+      int offscreen_width;
+      int offscreen_height;
+
+      if (meta_monitor_transform_is_rotated (view_transform))
+        {
+          offscreen_width = onscreen_height;
+          offscreen_height = onscreen_width;
+        }
+      else
+        {
+          offscreen_width = onscreen_width;
+          offscreen_height = onscreen_height;
+        }
+
       offscreen = meta_renderer_native_create_offscreen (renderer_native,
                                                          cogl_context,
-                                                         width,
-                                                         height,
+                                                         offscreen_width,
+                                                         offscreen_height,
                                                          &error);
       if (!offscreen)
         g_error ("Failed to allocate back buffer texture: %s", error->message);
@@ -3366,13 +3037,17 @@ meta_renderer_native_create_view (MetaRenderer       *renderer,
         g_error ("Failed to allocate shadow buffer texture: %s", error->message);
     }
 
+  if (meta_is_stage_views_scaled ())
+    scale = meta_logical_monitor_get_scale (logical_monitor);
+  else
+    scale = 1.0;
+
   view = g_object_new (META_TYPE_RENDERER_VIEW,
                        "layout", &logical_monitor->rect,
                        "scale", scale,
                        "framebuffer", onscreen,
                        "offscreen", offscreen,
                        "shadowfb", shadowfb,
-                       "logical-monitor", logical_monitor,
                        "transform", view_transform,
                        NULL);
   g_clear_pointer (&offscreen, cogl_object_unref);
diff --git a/src/backends/x11/nested/meta-renderer-x11-nested.c 
b/src/backends/x11/nested/meta-renderer-x11-nested.c
index caf80fc2b..6c8b9d63f 100644
--- a/src/backends/x11/nested/meta-renderer-x11-nested.c
+++ b/src/backends/x11/nested/meta-renderer-x11-nested.c
@@ -172,7 +172,9 @@ meta_renderer_x11_nested_ensure_legacy_view (MetaRendererX11Nested *renderer_x11
 
 static MetaRendererView *
 meta_renderer_x11_nested_create_view (MetaRenderer       *renderer,
-                                      MetaLogicalMonitor *logical_monitor)
+                                      MetaLogicalMonitor *logical_monitor,
+                                      MetaOutput         *output,
+                                      MetaCrtc           *crtc)
 {
   MetaBackend *backend = meta_get_backend ();
   MetaMonitorManager *monitor_manager =
@@ -184,6 +186,8 @@ meta_renderer_x11_nested_create_view (MetaRenderer       *renderer,
   int width, height;
   CoglOffscreen *fake_onscreen;
   CoglOffscreen *offscreen;
+  MetaRectangle view_layout;
+  MetaRendererView *view;
 
   view_transform = calculate_view_transform (monitor_manager, logical_monitor);
 
@@ -192,18 +196,8 @@ meta_renderer_x11_nested_create_view (MetaRenderer       *renderer,
   else
     view_scale = 1.0;
 
-  if (meta_monitor_transform_is_rotated (view_transform))
-    {
-      width = logical_monitor->rect.height;
-      height = logical_monitor->rect.width;
-    }
-  else
-    {
-      width = logical_monitor->rect.width;
-      height = logical_monitor->rect.height;
-    }
-  width = roundf (width * view_scale);
-  height = roundf (height * view_scale);
+  width = roundf (crtc->config->layout.size.width * view_scale);
+  height = roundf (crtc->config->layout.size.height * view_scale);
 
   fake_onscreen = create_offscreen (cogl_context, width, height);
 
@@ -212,14 +206,20 @@ meta_renderer_x11_nested_create_view (MetaRenderer       *renderer,
   else
     offscreen = NULL;
 
-  return g_object_new (META_TYPE_RENDERER_VIEW,
-                       "layout", &logical_monitor->rect,
+  meta_rectangle_from_graphene_rect (&crtc->config->layout,
+                                     META_ROUNDING_STRATEGY_ROUND,
+                                     &view_layout);
+
+  view = g_object_new (META_TYPE_RENDERER_VIEW,
+                       "layout", &view_layout,
                        "framebuffer", COGL_FRAMEBUFFER (fake_onscreen),
                        "offscreen", COGL_FRAMEBUFFER (offscreen),
                        "transform", view_transform,
                        "scale", view_scale,
-                       "logical-monitor", logical_monitor,
                        NULL);
+  g_object_set_data (G_OBJECT (view), "crtc", crtc);
+
+  return view;
 }
 
 static void
diff --git a/src/backends/x11/nested/meta-stage-x11-nested.c b/src/backends/x11/nested/meta-stage-x11-nested.c
index a9704e1f5..361f905ed 100644
--- a/src/backends/x11/nested/meta-stage-x11-nested.c
+++ b/src/backends/x11/nested/meta-stage-x11-nested.c
@@ -101,46 +101,33 @@ typedef struct
 } DrawCrtcData;
 
 static gboolean
-draw_crtc (MetaMonitor         *monitor,
-           MetaMonitorMode     *monitor_mode,
-           MetaMonitorCrtcMode *monitor_crtc_mode,
-           gpointer             user_data,
-           GError             **error)
+draw_view (MetaStageX11Nested *stage_nested,
+           MetaRendererView   *renderer_view,
+           CoglTexture        *texture)
 {
-  DrawCrtcData *data = user_data;
-  MetaStageX11 *stage_x11 = META_STAGE_X11 (data->stage_nested);
+  MetaStageX11 *stage_x11 = META_STAGE_X11 (stage_nested);
   CoglFramebuffer *onscreen = COGL_FRAMEBUFFER (stage_x11->onscreen);
-  CoglTexture *texture = data->texture;
-  MetaLogicalMonitor *logical_monitor = data->logical_monitor;
-  MetaOutput *output = monitor_crtc_mode->output;
+  ClutterStageView *stage_view = CLUTTER_STAGE_VIEW (renderer_view);
   MetaCrtc *crtc;
   MetaCrtcConfig *crtc_config;
-  MetaRendererView *renderer_view = META_RENDERER_VIEW (data->view);
-  MetaMonitorTransform view_transform;
-  MetaMonitorTransform layout_transform = META_MONITOR_TRANSFORM_NORMAL;
-  cairo_rectangle_int_t view_layout;
   CoglMatrix projection_matrix;
   CoglMatrix transform;
   float texture_width, texture_height;
   float sample_x, sample_y, sample_width, sample_height;
-  float scale;
-  int viewport_x, viewport_y;
-  int viewport_width, viewport_height;
   float s_1, t_1, s_2, t_2;
 
   texture_width = cogl_texture_get_width (texture);
   texture_height = cogl_texture_get_height (texture);
 
-  crtc = meta_output_get_assigned_crtc (output);
+  crtc = g_object_get_data (G_OBJECT (renderer_view), "crtc");
   crtc_config = crtc->config;
 
-  clutter_stage_view_get_layout (data->view, &view_layout);
-  sample_x = (int) roundf (crtc_config->layout.origin.x) - view_layout.x;
-  sample_y = (int) roundf (crtc_config->layout.origin.y) - view_layout.y;
-  sample_width = (int) roundf (crtc_config->layout.size.width);
-  sample_height = (int) roundf (crtc_config->layout.size.height);
+  sample_x = 0;
+  sample_y = 0;
+  sample_width = texture_width;
+  sample_height = texture_height;
 
-  clutter_stage_view_get_offscreen_transformation_matrix (data->view,
+  clutter_stage_view_get_offscreen_transformation_matrix (stage_view,
                                                           &transform);
 
   cogl_framebuffer_push_matrix (onscreen);
@@ -156,62 +143,14 @@ draw_crtc (MetaMonitor         *monitor,
   s_2 = (sample_x + sample_width) / texture_width;
   t_2 = (sample_y + sample_height) / texture_height;
 
-  view_transform = meta_renderer_view_get_transform (renderer_view);
-
-  if (view_transform == logical_monitor->transform)
-    {
-      switch (view_transform)
-        {
-        case META_MONITOR_TRANSFORM_NORMAL:
-        case META_MONITOR_TRANSFORM_FLIPPED:
-          layout_transform = META_MONITOR_TRANSFORM_NORMAL;
-          break;
-        case META_MONITOR_TRANSFORM_270:
-        case META_MONITOR_TRANSFORM_FLIPPED_270:
-          layout_transform = META_MONITOR_TRANSFORM_90;
-          break;
-        case META_MONITOR_TRANSFORM_180:
-        case META_MONITOR_TRANSFORM_FLIPPED_180:
-          layout_transform = META_MONITOR_TRANSFORM_180;
-          break;
-        case META_MONITOR_TRANSFORM_90:
-        case META_MONITOR_TRANSFORM_FLIPPED_90:
-          layout_transform = META_MONITOR_TRANSFORM_270;
-          break;
-        }
-    }
-  else
-    {
-      layout_transform = logical_monitor->transform;
-    }
-
-  meta_monitor_calculate_crtc_pos (monitor, monitor_mode, output,
-                                   layout_transform,
-                                   &viewport_x,
-                                   &viewport_y);
-  viewport_x += logical_monitor->rect.x;
-  viewport_y += logical_monitor->rect.y;
-  if (meta_monitor_transform_is_rotated (logical_monitor->transform))
-    {
-      viewport_width = monitor_crtc_mode->crtc_mode->height;
-      viewport_height = monitor_crtc_mode->crtc_mode->width;
-    }
-  else
-    {
-      viewport_width = monitor_crtc_mode->crtc_mode->width;
-      viewport_height = monitor_crtc_mode->crtc_mode->height;
-    }
-
-  scale = clutter_stage_view_get_scale (data->view);
-  viewport_width = roundf (viewport_width / scale);
-  viewport_height = roundf (viewport_height / scale);
-
   cogl_framebuffer_set_viewport (onscreen,
-                                 viewport_x, viewport_y,
-                                 viewport_width, viewport_height);
+                                 crtc_config->layout.origin.x,
+                                 crtc_config->layout.origin.y,
+                                 crtc_config->layout.size.width,
+                                 crtc_config->layout.size.height);
 
   cogl_framebuffer_draw_textured_rectangle (onscreen,
-                                            data->stage_nested->pipeline,
+                                            stage_nested->pipeline,
                                             0, 0, 1, 1,
                                             s_1, t_1, s_2, t_2);
 
@@ -219,32 +158,6 @@ draw_crtc (MetaMonitor         *monitor,
   return TRUE;
 }
 
-static void
-draw_logical_monitor (MetaStageX11Nested    *stage_nested,
-                      MetaLogicalMonitor    *logical_monitor,
-                      CoglTexture           *texture,
-                      ClutterStageView      *view,
-                      cairo_rectangle_int_t *view_layout)
-{
-  MetaMonitor *monitor;
-  MetaMonitorMode *current_mode;
-
-  cogl_pipeline_set_layer_wrap_mode (stage_nested->pipeline, 0,
-                                     COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE);
-
-  monitor = meta_logical_monitor_get_monitors (logical_monitor)->data;
-  current_mode = meta_monitor_get_current_mode (monitor);
-  meta_monitor_mode_foreach_crtc (monitor, current_mode,
-                                  draw_crtc,
-                                  &(DrawCrtcData) {
-                                    .stage_nested = stage_nested,
-                                    .texture = texture,
-                                    .view = view,
-                                    .logical_monitor = logical_monitor
-                                  },
-                                  NULL);
-}
-
 static void
 meta_stage_x11_nested_finish_frame (ClutterStageWindow *stage_window)
 {
@@ -267,39 +180,17 @@ meta_stage_x11_nested_finish_frame (ClutterStageWindow *stage_window)
     {
       ClutterStageView *view = l->data;
       MetaRendererView *renderer_view = META_RENDERER_VIEW (view);
-      MetaLogicalMonitor *logical_monitor;
-      cairo_rectangle_int_t view_layout;
       CoglFramebuffer *framebuffer;
       CoglTexture *texture;
 
-      clutter_stage_view_get_layout (view, &view_layout);
-
       framebuffer = clutter_stage_view_get_onscreen (view);
       texture = cogl_offscreen_get_texture (COGL_OFFSCREEN (framebuffer));
 
       cogl_pipeline_set_layer_texture (stage_nested->pipeline, 0, texture);
+      cogl_pipeline_set_layer_wrap_mode (stage_nested->pipeline, 0,
+                                         COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE);
 
-      logical_monitor = meta_renderer_view_get_logical_monitor (renderer_view);
-      if (logical_monitor)
-        {
-          draw_logical_monitor (stage_nested, logical_monitor, texture, view, &view_layout);
-        }
-      else
-        {
-          MetaMonitorManager *monitor_manager =
-            meta_backend_get_monitor_manager (backend);
-          GList *logical_monitors;
-          GList *k;
-
-          logical_monitors =
-            meta_monitor_manager_get_logical_monitors (monitor_manager);
-          for (k = logical_monitors; k; k = k->next)
-            {
-              logical_monitor = k->data;
-
-              draw_logical_monitor (stage_nested, logical_monitor, texture, view, &view_layout);
-            }
-        }
+      draw_view (stage_nested, renderer_view, texture);
     }
 
   cogl_onscreen_swap_buffers (stage_x11->onscreen);


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