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
This commit is contained in:
Jonas Ådahl 2020-04-27 13:30:26 +02:00
parent 510cbef15a
commit 1571f8078a
9 changed files with 214 additions and 128 deletions

View File

@ -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,

View File

@ -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 */

View File

@ -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:
*

View File

@ -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 ();

View File

@ -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;

View File

@ -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)
{

View File

@ -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)

View File

@ -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;

View File

@ -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);