From 65a6c4c361b7dad10b19f9bcabdcf7b576d7daa0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20=C3=85dahl?= Date: Thu, 12 Sep 2019 22:07:20 +0200 Subject: [PATCH] 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 | 15 +- src/meson.build | 6 +- 9 files changed, 241 insertions(+), 23 deletions(-) create mode 100644 src/compositor/meta-compositor-native.c create mode 100644 src/compositor/meta-compositor-native.h 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 ()) - return META_COMPOSITOR (meta_compositor_server_new (display)); - else + MetaBackend *backend = meta_get_backend (); + +#ifdef HAVE_NATIVE_BACKEND + if (META_IS_BACKEND_NATIVE (backend)) + return META_COMPOSITOR (meta_compositor_native_new (display)); #endif - return META_COMPOSITOR (meta_compositor_x11_new (display)); + if (META_IS_BACKEND_X11_NESTED (backend)) + return META_COMPOSITOR (meta_compositor_server_new (display)); +#endif + 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