[mutter] kms: Predict state changes when processing update



commit 104bdde746c9ceccd9e9ab09b22ef228b8f7026e
Author: Jonas Ådahl <jadahl gmail com>
Date:   Fri Oct 4 11:54:29 2019 +0200

    kms: Predict state changes when processing update
    
    We can't just update the state of the connector and CRTC from KMS since
    it might contain too new updates, e.g. from a from a future hot plug. In
    order to not add ad-hoc hot plug detection everywhere, predict the state
    changes by looking inside the MetaKmsUpdate object, and let the hot-plug
    state changes happen after the actual hot-plug event.
    
    This fixes issues where connectors were discovered as disconnected while
    doing a mode-set, meaning assumptions about the connectedness of
    monitors elsewhere were broken until the hot plug event was processed.
    
    Fixes: https://gitlab.gnome.org/GNOME/mutter/issues/782
    
    https://gitlab.gnome.org/GNOME/mutter/merge_requests/826

 src/backends/native/meta-kms-connector-private.h |  3 ++
 src/backends/native/meta-kms-connector.c         | 30 +++++++++++++
 src/backends/native/meta-kms-crtc-private.h      |  3 ++
 src/backends/native/meta-kms-crtc.c              | 57 ++++++++++++++++++++++++
 src/backends/native/meta-kms-device-private.h    |  6 ++-
 src/backends/native/meta-kms-device.c            | 32 +++++++------
 src/backends/native/meta-kms-impl-device.c       | 16 +++++--
 src/backends/native/meta-kms-impl-device.h       |  6 ++-
 src/backends/native/meta-kms-types.h             |  6 ---
 src/backends/native/meta-kms.c                   | 49 +++++++++-----------
 10 files changed, 153 insertions(+), 55 deletions(-)
---
diff --git a/src/backends/native/meta-kms-connector-private.h 
b/src/backends/native/meta-kms-connector-private.h
index 427502a34..29901c487 100644
--- a/src/backends/native/meta-kms-connector-private.h
+++ b/src/backends/native/meta-kms-connector-private.h
@@ -25,6 +25,9 @@
 void meta_kms_connector_update_state (MetaKmsConnector *connector,
                                       drmModeRes       *drm_resources);
 
+void meta_kms_connector_predict_state (MetaKmsConnector *connector,
+                                       MetaKmsUpdate    *update);
+
 MetaKmsConnector * meta_kms_connector_new (MetaKmsImplDevice *impl_device,
                                            drmModeConnector  *drm_connector,
                                            drmModeRes        *drm_resources);
diff --git a/src/backends/native/meta-kms-connector.c b/src/backends/native/meta-kms-connector.c
index 1508d4fea..c018a5e62 100644
--- a/src/backends/native/meta-kms-connector.c
+++ b/src/backends/native/meta-kms-connector.c
@@ -24,6 +24,7 @@
 
 #include <errno.h>
 
+#include "backends/native/meta-kms-crtc.h"
 #include "backends/native/meta-kms-device-private.h"
 #include "backends/native/meta-kms-impl-device.h"
 #include "backends/native/meta-kms-update-private.h"
@@ -495,6 +496,35 @@ meta_kms_connector_update_state (MetaKmsConnector *connector,
     drmModeFreeConnector (drm_connector);
 }
 
+void
+meta_kms_connector_predict_state (MetaKmsConnector *connector,
+                                  MetaKmsUpdate    *update)
+{
+  GList *mode_sets;
+  GList *l;
+
+  if (!connector->current_state)
+    return;
+
+  mode_sets = meta_kms_update_get_mode_sets (update);
+  for (l = mode_sets; l; l = l->next)
+    {
+      MetaKmsModeSet *mode_set = l->data;
+      MetaKmsCrtc *crtc;
+
+      if (!g_list_find (mode_set->connectors, connector))
+        continue;
+
+      crtc = mode_set->crtc;
+      if (crtc)
+        connector->current_state->current_crtc_id = meta_kms_crtc_get_id (crtc);
+      else
+        connector->current_state->current_crtc_id = 0;
+
+      break;
+    }
+}
+
 static void
 find_property_ids (MetaKmsConnector  *connector,
                    MetaKmsImplDevice *impl_device,
diff --git a/src/backends/native/meta-kms-crtc-private.h b/src/backends/native/meta-kms-crtc-private.h
index 41db399e6..f9a3a6e0a 100644
--- a/src/backends/native/meta-kms-crtc-private.h
+++ b/src/backends/native/meta-kms-crtc-private.h
@@ -30,4 +30,7 @@ MetaKmsCrtc * meta_kms_crtc_new (MetaKmsImplDevice *impl_device,
 
 void meta_kms_crtc_update_state (MetaKmsCrtc *crtc);
 
+void meta_kms_crtc_predict_state (MetaKmsCrtc   *crtc,
+                                  MetaKmsUpdate *update);
+
 #endif /* META_KMS_CRTC_PRIVATE_H */
diff --git a/src/backends/native/meta-kms-crtc.c b/src/backends/native/meta-kms-crtc.c
index 2b0f5385a..3610df903 100644
--- a/src/backends/native/meta-kms-crtc.c
+++ b/src/backends/native/meta-kms-crtc.c
@@ -143,6 +143,63 @@ meta_kms_crtc_update_state (MetaKmsCrtc *crtc)
   drmModeFreeCrtc (drm_crtc);
 }
 
+void
+meta_kms_crtc_predict_state (MetaKmsCrtc   *crtc,
+                             MetaKmsUpdate *update)
+{
+  GList *mode_sets;
+  GList *crtc_gammas;
+  GList *l;
+
+  mode_sets = meta_kms_update_get_mode_sets (update);
+  for (l = mode_sets; l; l = l->next)
+    {
+      MetaKmsModeSet *mode_set = l->data;
+
+      if (mode_set->crtc != crtc)
+        continue;
+
+      if (mode_set->drm_mode)
+        {
+          MetaKmsPlaneAssignment *plane_assignment;
+
+          plane_assignment =
+            meta_kms_update_get_primary_plane_assignment (update, crtc);
+
+          crtc->current_state.rect =
+            meta_fixed_16_rectangle_to_rectangle (plane_assignment->src_rect);
+          crtc->current_state.is_drm_mode_valid = TRUE;
+          crtc->current_state.drm_mode = *mode_set->drm_mode;
+        }
+      else
+        {
+          crtc->current_state.rect = (MetaRectangle) { 0 };
+          crtc->current_state.is_drm_mode_valid = FALSE;
+          crtc->current_state.drm_mode = (drmModeModeInfo) { 0 };
+        }
+
+      break;
+    }
+
+  crtc_gammas = meta_kms_update_get_crtc_gammas (update);
+  for (l = crtc_gammas; l; l = l->next)
+    {
+      MetaKmsCrtcGamma *gamma = l->data;
+
+      if (gamma->crtc != crtc)
+        continue;
+
+      crtc->current_state.gamma.size = gamma->size;
+      crtc->current_state.gamma.red =
+        g_memdup (gamma->red, gamma->size * sizeof (uint16_t));
+      crtc->current_state.gamma.green =
+        g_memdup (gamma->green, gamma->size * sizeof (uint16_t));
+      crtc->current_state.gamma.blue =
+        g_memdup (gamma->blue, gamma->size * sizeof (uint16_t));
+      break;
+    }
+}
+
 MetaKmsCrtc *
 meta_kms_crtc_new (MetaKmsImplDevice *impl_device,
                    drmModeCrtc       *drm_crtc,
diff --git a/src/backends/native/meta-kms-device-private.h b/src/backends/native/meta-kms-device-private.h
index bcb3a6e74..876fb30fc 100644
--- a/src/backends/native/meta-kms-device-private.h
+++ b/src/backends/native/meta-kms-device-private.h
@@ -24,7 +24,9 @@
 
 MetaKmsImplDevice * meta_kms_device_get_impl_device (MetaKmsDevice *device);
 
-void meta_kms_device_update_states_in_impl (MetaKmsDevice            *device,
-                                            MetaKmsUpdateStatesFlags  flags);
+void meta_kms_device_update_states_in_impl (MetaKmsDevice *device);
+
+void meta_kms_device_predict_states_in_impl (MetaKmsDevice *device,
+                                             MetaKmsUpdate *update);
 
 #endif /* META_KMS_DEVICE_PRIVATE_H */
diff --git a/src/backends/native/meta-kms-device.c b/src/backends/native/meta-kms-device.c
index d137c63b9..8ed2de024 100644
--- a/src/backends/native/meta-kms-device.c
+++ b/src/backends/native/meta-kms-device.c
@@ -109,28 +109,34 @@ meta_kms_device_get_primary_plane_for (MetaKmsDevice *device,
 }
 
 void
-meta_kms_device_update_states_in_impl (MetaKmsDevice            *device,
-                                       MetaKmsUpdateStatesFlags  flags)
+meta_kms_device_update_states_in_impl (MetaKmsDevice *device)
 {
   MetaKmsImplDevice *impl_device = meta_kms_device_get_impl_device (device);
 
   meta_assert_in_kms_impl (device->kms);
+  meta_assert_is_waiting_for_kms_impl_task (device->kms);
 
-  meta_kms_impl_device_update_states (impl_device, flags);
+  meta_kms_impl_device_update_states (impl_device);
 
-  if (flags & META_KMS_UPDATE_STATES_FLAG_HOTPLUG)
-    {
-      meta_assert_is_waiting_for_kms_impl_task (device->kms);
+  g_list_free (device->crtcs);
+  device->crtcs = meta_kms_impl_device_copy_crtcs (impl_device);
 
-      g_list_free (device->crtcs);
-      device->crtcs = meta_kms_impl_device_copy_crtcs (impl_device);
+  g_list_free (device->connectors);
+  device->connectors = meta_kms_impl_device_copy_connectors (impl_device);
 
-      g_list_free (device->connectors);
-      device->connectors = meta_kms_impl_device_copy_connectors (impl_device);
+  g_list_free (device->planes);
+  device->planes = meta_kms_impl_device_copy_planes (impl_device);
+}
 
-      g_list_free (device->planes);
-      device->planes = meta_kms_impl_device_copy_planes (impl_device);
-    }
+void
+meta_kms_device_predict_states_in_impl (MetaKmsDevice *device,
+                                        MetaKmsUpdate *update)
+{
+  MetaKmsImplDevice *impl_device = meta_kms_device_get_impl_device (device);
+
+  meta_assert_in_kms_impl (device->kms);
+
+  meta_kms_impl_device_predict_states (impl_device, update);
 }
 
 static gboolean
diff --git a/src/backends/native/meta-kms-impl-device.c b/src/backends/native/meta-kms-impl-device.c
index dde192b42..922aca103 100644
--- a/src/backends/native/meta-kms-impl-device.c
+++ b/src/backends/native/meta-kms-impl-device.c
@@ -319,8 +319,7 @@ init_planes (MetaKmsImplDevice *impl_device)
 }
 
 void
-meta_kms_impl_device_update_states (MetaKmsImplDevice        *impl_device,
-                                    MetaKmsUpdateStatesFlags  flags)
+meta_kms_impl_device_update_states (MetaKmsImplDevice *impl_device)
 {
   drmModeRes *drm_resources;
 
@@ -328,8 +327,7 @@ meta_kms_impl_device_update_states (MetaKmsImplDevice        *impl_device,
 
   drm_resources = drmModeGetResources (impl_device->fd);
 
-  if (flags & META_KMS_UPDATE_STATES_FLAG_HOTPLUG)
-    update_connectors (impl_device, drm_resources);
+  update_connectors (impl_device, drm_resources);
 
   g_list_foreach (impl_device->crtcs, (GFunc) meta_kms_crtc_update_state,
                   NULL);
@@ -338,6 +336,16 @@ meta_kms_impl_device_update_states (MetaKmsImplDevice        *impl_device,
   drmModeFreeResources (drm_resources);
 }
 
+void
+meta_kms_impl_device_predict_states (MetaKmsImplDevice *impl_device,
+                                     MetaKmsUpdate     *update)
+{
+  g_list_foreach (impl_device->crtcs, (GFunc) meta_kms_crtc_predict_state,
+                  update);
+  g_list_foreach (impl_device->connectors, (GFunc) meta_kms_connector_predict_state,
+                  update);
+}
+
 MetaKmsImplDevice *
 meta_kms_impl_device_new (MetaKmsDevice  *device,
                           MetaKmsImpl    *impl,
diff --git a/src/backends/native/meta-kms-impl-device.h b/src/backends/native/meta-kms-impl-device.h
index 1e971af8b..5bd0f5f98 100644
--- a/src/backends/native/meta-kms-impl-device.h
+++ b/src/backends/native/meta-kms-impl-device.h
@@ -53,8 +53,10 @@ int meta_kms_impl_device_get_fd (MetaKmsImplDevice *impl_device);
 
 int meta_kms_impl_device_leak_fd (MetaKmsImplDevice *impl_device);
 
-void meta_kms_impl_device_update_states (MetaKmsImplDevice        *impl_device,
-                                         MetaKmsUpdateStatesFlags  flags);
+void meta_kms_impl_device_update_states (MetaKmsImplDevice *impl_device);
+
+void meta_kms_impl_device_predict_states (MetaKmsImplDevice *impl_device,
+                                          MetaKmsUpdate     *update);
 
 int meta_kms_impl_device_close (MetaKmsImplDevice *impl_device);
 
diff --git a/src/backends/native/meta-kms-types.h b/src/backends/native/meta-kms-types.h
index ed4a4cd9d..dd14a7be7 100644
--- a/src/backends/native/meta-kms-types.h
+++ b/src/backends/native/meta-kms-types.h
@@ -56,10 +56,4 @@ typedef enum _MetaKmsDeviceFlag
   META_KMS_DEVICE_FLAG_PLATFORM_DEVICE = 1 << 1,
 } MetaKmsDeviceFlag;
 
-typedef enum _MetaKmsUpdateStatesFlags
-{
-  META_KMS_UPDATE_STATES_FLAG_NONE = 0,
-  META_KMS_UPDATE_STATES_FLAG_HOTPLUG = 1 << 0,
-} MetaKmsUpdateStatesFlags;
-
 #endif /* META_KMS_IMPL_TYPES_H */
diff --git a/src/backends/native/meta-kms.c b/src/backends/native/meta-kms.c
index 39d1f3155..9485bb4e8 100644
--- a/src/backends/native/meta-kms.c
+++ b/src/backends/native/meta-kms.c
@@ -175,10 +175,6 @@ struct _MetaKms
 
 G_DEFINE_TYPE (MetaKms, meta_kms, G_TYPE_OBJECT)
 
-static void
-meta_kms_update_states_in_impl (MetaKms                  *kms,
-                                MetaKmsUpdateStatesFlags  flags);
-
 MetaKmsUpdate *
 meta_kms_ensure_pending_update (MetaKms *kms)
 {
@@ -194,6 +190,17 @@ meta_kms_get_pending_update (MetaKms *kms)
   return kms->pending_update;
 }
 
+static void
+meta_kms_predict_states_in_impl (MetaKms       *kms,
+                                 MetaKmsUpdate *update)
+{
+  meta_assert_in_kms_impl (kms);
+
+  g_list_foreach (kms->devices,
+                  (GFunc) meta_kms_device_predict_states_in_impl,
+                  update);
+}
+
 static gboolean
 meta_kms_update_process_in_impl (MetaKmsImpl  *impl,
                                  gpointer      user_data,
@@ -205,8 +212,7 @@ meta_kms_update_process_in_impl (MetaKmsImpl  *impl,
   ret = meta_kms_impl_process_update (impl, update, error);
 
   if (meta_kms_update_has_mode_set (update))
-    meta_kms_update_states_in_impl (meta_kms_impl_get_kms (impl),
-                                    META_KMS_UPDATE_STATES_FLAG_NONE);
+    meta_kms_predict_states_in_impl (meta_kms_impl_get_kms (impl), update);
 
   return ret;
 }
@@ -461,22 +467,16 @@ meta_kms_is_waiting_for_impl_task (MetaKms *kms)
 }
 
 static void
-meta_kms_update_states_in_impl (MetaKms                  *kms,
-                                MetaKmsUpdateStatesFlags  flags)
+meta_kms_update_states_in_impl (MetaKms *kms)
 {
-  GList *l;
-
   COGL_TRACE_BEGIN_SCOPED (MetaKmsUpdateStates,
                            "KMS (update states)");
 
   meta_assert_in_kms_impl (kms);
 
-  for (l = kms->devices; l; l = l->next)
-    {
-      MetaKmsDevice *device = l->data;
-
-      meta_kms_device_update_states_in_impl (device, flags);
-    }
+  g_list_foreach (kms->devices,
+                  (GFunc) meta_kms_device_update_states_in_impl,
+                  NULL);
 }
 
 static gboolean
@@ -485,22 +485,17 @@ update_states_in_impl (MetaKmsImpl  *impl,
                        GError      **error)
 {
   MetaKms *kms = meta_kms_impl_get_kms (impl);;
-  MetaKmsUpdateStatesFlags flags = GPOINTER_TO_UINT (user_data);
 
-  meta_kms_update_states_in_impl (kms, flags);
+  meta_kms_update_states_in_impl (kms);
 
   return TRUE;
 }
 
 static gboolean
-meta_kms_update_states_sync (MetaKms                   *kms,
-                             MetaKmsUpdateStatesFlags   flags,
-                             GError                   **error)
+meta_kms_update_states_sync (MetaKms  *kms,
+                             GError  **error)
 {
-  return meta_kms_run_impl_task_sync (kms,
-                                      update_states_in_impl,
-                                      GUINT_TO_POINTER (flags),
-                                      error);
+  return meta_kms_run_impl_task_sync (kms, update_states_in_impl, NULL, error);
 }
 
 static void
@@ -508,9 +503,7 @@ handle_hotplug_event (MetaKms *kms)
 {
   g_autoptr (GError) error = NULL;
 
-  if (!meta_kms_update_states_sync (kms,
-                                    META_KMS_UPDATE_STATES_FLAG_HOTPLUG,
-                                    &error))
+  if (!meta_kms_update_states_sync (kms, &error))
     g_warning ("Updating KMS state failed: %s", error->message);
 
   g_signal_emit (kms, signals[RESOURCES_CHANGED], 0);


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