[mutter] kms/impl-simple: Add cursor plane processing



commit 7c3172a0afaebd181ae3582e01a5028d497599fb
Author: Jonas Ådahl <jadahl gmail com>
Date:   Sat Nov 9 00:17:33 2019 +0100

    kms/impl-simple: Add cursor plane processing
    
    A cursor plane can now be assigned, and for the simple KMS
    implementation, it'll translate into drmModeSetCursor() and
    drmModeMoveCursor() calls.
    
    When assignments failed, the cursor planes that failed to be assigned
    are communicated via the feedback object.
    
    https://gitlab.gnome.org/GNOME/mutter/merge_requests/930

 src/backends/native/meta-kms-impl-simple.c    | 168 +++++++++++++++++++++++++-
 src/backends/native/meta-kms-update-private.h |  13 +-
 src/backends/native/meta-kms-update.c         |  36 +++++-
 src/backends/native/meta-kms-update.h         |  10 ++
 4 files changed, 219 insertions(+), 8 deletions(-)
---
diff --git a/src/backends/native/meta-kms-impl-simple.c b/src/backends/native/meta-kms-impl-simple.c
index c3a9698ba..2b6df146a 100644
--- a/src/backends/native/meta-kms-impl-simple.c
+++ b/src/backends/native/meta-kms-impl-simple.c
@@ -747,11 +747,156 @@ process_entries (MetaKmsImpl     *impl,
   return TRUE;
 }
 
+static gboolean
+process_cursor_plane_assignment (MetaKmsImpl             *impl,
+                                 MetaKmsUpdate           *update,
+                                 MetaKmsPlaneAssignment  *plane_assignment,
+                                 GError                 **error)
+{
+  MetaKmsPlane *plane;
+  MetaKmsDevice *device;
+  MetaKmsImplDevice *impl_device;
+  int fd;
+
+  plane = plane_assignment->plane;
+  device = meta_kms_plane_get_device (plane);
+  impl_device = meta_kms_device_get_impl_device (device);
+  fd = meta_kms_impl_device_get_fd (impl_device);
+
+  if (!(plane_assignment->flags & META_KMS_ASSIGN_PLANE_FLAG_FB_UNCHANGED))
+    {
+      int width, height;
+      int ret;
+
+      width = meta_fixed_16_to_int (plane_assignment->dst_rect.width);
+      height = meta_fixed_16_to_int (plane_assignment->dst_rect.height);
+
+      ret = drmModeSetCursor (fd, meta_kms_crtc_get_id (plane_assignment->crtc),
+                              plane_assignment->fb_id,
+                              width, height);
+      if (ret != 0)
+        {
+          g_set_error (error, G_IO_ERROR, g_io_error_from_errno (-ret),
+                       "drmModeSetCursor failed: %s", g_strerror (-ret));
+          return FALSE;
+        }
+    }
+
+  drmModeMoveCursor (fd,
+                     meta_kms_crtc_get_id (plane_assignment->crtc),
+                     meta_fixed_16_to_int (plane_assignment->dst_rect.x),
+                     meta_fixed_16_to_int (plane_assignment->dst_rect.y));
+
+  return TRUE;
+}
+
+static gboolean
+process_plane_assignment (MetaKmsImpl             *impl,
+                          MetaKmsUpdate           *update,
+                          MetaKmsPlaneAssignment  *plane_assignment,
+                          MetaKmsPlaneFeedback   **plane_feedback)
+{
+  MetaKmsPlane *plane;
+  MetaKmsPlaneType plane_type;
+  GError *error = NULL;
+
+  plane = plane_assignment->plane;
+  plane_type = meta_kms_plane_get_plane_type (plane);
+  switch (plane_type)
+    {
+    case META_KMS_PLANE_TYPE_PRIMARY:
+      /* Handled as part of the mode-set and page flip. */
+      return TRUE;
+    case META_KMS_PLANE_TYPE_CURSOR:
+      if (!process_cursor_plane_assignment (impl, update,
+                                            plane_assignment,
+                                            &error))
+        {
+          *plane_feedback =
+            meta_kms_plane_feedback_new_take_error (plane,
+                                                    plane_assignment->crtc,
+                                                    g_steal_pointer (&error));
+          return FALSE;
+        }
+      else
+        {
+          return TRUE;
+        }
+    case META_KMS_PLANE_TYPE_OVERLAY:
+      error = g_error_new_literal (G_IO_ERROR, G_IO_ERROR_FAILED,
+                                   "Overlay planes cannot be assigned");
+      *plane_feedback =
+        meta_kms_plane_feedback_new_take_error (plane,
+                                                plane_assignment->crtc,
+                                                g_steal_pointer (&error));
+      return TRUE;
+    }
+
+  g_assert_not_reached ();
+}
+
+static GList *
+process_plane_assignments (MetaKmsImpl   *impl,
+                           MetaKmsUpdate *update)
+{
+  GList *failed_planes = NULL;
+  GList *l;
+
+  for (l = meta_kms_update_get_plane_assignments (update); l; l = l->next)
+    {
+      MetaKmsPlaneAssignment *plane_assignment = l->data;
+      MetaKmsPlaneFeedback *plane_feedback;
+
+      if (!process_plane_assignment (impl, update, plane_assignment,
+                                     &plane_feedback))
+        failed_planes = g_list_prepend (failed_planes, plane_feedback);
+    }
+
+  return failed_planes;
+}
+
+static GList *
+generate_all_failed_feedbacks (MetaKmsUpdate *update)
+{
+  GList *failed_planes = NULL;
+  GList *l;
+
+  for (l = meta_kms_update_get_plane_assignments (update); l; l = l->next)
+    {
+      MetaKmsPlaneAssignment *plane_assignment = l->data;
+      MetaKmsPlane *plane;
+      MetaKmsPlaneType plane_type;
+      MetaKmsPlaneFeedback *plane_feedback;
+
+      plane = plane_assignment->plane;
+      plane_type = meta_kms_plane_get_plane_type (plane);
+      switch (plane_type)
+        {
+        case META_KMS_PLANE_TYPE_PRIMARY:
+          continue;
+        case META_KMS_PLANE_TYPE_CURSOR:
+        case META_KMS_PLANE_TYPE_OVERLAY:
+          break;
+        }
+
+      plane_feedback =
+        meta_kms_plane_feedback_new_take_error (plane_assignment->plane,
+                                                plane_assignment->crtc,
+                                                g_error_new (G_IO_ERROR,
+                                                             G_IO_ERROR_FAILED,
+                                                             "Discarded"));
+      failed_planes = g_list_prepend (failed_planes, plane_feedback);
+    }
+
+  return failed_planes;
+}
+
 static MetaKmsFeedback *
 meta_kms_impl_simple_process_update (MetaKmsImpl   *impl,
                                      MetaKmsUpdate *update)
 {
   GError *error = NULL;
+  GList *failed_planes;
   GList *l;
 
   meta_assert_in_kms_impl (meta_kms_impl_get_kms (impl));
@@ -761,32 +906,43 @@ meta_kms_impl_simple_process_update (MetaKmsImpl   *impl,
                         meta_kms_update_get_connector_properties (update),
                         process_connector_property,
                         &error))
-    goto discard_page_flips;
+    goto err_planes_not_assigned;
 
   if (!process_entries (impl,
                         update,
                         meta_kms_update_get_mode_sets (update),
                         process_mode_set,
                         &error))
-    goto discard_page_flips;
+    goto err_planes_not_assigned;
 
   if (!process_entries (impl,
                         update,
                         meta_kms_update_get_crtc_gammas (update),
                         process_crtc_gamma,
                         &error))
-    goto discard_page_flips;
+    goto err_planes_not_assigned;
+
+  failed_planes = process_plane_assignments (impl, update);
+  if (failed_planes)
+    {
+      g_set_error (&error, G_IO_ERROR, G_IO_ERROR_FAILED,
+                   "Failed to assign one or more planes");
+      goto err_planes_assigned;
+    }
 
   if (!process_entries (impl,
                         update,
                         meta_kms_update_get_page_flips (update),
                         process_page_flip,
                         &error))
-    goto discard_page_flips;
+    goto err_planes_assigned;
 
   return meta_kms_feedback_new_passed ();
 
-discard_page_flips:
+err_planes_not_assigned:
+  failed_planes = generate_all_failed_feedbacks (update);
+
+err_planes_assigned:
   for (l = meta_kms_update_get_page_flips (update); l; l = l->next)
     {
       MetaKmsPageFlip *page_flip = l->data;
@@ -794,7 +950,7 @@ discard_page_flips:
       discard_page_flip (impl, update, page_flip);
     }
 
-  return meta_kms_feedback_new_failed (error);
+  return meta_kms_feedback_new_failed (failed_planes, error);
 }
 
 static void
diff --git a/src/backends/native/meta-kms-update-private.h b/src/backends/native/meta-kms-update-private.h
index f1046fb22..91a1de6dc 100644
--- a/src/backends/native/meta-kms-update-private.h
+++ b/src/backends/native/meta-kms-update-private.h
@@ -30,6 +30,7 @@ typedef struct _MetaKmsFeedback
 {
   MetaKmsFeedbackResult result;
 
+  GList *failed_planes;
   GError *error;
 } MetaKmsFeedback;
 
@@ -85,9 +86,16 @@ typedef struct _MetaKmsPageFlip
   gpointer custom_page_flip_user_data;
 } MetaKmsPageFlip;
 
+void meta_kms_plane_feedback_free (MetaKmsPlaneFeedback *plane_feedback);
+
+MetaKmsPlaneFeedback * meta_kms_plane_feedback_new_take_error (MetaKmsPlane *plane,
+                                                               MetaKmsCrtc  *crtc,
+                                                               GError       *error);
+
 MetaKmsFeedback * meta_kms_feedback_new_passed (void);
 
-MetaKmsFeedback * meta_kms_feedback_new_failed (GError *error);
+MetaKmsFeedback * meta_kms_feedback_new_failed (GList  *failed_planes,
+                                                GError *error);
 
 void meta_kms_update_seal (MetaKmsUpdate *update);
 
@@ -122,4 +130,7 @@ GList * meta_kms_update_get_connector_properties (MetaKmsUpdate *update);
 
 GList * meta_kms_update_get_crtc_gammas (MetaKmsUpdate *update);
 
+G_DEFINE_AUTOPTR_CLEANUP_FUNC (MetaKmsPlaneFeedback,
+                               meta_kms_plane_feedback_free)
+
 #endif /* META_KMS_UPDATE_PRIVATE_H */
diff --git a/src/backends/native/meta-kms-update.c b/src/backends/native/meta-kms-update.c
index ffabc948f..0371782b7 100644
--- a/src/backends/native/meta-kms-update.c
+++ b/src/backends/native/meta-kms-update.c
@@ -37,6 +37,30 @@ struct _MetaKmsUpdate
   GList *crtc_gammas;
 };
 
+void
+meta_kms_plane_feedback_free (MetaKmsPlaneFeedback *plane_feedback)
+{
+  g_error_free (plane_feedback->error);
+  g_free (plane_feedback);
+}
+
+MetaKmsPlaneFeedback *
+meta_kms_plane_feedback_new_take_error (MetaKmsPlane *plane,
+                                        MetaKmsCrtc  *crtc,
+                                        GError       *error)
+{
+  MetaKmsPlaneFeedback *plane_feedback;
+
+  plane_feedback = g_new0 (MetaKmsPlaneFeedback, 1);
+  *plane_feedback = (MetaKmsPlaneFeedback) {
+    .plane = plane,
+    .crtc = crtc,
+    .error = error,
+  };
+
+  return plane_feedback;
+}
+
 MetaKmsFeedback *
 meta_kms_feedback_new_passed (void)
 {
@@ -51,7 +75,8 @@ meta_kms_feedback_new_passed (void)
 }
 
 MetaKmsFeedback *
-meta_kms_feedback_new_failed (GError *error)
+meta_kms_feedback_new_failed (GList  *failed_planes,
+                              GError *error)
 {
   MetaKmsFeedback *feedback;
 
@@ -59,6 +84,7 @@ meta_kms_feedback_new_failed (GError *error)
   *feedback = (MetaKmsFeedback) {
     .result = META_KMS_FEEDBACK_FAILED,
     .error = error,
+    .failed_planes = failed_planes,
   };
 
   return feedback;
@@ -67,6 +93,8 @@ meta_kms_feedback_new_failed (GError *error)
 void
 meta_kms_feedback_free (MetaKmsFeedback *feedback)
 {
+  g_list_free_full (feedback->failed_planes,
+                    (GDestroyNotify) meta_kms_plane_feedback_free);
   g_clear_error (&feedback->error);
   g_free (feedback);
 }
@@ -77,6 +105,12 @@ meta_kms_feedback_get_result (MetaKmsFeedback *feedback)
   return feedback->result;
 }
 
+GList *
+meta_kms_feedback_get_failed_planes (MetaKmsFeedback *feedback)
+{
+  return feedback->failed_planes;
+}
+
 const GError *
 meta_kms_feedback_get_error (MetaKmsFeedback *feedback)
 {
diff --git a/src/backends/native/meta-kms-update.h b/src/backends/native/meta-kms-update.h
index 9f92050e3..cd1822e4a 100644
--- a/src/backends/native/meta-kms-update.h
+++ b/src/backends/native/meta-kms-update.h
@@ -38,6 +38,7 @@ typedef enum _MetaKmsFeedbackResult
 typedef enum _MetaKmsAssignPlaneFlag
 {
   META_KMS_ASSIGN_PLANE_FLAG_NONE = 0,
+  META_KMS_ASSIGN_PLANE_FLAG_FB_UNCHANGED = 1 << 0,
 } MetaKmsAssignPlaneFlag;
 
 struct _MetaKmsPageFlipFeedback
@@ -59,10 +60,19 @@ struct _MetaKmsPageFlipFeedback
 typedef int (* MetaKmsCustomPageFlipFunc) (gpointer custom_page_flip_data,
                                            gpointer user_data);
 
+typedef struct _MetaKmsPlaneFeedback
+{
+  MetaKmsPlane *plane;
+  MetaKmsCrtc *crtc;
+  GError *error;
+} MetaKmsPlaneFeedback;
+
 void meta_kms_feedback_free (MetaKmsFeedback *feedback);
 
 MetaKmsFeedbackResult meta_kms_feedback_get_result (MetaKmsFeedback *feedback);
 
+GList * meta_kms_feedback_get_failed_planes (MetaKmsFeedback *feedback);
+
 const GError * meta_kms_feedback_get_error (MetaKmsFeedback *feedback);
 
 MetaKmsUpdate * meta_kms_update_new (void);


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