[mutter] compositor: Add support for direct scanout of Wayland surfaces



commit 65a6c4c361b7dad10b19f9bcabdcf7b576d7daa0
Author: Jonas Ådahl <jadahl gmail com>
Date:   Thu Sep 12 22:07:20 2019 +0200

    compositor: Add support for direct scanout of Wayland surfaces
    
    Try to bypass compositing if there is a fullscreen toplevel window with
    a buffer compatible with the primary plane of the monitor it is
    fullscreen on. Only non-mirrored is currently supported; as well as
    fullscreened on a single monitor. It should be possible to extend with
    more cases, but this starts small.
    
    It does this by introducing a new MetaCompositor sub type
    MetaCompositorNative specific to the native backend, which derives from
    MetaCompositorServer, containing functionality only relevant for when
    running on top of the native backend.
    
    https://gitlab.gnome.org/GNOME/mutter/merge_requests/798

 clutter/clutter/clutter-stage-view.c        |   3 +-
 src/compositor/meta-compositor-native.c     | 148 ++++++++++++++++++++++++++++
 src/compositor/meta-compositor-native.h     |  32 ++++++
 src/compositor/meta-compositor-server.c     |   5 -
 src/compositor/meta-compositor-server.h     |   9 +-
 src/compositor/meta-surface-actor-wayland.c |  43 ++++++--
 src/compositor/meta-surface-actor-wayland.h |   3 +
 src/core/display.c                          |  13 ++-
 src/meson.build                             |   6 +-
 9 files changed, 240 insertions(+), 22 deletions(-)
---
diff --git a/clutter/clutter/clutter-stage-view.c b/clutter/clutter/clutter-stage-view.c
index b7413be7c..e4f10b5ac 100644
--- a/clutter/clutter/clutter-stage-view.c
+++ b/clutter/clutter/clutter-stage-view.c
@@ -418,8 +418,7 @@ clutter_stage_view_assign_next_scanout (ClutterStageView *view,
   ClutterStageViewPrivate *priv =
     clutter_stage_view_get_instance_private (view);
 
-  g_clear_object (&priv->next_scanout);
-  priv->next_scanout = scanout;
+  g_set_object (&priv->next_scanout, scanout);
 }
 
 CoglScanout *
diff --git a/src/compositor/meta-compositor-native.c b/src/compositor/meta-compositor-native.c
new file mode 100644
index 000000000..85929c035
--- /dev/null
+++ b/src/compositor/meta-compositor-native.c
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2019 Red Hat Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ */
+
+#include "config.h"
+
+#include "compositor/meta-compositor-native.h"
+
+#include "backends/meta-logical-monitor.h"
+#include "compositor/meta-surface-actor-wayland.h"
+
+struct _MetaCompositorNative
+{
+  MetaCompositorServer parent;
+};
+
+G_DEFINE_TYPE (MetaCompositorNative, meta_compositor_native,
+               META_TYPE_COMPOSITOR_SERVER)
+
+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)
+{
+  MetaBackend *backend = meta_get_backend ();
+  MetaRenderer *renderer = meta_backend_get_renderer (backend);
+  MetaWindowActor *window_actor;
+  MetaWindow *window;
+  MetaRendererView *view;
+  CoglFramebuffer *framebuffer;
+  CoglOnscreen *onscreen;
+  MetaSurfaceActor *surface_actor;
+  MetaSurfaceActorWayland *surface_actor_wayland;
+  g_autoptr (CoglScanout) scanout = NULL;
+
+  if (meta_compositor_is_unredirect_inhibited (compositor))
+    return;
+
+  window_actor = meta_compositor_get_top_window_actor (compositor);
+  if (!window_actor)
+    return;
+
+  if (meta_window_actor_effect_in_progress (window_actor))
+    return;
+
+  if (clutter_actor_has_transitions (CLUTTER_ACTOR (window_actor)))
+    return;
+
+  if (clutter_actor_get_n_children (CLUTTER_ACTOR (window_actor)) != 1)
+    return;
+
+  window = meta_window_actor_get_meta_window (window_actor);
+  if (!window)
+    return;
+
+  view = get_window_view (renderer, window);
+  if (!view)
+    return;
+
+  framebuffer = clutter_stage_view_get_framebuffer (CLUTTER_STAGE_VIEW (view));
+  if (!cogl_is_onscreen (framebuffer))
+    return;
+
+  surface_actor = meta_window_actor_get_surface (window_actor);
+  if (!META_IS_SURFACE_ACTOR_WAYLAND (surface_actor))
+    return;
+
+  surface_actor_wayland = META_SURFACE_ACTOR_WAYLAND (surface_actor);
+  onscreen = COGL_ONSCREEN (framebuffer);
+  scanout = meta_surface_actor_wayland_try_acquire_scanout (surface_actor_wayland,
+                                                            onscreen);
+  if (!scanout)
+    return;
+
+  clutter_stage_view_assign_next_scanout (CLUTTER_STAGE_VIEW (view), scanout);
+}
+
+static void
+meta_compositor_native_pre_paint (MetaCompositor *compositor)
+{
+  MetaCompositorClass *parent_class;
+
+  maybe_assign_primary_plane (compositor);
+
+  parent_class = META_COMPOSITOR_CLASS (meta_compositor_native_parent_class);
+  parent_class->pre_paint (compositor);
+}
+
+MetaCompositorNative *
+meta_compositor_native_new (MetaDisplay *display)
+{
+  return g_object_new (META_TYPE_COMPOSITOR_NATIVE,
+                       "display", display,
+                       NULL);
+}
+
+static void
+meta_compositor_native_init (MetaCompositorNative *compositor_native)
+{
+}
+
+static void
+meta_compositor_native_class_init (MetaCompositorNativeClass *klass)
+{
+  MetaCompositorClass *compositor_class = META_COMPOSITOR_CLASS (klass);
+
+  compositor_class->pre_paint = meta_compositor_native_pre_paint;
+}
diff --git a/src/compositor/meta-compositor-native.h b/src/compositor/meta-compositor-native.h
new file mode 100644
index 000000000..d276a5905
--- /dev/null
+++ b/src/compositor/meta-compositor-native.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2019 Red Hat Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ */
+
+#ifndef META_COMPOSITOR_NATIVE_H
+#define META_COMPOSITOR_NATIVE_H
+
+#include "compositor/meta-compositor-server.h"
+
+#define META_TYPE_COMPOSITOR_NATIVE (meta_compositor_native_get_type ())
+G_DECLARE_FINAL_TYPE (MetaCompositorNative, meta_compositor_native,
+                      META, COMPOSITOR_NATIVE, MetaCompositor)
+
+MetaCompositorNative * meta_compositor_native_new (MetaDisplay *display);
+
+#endif /* META_COMPOSITOR_NATIVE_H */
diff --git a/src/compositor/meta-compositor-server.c b/src/compositor/meta-compositor-server.c
index 361bcc599..f61f55560 100644
--- a/src/compositor/meta-compositor-server.c
+++ b/src/compositor/meta-compositor-server.c
@@ -22,11 +22,6 @@
 
 #include "compositor/meta-compositor-server.h"
 
-struct _MetaCompositorServer
-{
-  MetaCompositor parent;
-};
-
 G_DEFINE_TYPE (MetaCompositorServer, meta_compositor_server, META_TYPE_COMPOSITOR)
 
 static gboolean
diff --git a/src/compositor/meta-compositor-server.h b/src/compositor/meta-compositor-server.h
index 8bff05e7b..8b4a92748 100644
--- a/src/compositor/meta-compositor-server.h
+++ b/src/compositor/meta-compositor-server.h
@@ -24,8 +24,13 @@
 #include "compositor/compositor-private.h"
 
 #define META_TYPE_COMPOSITOR_SERVER (meta_compositor_server_get_type ())
-G_DECLARE_FINAL_TYPE (MetaCompositorServer, meta_compositor_server,
-                      META, COMPOSITOR_SERVER, MetaCompositor)
+G_DECLARE_DERIVABLE_TYPE (MetaCompositorServer, meta_compositor_server,
+                          META, COMPOSITOR_SERVER, MetaCompositor)
+
+struct _MetaCompositorServerClass
+{
+  MetaCompositorClass parent_class;
+};
 
 MetaCompositorServer * meta_compositor_server_new (MetaDisplay *display);
 
diff --git a/src/compositor/meta-surface-actor-wayland.c b/src/compositor/meta-surface-actor-wayland.c
index dbdd49017..d63d8a7f9 100644
--- a/src/compositor/meta-surface-actor-wayland.c
+++ b/src/compositor/meta-surface-actor-wayland.c
@@ -79,6 +79,40 @@ meta_surface_actor_wayland_is_opaque (MetaSurfaceActor *actor)
   return meta_shaped_texture_is_opaque (stex);
 }
 
+static void
+queue_frame_callbacks (MetaSurfaceActorWayland *self)
+{
+  MetaWaylandCompositor *wayland_compositor;
+
+  if (!self->surface)
+    return;
+
+  if (meta_surface_actor_is_obscured (META_SURFACE_ACTOR (self)))
+    return;
+
+  wayland_compositor = self->surface->compositor;
+  wl_list_insert_list (&wayland_compositor->frame_callbacks,
+                       &self->frame_callback_list);
+  wl_list_init (&self->frame_callback_list);
+}
+
+CoglScanout *
+meta_surface_actor_wayland_try_acquire_scanout (MetaSurfaceActorWayland *self,
+                                                CoglOnscreen            *onscreen)
+{
+  MetaWaylandSurface *surface;
+  CoglScanout *scanout;
+
+  surface = meta_surface_actor_wayland_get_surface (self);
+  scanout = meta_wayland_surface_try_acquire_scanout (surface, onscreen);
+  if (!scanout)
+    return NULL;
+
+  queue_frame_callbacks (self);
+
+  return scanout;
+}
+
 void
 meta_surface_actor_wayland_add_frame_callbacks (MetaSurfaceActorWayland *self,
                                                 struct wl_list *frame_callbacks)
@@ -92,14 +126,7 @@ meta_surface_actor_wayland_paint (ClutterActor        *actor,
 {
   MetaSurfaceActorWayland *self = META_SURFACE_ACTOR_WAYLAND (actor);
 
-  if (self->surface &&
-      !meta_surface_actor_is_obscured (META_SURFACE_ACTOR (actor)))
-    {
-      MetaWaylandCompositor *compositor = self->surface->compositor;
-
-      wl_list_insert_list (&compositor->frame_callbacks, &self->frame_callback_list);
-      wl_list_init (&self->frame_callback_list);
-    }
+  queue_frame_callbacks (self);
 
   CLUTTER_ACTOR_CLASS (meta_surface_actor_wayland_parent_class)->paint (actor,
                                                                         paint_context);
diff --git a/src/compositor/meta-surface-actor-wayland.h b/src/compositor/meta-surface-actor-wayland.h
index e1ad843f7..d61a4df57 100644
--- a/src/compositor/meta-surface-actor-wayland.h
+++ b/src/compositor/meta-surface-actor-wayland.h
@@ -52,6 +52,9 @@ void meta_surface_actor_wayland_get_subsurface_rect (MetaSurfaceActorWayland *se
 void meta_surface_actor_wayland_add_frame_callbacks (MetaSurfaceActorWayland *self,
                                                      struct wl_list *frame_callbacks);
 
+CoglScanout * meta_surface_actor_wayland_try_acquire_scanout (MetaSurfaceActorWayland *self,
+                                                              CoglOnscreen            *onscreen);
+
 G_END_DECLS
 
 #endif /* __META_SURFACE_ACTOR_WAYLAND_H__ */
diff --git a/src/core/display.c b/src/core/display.c
index 8de64b0e0..d49475dcb 100644
--- a/src/core/display.c
+++ b/src/core/display.c
@@ -51,6 +51,7 @@
 #include "backends/x11/meta-backend-x11.h"
 #include "backends/x11/meta-event-x11.h"
 #include "backends/x11/cm/meta-backend-x11-cm.h"
+#include "backends/x11/nested/meta-backend-x11-nested.h"
 #include "clutter/x11/clutter-x11.h"
 #include "compositor/compositor-private.h"
 #include "compositor/meta-compositor-x11.h"
@@ -81,6 +82,7 @@
 #include "x11/xprops.h"
 
 #ifdef HAVE_WAYLAND
+#include "compositor/meta-compositor-native.h"
 #include "compositor/meta-compositor-server.h"
 #include "wayland/meta-xwayland-private.h"
 #include "wayland/meta-wayland-tablet-seat.h"
@@ -572,11 +574,16 @@ static MetaCompositor *
 create_compositor (MetaDisplay *display)
 {
 #ifdef HAVE_WAYLAND
-  if (meta_is_wayland_compositor ())
+  MetaBackend *backend = meta_get_backend ();
+
+#ifdef HAVE_NATIVE_BACKEND
+  if (META_IS_BACKEND_NATIVE (backend))
+    return META_COMPOSITOR (meta_compositor_native_new (display));
+#endif
+  if (META_IS_BACKEND_X11_NESTED (backend))
     return META_COMPOSITOR (meta_compositor_server_new (display));
-  else
 #endif
-    return META_COMPOSITOR (meta_compositor_x11_new (display));
+  return META_COMPOSITOR (meta_compositor_x11_new (display));
 }
 
 static void
diff --git a/src/meson.build b/src/meson.build
index c5ff7966d..8ecfc6efb 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -291,6 +291,8 @@ mutter_sources = [
   'compositor/meta-background-group.c',
   'compositor/meta-background-image.c',
   'compositor/meta-background-private.h',
+  'compositor/meta-compositor-server.c',
+  'compositor/meta-compositor-server.h',
   'compositor/meta-compositor-x11.c',
   'compositor/meta-compositor-x11.h',
   'compositor/meta-cullable.c',
@@ -477,8 +479,6 @@ if have_wayland
     'compositor/meta-surface-actor-wayland.h',
     'compositor/meta-window-actor-wayland.c',
     'compositor/meta-window-actor-wayland.h',
-    'compositor/meta-compositor-server.c',
-    'compositor/meta-compositor-server.h',
     'wayland/meta-cursor-sprite-wayland.c',
     'wayland/meta-cursor-sprite-wayland.h',
     'wayland/meta-pointer-confinement-wayland.c',
@@ -676,6 +676,8 @@ if have_native_backend
     'backends/native/meta-virtual-input-device-native.h',
     'backends/native/meta-xkb-utils.c',
     'backends/native/meta-xkb-utils.h',
+    'compositor/meta-compositor-native.c',
+    'compositor/meta-compositor-native.h',
   ]
 endif
 


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