[mutter] compositor/native: Add support for direct scanout per view



commit 4736f873f216d4cfb5e5eb06ea4c69fc95fa25a6
Author: Dor Askayo <dor askayo gmail com>
Date:   Tue Jul 12 11:35:33 2022 +0300

    compositor/native: Add support for direct scanout per view
    
    This uses MetaCompositorViewNative to find a candidate surface for
    scanout and to keep track of it separately for each view, effectively
    allowing each CRTC to use a different buffer for direct scanout.
    
    There are three parts for potentially assigning a buffer for direct
    scanout at the compositor level:
      1. Finding a candidate surface actor on the view (if any)
      2. Attempting to assign the candidate's buffer for direct scanout
      3. Updating references relating to the scanout candidate as needed
    
    The three parts were moved in their entirety from being handled by the
    MetaCompositorNative to being handled by the MetaCompositorViewNative.
    As part of this transition, the logic was also slightly refactored so
    that each of the three parts is handled by its own helper function.
    This allowed to avoid the use of "goto" statements and hopefully make
    the logic easier to read and follow.
    
    The first part mentioned above was changed in this commit to make use
    of the new meta_compositor_view_get_top_window_actor () API to get the
    top window actor in the view instead of the top window actor on all
    views.
    
    The second part and third parts mentioned above weren't changed other
    than being done in the context of a view instead of globally.
    
    Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2526>

 src/compositor/meta-compositor-native.c      | 145 +----------------------
 src/compositor/meta-compositor-view-native.c | 167 +++++++++++++++++++++++++++
 src/compositor/meta-compositor-view-native.h |   6 +
 3 files changed, 177 insertions(+), 141 deletions(-)
---
diff --git a/src/compositor/meta-compositor-native.c b/src/compositor/meta-compositor-native.c
index cc635d48cb..e2e512494f 100644
--- a/src/compositor/meta-compositor-native.c
+++ b/src/compositor/meta-compositor-native.c
@@ -22,151 +22,27 @@
 
 #include "compositor/meta-compositor-native.h"
 
-#include "backends/meta-logical-monitor.h"
-#include "backends/native/meta-crtc-kms.h"
 #include "compositor/meta-compositor-view-native.h"
-#include "compositor/meta-surface-actor-wayland.h"
 
 struct _MetaCompositorNative
 {
   MetaCompositorServer parent;
-
-  MetaWaylandSurface *current_scanout_candidate;
 };
 
 G_DEFINE_TYPE (MetaCompositorNative, meta_compositor_native,
                META_TYPE_COMPOSITOR_SERVER)
 
-#ifdef HAVE_WAYLAND
-
-static MetaRendererView *
-get_window_view (MetaRenderer *renderer,
-                 MetaWindow   *window)
-{
-  GList *l;
-  MetaRendererView *view_found = NULL;
-
-  for (l = meta_renderer_get_views (renderer); l; l = l->next)
-    {
-      ClutterStageView *stage_view = l->data;
-      MetaRectangle view_layout;
-
-      clutter_stage_view_get_layout (stage_view, &view_layout);
-
-      if (meta_rectangle_equal (&window->buffer_rect,
-                                &view_layout))
-        {
-          if (view_found)
-            return NULL;
-          view_found = META_RENDERER_VIEW (stage_view);
-        }
-    }
-
-  return view_found;
-}
-
-static void
-maybe_assign_primary_plane (MetaCompositor *compositor)
-{
-  MetaCompositorNative *compositor_native = META_COMPOSITOR_NATIVE (compositor);
-  MetaBackend *backend = meta_get_backend ();
-  MetaRenderer *renderer = meta_backend_get_renderer (backend);
-  MetaWindowActor *window_actor;
-  MetaWindow *window;
-  MetaRendererView *view;
-  MetaCrtc *crtc;
-  CoglFramebuffer *framebuffer;
-  CoglOnscreen *onscreen;
-  MetaSurfaceActor *surface_actor;
-  MetaSurfaceActorWayland *surface_actor_wayland;
-  MetaWaylandSurface *surface;
-  int geometry_scale;
-  MetaWaylandSurface *old_candidate =
-    compositor_native->current_scanout_candidate;
-  MetaWaylandSurface *new_candidate = NULL;
-  g_autoptr (CoglScanout) scanout = NULL;
-
-  if (meta_compositor_is_unredirect_inhibited (compositor))
-    goto done;
-
-  window_actor = meta_compositor_get_top_window_actor (compositor);
-  if (!window_actor)
-    goto done;
-
-  if (meta_window_actor_effect_in_progress (window_actor))
-    goto done;
-
-  if (clutter_actor_has_transitions (CLUTTER_ACTOR (window_actor)))
-    goto done;
-
-  window = meta_window_actor_get_meta_window (window_actor);
-  if (!window)
-    goto done;
-
-  view = get_window_view (renderer, window);
-  if (!view)
-    goto done;
-
-  crtc = meta_renderer_view_get_crtc (META_RENDERER_VIEW (view));
-  if (!META_IS_CRTC_KMS (crtc))
-    goto done;
-
-  framebuffer = clutter_stage_view_get_framebuffer (CLUTTER_STAGE_VIEW (view));
-  if (!COGL_IS_ONSCREEN (framebuffer))
-    goto done;
-
-  surface_actor = meta_window_actor_get_scanout_candidate (window_actor);
-  if (!surface_actor)
-    goto done;
-
-  if (meta_surface_actor_is_obscured (surface_actor))
-    goto done;
-
-  surface_actor_wayland = META_SURFACE_ACTOR_WAYLAND (surface_actor);
-  surface = meta_surface_actor_wayland_get_surface (surface_actor_wayland);
-  if (!surface)
-    goto done;
-
-  geometry_scale = meta_window_actor_get_geometry_scale (window_actor);
-  if (!meta_wayland_surface_can_scanout_untransformed (surface, view,
-                                                       geometry_scale))
-    goto done;
-
-  new_candidate = surface;
-
-  onscreen = COGL_ONSCREEN (framebuffer);
-  scanout = meta_wayland_surface_try_acquire_scanout (surface,
-                                                      onscreen);
-  if (!scanout)
-    goto done;
-
-  clutter_stage_view_assign_next_scanout (CLUTTER_STAGE_VIEW (view), scanout);
-
-done:
-
-  if (old_candidate && old_candidate != new_candidate)
-    {
-      meta_wayland_surface_set_scanout_candidate (old_candidate, NULL);
-      g_clear_weak_pointer (&compositor_native->current_scanout_candidate);
-    }
-
-  if (new_candidate)
-    {
-      meta_wayland_surface_set_scanout_candidate (surface, crtc);
-      g_set_weak_pointer (&compositor_native->current_scanout_candidate,
-                          surface);
-    }
-}
-#endif /* HAVE_WAYLAND */
-
 static void
 meta_compositor_native_before_paint (MetaCompositor     *compositor,
                                      MetaCompositorView *compositor_view)
 {
+  MetaCompositorViewNative *compositor_view_native =
+    META_COMPOSITOR_VIEW_NATIVE (compositor_view);
   MetaCompositorClass *parent_class;
 
 #ifdef HAVE_WAYLAND
-  maybe_assign_primary_plane (compositor);
+  meta_compositor_view_native_maybe_assign_scanout (compositor_view_native,
+                                                    compositor);
 #endif
 
   parent_class = META_COMPOSITOR_CLASS (meta_compositor_native_parent_class);
@@ -194,16 +70,6 @@ meta_compositor_native_new (MetaDisplay *display,
                        NULL);
 }
 
-static void
-meta_compositor_native_finalize (GObject *object)
-{
-  MetaCompositorNative *compositor_native = META_COMPOSITOR_NATIVE (object);
-
-  g_clear_weak_pointer (&compositor_native->current_scanout_candidate);
-
-  G_OBJECT_CLASS (meta_compositor_native_parent_class)->finalize (object);
-}
-
 static void
 meta_compositor_native_init (MetaCompositorNative *compositor_native)
 {
@@ -212,11 +78,8 @@ meta_compositor_native_init (MetaCompositorNative *compositor_native)
 static void
 meta_compositor_native_class_init (MetaCompositorNativeClass *klass)
 {
-  GObjectClass *object_class = G_OBJECT_CLASS (klass);
   MetaCompositorClass *compositor_class = META_COMPOSITOR_CLASS (klass);
 
-  object_class->finalize = meta_compositor_native_finalize;
-
   compositor_class->before_paint = meta_compositor_native_before_paint;
   compositor_class->create_view = meta_compositor_native_create_view;
 }
diff --git a/src/compositor/meta-compositor-view-native.c b/src/compositor/meta-compositor-view-native.c
index 0841c954a6..ccba0ef723 100644
--- a/src/compositor/meta-compositor-view-native.c
+++ b/src/compositor/meta-compositor-view-native.c
@@ -26,14 +26,166 @@
 
 #include "compositor/meta-compositor-view-native.h"
 
+#include "backends/meta-crtc.h"
+#include "backends/native/meta-crtc-kms.h"
+#include "compositor/compositor-private.h"
+#include "compositor/meta-window-actor-private.h"
+
+#ifdef HAVE_WAYLAND
+#include "compositor/meta-surface-actor-wayland.h"
+#include "wayland/meta-wayland-surface.h"
+#endif /* HAVE_WAYLAND */
+
 struct _MetaCompositorViewNative
 {
   MetaCompositorView parent;
+
+#ifdef HAVE_WAYLAND
+  MetaWaylandSurface *scanout_candidate;
+#endif /* HAVE_WAYLAND */
 };
 
 G_DEFINE_TYPE (MetaCompositorViewNative, meta_compositor_view_native,
                META_TYPE_COMPOSITOR_VIEW)
 
+#ifdef HAVE_WAYLAND
+static void
+update_scanout_candidate (MetaCompositorViewNative *view_native,
+                          MetaWaylandSurface       *surface,
+                          MetaCrtc                 *crtc)
+{
+  if (view_native->scanout_candidate &&
+      view_native->scanout_candidate != surface)
+    {
+      meta_wayland_surface_set_scanout_candidate (view_native->scanout_candidate,
+                                                  NULL);
+      g_clear_weak_pointer (&view_native->scanout_candidate);
+    }
+
+  if (surface)
+    {
+      meta_wayland_surface_set_scanout_candidate (surface, crtc);
+      g_set_weak_pointer (&view_native->scanout_candidate,
+                          surface);
+    }
+}
+
+static gboolean
+find_scanout_candidate (MetaCompositorView  *compositor_view,
+                        MetaCompositor      *compositor,
+                        MetaCrtc           **crtc_out,
+                        CoglOnscreen       **onscreen_out,
+                        MetaWaylandSurface **surface_out)
+{
+  ClutterStageView *stage_view;
+  MetaRendererView *renderer_view;
+  MetaCrtc *crtc;
+  CoglFramebuffer *framebuffer;
+  MetaWindowActor *window_actor;
+  MetaWindow *window;
+  MetaSurfaceActor *surface_actor;
+  MetaSurfaceActorWayland *surface_actor_wayland;
+  MetaWaylandSurface *surface;
+  int geometry_scale;
+
+  if (meta_compositor_is_unredirect_inhibited (compositor))
+    return FALSE;
+
+  stage_view = meta_compositor_view_get_stage_view (compositor_view);
+  renderer_view = META_RENDERER_VIEW (stage_view);
+
+  crtc = meta_renderer_view_get_crtc (renderer_view);
+  if (!META_IS_CRTC_KMS (crtc))
+    return FALSE;
+
+  framebuffer = clutter_stage_view_get_framebuffer (stage_view);
+  if (!COGL_IS_ONSCREEN (framebuffer))
+    return FALSE;
+
+  window_actor = meta_compositor_view_get_top_window_actor (compositor_view);
+  if (!window_actor)
+    return FALSE;
+
+  if (meta_window_actor_effect_in_progress (window_actor))
+    return FALSE;
+
+  if (clutter_actor_has_transitions (CLUTTER_ACTOR (window_actor)))
+    return FALSE;
+
+  window = meta_window_actor_get_meta_window (window_actor);
+  if (!window)
+    return FALSE;
+
+  surface_actor = meta_window_actor_get_scanout_candidate (window_actor);
+  if (!surface_actor)
+    return FALSE;
+
+  if (meta_surface_actor_is_obscured (surface_actor))
+    return FALSE;
+
+  surface_actor_wayland = META_SURFACE_ACTOR_WAYLAND (surface_actor);
+  surface = meta_surface_actor_wayland_get_surface (surface_actor_wayland);
+  if (!surface)
+    return FALSE;
+
+  geometry_scale = meta_window_actor_get_geometry_scale (window_actor);
+
+  if (!meta_wayland_surface_can_scanout_untransformed (surface,
+                                                       renderer_view,
+                                                       geometry_scale))
+    return FALSE;
+
+  *crtc_out = crtc;
+  *onscreen_out = COGL_ONSCREEN (framebuffer);
+  *surface_out = surface;
+
+  return TRUE;
+}
+
+static void
+try_assign_next_scanout (MetaCompositorView *compositor_view,
+                         CoglOnscreen       *onscreen,
+                         MetaWaylandSurface *surface)
+{
+  ClutterStageView *stage_view;
+  g_autoptr (CoglScanout) scanout = NULL;
+
+  scanout = meta_wayland_surface_try_acquire_scanout (surface,
+                                                      onscreen);
+  if (!scanout)
+    return;
+
+  stage_view = meta_compositor_view_get_stage_view (compositor_view);
+
+  clutter_stage_view_assign_next_scanout (stage_view, scanout);
+}
+
+void
+meta_compositor_view_native_maybe_assign_scanout (MetaCompositorViewNative *view_native,
+                                                  MetaCompositor           *compositor)
+{
+  MetaCompositorView *compositor_view = META_COMPOSITOR_VIEW (view_native);
+  MetaCrtc *crtc = NULL;
+  CoglOnscreen *onscreen = NULL;
+  MetaWaylandSurface *surface = NULL;
+  gboolean candidate_found;
+
+  candidate_found = find_scanout_candidate (compositor_view,
+                                            compositor,
+                                            &crtc,
+                                            &onscreen,
+                                            &surface);
+  if (candidate_found)
+    {
+      try_assign_next_scanout (compositor_view,
+                               onscreen,
+                               surface);
+    }
+
+  update_scanout_candidate (view_native, surface, crtc);
+}
+#endif /* HAVE_WAYLAND */
+
 MetaCompositorViewNative *
 meta_compositor_view_native_new (ClutterStageView *stage_view)
 {
@@ -44,9 +196,24 @@ meta_compositor_view_native_new (ClutterStageView *stage_view)
                        NULL);
 }
 
+static void
+meta_compositor_view_native_finalize (GObject *object)
+{
+#ifdef HAVE_WAYLAND
+  MetaCompositorViewNative *view_native = META_COMPOSITOR_VIEW_NATIVE (object);
+
+  g_clear_weak_pointer (&view_native->scanout_candidate);
+#endif /* HAVE_WAYLAND */
+
+  G_OBJECT_CLASS (meta_compositor_view_native_parent_class)->finalize (object);
+}
+
 static void
 meta_compositor_view_native_class_init (MetaCompositorViewNativeClass *klass)
 {
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->finalize = meta_compositor_view_native_finalize;
 }
 
 static void
diff --git a/src/compositor/meta-compositor-view-native.h b/src/compositor/meta-compositor-view-native.h
index d0971cef34..af551854ee 100644
--- a/src/compositor/meta-compositor-view-native.h
+++ b/src/compositor/meta-compositor-view-native.h
@@ -27,6 +27,7 @@
 
 #include "clutter/clutter-mutter.h"
 #include "compositor/meta-compositor-view.h"
+#include "meta/compositor.h"
 
 #define META_TYPE_COMPOSITOR_VIEW_NATIVE (meta_compositor_view_native_get_type ())
 G_DECLARE_FINAL_TYPE (MetaCompositorViewNative, meta_compositor_view_native,
@@ -34,4 +35,9 @@ G_DECLARE_FINAL_TYPE (MetaCompositorViewNative, meta_compositor_view_native,
 
 MetaCompositorViewNative *meta_compositor_view_native_new (ClutterStageView *stage_view);
 
+#ifdef HAVE_WAYLAND
+void meta_compositor_view_native_maybe_assign_scanout (MetaCompositorViewNative *view_native,
+                                                       MetaCompositor           *compositor);
+#endif /* HAVE_WAYLAND */
+
 #endif /* META_COMPOSITOR_VIEW_NATIVE_H */


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