[mutter/wip/carlosg/fix-open-lid-flicker: 1531/1531] backends: Compare gpu/crtc/output configurations before applying



commit 18c85c9ffb23186f5e1739d31df6ceaee906893e
Author: Carlos Garnacho <carlosg gnome org>
Date:   Tue Jan 9 21:29:26 2018 +0100

    backends: Compare gpu/crtc/output configurations before applying
    
    This spares us from visible flickering whenever an unchanged configuration
    is reapplied, eg. after lid open. The code in the X11 paths that did the
    same comparisons has been removed in favor of the generic checks.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=791879

 src/backends/meta-monitor-manager-private.h    |   6 +
 src/backends/meta-monitor-manager.c            | 152 +++++++++++++++++++++++++
 src/backends/native/meta-monitor-manager-kms.c |  31 +++++
 src/backends/x11/meta-monitor-manager-xrandr.c | 142 +----------------------
 4 files changed, 194 insertions(+), 137 deletions(-)
---
diff --git a/src/backends/meta-monitor-manager-private.h b/src/backends/meta-monitor-manager-private.h
index 20bb6b679..dd9b25259 100644
--- a/src/backends/meta-monitor-manager-private.h
+++ b/src/backends/meta-monitor-manager-private.h
@@ -388,4 +388,10 @@ gboolean meta_monitor_has_aspect_as_size (MetaMonitor *monitor);
 char * meta_monitor_manager_get_vendor_name (MetaMonitorManager *manager,
                                              const char         *vendor);
 
+gboolean meta_monitor_manager_get_has_changed (MetaMonitorManager  *manager,
+                                               MetaCrtcInfo       **crtc_infos,
+                                               unsigned int         n_crtc_infos,
+                                               MetaOutputInfo     **output_infos,
+                                               unsigned int         n_output_infos);
+
 #endif /* META_MONITOR_MANAGER_PRIVATE_H */
diff --git a/src/backends/meta-monitor-manager.c b/src/backends/meta-monitor-manager.c
index 41036ca2a..4048249fe 100644
--- a/src/backends/meta-monitor-manager.c
+++ b/src/backends/meta-monitor-manager.c
@@ -483,6 +483,158 @@ meta_monitor_manager_ensure_initial_config (MetaMonitorManager *manager)
   META_MONITOR_MANAGER_GET_CLASS (manager)->ensure_initial_config (manager);
 }
 
+static gboolean
+is_crtc_assignment_changed (MetaCrtc      *crtc,
+                            MetaCrtcInfo **crtc_infos,
+                            unsigned int   n_crtc_infos)
+{
+  unsigned int i;
+
+  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 crtc->current_mode != NULL;
+}
+
+static gboolean
+is_output_assignment_changed (MetaOutput      *output,
+                              MetaCrtcInfo   **crtc_infos,
+                              unsigned int     n_crtc_infos,
+                              MetaOutputInfo **output_infos,
+                              unsigned int     n_output_infos)
+{
+  MetaCrtc *assigned_crtc;
+  gboolean output_is_found = FALSE;
+  unsigned int i;
+
+  for (i = 0; i < n_output_infos; i++)
+    {
+      MetaOutputInfo *output_info = output_infos[i];
+
+      if (output_info->output != output)
+        continue;
+
+      if (output->is_primary != output_info->is_primary)
+        return TRUE;
+
+      if (output->is_presentation != output_info->is_presentation)
+        return TRUE;
+
+      if (output->is_underscanning != output_info->is_underscanning)
+        return TRUE;
+
+      output_is_found = TRUE;
+    }
+
+  assigned_crtc = meta_output_get_assigned_crtc (output);
+
+  if (!output_is_found)
+    return assigned_crtc != NULL;
+
+  for (i = 0; i < n_crtc_infos; i++)
+    {
+      MetaCrtcInfo *crtc_info = crtc_infos[i];
+      unsigned int j;
+
+      for (j = 0; j < crtc_info->outputs->len; j++)
+        {
+          MetaOutput *crtc_info_output =
+            ((MetaOutput**) crtc_info->outputs->pdata)[j];
+
+          if (crtc_info_output == output &&
+              crtc_info->crtc == assigned_crtc)
+            return FALSE;
+        }
+    }
+
+  return TRUE;
+}
+
+static gboolean
+is_assignments_changed (MetaMonitorManager *manager,
+                        MetaGpu            *gpu,
+                        MetaCrtcInfo      **crtc_infos,
+                        unsigned int        n_crtc_infos,
+                        MetaOutputInfo    **output_infos,
+                        unsigned int        n_output_infos)
+{
+  GList *l;
+
+  for (l = meta_gpu_get_crtcs (gpu); l; l = l->next)
+    {
+      MetaCrtc *crtc = l->data;
+
+      if (is_crtc_assignment_changed (crtc, crtc_infos, n_crtc_infos))
+        return TRUE;
+    }
+
+  for (l = meta_gpu_get_outputs (gpu); l; l = l->next)
+    {
+      MetaOutput *output = l->data;
+
+      if (is_output_assignment_changed (output,
+                                        crtc_infos,
+                                        n_crtc_infos,
+                                        output_infos,
+                                        n_output_infos))
+        return TRUE;
+    }
+
+  return FALSE;
+}
+
+gboolean
+meta_monitor_manager_get_has_changed (MetaMonitorManager  *manager,
+                                      MetaCrtcInfo       **crtc_infos,
+                                      unsigned int         n_crtc_infos,
+                                      MetaOutputInfo     **output_infos,
+                                      unsigned int         n_output_infos)
+{
+  GList *gpus;
+  GList *l;
+
+  gpus = meta_backend_get_gpus (manager->backend);
+  for (l = gpus; l; l = l->next)
+    {
+      if (is_assignments_changed (manager, l->data,
+                                  crtc_infos, n_crtc_infos,
+                                  output_infos, n_output_infos))
+        return TRUE;
+    }
+
+  return FALSE;
+}
+
 static gboolean
 meta_monitor_manager_apply_monitors_config (MetaMonitorManager      *manager,
                                             MetaMonitorsConfig      *config,
diff --git a/src/backends/native/meta-monitor-manager-kms.c b/src/backends/native/meta-monitor-manager-kms.c
index 26c2ddb61..a768b74f2 100644
--- a/src/backends/native/meta-monitor-manager-kms.c
+++ b/src/backends/native/meta-monitor-manager-kms.c
@@ -77,6 +77,8 @@ struct _MetaMonitorManagerKms
 
   guint hotplug_handler_id;
   guint removed_handler_id;
+
+  guint logical_monitors_invalid : 1;
 };
 
 struct _MetaMonitorManagerKmsClass
@@ -322,6 +324,7 @@ meta_monitor_manager_kms_apply_monitors_config (MetaMonitorManager      *manager
                                                 MetaMonitorsConfigMethod method,
                                                 GError                 **error)
 {
+  MetaMonitorManagerKms *manager_kms = META_MONITOR_MANAGER_KMS (manager);
   GPtrArray *crtc_infos;
   GPtrArray *output_infos;
 
@@ -345,6 +348,26 @@ meta_monitor_manager_kms_apply_monitors_config (MetaMonitorManager      *manager
       return TRUE;
     }
 
+  if (!meta_monitor_manager_get_has_changed (manager,
+                                             (MetaCrtcInfo **) crtc_infos->pdata,
+                                             crtc_infos->len,
+                                             (MetaOutputInfo **) output_infos->pdata,
+                                             output_infos->len))
+    {
+      /* Rebuild logical monitors if invalid, i.e. after
+       * meta_monitor_manager_read_current_state().
+       */
+      if (manager_kms->logical_monitors_invalid)
+        {
+          meta_monitor_manager_rebuild (manager, config);
+          manager_kms->logical_monitors_invalid = FALSE;
+        }
+
+      g_ptr_array_free (crtc_infos, TRUE);
+      g_ptr_array_free (output_infos, TRUE);
+      return TRUE;
+    }
+
   apply_crtc_assignments (manager,
                           (MetaCrtcInfo **) crtc_infos->pdata,
                           crtc_infos->len,
@@ -356,6 +379,7 @@ meta_monitor_manager_kms_apply_monitors_config (MetaMonitorManager      *manager
 
   update_screen_size (manager, config);
   meta_monitor_manager_rebuild (manager, config);
+  manager_kms->logical_monitors_invalid = FALSE;
 
   return TRUE;
 }
@@ -474,6 +498,13 @@ meta_monitor_manager_kms_set_crtc_gamma (MetaMonitorManager *manager,
 static void
 handle_hotplug_event (MetaMonitorManager *manager)
 {
+  MetaMonitorManagerKms *manager_kms = META_MONITOR_MANAGER_KMS (manager);
+
+  /* read_current_state() will rebuild monitors, leaving MetaLogicalMonitors
+   * with stale pointers to those. We will need to rebuild those even though
+   * the configuration might not have actually changed (eg. tty switch).
+   */
+  manager_kms->logical_monitors_invalid = TRUE;
   meta_monitor_manager_read_current_state (manager);
   meta_monitor_manager_on_hotplug (manager);
 }
diff --git a/src/backends/x11/meta-monitor-manager-xrandr.c b/src/backends/x11/meta-monitor-manager-xrandr.c
index 8fae335f0..6e9d142f5 100644
--- a/src/backends/x11/meta-monitor-manager-xrandr.c
+++ b/src/backends/x11/meta-monitor-manager-xrandr.c
@@ -240,103 +240,6 @@ xrandr_set_crtc_config (MetaMonitorManagerXrandr *manager_xrandr,
   return TRUE;
 }
 
-static gboolean
-is_crtc_assignment_changed (MetaCrtc      *crtc,
-                            MetaCrtcInfo **crtc_infos,
-                            unsigned int   n_crtc_infos)
-{
-  unsigned int i;
-
-  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 crtc->current_mode != NULL;
-}
-
-static gboolean
-is_output_assignment_changed (MetaOutput      *output,
-                              MetaCrtcInfo   **crtc_infos,
-                              unsigned int     n_crtc_infos,
-                              MetaOutputInfo **output_infos,
-                              unsigned int     n_output_infos)
-{
-  MetaCrtc *assigned_crtc;
-  gboolean output_is_found = FALSE;
-  unsigned int i;
-
-  for (i = 0; i < n_output_infos; i++)
-    {
-      MetaOutputInfo *output_info = output_infos[i];
-
-      if (output_info->output != output)
-        continue;
-
-      if (output->is_primary != output_info->is_primary)
-        return TRUE;
-
-      if (output->is_presentation != output_info->is_presentation)
-        return TRUE;
-
-      if (output->is_underscanning != output_info->is_underscanning)
-        return TRUE;
-
-      output_is_found = TRUE;
-    }
-
-  assigned_crtc = meta_output_get_assigned_crtc (output);
-
-  if (!output_is_found)
-    return assigned_crtc != NULL;
-
-  for (i = 0; i < n_crtc_infos; i++)
-    {
-      MetaCrtcInfo *crtc_info = crtc_infos[i];
-      unsigned int j;
-
-      for (j = 0; j < crtc_info->outputs->len; j++)
-        {
-          MetaOutput *crtc_info_output =
-            ((MetaOutput**) crtc_info->outputs->pdata)[j];
-
-          if (crtc_info_output == output &&
-              crtc_info->crtc == assigned_crtc)
-            return FALSE;
-        }
-    }
-
-  return TRUE;
-}
-
 static MetaGpu *
 meta_monitor_manager_xrandr_get_gpu (MetaMonitorManagerXrandr *manager_xrandr)
 {
@@ -346,41 +249,6 @@ meta_monitor_manager_xrandr_get_gpu (MetaMonitorManagerXrandr *manager_xrandr)
   return META_GPU (meta_backend_get_gpus (backend)->data);
 }
 
-static gboolean
-is_assignments_changed (MetaMonitorManager *manager,
-                        MetaCrtcInfo      **crtc_infos,
-                        unsigned int        n_crtc_infos,
-                        MetaOutputInfo    **output_infos,
-                        unsigned int        n_output_infos)
-{
-  MetaMonitorManagerXrandr *manager_xrandr =
-    META_MONITOR_MANAGER_XRANDR (manager);
-  MetaGpu *gpu = meta_monitor_manager_xrandr_get_gpu (manager_xrandr);
-  GList *l;
-
-  for (l = meta_gpu_get_crtcs (gpu); l; l = l->next)
-    {
-      MetaCrtc *crtc = l->data;
-
-      if (is_crtc_assignment_changed (crtc, crtc_infos, n_crtc_infos))
-        return TRUE;
-    }
-
-  for (l = meta_gpu_get_outputs (gpu); l; l = l->next)
-    {
-      MetaOutput *output = l->data;
-
-      if (is_output_assignment_changed (output,
-                                        crtc_infos,
-                                        n_crtc_infos,
-                                        output_infos,
-                                        n_output_infos))
-        return TRUE;
-    }
-
-  return FALSE;
-}
-
 static void
 apply_crtc_assignments (MetaMonitorManager *manager,
                         gboolean            save_timestamp,
@@ -651,11 +519,11 @@ meta_monitor_manager_xrandr_apply_monitors_config (MetaMonitorManager      *mana
        * must check that our new assignment actually changes anything, otherwise
        * just update the logical state.
        */
-      if (is_assignments_changed (manager,
-                                  (MetaCrtcInfo **) crtc_infos->pdata,
-                                  crtc_infos->len,
-                                  (MetaOutputInfo **) output_infos->pdata,
-                                  output_infos->len))
+      if (meta_monitor_manager_get_has_changed (manager,
+                                                (MetaCrtcInfo **) crtc_infos->pdata,
+                                                crtc_infos->len,
+                                                (MetaOutputInfo **) output_infos->pdata,
+                                                output_infos->len))
         {
           apply_crtc_assignments (manager,
                                   TRUE,


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