[mutter] wayland: Send presentation feedbacks to cursors



commit 82af1fb87ee7c32a0e788c08b78e415b703f8553
Author: Ivan Molodetskikh <yalterz gmail com>
Date:   Tue Feb 2 16:51:34 2021 +0300

    wayland: Send presentation feedbacks to cursors
    
    This commit assumes that cursor surfaces work in a "mailbox" fashion. If
    they are painted multiple times before a successful flip, all commits
    but the last get discarded, and the last commit gets presented after the
    flip succeeds. This is more or less how it works in the atomic backend,
    and also more or less how it works in other backends, with the exception
    that the cursor painting might fail without any way of knowing. This
    assumption is still better than unconditionally discarding all cursor
    surface feedbacks as if the cursor painting always fails.
    
    Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1484>

 src/wayland/meta-wayland-cursor-surface.c          |  8 +++
 .../meta-wayland-presentation-time-private.h       |  5 ++
 src/wayland/meta-wayland-presentation-time.c       | 65 +++++++++++++++++++---
 3 files changed, 69 insertions(+), 9 deletions(-)
---
diff --git a/src/wayland/meta-wayland-cursor-surface.c b/src/wayland/meta-wayland-cursor-surface.c
index a24f3a3be8..bece48b04a 100644
--- a/src/wayland/meta-wayland-cursor-surface.c
+++ b/src/wayland/meta-wayland-cursor-surface.c
@@ -30,6 +30,7 @@
 #include "core/boxes-private.h"
 #include "wayland/meta-cursor-sprite-wayland.h"
 #include "wayland/meta-wayland-buffer.h"
+#include "wayland/meta-wayland-presentation-time-private.h"
 #include "wayland/meta-wayland-private.h"
 #include "wayland/meta-xwayland.h"
 
@@ -340,6 +341,9 @@ on_cursor_painted (MetaCursorRenderer       *renderer,
   MetaWaylandCursorSurfacePrivate *priv =
     meta_wayland_cursor_surface_get_instance_private (cursor_surface);
   guint32 time = (guint32) (g_get_monotonic_time () / 1000);
+  MetaBackend *backend = meta_get_backend ();
+  MetaWaylandCompositor *compositor =
+    meta_backend_get_wayland_compositor (backend);
 
   if (displayed_sprite != META_CURSOR_SPRITE (priv->cursor_sprite))
     return;
@@ -352,6 +356,10 @@ on_cursor_painted (MetaCursorRenderer       *renderer,
       wl_callback_send_done (callback->resource, time);
       wl_resource_destroy (callback->resource);
     }
+
+  meta_wayland_presentation_time_cursor_painted (&compositor->presentation_time,
+                                                 stage_view,
+                                                 cursor_surface);
 }
 
 void
diff --git a/src/wayland/meta-wayland-presentation-time-private.h 
b/src/wayland/meta-wayland-presentation-time-private.h
index 0a1298bbf6..bc3dc6a40f 100644
--- a/src/wayland/meta-wayland-presentation-time-private.h
+++ b/src/wayland/meta-wayland-presentation-time-private.h
@@ -26,6 +26,7 @@
 #include <wayland-server.h>
 
 #include "clutter/clutter.h"
+#include "wayland/meta-wayland-cursor-surface.h"
 #include "wayland/meta-wayland-types.h"
 
 typedef struct _MetaWaylandPresentationFeedback
@@ -59,4 +60,8 @@ void meta_wayland_presentation_feedback_present (MetaWaylandPresentationFeedback
 struct wl_list * meta_wayland_presentation_time_ensure_feedbacks (MetaWaylandPresentationTime 
*presentation_time,
                                                                   ClutterStageView            *stage_view);
 
+void meta_wayland_presentation_time_cursor_painted (MetaWaylandPresentationTime *presentation_time,
+                                                    ClutterStageView            *stage_view,
+                                                    MetaWaylandCursorSurface    *cursor_surface);
+
 #endif /* META_WAYLAND_PRESENTATION_TIME_PRIVATE_H */
diff --git a/src/wayland/meta-wayland-presentation-time.c b/src/wayland/meta-wayland-presentation-time.c
index be1319fd9d..29650698cf 100644
--- a/src/wayland/meta-wayland-presentation-time.c
+++ b/src/wayland/meta-wayland-presentation-time.c
@@ -27,6 +27,7 @@
 #include <glib.h>
 
 #include "compositor/meta-surface-actor-wayland.h"
+#include "wayland/meta-wayland-cursor-surface.h"
 #include "wayland/meta-wayland-private.h"
 #include "wayland/meta-wayland-surface.h"
 #include "wayland/meta-wayland-outputs.h"
@@ -113,12 +114,14 @@ wp_presentation_bind (struct wl_client *client,
 }
 
 static void
-discard_feedbacks (struct wl_list *feedbacks)
+discard_non_cursor_feedbacks (struct wl_list *feedbacks)
 {
-  while (!wl_list_empty (feedbacks))
+  MetaWaylandPresentationFeedback *feedback, *next;
+
+  wl_list_for_each_safe (feedback, next, feedbacks, link)
     {
-      MetaWaylandPresentationFeedback *feedback =
-        wl_container_of (feedbacks->next, feedback, link);
+      if (META_IS_WAYLAND_CURSOR_SURFACE (feedback->surface->role))
+        continue;
 
       meta_wayland_presentation_feedback_discard (feedback);
     }
@@ -133,14 +136,19 @@ on_after_paint (ClutterStage          *stage,
   GList *l;
 
   /*
-   * We just painted this stage view, which means that all feedbacks that didn't
-   * fire (e.g. due to page flip failing) are now obsolete and should be
-   * discarded.
+   * We just painted this stage view, which means that all non-cursor feedbacks
+   * that didn't fire (e.g. due to page flip failing) are now obsolete and
+   * should be discarded.
+   *
+   * Cursor feedbacks have a similar mechanism done separately, mainly because
+   * they are painted earlier, in prepare_frame(). This means that the feedbacks
+   * list currently contains stale non-cursor feedbacks and up-to-date cursor
+   * feedbacks.
    */
   feedbacks =
     meta_wayland_presentation_time_ensure_feedbacks (&compositor->presentation_time,
                                                      stage_view);
-  discard_feedbacks (feedbacks);
+  discard_non_cursor_feedbacks (feedbacks);
 
   l = compositor->presentation_time.feedback_surfaces;
   while (l)
@@ -182,7 +190,14 @@ destroy_feedback_list (gpointer data)
 {
   struct wl_list *feedbacks = data;
 
-  discard_feedbacks (feedbacks);
+  while (!wl_list_empty (feedbacks))
+    {
+      MetaWaylandPresentationFeedback *feedback =
+        wl_container_of (feedbacks->next, feedback, link);
+
+      meta_wayland_presentation_feedback_discard (feedback);
+    }
+
   g_free (feedbacks);
 }
 
@@ -367,3 +382,35 @@ meta_wayland_presentation_time_ensure_feedbacks (MetaWaylandPresentationTime *pr
 
   return g_hash_table_lookup (presentation_time->feedbacks, stage_view);
 }
+
+void
+meta_wayland_presentation_time_cursor_painted (MetaWaylandPresentationTime *presentation_time,
+                                               ClutterStageView            *stage_view,
+                                               MetaWaylandCursorSurface    *cursor_surface)
+{
+  struct wl_list *feedbacks;
+  MetaWaylandPresentationFeedback *feedback, *next;
+  MetaWaylandSurfaceRole *role = META_WAYLAND_SURFACE_ROLE (cursor_surface);
+  MetaWaylandSurface *surface = meta_wayland_surface_role_get_surface (role);
+
+  feedbacks =
+    meta_wayland_presentation_time_ensure_feedbacks (presentation_time,
+                                                     stage_view);
+
+  /* Discard previous feedbacks for this cursor as now it has gone stale. */
+  wl_list_for_each_safe (feedback, next, feedbacks, link)
+    {
+      if (feedback->surface->role == role)
+        meta_wayland_presentation_feedback_discard (feedback);
+    }
+
+  /* Add new feedbacks. */
+  if (!wl_list_empty (&surface->presentation_time.feedback_list))
+    {
+      wl_list_insert_list (feedbacks,
+                           &surface->presentation_time.feedback_list);
+      wl_list_init (&surface->presentation_time.feedback_list);
+
+      surface->presentation_time.needs_sequence_update = TRUE;
+    }
+}


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