[mutter] crtc: Move configured state to separate struct



commit fe42d56db39f994144e4eedd1430363c373ab9c4
Author: Jonas Ådahl <jadahl gmail com>
Date:   Tue Jan 14 22:34:44 2020 +0100

    crtc: Move configured state to separate struct
    
    To make it more reliable to distinguish between values that are read
    from the backend implementation (which is likely to be irrelevant for
    anything but the backend implementation), split out those values (e.g.
    layout).
    
    This changes the meaning of what was MetaCrtc::rect, to a
    MetaCrtcConfig::layout which is the layout the CRTC has in the global
    coordinate space.
    
    https://gitlab.gnome.org/GNOME/mutter/merge_requests/1042

 src/backends/meta-crtc.c                        |  24 +++++
 src/backends/meta-crtc.h                        |  20 +++-
 src/backends/meta-logical-monitor.c             |   2 +-
 src/backends/meta-monitor-config-manager.c      |  43 +++++---
 src/backends/meta-monitor-manager-dummy.c       |  37 ++-----
 src/backends/meta-monitor-manager-private.h     |   4 +-
 src/backends/meta-monitor-manager.c             |  48 ++++++---
 src/backends/meta-monitor.c                     |  50 ++++++---
 src/backends/native/meta-crtc-kms.c             |  59 +++++------
 src/backends/native/meta-crtc-kms.h             |   2 +
 src/backends/native/meta-monitor-manager-kms.c  |  37 ++-----
 src/backends/native/meta-output-kms.c           |   6 +-
 src/backends/native/meta-renderer-native.c      |  16 ++-
 src/backends/x11/meta-crtc-xrandr.c             |  86 +++++++++++++--
 src/backends/x11/meta-crtc-xrandr.h             |   5 +
 src/backends/x11/meta-monitor-manager-xrandr.c  |  95 +++++------------
 src/backends/x11/meta-output-xrandr.c           |   6 +-
 src/backends/x11/nested/meta-stage-x11-nested.c |  10 +-
 src/tests/meta-monitor-manager-test.c           |  37 ++-----
 src/tests/monitor-unit-tests.c                  | 133 +++++++++---------------
 20 files changed, 370 insertions(+), 350 deletions(-)
---
diff --git a/src/backends/meta-crtc.c b/src/backends/meta-crtc.c
index 85424c575..2212c6ca9 100644
--- a/src/backends/meta-crtc.c
+++ b/src/backends/meta-crtc.c
@@ -31,6 +31,30 @@ meta_crtc_get_gpu (MetaCrtc *crtc)
   return crtc->gpu;
 }
 
+void
+meta_crtc_set_config (MetaCrtc             *crtc,
+                      graphene_rect_t      *layout,
+                      MetaCrtcMode         *mode,
+                      MetaMonitorTransform  transform)
+{
+  MetaCrtcConfig *config;
+
+  meta_crtc_unset_config (crtc);
+
+  config = g_new0 (MetaCrtcConfig, 1);
+  config->layout = *layout;
+  config->mode = mode;
+  config->transform = transform;
+
+  crtc->config = config;
+}
+
+void
+meta_crtc_unset_config (MetaCrtc *crtc)
+{
+  g_clear_pointer (&crtc->config, g_free);
+}
+
 static void
 meta_crtc_finalize (GObject *object)
 {
diff --git a/src/backends/meta-crtc.h b/src/backends/meta-crtc.h
index ddacfea49..af75eb9b2 100644
--- a/src/backends/meta-crtc.h
+++ b/src/backends/meta-crtc.h
@@ -49,6 +49,13 @@ typedef enum _MetaCrtcModeFlag
   META_CRTC_MODE_FLAG_MASK = 0x3fff
 } MetaCrtcModeFlag;
 
+typedef struct _MetaCrtcConfig
+{
+  graphene_rect_t layout;
+  MetaMonitorTransform transform;
+  MetaCrtcMode *mode;
+} MetaCrtcConfig;
+
 struct _MetaCrtc
 {
   GObject parent;
@@ -56,12 +63,10 @@ struct _MetaCrtc
   MetaGpu *gpu;
 
   glong crtc_id;
-  MetaRectangle rect;
-  MetaCrtcMode *current_mode;
-  MetaMonitorTransform transform;
   unsigned int all_transforms;
 
   MetaLogicalMonitor *logical_monitor;
+  MetaCrtcConfig *config;
 
   /* Used when changing configuration */
   gboolean is_dirty;
@@ -98,4 +103,13 @@ META_EXPORT_TEST G_DECLARE_FINAL_TYPE (MetaCrtcMode, meta_crtc_mode, META, CRTC_
 
 MetaGpu * meta_crtc_get_gpu (MetaCrtc *crtc);
 
+META_EXPORT_TEST
+void meta_crtc_set_config (MetaCrtc             *crtc,
+                           graphene_rect_t      *layout,
+                           MetaCrtcMode         *mode,
+                           MetaMonitorTransform  transform);
+
+META_EXPORT_TEST
+void meta_crtc_unset_config (MetaCrtc *crtc);
+
 #endif /* META_CRTC_H */
diff --git a/src/backends/meta-logical-monitor.c b/src/backends/meta-logical-monitor.c
index 3f98de2cd..8e0f24827 100644
--- a/src/backends/meta-logical-monitor.c
+++ b/src/backends/meta-logical-monitor.c
@@ -122,7 +122,7 @@ derive_monitor_transform (MetaMonitor *monitor)
   MetaMonitorTransform transform;
 
   main_output = meta_monitor_get_main_output (monitor);
-  transform = meta_output_get_assigned_crtc (main_output)->transform;
+  transform = meta_output_get_assigned_crtc (main_output)->config->transform;
 
   return meta_monitor_crtc_to_logical_transform (monitor, transform);
 }
diff --git a/src/backends/meta-monitor-config-manager.c b/src/backends/meta-monitor-config-manager.c
index c99d31e54..2107b7463 100644
--- a/src/backends/meta-monitor-config-manager.c
+++ b/src/backends/meta-monitor-config-manager.c
@@ -172,6 +172,11 @@ assign_monitor_crtc (MetaMonitor         *monitor,
   MetaMonitorTransform transform;
   MetaMonitorTransform crtc_transform;
   int crtc_x, crtc_y;
+  float x_offset, y_offset;
+  float scale;
+  float width, height;
+  MetaCrtcMode *crtc_mode;
+  graphene_rect_t crtc_layout;
   MetaCrtcInfo *crtc_info;
   MetaOutputInfo *output_info;
   MetaMonitorConfig *first_monitor_config;
@@ -202,29 +207,37 @@ assign_monitor_crtc (MetaMonitor         *monitor,
   meta_monitor_calculate_crtc_pos (monitor, mode, output, crtc_transform,
                                    &crtc_x, &crtc_y);
 
+  x_offset = data->logical_monitor_config->layout.x;
+  y_offset = data->logical_monitor_config->layout.y;
+  scale = data->logical_monitor_config->scale;
+  crtc_mode = monitor_crtc_mode->crtc_mode;
+
+  if (meta_monitor_transform_is_rotated (crtc_transform))
+    {
+      width = crtc_mode->height / scale;
+      height = crtc_mode->width / scale;
+    }
+  else
+    {
+      width = crtc_mode->width / scale;
+      height = crtc_mode->height / scale;
+    }
+
+  crtc_layout = GRAPHENE_RECT_INIT (x_offset + (crtc_x / scale),
+                                    y_offset + (crtc_y / scale),
+                                    width,
+                                    height);
+
   crtc_info = g_slice_new0 (MetaCrtcInfo);
   *crtc_info = (MetaCrtcInfo) {
     .crtc = crtc,
-    .mode = monitor_crtc_mode->crtc_mode,
-    .x = crtc_x,
-    .y = crtc_y,
+    .mode = crtc_mode,
+    .layout = crtc_layout,
     .transform = crtc_transform,
     .outputs = g_ptr_array_new ()
   };
   g_ptr_array_add (crtc_info->outputs, output);
 
-  /*
-   * Currently, MetaCrtcInfo are deliberately offset incorrectly to carry over
-   * logical monitor location inside the MetaCrtc struct, when in fact this
-   * depends on the framebuffer configuration. This will eventually be negated
-   * when setting the actual KMS mode.
-   *
-   * TODO: Remove this hack when we don't need to rely on MetaCrtc to pass
-   * logical monitor state.
-   */
-  crtc_info->x += data->logical_monitor_config->layout.x;
-  crtc_info->y += data->logical_monitor_config->layout.y;
-
   /*
    * Only one output can be marked as primary (due to Xrandr limitation),
    * so only mark the main output of the first monitor in the logical monitor
diff --git a/src/backends/meta-monitor-manager-dummy.c b/src/backends/meta-monitor-manager-dummy.c
index 906773916..2d02327d7 100644
--- a/src/backends/meta-monitor-manager-dummy.c
+++ b/src/backends/meta-monitor-manager-dummy.c
@@ -512,38 +512,17 @@ apply_crtc_assignments (MetaMonitorManager *manager,
 
       if (crtc_info->mode == NULL)
         {
-          crtc->rect.x = 0;
-          crtc->rect.y = 0;
-          crtc->rect.width = 0;
-          crtc->rect.height = 0;
-          crtc->current_mode = NULL;
+          meta_crtc_unset_config (crtc);
         }
       else
         {
-          MetaCrtcMode *mode;
           MetaOutput *output;
           unsigned int j;
-          int width, height;
-
-          mode = crtc_info->mode;
-
-          if (meta_monitor_transform_is_rotated (crtc_info->transform))
-            {
-              width = mode->height;
-              height = mode->width;
-            }
-          else
-            {
-              width = mode->width;
-              height = mode->height;
-            }
 
-          crtc->rect.x = crtc_info->x;
-          crtc->rect.y = crtc_info->y;
-          crtc->rect.width = width;
-          crtc->rect.height = height;
-          crtc->current_mode = mode;
-          crtc->transform = crtc_info->transform;
+          meta_crtc_set_config (crtc,
+                                &crtc_info->layout,
+                                crtc_info->mode,
+                                crtc_info->transform);
 
           for (j = 0; j < crtc_info->outputs->len; j++)
             {
@@ -577,11 +556,7 @@ apply_crtc_assignments (MetaMonitorManager *manager,
           continue;
         }
 
-      crtc->rect.x = 0;
-      crtc->rect.y = 0;
-      crtc->rect.width = 0;
-      crtc->rect.height = 0;
-      crtc->current_mode = NULL;
+      meta_crtc_unset_config (crtc);
     }
 
   /* Disable outputs not mentioned in the list */
diff --git a/src/backends/meta-monitor-manager-private.h b/src/backends/meta-monitor-manager-private.h
index 20bb6b679..4dd0364a8 100644
--- a/src/backends/meta-monitor-manager-private.h
+++ b/src/backends/meta-monitor-manager-private.h
@@ -24,6 +24,7 @@
 #define META_MONITOR_MANAGER_PRIVATE_H
 
 #include <cogl/cogl.h>
+#include <graphene.h>
 #include <libgnome-desktop/gnome-pnp-ids.h>
 
 #include "backends/meta-backend-private.h"
@@ -72,8 +73,7 @@ struct _MetaCrtcInfo
 {
   MetaCrtc                 *crtc;
   MetaCrtcMode             *mode;
-  int                       x;
-  int                       y;
+  graphene_rect_t           layout;
   MetaMonitorTransform      transform;
   GPtrArray                *outputs;
 };
diff --git a/src/backends/meta-monitor-manager.c b/src/backends/meta-monitor-manager.c
index b773d436f..b94967d79 100644
--- a/src/backends/meta-monitor-manager.c
+++ b/src/backends/meta-monitor-manager.c
@@ -1014,28 +1014,46 @@ meta_monitor_manager_handle_get_resources (MetaDBusDisplayConfig *skeleton,
     {
       MetaCrtc *crtc = l->data;
       GVariantBuilder transforms;
-      int current_mode_index;
+      MetaCrtcConfig *crtc_config;
 
       g_variant_builder_init (&transforms, G_VARIANT_TYPE ("au"));
       for (j = 0; j <= META_MONITOR_TRANSFORM_FLIPPED_270; j++)
         if (crtc->all_transforms & (1 << j))
           g_variant_builder_add (&transforms, "u", j);
 
-      if (crtc->current_mode)
-        current_mode_index = g_list_index (combined_modes, crtc->current_mode);
+      crtc_config = crtc->config;
+
+      if (crtc_config)
+        {
+          int current_mode_index;
+
+          current_mode_index = g_list_index (combined_modes, crtc_config->mode);
+          g_variant_builder_add (&crtc_builder, "(uxiiiiiuaua{sv})",
+                                 i, /* ID */
+                                 (int64_t) crtc->crtc_id,
+                                 (int) roundf (crtc_config->layout.origin.x),
+                                 (int) roundf (crtc_config->layout.origin.y),
+                                 (int) roundf (crtc_config->layout.size.width),
+                                 (int) roundf (crtc_config->layout.size.height),
+                                 current_mode_index,
+                                 (uint32_t) crtc_config->transform,
+                                 &transforms,
+                                 NULL /* properties */);
+        }
       else
-        current_mode_index = -1;
-      g_variant_builder_add (&crtc_builder, "(uxiiiiiuaua{sv})",
-                             i, /* ID */
-                             (gint64)crtc->crtc_id,
-                             (int)crtc->rect.x,
-                             (int)crtc->rect.y,
-                             (int)crtc->rect.width,
-                             (int)crtc->rect.height,
-                             current_mode_index,
-                             (guint32)crtc->transform,
-                             &transforms,
-                             NULL /* properties */);
+        {
+          g_variant_builder_add (&crtc_builder, "(uxiiiiiuaua{sv})",
+                                 i, /* ID */
+                                 (int64_t) crtc->crtc_id,
+                                 0,
+                                 0,
+                                 0,
+                                 0,
+                                 -1,
+                                 (uint32_t) META_MONITOR_TRANSFORM_NORMAL,
+                                 &transforms,
+                                 NULL /* properties */);
+        }
     }
 
   for (l = combined_outputs, i = 0; l; l = l->next, i++)
diff --git a/src/backends/meta-monitor.c b/src/backends/meta-monitor.c
index 578fec941..9b60441eb 100644
--- a/src/backends/meta-monitor.c
+++ b/src/backends/meta-monitor.c
@@ -29,6 +29,7 @@
 #include "backends/meta-monitor-manager-private.h"
 #include "backends/meta-settings-private.h"
 #include "backends/meta-output.h"
+#include "core/boxes-private.h"
 
 #define SCALE_FACTORS_PER_INTEGER 4
 #define SCALE_FACTORS_STEPS (1.0 / (float) SCALE_FACTORS_PER_INTEGER)
@@ -636,7 +637,7 @@ meta_monitor_normal_generate_modes (MetaMonitorNormal *monitor_normal)
         monitor_priv->preferred_mode = mode;
 
       crtc = meta_output_get_assigned_crtc (output);
-      if (crtc && crtc_mode == crtc->current_mode)
+      if (crtc && crtc->config && crtc_mode == crtc->config->mode)
         monitor_priv->current_mode = mode;
     }
 }
@@ -683,10 +684,17 @@ meta_monitor_normal_derive_layout (MetaMonitor   *monitor,
 {
   MetaOutput *output;
   MetaCrtc *crtc;
+  MetaCrtcConfig *crtc_config;
 
   output = meta_monitor_get_main_output (monitor);
   crtc = meta_output_get_assigned_crtc (output);
-  *layout = crtc->rect;
+  crtc_config = crtc->config;
+
+  g_return_if_fail (crtc_config);
+
+  meta_rectangle_from_graphene_rect (&crtc_config->layout,
+                                     META_ROUNDING_STRATEGY_ROUND,
+                                     layout);
 }
 
 static gboolean
@@ -880,7 +888,8 @@ is_monitor_mode_assigned (MetaMonitor     *monitor,
 
       crtc = meta_output_get_assigned_crtc (output);
       if (monitor_crtc_mode->crtc_mode &&
-          (!crtc || crtc->current_mode != monitor_crtc_mode->crtc_mode))
+          (!crtc || !crtc->config ||
+           crtc->config->mode != monitor_crtc_mode->crtc_mode))
         return FALSE;
       else if (!monitor_crtc_mode->crtc_mode && crtc)
         return FALSE;
@@ -1324,32 +1333,39 @@ meta_monitor_tiled_derive_layout (MetaMonitor   *monitor,
   MetaMonitorPrivate *monitor_priv =
     meta_monitor_get_instance_private (monitor);
   GList *l;
-  int min_x, min_y, max_x, max_y;
+  float min_x, min_y, max_x, max_y;
 
-  min_x = INT_MAX;
-  min_y = INT_MAX;
-  max_x = 0;
-  max_y = 0;
+  min_x = FLT_MAX;
+  min_y = FLT_MAX;
+  max_x = 0.0;
+  max_y = 0.0;
   for (l = monitor_priv->outputs; l; l = l->next)
     {
       MetaOutput *output = l->data;
       MetaCrtc *crtc;
+      MetaCrtcConfig *crtc_config;
+      graphene_rect_t *crtc_layout;
 
       crtc = meta_output_get_assigned_crtc (output);
       if (!crtc)
         continue;
 
-      min_x = MIN (crtc->rect.x, min_x);
-      min_y = MIN (crtc->rect.y, min_y);
-      max_x = MAX (crtc->rect.x + crtc->rect.width, max_x);
-      max_y = MAX (crtc->rect.y + crtc->rect.height, max_y);
+      crtc_config = crtc->config;
+      g_return_if_fail (crtc_config);
+
+      crtc_layout = &crtc_config->layout;
+
+      min_x = MIN (crtc_layout->origin.x, min_x);
+      min_y = MIN (crtc_layout->origin.y, min_y);
+      max_x = MAX (crtc_layout->origin.x + crtc_layout->size.width, max_x);
+      max_y = MAX (crtc_layout->origin.y + crtc_layout->size.height, max_y);
     }
 
   *layout = (MetaRectangle) {
-    .x = min_x,
-    .y = min_y,
-    .width = max_x - min_x,
-    .height = max_y - min_y
+    .x = roundf (min_x),
+    .y = roundf (min_y),
+    .width = roundf (max_x - min_x),
+    .height = roundf (max_y - min_y)
   };
 }
 
@@ -1508,7 +1524,7 @@ is_current_mode_known (MetaMonitor *monitor)
   output = meta_monitor_get_main_output (monitor);
   crtc = meta_output_get_assigned_crtc (output);
 
-  return meta_monitor_is_active (monitor) == (crtc && crtc->current_mode);
+  return meta_monitor_is_active (monitor) == (crtc && crtc->config);
 }
 
 void
diff --git a/src/backends/native/meta-crtc-kms.c b/src/backends/native/meta-crtc-kms.c
index 2bd6ccdf8..1ec6654f8 100644
--- a/src/backends/native/meta-crtc-kms.c
+++ b/src/backends/native/meta-crtc-kms.c
@@ -63,7 +63,7 @@ meta_crtc_kms_apply_transform (MetaCrtc               *crtc,
   MetaCrtcKms *crtc_kms = crtc->driver_private;
   MetaMonitorTransform hw_transform;
 
-  hw_transform = crtc->transform;
+  hw_transform = crtc->config->transform;
   if (!meta_crtc_kms_is_transform_handled (crtc, hw_transform))
     hw_transform = META_MONITOR_TRANSFORM_NORMAL;
   if (!meta_crtc_kms_is_transform_handled (crtc, hw_transform))
@@ -76,11 +76,14 @@ 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)
 {
-  MetaRectangle logical_monitor_rect;
-  int x, y;
+  MetaMonitorMode *monitor_mode;
+  MetaCrtcConfig *crtc_config;
+  int crtc_x, crtc_y;
   MetaFixed16Rectangle src_rect;
   MetaFixed16Rectangle dst_rect;
   MetaKmsAssignPlaneFlag flags;
@@ -89,21 +92,27 @@ meta_crtc_kms_assign_primary_plane (MetaCrtc      *crtc,
   MetaKmsPlane *primary_kms_plane;
   MetaKmsPlaneAssignment *plane_assignment;
 
-  logical_monitor_rect =
-    meta_logical_monitor_get_layout (crtc->logical_monitor);
-  x = crtc->rect.x - logical_monitor_rect.x;
-  y = crtc->rect.y - logical_monitor_rect.y;
+  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 (x),
-    .y = meta_fixed_16_from_int (y),
-    .width = meta_fixed_16_from_int (crtc->rect.width),
-    .height = meta_fixed_16_from_int (crtc->rect.height),
+    .x = meta_fixed_16_from_int (crtc_x),
+    .y = meta_fixed_16_from_int (crtc_y),
+    .width = meta_fixed_16_from_int (crtc_config->mode->width),
+    .height = meta_fixed_16_from_int (crtc_config->mode->height),
   };
   dst_rect = (MetaFixed16Rectangle) {
     .x = meta_fixed_16_from_int (0),
     .y = meta_fixed_16_from_int (0),
-    .width = meta_fixed_16_from_int (crtc->rect.width),
-    .height = meta_fixed_16_from_int (crtc->rect.height),
+    .width = meta_fixed_16_from_int (crtc_config->mode->width),
+    .height = meta_fixed_16_from_int (crtc_config->mode->height),
   };
 
   flags = META_KMS_ASSIGN_PLANE_FLAG_NONE;
@@ -151,6 +160,7 @@ void
 meta_crtc_kms_set_mode (MetaCrtc      *crtc,
                         MetaKmsUpdate *kms_update)
 {
+  MetaCrtcConfig *crtc_config = crtc->config;
   MetaGpu *gpu = meta_crtc_get_gpu (crtc);
   GList *connectors;
   drmModeModeInfo *mode;
@@ -159,7 +169,7 @@ meta_crtc_kms_set_mode (MetaCrtc      *crtc,
 
   if (connectors)
     {
-      mode = crtc->current_mode->driver_private;
+      mode = crtc_config->mode->driver_private;
 
       g_debug ("Setting CRTC (%ld) mode to %s", crtc->crtc_id, mode->name);
     }
@@ -274,37 +284,16 @@ meta_create_kms_crtc (MetaGpuKms  *gpu_kms,
   MetaCrtc *crtc;
   MetaCrtcKms *crtc_kms;
   MetaKmsPlane *primary_plane;
-  const MetaKmsCrtcState *crtc_state;
 
   kms_device = meta_gpu_kms_get_kms_device (gpu_kms);
   primary_plane = meta_kms_device_get_primary_plane_for (kms_device,
                                                          kms_crtc);
-  crtc_state = meta_kms_crtc_get_current_state (kms_crtc);
-
   crtc = g_object_new (META_TYPE_CRTC, NULL);
   crtc->gpu = gpu;
   crtc->crtc_id = meta_kms_crtc_get_id (kms_crtc);
-  crtc->rect = crtc_state->rect;
   crtc->is_dirty = FALSE;
-  crtc->transform = META_MONITOR_TRANSFORM_NORMAL;
   crtc->all_transforms = ALL_TRANSFORMS_MASK;
 
-  if (crtc_state->is_drm_mode_valid)
-    {
-      GList *l;
-
-      for (l = meta_gpu_get_modes (gpu); l; l = l->next)
-        {
-          MetaCrtcMode *mode = l->data;
-
-          if (meta_drm_mode_equal (&crtc_state->drm_mode, mode->driver_private))
-            {
-              crtc->current_mode = mode;
-              break;
-            }
-        }
-    }
-
   crtc_kms = g_new0 (MetaCrtcKms, 1);
   crtc_kms->kms_crtc = kms_crtc;
   crtc_kms->primary_plane = primary_plane;
diff --git a/src/backends/native/meta-crtc-kms.h b/src/backends/native/meta-crtc-kms.h
index 898622478..4b2df3cfa 100644
--- a/src/backends/native/meta-crtc-kms.h
+++ b/src/backends/native/meta-crtc-kms.h
@@ -38,6 +38,8 @@ 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-monitor-manager-kms.c b/src/backends/native/meta-monitor-manager-kms.c
index 8e7030d91..d381a75f4 100644
--- a/src/backends/native/meta-monitor-manager-kms.c
+++ b/src/backends/native/meta-monitor-manager-kms.c
@@ -189,37 +189,16 @@ apply_crtc_assignments (MetaMonitorManager *manager,
 
       if (crtc_info->mode == NULL)
         {
-          crtc->rect.x = 0;
-          crtc->rect.y = 0;
-          crtc->rect.width = 0;
-          crtc->rect.height = 0;
-          crtc->current_mode = NULL;
+          meta_crtc_unset_config (crtc);
         }
       else
         {
-          MetaCrtcMode *mode;
           unsigned int j;
-          int width, height;
 
-          mode = crtc_info->mode;
-
-          if (meta_monitor_transform_is_rotated (crtc_info->transform))
-            {
-              width = mode->height;
-              height = mode->width;
-            }
-          else
-            {
-              width = mode->width;
-              height = mode->height;
-            }
-
-          crtc->rect.x = crtc_info->x;
-          crtc->rect.y = crtc_info->y;
-          crtc->rect.width = width;
-          crtc->rect.height = height;
-          crtc->current_mode = mode;
-          crtc->transform = crtc_info->transform;
+          meta_crtc_set_config (crtc,
+                                &crtc_info->layout,
+                                crtc_info->mode,
+                                crtc_info->transform);
 
           for (j = 0; j < crtc_info->outputs->len; j++)
             {
@@ -250,11 +229,7 @@ apply_crtc_assignments (MetaMonitorManager *manager,
               continue;
             }
 
-          crtc->rect.x = 0;
-          crtc->rect.y = 0;
-          crtc->rect.width = 0;
-          crtc->rect.height = 0;
-          crtc->current_mode = NULL;
+          meta_crtc_unset_config (crtc);
         }
     }
 
diff --git a/src/backends/native/meta-output-kms.c b/src/backends/native/meta-output-kms.c
index 84c7d4d7b..e552113c0 100644
--- a/src/backends/native/meta-output-kms.c
+++ b/src/backends/native/meta-output-kms.c
@@ -64,11 +64,13 @@ meta_output_kms_set_underscan (MetaOutput    *output,
   if (output->is_underscanning)
     {
       MetaCrtc *crtc;
+      MetaCrtcConfig *crtc_config;
       uint64_t hborder, vborder;
 
       crtc = meta_output_get_assigned_crtc (output);
-      hborder = MIN (128, (uint64_t) round (crtc->current_mode->width * 0.05));
-      vborder = MIN (128, (uint64_t) round (crtc->current_mode->height * 0.05));
+      crtc_config = crtc->config;
+      hborder = MIN (128, (uint64_t) round (crtc_config->mode->width * 0.05));
+      vborder = MIN (128, (uint64_t) round (crtc_config->mode->height * 0.05));
 
       g_debug ("Setting underscan of connector %s to %" G_GUINT64_FORMAT " x %" G_GUINT64_FORMAT,
                meta_kms_connector_get_name (output_kms->kms_connector),
diff --git a/src/backends/native/meta-renderer-native.c b/src/backends/native/meta-renderer-native.c
index 68dabe91d..b99b2f195 100644
--- a/src/backends/native/meta-renderer-native.c
+++ b/src/backends/native/meta-renderer-native.c
@@ -1342,8 +1342,8 @@ notify_view_crtc_presented (MetaRendererView *view,
   frame_info = g_queue_peek_tail (&onscreen->pending_frame_infos);
 
   crtc = meta_crtc_kms_from_kms_crtc (kms_crtc);
-  refresh_rate = crtc && crtc->current_mode ?
-                 crtc->current_mode->refresh_rate :
+  refresh_rate = crtc && crtc->config ?
+                 crtc->config->mode->refresh_rate :
                  0.0f;
   if (refresh_rate >= frame_info->refresh_rate)
     {
@@ -1555,6 +1555,8 @@ 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)
 {
@@ -1586,7 +1588,8 @@ meta_onscreen_native_flip_crtc (CoglOnscreen     *onscreen,
           fb_id = meta_drm_buffer_get_fb_id (secondary_gpu_state->gbm.next_fb);
         }
 
-      meta_crtc_kms_assign_primary_plane (crtc, fb_id, kms_update);
+      meta_crtc_kms_assign_primary_plane (crtc, monitor, output,
+                                          fb_id, kms_update);
       meta_crtc_kms_page_flip (crtc,
                                &page_flip_feedback,
                                g_object_ref (view),
@@ -1637,7 +1640,8 @@ 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, fb_id, data->kms_update);
+        meta_crtc_kms_assign_primary_plane (crtc, monitor, output,
+                                            fb_id, data->kms_update);
         break;
       }
 #endif
@@ -1688,6 +1692,8 @@ flip_crtc (MetaLogicalMonitor *logical_monitor,
 
   meta_onscreen_native_flip_crtc (data->onscreen,
                                   data->view,
+                                  monitor,
+                                  output,
                                   crtc,
                                   data->kms_update);
 }
@@ -3437,7 +3443,7 @@ meta_renderer_native_finish_frame (MetaRendererNative *renderer_native)
             {
               MetaCrtc *crtc = k->data;
 
-              if (crtc->current_mode)
+              if (crtc->config)
                 continue;
 
               kms_update = meta_kms_ensure_pending_update (kms);
diff --git a/src/backends/x11/meta-crtc-xrandr.c b/src/backends/x11/meta-crtc-xrandr.c
index e917f9c7d..3b9d90aa7 100644
--- a/src/backends/x11/meta-crtc-xrandr.c
+++ b/src/backends/x11/meta-crtc-xrandr.c
@@ -41,12 +41,20 @@
 
 #include "backends/meta-backend-private.h"
 #include "backends/meta-crtc.h"
+#include "backends/meta-output.h"
 #include "backends/x11/meta-crtc-xrandr.h"
 #include "backends/x11/meta-gpu-xrandr.h"
 #include "backends/x11/meta-monitor-manager-xrandr.h"
 
 #define ALL_TRANSFORMS ((1 << (META_MONITOR_TRANSFORM_FLIPPED_270 + 1)) - 1)
 
+typedef struct _MetaCrtcXrandr
+{
+  MetaRectangle rect;
+  MetaMonitorTransform transform;
+  MetaCrtcMode *current_mode;
+} MetaCrtcXrandr;
+
 gboolean
 meta_crtc_xrandr_set_config (MetaCrtc            *crtc,
                              xcb_randr_crtc_t     xrandr_crtc,
@@ -174,6 +182,52 @@ meta_monitor_transform_from_xrandr_all (Rotation rotation)
   return ret;
 }
 
+gboolean
+meta_crtc_xrandr_is_assignment_changed (MetaCrtc     *crtc,
+                                        MetaCrtcInfo *crtc_info)
+{
+  MetaCrtcXrandr *crtc_xrandr = crtc->driver_private;
+  unsigned int i;
+
+  if (crtc_xrandr->current_mode != crtc_info->mode)
+    return TRUE;
+
+  if (crtc_xrandr->rect.x != (int) roundf (crtc_info->layout.origin.x))
+    return TRUE;
+
+  if (crtc_xrandr->rect.y != (int) roundf (crtc_info->layout.origin.x))
+    return TRUE;
+
+  if (crtc_xrandr->transform != crtc_info->transform)
+    return TRUE;
+
+  for (i = 0; i < crtc_info->outputs->len; i++)
+    {
+      MetaOutput *output = ((MetaOutput**) crtc_info->outputs->pdata)[i];
+      MetaCrtc *assigned_crtc;
+
+      assigned_crtc = meta_output_get_assigned_crtc (output);
+      if (assigned_crtc != crtc)
+        return TRUE;
+    }
+
+  return FALSE;
+}
+
+MetaCrtcMode *
+meta_crtc_xrandr_get_current_mode (MetaCrtc *crtc)
+{
+  MetaCrtcXrandr *crtc_xrandr = crtc->driver_private;
+
+  return crtc_xrandr->current_mode;
+}
+
+static void
+meta_crtc_destroy_notify (MetaCrtc *crtc)
+{
+  g_free (crtc->driver_private);
+}
+
 MetaCrtc *
 meta_create_xrandr_crtc (MetaGpuXrandr      *gpu_xrandr,
                          XRRCrtcInfo        *xrandr_crtc,
@@ -181,20 +235,27 @@ meta_create_xrandr_crtc (MetaGpuXrandr      *gpu_xrandr,
                          XRRScreenResources *resources)
 {
   MetaCrtc *crtc;
+  MetaCrtcXrandr *crtc_xrandr;
   unsigned int i;
   GList *modes;
 
   crtc = g_object_new (META_TYPE_CRTC, NULL);
 
+  crtc_xrandr = g_new0 (MetaCrtcXrandr, 1);
+  crtc_xrandr->rect = (MetaRectangle) {
+    .x = xrandr_crtc->x,
+    .y = xrandr_crtc->y,
+    .width = xrandr_crtc->width,
+    .height = xrandr_crtc->height,
+  };
+  crtc_xrandr->transform =
+    meta_monitor_transform_from_xrandr (xrandr_crtc->rotation);
+
+  crtc->driver_private = crtc_xrandr;
+  crtc->driver_notify = (GDestroyNotify) meta_crtc_destroy_notify;
   crtc->gpu = META_GPU (gpu_xrandr);
   crtc->crtc_id = crtc_id;
-  crtc->rect.x = xrandr_crtc->x;
-  crtc->rect.y = xrandr_crtc->y;
-  crtc->rect.width = xrandr_crtc->width;
-  crtc->rect.height = xrandr_crtc->height;
   crtc->is_dirty = FALSE;
-  crtc->transform =
-    meta_monitor_transform_from_xrandr (xrandr_crtc->rotation);
   crtc->all_transforms =
     meta_monitor_transform_from_xrandr_all (xrandr_crtc->rotations);
 
@@ -203,10 +264,21 @@ meta_create_xrandr_crtc (MetaGpuXrandr      *gpu_xrandr,
     {
       if (resources->modes[i].id == xrandr_crtc->mode)
         {
-          crtc->current_mode = g_list_nth_data (modes, i);
+          crtc_xrandr->current_mode = g_list_nth_data (modes, i);
           break;
         }
     }
 
+  if (crtc_xrandr->current_mode)
+    {
+      meta_crtc_set_config (crtc,
+                            &GRAPHENE_RECT_INIT (crtc_xrandr->rect.x,
+                                                 crtc_xrandr->rect.y,
+                                                 crtc_xrandr->rect.width,
+                                                 crtc_xrandr->rect.height),
+                            crtc_xrandr->current_mode,
+                            crtc_xrandr->transform);
+    }
+
   return crtc;
 }
diff --git a/src/backends/x11/meta-crtc-xrandr.h b/src/backends/x11/meta-crtc-xrandr.h
index d38a09a55..3226378b5 100644
--- a/src/backends/x11/meta-crtc-xrandr.h
+++ b/src/backends/x11/meta-crtc-xrandr.h
@@ -39,6 +39,11 @@ gboolean meta_crtc_xrandr_set_config (MetaCrtc            *crtc,
                                       int                  n_outputs,
                                       xcb_timestamp_t     *out_timestamp);
 
+gboolean meta_crtc_xrandr_is_assignment_changed (MetaCrtc     *crtc,
+                                                 MetaCrtcInfo *crtc_info);
+
+MetaCrtcMode * meta_crtc_xrandr_get_current_mode (MetaCrtc *crtc);
+
 MetaCrtc * meta_create_xrandr_crtc (MetaGpuXrandr      *gpu_xrandr,
                                     XRRCrtcInfo        *xrandr_crtc,
                                     RRCrtc              crtc_id,
diff --git a/src/backends/x11/meta-monitor-manager-xrandr.c b/src/backends/x11/meta-monitor-manager-xrandr.c
index 8fae335f0..9531bb276 100644
--- a/src/backends/x11/meta-monitor-manager-xrandr.c
+++ b/src/backends/x11/meta-monitor-manager-xrandr.c
@@ -250,37 +250,14 @@ is_crtc_assignment_changed (MetaCrtc      *crtc,
   for (i = 0; i < n_crtc_infos; i++)
     {
       MetaCrtcInfo *crtc_info = crtc_infos[i];
-      unsigned int j;
 
       if (crtc_info->crtc != crtc)
         continue;
 
-      if (crtc->current_mode != crtc_info->mode)
-        return TRUE;
-
-      if (crtc->rect.x != crtc_info->x)
-        return TRUE;
-
-      if (crtc->rect.y != crtc_info->y)
-        return TRUE;
-
-      if (crtc->transform != crtc_info->transform)
-        return TRUE;
-
-      for (j = 0; j < crtc_info->outputs->len; j++)
-        {
-          MetaOutput *output = ((MetaOutput**) crtc_info->outputs->pdata)[j];
-          MetaCrtc *assigned_crtc;
-
-          assigned_crtc = meta_output_get_assigned_crtc (output);
-          if (assigned_crtc != crtc)
-            return TRUE;
-        }
-
-      return FALSE;
+      return meta_crtc_xrandr_is_assignment_changed (crtc, crtc_info);
     }
 
-  return crtc->current_mode != NULL;
+  return !!meta_crtc_xrandr_get_current_mode (crtc);
 }
 
 static gboolean
@@ -408,16 +385,10 @@ apply_crtc_assignments (MetaMonitorManager *manager,
       if (crtc_info->mode == NULL)
         continue;
 
-      if (meta_monitor_transform_is_rotated (crtc_info->transform))
-        {
-          width = MAX (width, crtc_info->x + crtc_info->mode->height);
-          height = MAX (height, crtc_info->y + crtc_info->mode->width);
-        }
-      else
-        {
-          width = MAX (width, crtc_info->x + crtc_info->mode->width);
-          height = MAX (height, crtc_info->y + crtc_info->mode->height);
-        }
+      width = MAX (width, (int) roundf (crtc_info->layout.origin.x +
+                                        crtc_info->layout.size.width));
+      height = MAX (height, (int) roundf (crtc_info->layout.origin.y +
+                                          crtc_info->layout.size.height));
     }
 
   /* Second disable all newly disabled CRTCs, or CRTCs that in the previous
@@ -429,10 +400,15 @@ apply_crtc_assignments (MetaMonitorManager *manager,
     {
       MetaCrtcInfo *crtc_info = crtcs[i];
       MetaCrtc *crtc = crtc_info->crtc;
+      MetaCrtcConfig *crtc_config = crtc->config;
+      int x2, y2;
+
+      x2 = (int) roundf (crtc_config->layout.origin.x +
+                         crtc_config->layout.size.width);
+      y2 = (int) roundf (crtc_config->layout.origin.y +
+                         crtc_config->layout.size.height);
 
-      if (crtc_info->mode == NULL ||
-          crtc->rect.x + crtc->rect.width > width ||
-          crtc->rect.y + crtc->rect.height > height)
+      if (!crtc_info->mode || x2 > width || y2 > height)
         {
           xrandr_set_crtc_config (manager_xrandr,
                                   crtc,
@@ -443,11 +419,7 @@ apply_crtc_assignments (MetaMonitorManager *manager,
                                   XCB_RANDR_ROTATION_ROTATE_0,
                                   NULL, 0);
 
-          crtc->rect.x = 0;
-          crtc->rect.y = 0;
-          crtc->rect.width = 0;
-          crtc->rect.height = 0;
-          crtc->current_mode = NULL;
+          meta_crtc_unset_config (crtc);
         }
     }
 
@@ -461,7 +433,8 @@ apply_crtc_assignments (MetaMonitorManager *manager,
           crtc->is_dirty = FALSE;
           continue;
         }
-      if (crtc->current_mode == NULL)
+
+      if (!crtc->config)
         continue;
 
       xrandr_set_crtc_config (manager_xrandr,
@@ -473,11 +446,7 @@ apply_crtc_assignments (MetaMonitorManager *manager,
                               XCB_RANDR_ROTATION_ROTATE_0,
                               NULL, 0);
 
-      crtc->rect.x = 0;
-      crtc->rect.y = 0;
-      crtc->rect.width = 0;
-      crtc->rect.height = 0;
-      crtc->current_mode = NULL;
+      meta_crtc_unset_config (crtc);
     }
 
   g_assert (width > 0 && height > 0);
@@ -527,7 +496,8 @@ apply_crtc_assignments (MetaMonitorManager *manager,
                                        save_timestamp,
                                        (xcb_randr_crtc_t) crtc->crtc_id,
                                        XCB_CURRENT_TIME,
-                                       crtc_info->x, crtc_info->y,
+                                       (int) roundf (crtc_info->layout.origin.x),
+                                       (int) roundf (crtc_info->layout.origin.y),
                                        (xcb_randr_mode_t) mode->mode_id,
                                        rotation,
                                        output_ids, n_output_ids))
@@ -535,27 +505,16 @@ apply_crtc_assignments (MetaMonitorManager *manager,
               meta_warning ("Configuring CRTC %d with mode %d (%d x %d @ %f) at position %d, %d and 
transform %u failed\n",
                             (unsigned)(crtc->crtc_id), (unsigned)(mode->mode_id),
                             mode->width, mode->height, (float)mode->refresh_rate,
-                            crtc_info->x, crtc_info->y, crtc_info->transform);
+                            (int) roundf (crtc_info->layout.origin.x),
+                            (int) roundf (crtc_info->layout.origin.y),
+                            crtc_info->transform);
               continue;
             }
 
-          if (meta_monitor_transform_is_rotated (crtc_info->transform))
-            {
-              width = mode->height;
-              height = mode->width;
-            }
-          else
-            {
-              width = mode->width;
-              height = mode->height;
-            }
-
-          crtc->rect.x = crtc_info->x;
-          crtc->rect.y = crtc_info->y;
-          crtc->rect.width = width;
-          crtc->rect.height = height;
-          crtc->current_mode = mode;
-          crtc->transform = crtc_info->transform;
+          meta_crtc_set_config (crtc,
+                                &crtc_info->layout,
+                                mode,
+                                crtc_info->transform);
         }
     }
 
diff --git a/src/backends/x11/meta-output-xrandr.c b/src/backends/x11/meta-output-xrandr.c
index 42f22d1ae..869a39eef 100644
--- a/src/backends/x11/meta-output-xrandr.c
+++ b/src/backends/x11/meta-output-xrandr.c
@@ -101,12 +101,14 @@ output_set_underscanning_xrandr (MetaOutput *output,
   if (underscanning)
     {
       MetaCrtc *crtc;
+      MetaCrtcConfig *crtc_config;
       uint32_t border_value;
 
       crtc = meta_output_get_assigned_crtc (output);
+      crtc_config = crtc->config;
 
       prop = XInternAtom (xdisplay, "underscan hborder", False);
-      border_value = crtc->current_mode->width * 0.05;
+      border_value = crtc_config->mode->width * 0.05;
 
       xcb_randr_change_output_property (XGetXCBConnection (xdisplay),
                                         (XID) output->winsys_id,
@@ -115,7 +117,7 @@ output_set_underscanning_xrandr (MetaOutput *output,
                                         1, &border_value);
 
       prop = XInternAtom (xdisplay, "underscan vborder", False);
-      border_value = crtc->current_mode->height * 0.05;
+      border_value = crtc_config->mode->height * 0.05;
 
       xcb_randr_change_output_property (XGetXCBConnection (xdisplay),
                                         (XID) output->winsys_id,
diff --git a/src/backends/x11/nested/meta-stage-x11-nested.c b/src/backends/x11/nested/meta-stage-x11-nested.c
index decb4dd1d..a9704e1f5 100644
--- a/src/backends/x11/nested/meta-stage-x11-nested.c
+++ b/src/backends/x11/nested/meta-stage-x11-nested.c
@@ -114,6 +114,7 @@ draw_crtc (MetaMonitor         *monitor,
   MetaLogicalMonitor *logical_monitor = data->logical_monitor;
   MetaOutput *output = monitor_crtc_mode->output;
   MetaCrtc *crtc;
+  MetaCrtcConfig *crtc_config;
   MetaRendererView *renderer_view = META_RENDERER_VIEW (data->view);
   MetaMonitorTransform view_transform;
   MetaMonitorTransform layout_transform = META_MONITOR_TRANSFORM_NORMAL;
@@ -131,12 +132,13 @@ draw_crtc (MetaMonitor         *monitor,
   texture_height = cogl_texture_get_height (texture);
 
   crtc = meta_output_get_assigned_crtc (output);
+  crtc_config = crtc->config;
 
   clutter_stage_view_get_layout (data->view, &view_layout);
-  sample_x = crtc->rect.x - view_layout.x;
-  sample_y = crtc->rect.y - view_layout.y;
-  sample_width = crtc->rect.width;
-  sample_height = crtc->rect.height;
+  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);
 
   clutter_stage_view_get_offscreen_transformation_matrix (data->view,
                                                           &transform);
diff --git a/src/tests/meta-monitor-manager-test.c b/src/tests/meta-monitor-manager-test.c
index 8232aaa2a..89c373c93 100644
--- a/src/tests/meta-monitor-manager-test.c
+++ b/src/tests/meta-monitor-manager-test.c
@@ -140,38 +140,17 @@ apply_crtc_assignments (MetaMonitorManager *manager,
 
       if (crtc_info->mode == NULL)
         {
-          crtc->rect.x = 0;
-          crtc->rect.y = 0;
-          crtc->rect.width = 0;
-          crtc->rect.height = 0;
-          crtc->current_mode = NULL;
+          meta_crtc_unset_config (crtc);
         }
       else
         {
-          MetaCrtcMode *mode;
           MetaOutput *output;
           unsigned int j;
-          int width, height;
 
-          mode = crtc_info->mode;
-
-          if (meta_monitor_transform_is_rotated (crtc_info->transform))
-            {
-              width = mode->height;
-              height = mode->width;
-            }
-          else
-            {
-              width = mode->width;
-              height = mode->height;
-            }
-
-          crtc->rect.x = crtc_info->x;
-          crtc->rect.y = crtc_info->y;
-          crtc->rect.width = width;
-          crtc->rect.height = height;
-          crtc->current_mode = mode;
-          crtc->transform = crtc_info->transform;
+          meta_crtc_set_config (crtc,
+                                &crtc_info->layout,
+                                crtc_info->mode,
+                                crtc_info->transform);
 
           for (j = 0; j < crtc_info->outputs->len; j++)
             {
@@ -206,11 +185,7 @@ apply_crtc_assignments (MetaMonitorManager *manager,
           continue;
         }
 
-      crtc->rect.x = 0;
-      crtc->rect.y = 0;
-      crtc->rect.width = 0;
-      crtc->rect.height = 0;
-      crtc->current_mode = NULL;
+      meta_crtc_unset_config (crtc);
     }
 
   /* Disable outputs not mentioned in the list */
diff --git a/src/tests/monitor-unit-tests.c b/src/tests/monitor-unit-tests.c
index b498d899f..5540f4b5f 100644
--- a/src/tests/monitor-unit-tests.c
+++ b/src/tests/monitor-unit-tests.c
@@ -175,8 +175,8 @@ typedef struct _MonitorTestCaseCrtcExpect
 {
   MetaMonitorTransform transform;
   int current_mode;
-  int x;
-  int y;
+  float x;
+  float y;
 } MonitorTestCaseCrtcExpect;
 
 typedef struct _MonitorTestCaseExpect
@@ -313,6 +313,7 @@ static MonitorTestCase initial_test_case = {
       },
       {
         .current_mode = 0,
+        .x = 1024,
       }
     },
     .n_crtcs = 2,
@@ -509,10 +510,15 @@ check_current_monitor_mode (MetaMonitor         *monitor,
     }
   else
     {
+      MetaCrtcConfig *crtc_config;
       MetaLogicalMonitor *logical_monitor;
 
       g_assert_nonnull (crtc);
-      g_assert (monitor_crtc_mode->crtc_mode == crtc->current_mode);
+
+      crtc_config  = crtc->config;
+      g_assert_nonnull (crtc_config);
+
+      g_assert (monitor_crtc_mode->crtc_mode == crtc_config->mode);
 
       logical_monitor = crtc->logical_monitor;
       g_assert_nonnull (logical_monitor);
@@ -623,42 +629,6 @@ check_logical_monitor (MonitorTestCase               *test_case,
     g_assert_nonnull (primary_output);
 }
 
-static void
-get_compensated_crtc_position (MetaCrtc *crtc,
-                               int      *x,
-                               int      *y)
-{
-  MetaLogicalMonitor *logical_monitor;
-  MetaBackend *backend = meta_get_backend ();
-  MetaRenderer *renderer = meta_backend_get_renderer (backend);
-  GList *views;
-  GList *l;
-
-  logical_monitor = crtc->logical_monitor;
-  g_assert_nonnull (logical_monitor);
-
-  views = meta_renderer_get_views (renderer);
-  for (l = views; 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_equal (&view_layout,
-                                &logical_monitor->rect))
-        {
-          *x = crtc->rect.x - view_layout.x;
-          *y = crtc->rect.y - view_layout.y;
-          return;
-        }
-    }
-
-  *x = crtc->rect.x;
-  *y = crtc->rect.y;
-}
-
 static void
 check_monitor_configuration (MonitorTestCase *test_case)
 {
@@ -853,50 +823,37 @@ check_monitor_configuration (MonitorTestCase *test_case)
   for (l = crtcs, i = 0; l; l = l->next, i++)
     {
       MetaCrtc *crtc = l->data;
+      MetaCrtcConfig *crtc_config = crtc->config;
 
       if (test_case->expect.crtcs[i].current_mode == -1)
         {
-          g_assert_null (crtc->current_mode);
+          g_assert_null (crtc_config);
         }
       else
         {
           MetaLogicalMonitor *logical_monitor = crtc->logical_monitor;
           MetaCrtcMode *expected_current_mode;
-          int crtc_x, crtc_y;
+
+          g_assert_nonnull (crtc_config);
 
           expected_current_mode =
             g_list_nth_data (meta_gpu_get_modes (gpu),
                              test_case->expect.crtcs[i].current_mode);
-          g_assert (crtc->current_mode == expected_current_mode);
+          g_assert (crtc_config->mode == expected_current_mode);
 
-          g_assert_cmpuint (crtc->transform,
+          g_assert_cmpuint (crtc_config->transform,
                             ==,
                             test_case->expect.crtcs[i].transform);
 
-          if (meta_is_stage_views_enabled ())
-            {
-              get_compensated_crtc_position (crtc, &crtc_x, &crtc_y);
+          logical_monitor = crtc->logical_monitor;
+          g_assert_nonnull (logical_monitor);
 
-              g_assert_cmpint (crtc_x, ==, test_case->expect.crtcs[i].x);
-              g_assert_cmpint (crtc_y, ==, test_case->expect.crtcs[i].y);
-            }
-          else
-            {
-              int expect_crtc_x;
-              int expect_crtc_y;
-
-              g_assert_cmpuint (logical_monitor->transform,
-                                ==,
-                                crtc->transform);
-
-              expect_crtc_x = (test_case->expect.crtcs[i].x +
-                               logical_monitor->rect.x);
-              expect_crtc_y = (test_case->expect.crtcs[i].y +
-                               logical_monitor->rect.y);
-
-              g_assert_cmpint (crtc->rect.x, ==, expect_crtc_x);
-              g_assert_cmpint (crtc->rect.y, ==, expect_crtc_y);
-            }
+          g_assert_cmpfloat_with_epsilon (crtc_config->layout.origin.x,
+                                          test_case->expect.crtcs[i].x,
+                                          FLT_EPSILON);
+          g_assert_cmpfloat_with_epsilon (crtc_config->layout.origin.y,
+                                          test_case->expect.crtcs[i].y,
+                                          FLT_EPSILON);
         }
     }
 
@@ -945,19 +902,9 @@ create_monitor_test_setup (MonitorTestCase *test_case,
   for (i = 0; i < test_case->setup.n_crtcs; i++)
     {
       MetaCrtc *crtc;
-      int current_mode_index;
-      MetaCrtcMode *current_mode;
-
-      current_mode_index = test_case->setup.crtcs[i].current_mode;
-      if (current_mode_index == -1)
-        current_mode = NULL;
-      else
-        current_mode = g_list_nth_data (test_setup->modes, current_mode_index);
 
       crtc = g_object_new (META_TYPE_CRTC, NULL);
       crtc->crtc_id = i + 1;
-      crtc->current_mode = current_mode;
-      crtc->transform = META_MONITOR_TRANSFORM_NORMAL;
       crtc->all_transforms = ALL_TRANSFORMS;
 
       test_setup->crtcs = g_list_append (test_setup->crtcs, crtc);
@@ -1258,6 +1205,7 @@ meta_test_monitor_one_off_linear_config (void)
       },
       {
         .current_mode = 0,
+        .x = 1024,
       }
     },
     .n_crtcs = 2,
@@ -1966,6 +1914,7 @@ meta_test_monitor_hidpi_linear_config (void)
         },
         {
           .current_mode = 1,
+          .x = 640,
         }
       },
       .n_crtcs = 2,
@@ -2118,6 +2067,8 @@ meta_test_monitor_suggested_config (void)
       .crtcs = {
         {
           .current_mode = 0,
+          .x = 1024,
+          .y = 758,
         },
         {
           .current_mode = 1,
@@ -2386,6 +2337,7 @@ meta_test_monitor_lid_switch_config (void)
         },
         {
           .current_mode = 0,
+          .x = 1024,
         }
       },
       .n_crtcs = 2,
@@ -2417,6 +2369,7 @@ meta_test_monitor_lid_switch_config (void)
   test_case.expect.screen_width = 1024;
   test_case.expect.monitors[0].current_mode = -1;
   test_case.expect.crtcs[0].current_mode = -1;
+  test_case.expect.crtcs[1].x = 0;
 
   check_monitor_configuration (&test_case);
 
@@ -2436,6 +2389,7 @@ meta_test_monitor_lid_switch_config (void)
 
   test_case.expect.crtcs[0].current_mode = 0;
   test_case.expect.crtcs[1].current_mode = 0;
+  test_case.expect.crtcs[1].x = 1024;
 
   check_monitor_configuration (&test_case);
 }
@@ -2584,7 +2538,9 @@ meta_test_monitor_lid_opened_config (void)
   test_case.expect.screen_width = 1024 * 2;
   test_case.expect.monitors[0].current_mode = 0;
   test_case.expect.crtcs[0].current_mode = 0;
+  test_case.expect.crtcs[0].x = 1024;
   test_case.expect.crtcs[1].current_mode = 0;
+  test_case.expect.crtcs[1].x = 0;
 
   check_monitor_configuration (&test_case);
 }
@@ -2831,6 +2787,7 @@ meta_test_monitor_lid_closed_with_hotplugged_external (void)
   test_case.expect.n_monitors = 2;
   test_case.expect.n_logical_monitors = 2;
   test_case.expect.crtcs[1].current_mode = 0;
+  test_case.expect.crtcs[1].x = 1024;
   test_case.expect.screen_width = 1024 * 2;
 
   test_setup = create_monitor_test_setup (&test_case,
@@ -2844,6 +2801,7 @@ meta_test_monitor_lid_closed_with_hotplugged_external (void)
   test_case.expect.logical_monitors[0].monitors[0] = 1,
   test_case.expect.n_logical_monitors = 1;
   test_case.expect.crtcs[0].current_mode = -1;
+  test_case.expect.crtcs[1].x = 0;
   test_case.expect.screen_width = 1024;
 
   test_setup = create_monitor_test_setup (&test_case,
@@ -2867,6 +2825,7 @@ meta_test_monitor_lid_closed_with_hotplugged_external (void)
   test_case.expect.logical_monitors[1].monitors[0] = 1,
   test_case.expect.n_logical_monitors = 2;
   test_case.expect.crtcs[0].current_mode = 0;
+  test_case.expect.crtcs[1].x = 1024;
   test_case.expect.screen_width = 1024 * 2;
 
   test_setup = create_monitor_test_setup (&test_case,
@@ -3301,6 +3260,7 @@ meta_test_monitor_custom_vertical_config (void)
         },
         {
           .current_mode = 1,
+          .y = 768,
         }
       },
       .n_crtcs = 2,
@@ -3440,6 +3400,7 @@ meta_test_monitor_custom_primary_config (void)
         },
         {
           .current_mode = 1,
+          .x = 1024,
         }
       },
       .n_crtcs = 2,
@@ -3952,7 +3913,7 @@ meta_test_monitor_custom_tiled_config (void)
         },
         {
           .current_mode = 0,
-          .x = 400,
+          .x = 200,
           .y = 0
         }
       },
@@ -4555,6 +4516,7 @@ meta_test_monitor_custom_first_rotated_config (void)
         },
         {
           .current_mode = 0,
+          .x = 768,
         }
       },
       .n_crtcs = 2,
@@ -4685,10 +4647,12 @@ meta_test_monitor_custom_second_rotated_config (void)
       .crtcs = {
         {
           .current_mode = 0,
+          .y = 256,
         },
         {
           .current_mode = 0,
-          .transform = META_MONITOR_TRANSFORM_90
+          .transform = META_MONITOR_TRANSFORM_90,
+          .x = 1024,
         }
       },
       .n_crtcs = 2,
@@ -4859,16 +4823,18 @@ meta_test_monitor_custom_second_rotated_tiled_config (void)
       .crtcs = {
         {
           .current_mode = 0,
+          .y = 256,
         },
         {
           .current_mode = 1,
           .transform = META_MONITOR_TRANSFORM_90,
-          .x = 0,
+          .x = 1024,
           .y = 400,
         },
         {
           .current_mode = 1,
-          .transform = META_MONITOR_TRANSFORM_90
+          .transform = META_MONITOR_TRANSFORM_90,
+          .x = 1024,
         }
       },
       .n_crtcs = 3,
@@ -5008,10 +4974,12 @@ meta_test_monitor_custom_second_rotated_nonnative_config (void)
       .crtcs = {
         {
           .current_mode = 0,
+          .y = 256,
         },
         {
           .current_mode = 0,
-          .transform = META_MONITOR_TRANSFORM_NORMAL
+          .transform = META_MONITOR_TRANSFORM_NORMAL,
+          .x = 1024,
         }
       },
       .n_crtcs = 2,
@@ -5423,6 +5391,7 @@ meta_test_monitor_custom_lid_switch_config (void)
   test_case.expect.n_outputs = 2;
   test_case.expect.crtcs[0].transform = META_MONITOR_TRANSFORM_NORMAL;
   test_case.expect.crtcs[1].current_mode = 0;
+  test_case.expect.crtcs[1].x = 1024;
   test_case.expect.crtcs[1].transform = META_MONITOR_TRANSFORM_270;
   test_case.expect.logical_monitors[0].layout =
     (MetaRectangle) { .width = 1024, .height = 768 };
@@ -5440,6 +5409,7 @@ meta_test_monitor_custom_lid_switch_config (void)
 
   test_case.expect.crtcs[0].current_mode = -1;
   test_case.expect.crtcs[1].transform = META_MONITOR_TRANSFORM_90;
+  test_case.expect.crtcs[1].x = 0;
   test_case.expect.monitors[0].current_mode = -1;
   test_case.expect.logical_monitors[0].layout =
     (MetaRectangle) { .width = 768, .height = 1024 };
@@ -5460,6 +5430,7 @@ meta_test_monitor_custom_lid_switch_config (void)
   test_case.expect.crtcs[0].transform = META_MONITOR_TRANSFORM_NORMAL;
   test_case.expect.crtcs[1].current_mode = 0;
   test_case.expect.crtcs[1].transform = META_MONITOR_TRANSFORM_270;
+  test_case.expect.crtcs[1].x = 1024;
   test_case.expect.monitors[0].current_mode = 0;
   test_case.expect.logical_monitors[0].layout =
     (MetaRectangle) { .width = 1024, .height = 768 };


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