[mutter] kms/update: Make each MetaKmsUpdate update a single device



commit 37fe30c515792dc9c6945c00478b3169c984d122
Author: Jonas Ã…dahl <jadahl gmail com>
Date:   Thu Jul 16 23:38:10 2020 +0200

    kms/update: Make each MetaKmsUpdate update a single device
    
    For now feedbacks from an update are combined, meaning we might lose
    error information. The feedback API may have to be reconsidered and
    redesigned when planes gets a more front seat position.
    
    This means we need to avoid trying to post updates if we're in power
    save mode, as it may be empty.
    
    Note that this is an intermediate state during refactoring that aims to
    introduce atomic mode setting support, and we'll stop combining
    feedbacks completely in the future.
    
    Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1488>

 src/backends/native/meta-cursor-renderer-native.c |  19 ++--
 src/backends/native/meta-kms-device.c             |   6 +
 src/backends/native/meta-kms-device.h             |   2 +
 src/backends/native/meta-kms-update-private.h     |   2 +
 src/backends/native/meta-kms-update.c             |  30 ++++-
 src/backends/native/meta-kms-update.h             |   2 +-
 src/backends/native/meta-kms.c                    | 109 ++++++++++++++----
 src/backends/native/meta-kms.h                    |   8 +-
 src/backends/native/meta-monitor-manager-kms.c    |  22 ++--
 src/backends/native/meta-renderer-native.c        | 131 +++++++++++-----------
 10 files changed, 219 insertions(+), 112 deletions(-)
---
diff --git a/src/backends/native/meta-cursor-renderer-native.c 
b/src/backends/native/meta-cursor-renderer-native.c
index ccf0434ee7..c9de9436e8 100644
--- a/src/backends/native/meta-cursor-renderer-native.c
+++ b/src/backends/native/meta-cursor-renderer-native.c
@@ -383,7 +383,6 @@ typedef struct
   MetaLogicalMonitor *in_logical_monitor;
   graphene_rect_t in_local_cursor_rect;
   MetaCursorSprite *in_cursor_sprite;
-  MetaKmsUpdate *in_kms_update;
 
   gboolean out_painted;
 } UpdateCrtcCursorData;
@@ -401,6 +400,10 @@ update_monitor_crtc_cursor (MetaMonitor         *monitor,
   MetaCursorRendererNativePrivate *priv =
     meta_cursor_renderer_native_get_instance_private (cursor_renderer_native);
   MetaCrtc *crtc;
+  MetaGpuKms *gpu_kms;
+  MetaKmsDevice *kms_device;
+  MetaKms *kms;
+  MetaKmsUpdate *kms_update;
   MetaMonitorTransform transform;
   const MetaCrtcModeInfo *crtc_mode_info;
   graphene_rect_t scaled_crtc_rect;
@@ -446,6 +449,10 @@ update_monitor_crtc_cursor (MetaMonitor         *monitor,
   };
 
   crtc = meta_output_get_assigned_crtc (monitor_crtc_mode->output);
+  gpu_kms = META_GPU_KMS (meta_crtc_get_gpu (crtc));
+  kms_device = meta_gpu_kms_get_kms_device (gpu_kms);
+  kms = meta_kms_device_get_kms (kms_device);
+  kms_update = meta_kms_ensure_pending_update (kms, kms_device);
 
   if (priv->has_hw_cursor &&
       graphene_rect_intersection (&scaled_crtc_rect,
@@ -487,7 +494,7 @@ update_monitor_crtc_cursor (MetaMonitor         *monitor,
                                 &cursor_rect);
 
       set_crtc_cursor (data->in_cursor_renderer_native,
-                       data->in_kms_update,
+                       kms_update,
                        META_CRTC_KMS (crtc),
                        cursor_rect.x,
                        cursor_rect.y,
@@ -498,7 +505,7 @@ update_monitor_crtc_cursor (MetaMonitor         *monitor,
   else
     {
       unset_crtc_cursor (data->in_cursor_renderer_native,
-                         data->in_kms_update,
+                         kms_update,
                          META_CRTC_KMS (crtc));
     }
 
@@ -533,15 +540,12 @@ update_hw_cursor (MetaCursorRendererNative *native,
   MetaKms *kms = meta_backend_native_get_kms (backend_native);
   MetaMonitorManager *monitor_manager =
     meta_backend_get_monitor_manager (backend);
-  MetaKmsUpdate *kms_update;
   GList *logical_monitors;
   GList *l;
   graphene_rect_t rect;
   gboolean painted = FALSE;
   g_autoptr (MetaKmsFeedback) feedback = NULL;
 
-  kms_update = meta_kms_ensure_pending_update (kms);
-
   if (cursor_sprite)
     rect = meta_cursor_renderer_calculate_rect (renderer, cursor_sprite);
   else
@@ -567,7 +571,6 @@ update_hw_cursor (MetaCursorRendererNative *native,
           .size = rect.size
         },
         .in_cursor_sprite = cursor_sprite,
-        .in_kms_update = kms_update,
       };
 
       monitors = meta_logical_monitor_get_monitors (logical_monitor);
@@ -586,7 +589,7 @@ update_hw_cursor (MetaCursorRendererNative *native,
       painted = painted || data.out_painted;
     }
 
-  feedback = meta_kms_post_pending_update_sync (kms);
+  feedback = meta_kms_post_pending_updates_sync (kms);
   if (meta_kms_feedback_get_result (feedback) != META_KMS_FEEDBACK_PASSED)
     {
       for (l = meta_kms_feedback_get_failed_planes (feedback); l; l = l->next)
diff --git a/src/backends/native/meta-kms-device.c b/src/backends/native/meta-kms-device.c
index a8abd8842c..4179c623c7 100644
--- a/src/backends/native/meta-kms-device.c
+++ b/src/backends/native/meta-kms-device.c
@@ -55,6 +55,12 @@ struct _MetaKmsDevice
 
 G_DEFINE_TYPE (MetaKmsDevice, meta_kms_device, G_TYPE_OBJECT);
 
+MetaKms *
+meta_kms_device_get_kms (MetaKmsDevice *device)
+{
+  return device->kms;
+}
+
 MetaKmsImplDevice *
 meta_kms_device_get_impl_device (MetaKmsDevice *device)
 {
diff --git a/src/backends/native/meta-kms-device.h b/src/backends/native/meta-kms-device.h
index bd2e856675..0b7c10273c 100644
--- a/src/backends/native/meta-kms-device.h
+++ b/src/backends/native/meta-kms-device.h
@@ -29,6 +29,8 @@ G_DECLARE_FINAL_TYPE (MetaKmsDevice, meta_kms_device,
                       META, KMS_DEVICE,
                       GObject)
 
+MetaKms * meta_kms_device_get_kms (MetaKmsDevice *device);
+
 int meta_kms_device_leak_fd (MetaKmsDevice *device);
 
 const char * meta_kms_device_get_path (MetaKmsDevice *device);
diff --git a/src/backends/native/meta-kms-update-private.h b/src/backends/native/meta-kms-update-private.h
index 8d67b3110d..30290c3be5 100644
--- a/src/backends/native/meta-kms-update-private.h
+++ b/src/backends/native/meta-kms-update-private.h
@@ -111,6 +111,8 @@ void meta_kms_update_seal (MetaKmsUpdate *update);
 
 gboolean meta_kms_update_is_sealed (MetaKmsUpdate *update);
 
+MetaKmsDevice * meta_kms_update_get_device (MetaKmsUpdate *update);
+
 void meta_kms_plane_assignment_set_rotation (MetaKmsPlaneAssignment *plane_assignment,
                                              uint64_t                rotation);
 
diff --git a/src/backends/native/meta-kms-update.c b/src/backends/native/meta-kms-update.c
index 8d9b4002e6..226ede0162 100644
--- a/src/backends/native/meta-kms-update.c
+++ b/src/backends/native/meta-kms-update.c
@@ -23,11 +23,15 @@
 #include "backends/native/meta-kms-update-private.h"
 
 #include "backends/meta-display-config-shared.h"
+#include "backends/native/meta-kms-crtc.h"
+#include "backends/native/meta-kms-connector.h"
 #include "backends/native/meta-kms-mode-private.h"
 #include "backends/native/meta-kms-plane.h"
 
 struct _MetaKmsUpdate
 {
+  MetaKmsDevice *device;
+
   gboolean is_sealed;
 
   MetaPowerSave power_save;
@@ -143,6 +147,8 @@ meta_kms_update_assign_plane (MetaKmsUpdate          *update,
   MetaKmsPlaneAssignment *plane_assignment;
 
   g_assert (!meta_kms_update_is_sealed (update));
+  g_assert (meta_kms_crtc_get_device (crtc) == update->device);
+  g_assert (meta_kms_plane_get_device (plane) == update->device);
 
   plane_assignment = g_new0 (MetaKmsPlaneAssignment, 1);
   *plane_assignment = (MetaKmsPlaneAssignment) {
@@ -169,6 +175,8 @@ meta_kms_update_unassign_plane (MetaKmsUpdate *update,
   MetaKmsPlaneAssignment *plane_assignment;
 
   g_assert (!meta_kms_update_is_sealed (update));
+  g_assert (meta_kms_crtc_get_device (crtc) == update->device);
+  g_assert (meta_kms_plane_get_device (plane) == update->device);
 
   plane_assignment = g_new0 (MetaKmsPlaneAssignment, 1);
   *plane_assignment = (MetaKmsPlaneAssignment) {
@@ -193,6 +201,7 @@ meta_kms_update_mode_set (MetaKmsUpdate *update,
   MetaKmsModeSet *mode_set;
 
   g_assert (!meta_kms_update_is_sealed (update));
+  g_assert (meta_kms_crtc_get_device (crtc) == update->device);
 
   mode_set = g_new0 (MetaKmsModeSet, 1);
   *mode_set = (MetaKmsModeSet) {
@@ -237,6 +246,7 @@ meta_kms_update_set_underscanning (MetaKmsUpdate    *update,
   MetaKmsConnectorUpdate *connector_update;
 
   g_assert (!meta_kms_update_is_sealed (update));
+  g_assert (meta_kms_connector_get_device (connector) == update->device);
 
   connector_update = ensure_connector_update (update, connector);
   connector_update->underscanning.has_update = TRUE;
@@ -252,6 +262,7 @@ meta_kms_update_unset_underscanning (MetaKmsUpdate    *update,
   MetaKmsConnectorUpdate *connector_update;
 
   g_assert (!meta_kms_update_is_sealed (update));
+  g_assert (meta_kms_connector_get_device (connector) == update->device);
 
   connector_update = ensure_connector_update (update, connector);
   connector_update->underscanning.has_update = TRUE;
@@ -266,6 +277,7 @@ meta_kms_update_set_dpms_state (MetaKmsUpdate    *update,
   MetaKmsConnectorUpdate *connector_update;
 
   g_assert (!meta_kms_update_is_sealed (update));
+  g_assert (meta_kms_connector_get_device (connector) == update->device);
 
   connector_update = ensure_connector_update (update, connector);
   connector_update->dpms.has_update = TRUE;
@@ -292,6 +304,7 @@ meta_kms_update_set_crtc_gamma (MetaKmsUpdate  *update,
   MetaKmsCrtcGamma *gamma;
 
   g_assert (!meta_kms_update_is_sealed (update));
+  g_assert (meta_kms_crtc_get_device (crtc) == update->device);
 
   gamma = g_new0 (MetaKmsCrtcGamma, 1);
   *gamma = (MetaKmsCrtcGamma) {
@@ -315,6 +328,7 @@ meta_kms_update_page_flip (MetaKmsUpdate                 *update,
   MetaKmsPageFlip *page_flip;
 
   g_assert (!meta_kms_update_is_sealed (update));
+  g_assert (meta_kms_crtc_get_device (crtc) == update->device);
 
   page_flip = g_new0 (MetaKmsPageFlip, 1);
   *page_flip = (MetaKmsPageFlip) {
@@ -338,6 +352,7 @@ meta_kms_update_custom_page_flip (MetaKmsUpdate                 *update,
   MetaKmsPageFlip *page_flip;
 
   g_assert (!meta_kms_update_is_sealed (update));
+  g_assert (meta_kms_crtc_get_device (crtc) == update->device);
 
   page_flip = g_new0 (MetaKmsPageFlip, 1);
   *page_flip = (MetaKmsPageFlip) {
@@ -430,10 +445,21 @@ meta_kms_update_is_sealed (MetaKmsUpdate *update)
   return update->is_sealed;
 }
 
+MetaKmsDevice *
+meta_kms_update_get_device (MetaKmsUpdate *update)
+{
+  return update->device;
+}
+
 MetaKmsUpdate *
-meta_kms_update_new (void)
+meta_kms_update_new (MetaKmsDevice *device)
 {
-  return g_new0 (MetaKmsUpdate, 1);
+  MetaKmsUpdate *update;
+
+  update = g_new0 (MetaKmsUpdate, 1);
+  update->device = device;
+
+  return update;
 }
 
 void
diff --git a/src/backends/native/meta-kms-update.h b/src/backends/native/meta-kms-update.h
index 71fc01271b..65b510f975 100644
--- a/src/backends/native/meta-kms-update.h
+++ b/src/backends/native/meta-kms-update.h
@@ -81,7 +81,7 @@ GList * meta_kms_feedback_get_failed_planes (MetaKmsFeedback *feedback);
 
 const GError * meta_kms_feedback_get_error (MetaKmsFeedback *feedback);
 
-MetaKmsUpdate * meta_kms_update_new (void);
+MetaKmsUpdate * meta_kms_update_new (MetaKmsDevice *device);
 
 void meta_kms_update_free (MetaKmsUpdate *update);
 
diff --git a/src/backends/native/meta-kms.c b/src/backends/native/meta-kms.c
index 957cc274e6..1a7afe2ada 100644
--- a/src/backends/native/meta-kms.c
+++ b/src/backends/native/meta-kms.c
@@ -95,7 +95,8 @@
  * posted. An update consists of plane assignments, mode sets and KMS object
  * property entries. The user adds updates to the object, and then posts it via
  * MetaKms. It will then be processed by the MetaKms backend (See
- * #MetaKmsImpl), potentially atomically.
+ * #MetaKmsImpl), potentially atomically. Each #MetaKmsUpdate deals with
+ * updating a single device.
  *
  *
  * There are also these private objects, without public facing API:
@@ -174,7 +175,7 @@ struct _MetaKms
 
   GList *devices;
 
-  MetaKmsUpdate *pending_update;
+  GList *pending_updates;
 
   GList *pending_callbacks;
   guint callback_source_id;
@@ -183,18 +184,36 @@ struct _MetaKms
 G_DEFINE_TYPE (MetaKms, meta_kms, G_TYPE_OBJECT)
 
 MetaKmsUpdate *
-meta_kms_ensure_pending_update (MetaKms *kms)
+meta_kms_ensure_pending_update (MetaKms       *kms,
+                                MetaKmsDevice *device)
 {
-  if (!kms->pending_update)
-    kms->pending_update = meta_kms_update_new ();
+  MetaKmsUpdate *update;
 
-  return meta_kms_get_pending_update (kms);
+  update = meta_kms_get_pending_update (kms, device);
+  if (update)
+    return update;
+
+  update = meta_kms_update_new (device);
+  kms->pending_updates = g_list_prepend (kms->pending_updates, update);
+
+  return update;
 }
 
 MetaKmsUpdate *
-meta_kms_get_pending_update (MetaKms *kms)
+meta_kms_get_pending_update (MetaKms       *kms,
+                             MetaKmsDevice *device)
 {
-  return kms->pending_update;
+  GList *l;
+
+  for (l = kms->pending_updates; l; l = l->next)
+    {
+      MetaKmsUpdate *update = l->data;
+
+      if (meta_kms_update_get_device (update) == device)
+        return update;
+    }
+
+  return NULL;
 }
 
 static void
@@ -208,40 +227,84 @@ meta_kms_predict_states_in_impl (MetaKms       *kms,
                   update);
 }
 
+static MetaKmsFeedback *
+combine_feedbacks (MetaKmsFeedback *feedback,
+                   MetaKmsFeedback *other_feedback)
+{
+  GList *failed_planes;
+  MetaKmsFeedback *new_feedback;
+  const GError *error;
+
+  if (!feedback)
+    return other_feedback;
+
+  failed_planes =
+    g_list_concat (meta_kms_feedback_get_failed_planes (feedback),
+                   meta_kms_feedback_get_failed_planes (other_feedback));
+  error = meta_kms_feedback_get_error (feedback);
+  if (!error)
+    error = meta_kms_feedback_get_error (other_feedback);
+
+  if (error)
+    {
+      new_feedback = meta_kms_feedback_new_failed (failed_planes,
+                                                   g_error_copy (error));
+    }
+  else
+    {
+      new_feedback = meta_kms_feedback_new_passed ();
+    }
+
+  meta_kms_feedback_free (feedback);
+  meta_kms_feedback_free (other_feedback);
+
+  return new_feedback;
+}
+
 static gpointer
-meta_kms_process_update_in_impl (MetaKmsImpl  *impl,
-                                 gpointer      user_data,
-                                 GError      **error)
+meta_kms_process_updates_in_impl (MetaKmsImpl  *impl,
+                                  gpointer      user_data,
+                                  GError      **error)
 {
-  g_autoptr (MetaKmsUpdate) update = user_data;
-  MetaKmsFeedback *feedback;
+  GList *updates = user_data;
+  MetaKmsFeedback *feedback = NULL;
+  GList *l;
+
+  for (l = updates; l; l = l->next)
+    {
+      MetaKmsUpdate *update = l->data;
+      MetaKmsFeedback *device_feedback;
+
+      device_feedback = meta_kms_impl_process_update (impl, update);
+      feedback = combine_feedbacks (feedback, device_feedback);
+      meta_kms_predict_states_in_impl (meta_kms_impl_get_kms (impl), update);
+    }
 
-  feedback = meta_kms_impl_process_update (impl, update);
-  meta_kms_predict_states_in_impl (meta_kms_impl_get_kms (impl), update);
+  g_list_free_full (updates, (GDestroyNotify) meta_kms_update_free);
 
   return feedback;
 }
 
 static MetaKmsFeedback *
-meta_kms_post_update_sync (MetaKms       *kms,
-                           MetaKmsUpdate *update)
+meta_kms_post_updates_sync (MetaKms *kms,
+                            GList   *updates)
 {
-  meta_kms_update_seal (update);
+  g_list_foreach (updates, (GFunc) meta_kms_update_seal, NULL);
 
   COGL_TRACE_BEGIN_SCOPED (MetaKmsPostUpdateSync,
                            "KMS (post update)");
 
   return meta_kms_run_impl_task_sync (kms,
-                                      meta_kms_process_update_in_impl,
-                                      update,
+                                      meta_kms_process_updates_in_impl,
+                                      updates,
                                       NULL);
 }
 
 MetaKmsFeedback *
-meta_kms_post_pending_update_sync (MetaKms *kms)
+meta_kms_post_pending_updates_sync (MetaKms *kms)
 {
-  return meta_kms_post_update_sync (kms,
-                                    g_steal_pointer (&kms->pending_update));
+  return meta_kms_post_updates_sync (kms,
+                                     g_steal_pointer (&kms->pending_updates));
 }
 
 static gpointer
diff --git a/src/backends/native/meta-kms.h b/src/backends/native/meta-kms.h
index ab25b70bd1..237ecbce90 100644
--- a/src/backends/native/meta-kms.h
+++ b/src/backends/native/meta-kms.h
@@ -28,11 +28,13 @@
 #define META_TYPE_KMS (meta_kms_get_type ())
 G_DECLARE_FINAL_TYPE (MetaKms, meta_kms, META, KMS, GObject)
 
-MetaKmsUpdate * meta_kms_ensure_pending_update (MetaKms *kms);
+MetaKmsUpdate * meta_kms_ensure_pending_update (MetaKms       *kms,
+                                                MetaKmsDevice *device);
 
-MetaKmsUpdate * meta_kms_get_pending_update (MetaKms *kms);
+MetaKmsUpdate * meta_kms_get_pending_update (MetaKms       *kms,
+                                             MetaKmsDevice *device);
 
-MetaKmsFeedback * meta_kms_post_pending_update_sync (MetaKms *kms);
+MetaKmsFeedback * meta_kms_post_pending_updates_sync (MetaKms *kms);
 
 void meta_kms_discard_pending_page_flips (MetaKms *kms);
 
diff --git a/src/backends/native/meta-monitor-manager-kms.c b/src/backends/native/meta-monitor-manager-kms.c
index aa3c927cb0..d6a40688af 100644
--- a/src/backends/native/meta-monitor-manager-kms.c
+++ b/src/backends/native/meta-monitor-manager-kms.c
@@ -120,7 +120,6 @@ meta_monitor_manager_kms_set_power_save_mode (MetaMonitorManager *manager,
   MetaBackend *backend = meta_monitor_manager_get_backend (manager);
   MetaBackendNative *backend_native = META_BACKEND_NATIVE (backend);
   MetaKms *kms = meta_backend_native_get_kms (backend_native);
-  MetaKmsUpdate *kms_update;
   uint64_t state;
   GList *l;
   g_autoptr (MetaKmsFeedback) kms_feedback = NULL;
@@ -142,15 +141,17 @@ meta_monitor_manager_kms_set_power_save_mode (MetaMonitorManager *manager,
     return;
   }
 
-  kms_update = meta_kms_ensure_pending_update (kms);
   for (l = meta_backend_get_gpus (backend); l; l = l->next)
     {
       MetaGpuKms *gpu_kms = l->data;
+      MetaKmsDevice *kms_device = meta_gpu_kms_get_kms_device (gpu_kms);
+      MetaKmsUpdate *kms_update;
 
+      kms_update = meta_kms_ensure_pending_update (kms, kms_device);
       meta_gpu_kms_set_power_save_mode (gpu_kms, state, kms_update);
     }
 
-  kms_feedback = meta_kms_post_pending_update_sync (kms);
+  kms_feedback = meta_kms_post_pending_updates_sync (kms);
   if (meta_kms_feedback_get_result (kms_feedback) != META_KMS_FEEDBACK_PASSED)
     {
       g_warning ("Failed to set DPMS: %s",
@@ -418,20 +419,21 @@ meta_monitor_manager_kms_set_crtc_gamma (MetaMonitorManager *manager,
   MetaBackendNative *backend_native = META_BACKEND_NATIVE (backend);
   MetaKms *kms = meta_backend_native_get_kms (backend_native);
   MetaKmsCrtc *kms_crtc;
-  g_autofree char *gamma_ramp_string = NULL;
+  MetaKmsDevice *kms_device;
   MetaKmsUpdate *kms_update;
+  g_autofree char *gamma_ramp_string = NULL;
   g_autoptr (MetaKmsFeedback) kms_feedback = NULL;
 
+  kms_crtc = meta_crtc_kms_get_kms_crtc (META_CRTC_KMS (crtc));
+  kms_device = meta_kms_crtc_get_device (kms_crtc);
+  kms_update = meta_kms_ensure_pending_update (kms, kms_device);
+  meta_kms_update_set_crtc_gamma (kms_update, kms_crtc, size, red, green, blue);
+
   gamma_ramp_string = generate_gamma_ramp_string (size, red, green, blue);
   g_debug ("Setting CRTC (%" G_GUINT64_FORMAT ") gamma to %s",
            meta_crtc_get_id (crtc), gamma_ramp_string);
 
-  kms_update = meta_kms_ensure_pending_update (kms);
-
-  kms_crtc = meta_crtc_kms_get_kms_crtc (META_CRTC_KMS (crtc));
-  meta_kms_update_set_crtc_gamma (kms_update, kms_crtc, size, red, green, blue);
-
-  kms_feedback = meta_kms_post_pending_update_sync (kms);
+  kms_feedback = meta_kms_post_pending_updates_sync (kms);
   if (meta_kms_feedback_get_result (kms_feedback) != META_KMS_FEEDBACK_PASSED)
     {
       g_warning ("Failed to set CRTC gamma: %s",
diff --git a/src/backends/native/meta-renderer-native.c b/src/backends/native/meta-renderer-native.c
index 06e698fb08..3cb68c8b07 100644
--- a/src/backends/native/meta-renderer-native.c
+++ b/src/backends/native/meta-renderer-native.c
@@ -1285,8 +1285,7 @@ static void
 meta_onscreen_native_flip_crtc (CoglOnscreen        *onscreen,
                                 MetaRendererView    *view,
                                 MetaCrtc            *crtc,
-                                MetaKmsPageFlipFlag  flags,
-                                MetaKmsUpdate       *kms_update)
+                                MetaKmsPageFlipFlag  flags)
 {
   CoglOnscreenEGL *onscreen_egl = onscreen->winsys;
   MetaOnscreenNative *onscreen_native = onscreen_egl->platform;
@@ -1295,10 +1294,16 @@ meta_onscreen_native_flip_crtc (CoglOnscreen        *onscreen,
   MetaCrtcKms *crtc_kms = META_CRTC_KMS (crtc);
   MetaRendererNativeGpuData *renderer_gpu_data;
   MetaGpuKms *gpu_kms;
+  MetaKmsDevice *kms_device;
+  MetaKms *kms;
+  MetaKmsUpdate *kms_update;
   MetaOnscreenNativeSecondaryGpuState *secondary_gpu_state = NULL;
   uint32_t fb_id;
 
   gpu_kms = META_GPU_KMS (meta_crtc_get_gpu (crtc));
+  kms_device = meta_gpu_kms_get_kms_device (gpu_kms);
+  kms = meta_kms_device_get_kms (kms_device);
+  kms_update = meta_kms_ensure_pending_update (kms, kms_device);
 
   g_assert (meta_gpu_kms_is_crtc_active (gpu_kms, crtc));
 
@@ -1340,16 +1345,21 @@ meta_onscreen_native_flip_crtc (CoglOnscreen        *onscreen,
 
 static void
 meta_onscreen_native_set_crtc_mode (CoglOnscreen              *onscreen,
-                                    MetaRendererNativeGpuData *renderer_gpu_data,
-                                    MetaKmsUpdate             *kms_update)
+                                    MetaRendererNativeGpuData *renderer_gpu_data)
 {
   CoglOnscreenEGL *onscreen_egl = onscreen->winsys;
   MetaOnscreenNative *onscreen_native = onscreen_egl->platform;
   MetaCrtcKms *crtc_kms = META_CRTC_KMS (onscreen_native->crtc);
+  MetaKmsCrtc *kms_crtc = meta_crtc_kms_get_kms_crtc (crtc_kms);
+  MetaKmsDevice *kms_device = meta_kms_crtc_get_device (kms_crtc);
+  MetaKms *kms = meta_kms_device_get_kms (kms_device);
+  MetaKmsUpdate *kms_update;
 
   COGL_TRACE_BEGIN_SCOPED (MetaOnscreenNativeSetCrtcModes,
                            "Onscreen (set CRTC modes)");
 
+  kms_update = meta_kms_ensure_pending_update (kms, kms_device);
+
   switch (renderer_gpu_data->mode)
     {
     case META_RENDERER_NATIVE_MODE_GBM:
@@ -1374,32 +1384,17 @@ meta_onscreen_native_set_crtc_mode (CoglOnscreen              *onscreen,
 
 static void
 meta_onscreen_native_flip_crtcs (CoglOnscreen        *onscreen,
-                                 MetaKmsPageFlipFlag  flags,
-                                 MetaKmsUpdate       *kms_update)
+                                 MetaKmsPageFlipFlag  flags)
 {
   CoglOnscreenEGL *onscreen_egl = onscreen->winsys;
   MetaOnscreenNative *onscreen_native = onscreen_egl->platform;
   MetaRendererView *view = onscreen_native->view;
-  MetaRendererNative *renderer_native = onscreen_native->renderer_native;
-  MetaRenderer *renderer = META_RENDERER (renderer_native);
-  MetaMonitorManager *monitor_manager =
-    meta_backend_get_monitor_manager (meta_renderer_get_backend (renderer));
-  MetaPowerSave power_save_mode;
 
   COGL_TRACE_BEGIN_SCOPED (MetaOnscreenNativeFlipCrtcs,
                            "Onscreen (flip CRTCs)");
 
-  power_save_mode = meta_monitor_manager_get_power_save_mode (monitor_manager);
-  if (power_save_mode == META_POWER_SAVE_ON)
-    {
-      meta_onscreen_native_flip_crtc (onscreen, view, onscreen_native->crtc,
-                                      flags,
-                                      kms_update);
-    }
-  else
-    {
-      queue_dummy_power_save_page_flip (onscreen);
-    }
+  meta_onscreen_native_flip_crtc (onscreen, view, onscreen_native->crtc,
+                                  flags);
 }
 
 static gboolean
@@ -1864,8 +1859,7 @@ retry:
 }
 
 static void
-ensure_crtc_modes (CoglOnscreen  *onscreen,
-                   MetaKmsUpdate *kms_update)
+ensure_crtc_modes (CoglOnscreen *onscreen)
 {
   CoglOnscreenEGL *onscreen_egl = onscreen->winsys;
   MetaOnscreenNative *onscreen_native = onscreen_egl->platform;
@@ -1874,29 +1868,19 @@ ensure_crtc_modes (CoglOnscreen  *onscreen,
   CoglRenderer *cogl_renderer = cogl_context->display->renderer;
   CoglRendererEGL *cogl_renderer_egl = cogl_renderer->winsys;
   MetaRendererNativeGpuData *renderer_gpu_data = cogl_renderer_egl->platform;
-  MetaRendererNative *renderer_native = renderer_gpu_data->renderer_native;
-  MetaRenderer *renderer = META_RENDERER (renderer_native);
-  MetaBackend *backend = meta_renderer_get_backend (renderer);
-  MetaMonitorManager *monitor_manager =
-    meta_backend_get_monitor_manager (backend);
-  MetaPowerSave power_save_mode;
 
-  power_save_mode = meta_monitor_manager_get_power_save_mode (monitor_manager);
-  if (onscreen_native->pending_set_crtc &&
-      power_save_mode == META_POWER_SAVE_ON)
+  if (onscreen_native->pending_set_crtc)
     {
-      meta_onscreen_native_set_crtc_mode (onscreen,
-                                          renderer_gpu_data,
-                                          kms_update);
+      meta_onscreen_native_set_crtc_mode (onscreen, renderer_gpu_data);
       onscreen_native->pending_set_crtc = FALSE;
     }
 }
 
-static MetaKmsUpdate *
+static gboolean
 unset_disabled_crtcs (MetaBackend *backend,
                       MetaKms     *kms)
 {
-  MetaKmsUpdate *kms_update = NULL;
+  gboolean did_mode_set = FALSE;
   GList *l;
 
   for (l = meta_backend_get_gpus (backend); l; l = l->next)
@@ -1907,24 +1891,30 @@ unset_disabled_crtcs (MetaBackend *backend,
       for (k = meta_gpu_get_crtcs (gpu); k; k = k->next)
         {
           MetaCrtc *crtc = k->data;
+          MetaKmsCrtc *kms_crtc =
+            meta_crtc_kms_get_kms_crtc (META_CRTC_KMS (crtc));
+          MetaKmsDevice *kms_device = meta_kms_crtc_get_device (kms_crtc);
+          MetaKmsUpdate *kms_update;
 
           if (meta_crtc_get_config (crtc))
             continue;
 
-          kms_update = meta_kms_ensure_pending_update (kms);
+          kms_update = meta_kms_ensure_pending_update (kms, kms_device);
           meta_crtc_kms_set_mode (META_CRTC_KMS (crtc), kms_update);
+
+          did_mode_set = TRUE;
         }
     }
 
-  return kms_update;
+  return did_mode_set;
 }
 
 static void
-post_pending_update (MetaKms *kms)
+post_pending_updates (MetaKms *kms)
 {
   g_autoptr (MetaKmsFeedback) kms_feedback = NULL;
 
-  kms_feedback = meta_kms_post_pending_update_sync (kms);
+  kms_feedback = meta_kms_post_pending_updates_sync (kms);
   if (meta_kms_feedback_get_result (kms_feedback) != META_KMS_FEEDBACK_PASSED)
     {
       const GError *error = meta_kms_feedback_get_error (kms_feedback);
@@ -1950,12 +1940,14 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen  *onscreen,
   MetaRenderer *renderer = META_RENDERER (renderer_native);
   MetaBackend *backend = meta_renderer_get_backend (renderer);
   MetaBackendNative *backend_native = META_BACKEND_NATIVE (backend);
+  MetaMonitorManager *monitor_manager =
+    meta_backend_get_monitor_manager (backend);
   MetaKms *kms = meta_backend_native_get_kms (backend_native);
   CoglOnscreenEGL *onscreen_egl = onscreen->winsys;
   MetaOnscreenNative *onscreen_native = onscreen_egl->platform;
   MetaGpuKms *render_gpu = onscreen_native->render_gpu;
   gboolean egl_context_changed = FALSE;
-  MetaKmsUpdate *kms_update;
+  MetaPowerSave power_save_mode;
   g_autoptr (GError) error = NULL;
   MetaDrmBufferGbm *buffer_gbm;
   g_autoptr (MetaKmsFeedback) kms_feedback = NULL;
@@ -1963,8 +1955,6 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen  *onscreen,
   COGL_TRACE_BEGIN_SCOPED (MetaRendererNativeSwapBuffers,
                            "Onscreen (swap-buffers)");
 
-  kms_update = meta_kms_ensure_pending_update (kms);
-
   update_secondary_gpu_state_pre_swap_buffers (onscreen);
 
   parent_vtable->onscreen_swap_buffers_with_damage (onscreen,
@@ -2003,10 +1993,17 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen  *onscreen,
 
   update_secondary_gpu_state_post_swap_buffers (onscreen, &egl_context_changed);
 
-  ensure_crtc_modes (onscreen, kms_update);
-  meta_onscreen_native_flip_crtcs (onscreen,
-                                   META_KMS_PAGE_FLIP_FLAG_NONE,
-                                   kms_update);
+  power_save_mode = meta_monitor_manager_get_power_save_mode (monitor_manager);
+  if (power_save_mode == META_POWER_SAVE_ON)
+    {
+      ensure_crtc_modes (onscreen);
+      meta_onscreen_native_flip_crtcs (onscreen, META_KMS_PAGE_FLIP_FLAG_NONE);
+    }
+  else
+    {
+      queue_dummy_power_save_page_flip (onscreen);
+      return;
+    }
 
   /*
    * If we changed EGL context, cogl will have the wrong idea about what is
@@ -2019,7 +2016,7 @@ meta_onscreen_native_swap_buffers_with_damage (CoglOnscreen  *onscreen,
 
   COGL_TRACE_BEGIN (MetaRendererNativePostKmsUpdate,
                     "Onscreen (post pending update)");
-  post_pending_update (kms);
+  post_pending_updates (kms);
   COGL_TRACE_END (MetaRendererNativePostKmsUpdate);
 }
 
@@ -2165,10 +2162,18 @@ meta_onscreen_native_direct_scanout (CoglOnscreen   *onscreen,
   MetaBackend *backend = meta_renderer_get_backend (renderer);
   MetaBackendNative *backend_native = META_BACKEND_NATIVE (backend);
   MetaKms *kms = meta_backend_native_get_kms (backend_native);
-  MetaKmsUpdate *kms_update;
+  MetaMonitorManager *monitor_manager =
+    meta_backend_get_monitor_manager (backend);
+  MetaPowerSave power_save_mode;
   g_autoptr (MetaKmsFeedback) kms_feedback = NULL;
 
-  kms_update = meta_kms_ensure_pending_update (kms);
+  power_save_mode = meta_monitor_manager_get_power_save_mode (monitor_manager);
+  if (power_save_mode != META_POWER_SAVE_ON)
+    {
+      g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+                   "Can't scanout directly while power saving");
+      return FALSE;
+    }
 
   renderer_gpu_data = meta_renderer_native_get_gpu_data (renderer_native,
                                                          render_gpu);
@@ -2178,12 +2183,11 @@ meta_onscreen_native_direct_scanout (CoglOnscreen   *onscreen,
 
   g_set_object (&onscreen_native->gbm.next_fb, META_DRM_BUFFER (scanout));
 
-  ensure_crtc_modes (onscreen, kms_update);
+  ensure_crtc_modes (onscreen);
   meta_onscreen_native_flip_crtcs (onscreen,
-                                   META_KMS_PAGE_FLIP_FLAG_NO_DISCARD_FEEDBACK,
-                                   kms_update);
+                                   META_KMS_PAGE_FLIP_FLAG_NO_DISCARD_FEEDBACK);
 
-  kms_feedback = meta_kms_post_pending_update_sync (kms);
+  kms_feedback = meta_kms_post_pending_updates_sync (kms);
   if (meta_kms_feedback_get_result (kms_feedback) != META_KMS_FEEDBACK_PASSED)
     {
       const GError *feedback_error = meta_kms_feedback_get_error (kms_feedback);
@@ -3159,16 +3163,16 @@ meta_renderer_native_finish_frame (MetaRendererNative *renderer_native)
   MetaBackend *backend = meta_renderer_get_backend (renderer);
   MetaBackendNative *backend_native = META_BACKEND_NATIVE (backend);
   MetaKms *kms = meta_backend_native_get_kms (backend_native);
-  MetaKmsUpdate *kms_update = NULL;
+  gboolean did_mode_set = FALSE;
 
   if (renderer_native->pending_unset_disabled_crtcs)
     {
-      kms_update = unset_disabled_crtcs (backend, kms);
+      did_mode_set = unset_disabled_crtcs (backend, kms);
       renderer_native->pending_unset_disabled_crtcs = FALSE;
     }
 
-  if (kms_update)
-    post_pending_update (kms);
+  if (did_mode_set)
+    post_pending_updates (kms);
 }
 
 static gboolean
@@ -3751,12 +3755,9 @@ meta_renderer_native_reset_modes (MetaRendererNative *renderer_native)
   MetaBackend *backend = meta_renderer_get_backend (renderer);
   MetaBackendNative *backend_native = META_BACKEND_NATIVE (backend);
   MetaKms *kms = meta_backend_native_get_kms (backend_native);
-  MetaKmsUpdate *kms_update;
-
-  kms_update = unset_disabled_crtcs (backend, kms);
 
-  if (kms_update)
-    post_pending_update (kms);
+  if (unset_disabled_crtcs (backend, kms))
+    post_pending_updates (kms);
 }
 
 static MetaGpuKms *


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