[mutter] wayland: Wire up presentation-time machinery



commit 2ce3a050f02c3424f35c09cfb90cf80121a9bdb7
Author: Ivan Molodetskikh <yalterz gmail com>
Date:   Thu Oct 8 15:34:28 2020 +0300

    wayland: Wire up presentation-time machinery
    
    - add surfaces to the presentation list,
    - move their feedbacks to the map in on-after-update,
    - fire the feedbacks in on_presented().
    
    Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1484>

 src/wayland/meta-wayland-presentation-time.c | 69 ++++++++++++++++++++++++++--
 src/wayland/meta-wayland-surface.c           |  6 +++
 src/wayland/meta-wayland.c                   | 48 +++++++++++++++++++
 3 files changed, 120 insertions(+), 3 deletions(-)
---
diff --git a/src/wayland/meta-wayland-presentation-time.c b/src/wayland/meta-wayland-presentation-time.c
index 54351690ac..be1319fd9d 100644
--- a/src/wayland/meta-wayland-presentation-time.c
+++ b/src/wayland/meta-wayland-presentation-time.c
@@ -26,6 +26,7 @@
 
 #include <glib.h>
 
+#include "compositor/meta-surface-actor-wayland.h"
 #include "wayland/meta-wayland-private.h"
 #include "wayland/meta-wayland-surface.h"
 #include "wayland/meta-wayland-outputs.h"
@@ -112,10 +113,8 @@ wp_presentation_bind (struct wl_client *client,
 }
 
 static void
-destroy_feedback_list (gpointer data)
+discard_feedbacks (struct wl_list *feedbacks)
 {
-  struct wl_list *feedbacks = data;
-
   while (!wl_list_empty (feedbacks))
     {
       MetaWaylandPresentationFeedback *feedback =
@@ -123,7 +122,67 @@ destroy_feedback_list (gpointer data)
 
       meta_wayland_presentation_feedback_discard (feedback);
     }
+}
+
+static void
+on_after_paint (ClutterStage          *stage,
+                ClutterStageView      *stage_view,
+                MetaWaylandCompositor *compositor)
+{
+  struct wl_list *feedbacks;
+  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.
+   */
+  feedbacks =
+    meta_wayland_presentation_time_ensure_feedbacks (&compositor->presentation_time,
+                                                     stage_view);
+  discard_feedbacks (feedbacks);
+
+  l = compositor->presentation_time.feedback_surfaces;
+  while (l)
+    {
+      GList *l_cur = l;
+      MetaWaylandSurface *surface = l->data;
+      MetaSurfaceActor *actor;
+      ClutterStageView *surface_primary_view;
+
+      l = l->next;
+
+      actor = meta_wayland_surface_get_actor (surface);
+      if (!actor)
+        continue;
+
+      surface_primary_view =
+        meta_surface_actor_wayland_get_current_primary_view (actor, stage);
+      if (stage_view != surface_primary_view)
+        continue;
+
+      if (!wl_list_empty (&surface->presentation_time.feedback_list))
+        {
+          /* Add feedbacks to the list to be fired on presentation. */
+          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;
+        }
+
+      compositor->presentation_time.feedback_surfaces =
+        g_list_delete_link (compositor->presentation_time.feedback_surfaces,
+                            l_cur);
+    }
+}
 
+static void
+destroy_feedback_list (gpointer data)
+{
+  struct wl_list *feedbacks = data;
+
+  discard_feedbacks (feedbacks);
   g_free (feedbacks);
 }
 
@@ -141,6 +200,7 @@ meta_wayland_init_presentation_time (MetaWaylandCompositor *compositor)
   MetaBackend *backend = compositor->backend;
   MetaMonitorManager *monitor_manager =
     meta_backend_get_monitor_manager (backend);
+  ClutterActor *stage = meta_backend_get_stage (backend);
 
   compositor->presentation_time.feedbacks =
     g_hash_table_new_full (NULL, NULL, NULL, destroy_feedback_list);
@@ -148,6 +208,9 @@ meta_wayland_init_presentation_time (MetaWaylandCompositor *compositor)
   g_signal_connect (monitor_manager, "monitors-changed-internal",
                     G_CALLBACK (on_monitors_changed), compositor);
 
+  g_signal_connect (stage, "after-paint",
+                    G_CALLBACK (on_after_paint), compositor);
+
   if (wl_global_create (compositor->wayland_display,
                         &wp_presentation_interface,
                         META_WP_PRESENTATION_VERSION,
diff --git a/src/wayland/meta-wayland-surface.c b/src/wayland/meta-wayland-surface.c
index db0d7f2f31..962ab05ff3 100644
--- a/src/wayland/meta-wayland-surface.c
+++ b/src/wayland/meta-wayland-surface.c
@@ -799,6 +799,10 @@ meta_wayland_surface_apply_state (MetaWaylandSurface      *surface,
                        &state->presentation_feedback_list);
   wl_list_init (&state->presentation_feedback_list);
 
+  if (!wl_list_empty (&surface->presentation_time.feedback_list))
+    meta_wayland_compositor_add_presentation_feedback_surface (surface->compositor,
+                                                               surface);
+
   if (surface->role)
     {
       meta_wayland_surface_role_apply_state (surface->role, state);
@@ -1390,6 +1394,8 @@ wl_surface_destructor (struct wl_resource *resource)
     cairo_region_destroy (surface->input_region);
 
   meta_wayland_compositor_remove_frame_callback_surface (compositor, surface);
+  meta_wayland_compositor_remove_presentation_feedback_surface (compositor,
+                                                                surface);
 
   g_hash_table_foreach (surface->outputs,
                         surface_output_disconnect_signals,
diff --git a/src/wayland/meta-wayland.c b/src/wayland/meta-wayland.c
index 731e247273..b032a8bfce 100644
--- a/src/wayland/meta-wayland.c
+++ b/src/wayland/meta-wayland.c
@@ -230,6 +230,52 @@ on_after_update (ClutterStage          *stage,
     }
 }
 
+static MetaWaylandOutput *
+get_output_for_stage_view (MetaWaylandCompositor *compositor,
+                           ClutterStageView      *stage_view)
+{
+  MetaCrtc *crtc;
+  MetaOutput *output;
+  MetaMonitor *monitor;
+  MetaLogicalMonitor *logical_monitor;
+
+  crtc = meta_renderer_view_get_crtc (META_RENDERER_VIEW (stage_view));
+
+  /*
+   * All outputs occupy the same region of the screen, as their contents are
+   * the same, so pick the first one.
+   */
+  output = meta_crtc_get_outputs (crtc)->data;
+
+  monitor = meta_output_get_monitor (output);
+  logical_monitor = meta_monitor_get_logical_monitor (monitor);
+  return g_hash_table_lookup (compositor->outputs, &logical_monitor->winsys_id);
+}
+
+static void
+on_presented (ClutterStage          *stage,
+              ClutterStageView      *stage_view,
+              ClutterFrameInfo      *frame_info,
+              MetaWaylandCompositor *compositor)
+{
+  MetaWaylandPresentationFeedback *feedback, *next;
+  struct wl_list *feedbacks;
+  MetaWaylandOutput *output;
+
+  feedbacks =
+    meta_wayland_presentation_time_ensure_feedbacks (&compositor->presentation_time,
+                                                     stage_view);
+
+  output = get_output_for_stage_view (compositor, stage_view);
+
+  wl_list_for_each_safe (feedback, next, feedbacks, link)
+    {
+      meta_wayland_presentation_feedback_present (feedback,
+                                                  frame_info,
+                                                  output);
+    }
+}
+
 /**
  * meta_wayland_compositor_handle_event:
  * @compositor: the #MetaWaylandCompositor instance
@@ -438,6 +484,8 @@ meta_wayland_compositor_setup (MetaWaylandCompositor *compositor)
 
   g_signal_connect (stage, "after-update",
                     G_CALLBACK (on_after_update), compositor);
+  g_signal_connect (stage, "presented",
+                    G_CALLBACK (on_presented), compositor);
 
   if (!wl_global_create (compositor->wayland_display,
                         &wl_compositor_interface,


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