From 1571f8078a23b7cbd794e7f9479cf3512bf01122 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20=C3=85dahl?= Date: Mon, 27 Apr 2020 13:30:26 +0200 Subject: [PATCH] Reshuffle Wayland initailization Move Wayland support (i.e. the MetaWaylandCompositor object) made to be part of the backend. This is due to the fact that it is needed by the backend initialization, e.g. the Wayland EGLDisplay server support. The backend is changed to be more involved in Wayland and clutter initialization, so that the parts needed for clutter initialization happens before clutter itself initialization happens, and the rest happens after. This simplifies the setup a bit, as clutter and Wayland init now happens as part of the backend initialization. https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1218 --- src/backends/meta-backend-private.h | 8 + src/backends/meta-backend-types.h | 2 + src/backends/meta-backend.c | 216 ++++++++++-------- src/backends/native/meta-backend-native.c | 8 + .../x11/nested/meta-backend-x11-nested.c | 46 +++- src/compositor/compositor.c | 10 +- src/core/main.c | 13 -- src/wayland/meta-wayland.c | 33 ++- src/wayland/meta-wayland.h | 6 +- 9 files changed, 214 insertions(+), 128 deletions(-) diff --git a/src/backends/meta-backend-private.h b/src/backends/meta-backend-private.h index 4678f7768..5b0c849ec 100644 --- a/src/backends/meta-backend-private.h +++ b/src/backends/meta-backend-private.h @@ -108,6 +108,14 @@ struct _MetaBackendClass void meta_init_backend (GType backend_gtype); +#ifdef HAVE_WAYLAND +MetaWaylandCompositor * meta_backend_get_wayland_compositor (MetaBackend *backend); + +void meta_backend_init_wayland_display (MetaBackend *backend); + +void meta_backend_init_wayland (MetaBackend *backend); +#endif + ClutterBackend * meta_backend_get_clutter_backend (MetaBackend *backend); MetaIdleMonitor * meta_backend_get_idle_monitor (MetaBackend *backend, diff --git a/src/backends/meta-backend-types.h b/src/backends/meta-backend-types.h index 98cac8b9e..2961a8b20 100644 --- a/src/backends/meta-backend-types.h +++ b/src/backends/meta-backend-types.h @@ -54,4 +54,6 @@ typedef struct _MetaScreenCast MetaScreenCast; typedef struct _MetaScreenCastSession MetaScreenCastSession; typedef struct _MetaScreenCastStream MetaScreenCastStream; +typedef struct _MetaWaylandCompositor MetaWaylandCompositor; + #endif /* META_BACKEND_TYPE_H */ diff --git a/src/backends/meta-backend.c b/src/backends/meta-backend.c index 1c6a6783a..d6892f5bb 100644 --- a/src/backends/meta-backend.c +++ b/src/backends/meta-backend.c @@ -81,6 +81,10 @@ #include "backends/native/meta-backend-native.h" #endif +#ifdef HAVE_WAYLAND +#include "wayland/meta-wayland.h" +#endif + enum { KEYMAP_CHANGED, @@ -130,6 +134,10 @@ struct _MetaBackendPrivate MetaRemoteDesktop *remote_desktop; #endif +#ifdef HAVE_WAYLAND + MetaWaylandCompositor *wayland_compositor; +#endif + #ifdef HAVE_PROFILER MetaProfiler *profiler; #endif @@ -864,6 +872,120 @@ system_bus_gotten_cb (GObject *object, NULL); } +#ifdef HAVE_WAYLAND +MetaWaylandCompositor * +meta_backend_get_wayland_compositor (MetaBackend *backend) +{ + MetaBackendPrivate *priv = meta_backend_get_instance_private (backend); + + return priv->wayland_compositor; +} + +void +meta_backend_init_wayland_display (MetaBackend *backend) +{ + MetaBackendPrivate *priv = meta_backend_get_instance_private (backend); + + priv->wayland_compositor = meta_wayland_compositor_new (); +} + +void +meta_backend_init_wayland (MetaBackend *backend) +{ + MetaBackendPrivate *priv = meta_backend_get_instance_private (backend); + + meta_wayland_compositor_setup (priv->wayland_compositor); +} +#endif + +/* Mutter is responsible for pulling events off the X queue, so Clutter + * doesn't need (and shouldn't) run its normal event source which polls + * the X fd, but we do have to deal with dispatching events that accumulate + * in the clutter queue. This happens, for example, when clutter generate + * enter/leave events on mouse motion - several events are queued in the + * clutter queue but only one dispatched. It could also happen because of + * explicit calls to clutter_event_put(). We add a very simple custom + * event loop source which is simply responsible for pulling events off + * of the queue and dispatching them before we block for new events. + */ + +static gboolean +clutter_source_prepare (GSource *source, + int *timeout) +{ + *timeout = -1; + + return clutter_events_pending (); +} + +static gboolean +clutter_source_check (GSource *source) +{ + return clutter_events_pending (); +} + +static gboolean +clutter_source_dispatch (GSource *source, + GSourceFunc callback, + gpointer user_data) +{ + ClutterEvent *event = clutter_event_get (); + + if (event) + { + clutter_do_event (event); + clutter_event_free (event); + } + + return TRUE; +} + +static GSourceFuncs clutter_source_funcs = { + clutter_source_prepare, + clutter_source_check, + clutter_source_dispatch +}; + +static ClutterBackend * +meta_get_clutter_backend (void) +{ + MetaBackend *backend = meta_get_backend (); + + return meta_backend_get_clutter_backend (backend); +} + +static gboolean +init_clutter (MetaBackend *backend, + GError **error) +{ + GSource *source; + + clutter_set_custom_backend_func (meta_get_clutter_backend); + + if (clutter_init (NULL, NULL) != CLUTTER_INIT_SUCCESS) + { + g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, + "Unable to initialize Clutter"); + return FALSE; + } + + source = g_source_new (&clutter_source_funcs, sizeof (GSource)); + g_source_attach (source, NULL); + g_source_unref (source); + + return TRUE; +} + +static void +meta_backend_post_init (MetaBackend *backend) +{ + MetaBackendPrivate *priv = meta_backend_get_instance_private (backend); + + META_BACKEND_GET_CLASS (backend)->post_init (backend); + + meta_settings_post_init (priv->settings); +} + static gboolean meta_backend_initable_init (GInitable *initable, GCancellable *cancellable, @@ -902,6 +1024,11 @@ meta_backend_initable_init (GInitable *initable, priv->profiler = meta_profiler_new (); #endif + if (!init_clutter (backend, error)) + return FALSE; + + meta_backend_post_init (backend); + return TRUE; } @@ -917,16 +1044,6 @@ meta_backend_init (MetaBackend *backend) _backend = backend; } -static void -meta_backend_post_init (MetaBackend *backend) -{ - MetaBackendPrivate *priv = meta_backend_get_instance_private (backend); - - META_BACKEND_GET_CLASS (backend)->post_init (backend); - - meta_settings_post_init (priv->settings); -} - /** * meta_backend_get_idle_monitor: (skip) */ @@ -1258,54 +1375,6 @@ meta_backend_set_client_pointer_constraint (MetaBackend *backend, priv->client_pointer_constraint = g_object_ref (constraint); } -/* Mutter is responsible for pulling events off the X queue, so Clutter - * doesn't need (and shouldn't) run its normal event source which polls - * the X fd, but we do have to deal with dispatching events that accumulate - * in the clutter queue. This happens, for example, when clutter generate - * enter/leave events on mouse motion - several events are queued in the - * clutter queue but only one dispatched. It could also happen because of - * explicit calls to clutter_event_put(). We add a very simple custom - * event loop source which is simply responsible for pulling events off - * of the queue and dispatching them before we block for new events. - */ - -static gboolean -event_prepare (GSource *source, - gint *timeout_) -{ - *timeout_ = -1; - - return clutter_events_pending (); -} - -static gboolean -event_check (GSource *source) -{ - return clutter_events_pending (); -} - -static gboolean -event_dispatch (GSource *source, - GSourceFunc callback, - gpointer user_data) -{ - ClutterEvent *event = clutter_event_get (); - - if (event) - { - clutter_do_event (event); - clutter_event_free (event); - } - - return TRUE; -} - -static GSourceFuncs event_funcs = { - event_prepare, - event_check, - event_dispatch -}; - ClutterBackend * meta_backend_get_clutter_backend (MetaBackend *backend) { @@ -1320,14 +1389,6 @@ meta_backend_get_clutter_backend (MetaBackend *backend) return priv->clutter_backend; } -static ClutterBackend * -meta_get_clutter_backend (void) -{ - MetaBackend *backend = meta_get_backend (); - - return meta_backend_get_clutter_backend (backend); -} - void meta_init_backend (GType backend_gtype) { @@ -1344,29 +1405,6 @@ meta_init_backend (GType backend_gtype) } } -/** - * meta_clutter_init: (skip) - */ -void -meta_clutter_init (void) -{ - GSource *source; - - clutter_set_custom_backend_func (meta_get_clutter_backend); - - if (clutter_init (NULL, NULL) != CLUTTER_INIT_SUCCESS) - { - g_warning ("Unable to initialize Clutter.\n"); - exit (1); - } - - source = g_source_new (&event_funcs, sizeof (GSource)); - g_source_attach (source, NULL); - g_source_unref (source); - - meta_backend_post_init (_backend); -} - /** * meta_is_stage_views_enabled: * diff --git a/src/backends/native/meta-backend-native.c b/src/backends/native/meta-backend-native.c index 6c4a474e2..e5a16f337 100644 --- a/src/backends/native/meta-backend-native.c +++ b/src/backends/native/meta-backend-native.c @@ -366,6 +366,10 @@ meta_backend_native_post_init (MetaBackend *backend) if (retval != 0) g_warning ("Failed to set RT scheduler: %m"); } + +#ifdef HAVE_WAYLAND + meta_backend_init_wayland (backend); +#endif } static MetaMonitorManager * @@ -647,6 +651,10 @@ meta_backend_native_initable_init (GInitable *initable, if (!native->launcher) return FALSE; +#ifdef HAVE_WAYLAND + meta_backend_init_wayland_display (META_BACKEND (native)); +#endif + native->udev = meta_udev_new (native); native->barrier_manager = meta_barrier_manager_native_new (); diff --git a/src/backends/x11/nested/meta-backend-x11-nested.c b/src/backends/x11/nested/meta-backend-x11-nested.c index b9e7ff3b8..def74bb74 100644 --- a/src/backends/x11/nested/meta-backend-x11-nested.c +++ b/src/backends/x11/nested/meta-backend-x11-nested.c @@ -33,8 +33,16 @@ typedef struct _MetaBackendX11NestedPrivate MetaGpu *gpu; } MetaBackendX11NestedPrivate; -G_DEFINE_TYPE_WITH_PRIVATE (MetaBackendX11Nested, meta_backend_x11_nested, - META_TYPE_BACKEND_X11) +static GInitableIface *initable_parent_iface; + +static void +initable_iface_init (GInitableIface *initable_iface); + +G_DEFINE_TYPE_WITH_CODE (MetaBackendX11Nested, meta_backend_x11_nested, + META_TYPE_BACKEND_X11, + G_ADD_PRIVATE (MetaBackendX11Nested) + G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, + initable_iface_init)); static MetaRenderer * meta_backend_x11_nested_create_renderer (MetaBackend *backend, @@ -201,6 +209,39 @@ meta_backend_x11_nested_real_init_gpus (MetaBackendX11Nested *backend_x11_nested meta_backend_add_gpu (META_BACKEND (backend_x11_nested), priv->gpu); } +static void +meta_backend_x11_nested_post_init (MetaBackend *backend) +{ + MetaBackendClass *backend_class = + META_BACKEND_CLASS (meta_backend_x11_nested_parent_class); + + backend_class->post_init (backend); + +#ifdef HAVE_WAYLAND + meta_backend_init_wayland (backend); +#endif +} + +static gboolean +meta_backend_x11_nested_initable_init (GInitable *initable, + GCancellable *cancellable, + GError **error) +{ +#ifdef HAVE_WAYLAND + meta_backend_init_wayland_display (META_BACKEND (initable)); +#endif + + return initable_parent_iface->init (initable, cancellable, error); +} + +static void +initable_iface_init (GInitableIface *initable_iface) +{ + initable_parent_iface = g_type_interface_peek_parent (initable_iface); + + initable_iface->init = meta_backend_x11_nested_initable_init; +} + static void meta_backend_x11_nested_constructed (GObject *object) { @@ -229,6 +270,7 @@ meta_backend_x11_nested_class_init (MetaBackendX11NestedClass *klass) object_class->constructed = meta_backend_x11_nested_constructed; + backend_class->post_init = meta_backend_x11_nested_post_init; backend_class->create_renderer = meta_backend_x11_nested_create_renderer; backend_class->create_monitor_manager = meta_backend_x11_nested_create_monitor_manager; backend_class->create_cursor_renderer = meta_backend_x11_nested_create_cursor_renderer; diff --git a/src/compositor/compositor.c b/src/compositor/compositor.c index 338817127..d45d50743 100644 --- a/src/compositor/compositor.c +++ b/src/compositor/compositor.c @@ -502,11 +502,6 @@ after_stage_paint (ClutterStage *stage, for (l = priv->windows; l; l = l->next) meta_window_actor_post_paint (l->data); - -#ifdef HAVE_WAYLAND - if (meta_is_wayland_compositor ()) - meta_wayland_compositor_paint_finished (meta_wayland_compositor_get_default ()); -#endif } static void @@ -1154,6 +1149,11 @@ meta_compositor_real_post_paint (MetaCompositor *compositor) meta_compositor_get_instance_private (compositor); CoglGraphicsResetStatus status; +#ifdef HAVE_WAYLAND + if (meta_is_wayland_compositor ()) + meta_wayland_compositor_paint_finished (meta_wayland_compositor_get_default ()); +#endif + status = cogl_get_graphics_reset_status (priv->context); switch (status) { diff --git a/src/core/main.c b/src/core/main.c index 16aa8736a..16ab6e81f 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -586,11 +586,6 @@ meta_init (void) g_irepository_prepend_search_path (MUTTER_PKGLIBDIR); #endif -#ifdef HAVE_WAYLAND - if (meta_is_wayland_compositor ()) - meta_wayland_pre_clutter_init (); -#endif - /* NB: When running as a hybrid wayland compositor we run our own headless X * server so the user can't control the X display to connect too. */ if (!meta_is_wayland_compositor ()) @@ -598,14 +593,6 @@ meta_init (void) meta_init_backend (backend_gtype); - meta_clutter_init (); - -#ifdef HAVE_WAYLAND - /* Bring up Wayland. This also launches Xwayland and sets DISPLAY as well... */ - if (meta_is_wayland_compositor ()) - meta_wayland_init (); -#endif - meta_set_syncing (opt_sync || (g_getenv ("MUTTER_SYNC") != NULL)); if (opt_replace_wm) diff --git a/src/wayland/meta-wayland.c b/src/wayland/meta-wayland.c index f3f922635..a7bf9158c 100644 --- a/src/wayland/meta-wayland.c +++ b/src/wayland/meta-wayland.c @@ -47,7 +47,6 @@ #include "wayland/meta-xwayland-private.h" #include "wayland/meta-xwayland.h" -static MetaWaylandCompositor *_meta_wayland_compositor = NULL; static char *_display_name_override; G_DEFINE_TYPE (MetaWaylandCompositor, meta_wayland_compositor, G_TYPE_OBJECT) @@ -55,9 +54,14 @@ G_DEFINE_TYPE (MetaWaylandCompositor, meta_wayland_compositor, G_TYPE_OBJECT) MetaWaylandCompositor * meta_wayland_compositor_get_default (void) { - g_assert (_meta_wayland_compositor); + MetaBackend *backend; + MetaWaylandCompositor *wayland_compositor; - return _meta_wayland_compositor; + backend = meta_get_backend (); + wayland_compositor = meta_backend_get_wayland_compositor (backend); + g_assert (wayland_compositor); + + return wayland_compositor; } typedef struct @@ -318,6 +322,8 @@ meta_wayland_compositor_init (MetaWaylandCompositor *compositor) compositor->wayland_display = wl_display_create (); if (compositor->wayland_display == NULL) g_error ("Failed to create the global wl_display"); + + clutter_wayland_set_compositor_display (compositor->wayland_display); } static void @@ -325,19 +331,6 @@ meta_wayland_compositor_class_init (MetaWaylandCompositorClass *klass) { } -void -meta_wayland_pre_clutter_init (void) -{ - MetaWaylandCompositor *compositor; - - g_assert (!_meta_wayland_compositor); - - compositor = g_object_new (META_TYPE_WAYLAND_COMPOSITOR, NULL); - clutter_wayland_set_compositor_display (compositor->wayland_display); - - _meta_wayland_compositor = compositor; -} - static bool meta_xwayland_global_filter (const struct wl_client *client, const struct wl_global *global, @@ -368,8 +361,14 @@ meta_wayland_get_xwayland_auth_file (MetaWaylandCompositor *compositor) return compositor->xwayland_manager.auth_file; } +MetaWaylandCompositor * +meta_wayland_compositor_new (void) +{ + return g_object_new (META_TYPE_WAYLAND_COMPOSITOR, NULL); +} + void -meta_wayland_init (void) +meta_wayland_compositor_setup (MetaWaylandCompositor *wayland_compositor) { MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default (); GSource *wayland_event_source; diff --git a/src/wayland/meta-wayland.h b/src/wayland/meta-wayland.h index c5690c34e..15b7310ba 100644 --- a/src/wayland/meta-wayland.h +++ b/src/wayland/meta-wayland.h @@ -37,8 +37,10 @@ void meta_wayland_init (void); void meta_wayland_finalize (void); -/* We maintain a singleton MetaWaylandCompositor which can be got at via this - * API after meta_wayland_init() has been called. */ +MetaWaylandCompositor * meta_wayland_compositor_new (void); + +void meta_wayland_compositor_setup (MetaWaylandCompositor *compositor); + META_EXPORT_TEST MetaWaylandCompositor *meta_wayland_compositor_get_default (void);