[RFC v3 1/3] xwayland: Decouple GBM from glamor

Lyude Paul lyude at redhat.com
Fri Feb 9 21:41:08 UTC 2018


This takes all of the gbm related code in wayland-glamor.c and moves it
into it's own EGL backend for Xwayland, xwayland-glamor-gbm.c.
Additionally, we add the egl_backend struct into xwl_screen in order to
provide hooks for alternative EGL backends such as nvidia's EGLStreams.

Signed-off-by: Lyude Paul <lyude at redhat.com>
---
 hw/xwayland/Makefile.am           |   3 +-
 hw/xwayland/meson.build           |   1 +
 hw/xwayland/xwayland-glamor-gbm.c | 632 ++++++++++++++++++++++++++++++++++++++
 hw/xwayland/xwayland-glamor.c     | 500 +-----------------------------
 hw/xwayland/xwayland.c            |  13 +-
 hw/xwayland/xwayland.h            |  54 +++-
 6 files changed, 705 insertions(+), 498 deletions(-)
 create mode 100644 hw/xwayland/xwayland-glamor-gbm.c

diff --git a/hw/xwayland/Makefile.am b/hw/xwayland/Makefile.am
index 7204591e3..d9e9fe8b6 100644
--- a/hw/xwayland/Makefile.am
+++ b/hw/xwayland/Makefile.am
@@ -33,7 +33,8 @@ Xwayland_built_sources =
 
 if GLAMOR_EGL
 Xwayland_SOURCES += 				\
-	xwayland-glamor.c
+	xwayland-glamor.c			\
+	xwayland-glamor-gbm.c
 if XV
 Xwayland_SOURCES += 				\
 	xwayland-glamor-xv.c
diff --git a/hw/xwayland/meson.build b/hw/xwayland/meson.build
index 24203c63e..d219e2f44 100644
--- a/hw/xwayland/meson.build
+++ b/hw/xwayland/meson.build
@@ -43,6 +43,7 @@ srcs += code.process(xdg_output_xml)
 xwayland_glamor = []
 if gbm_dep.found()
     srcs += 'xwayland-glamor.c'
+    srcs += 'xwayland-glamor-gbm.c'
     if build_xv
         srcs += 'xwayland-glamor-xv.c'
     endif
diff --git a/hw/xwayland/xwayland-glamor-gbm.c b/hw/xwayland/xwayland-glamor-gbm.c
new file mode 100644
index 000000000..4b973019f
--- /dev/null
+++ b/hw/xwayland/xwayland-glamor-gbm.c
@@ -0,0 +1,632 @@
+/*
+ * Copyright © 2011-2014 Intel Corporation
+ * Copyright © 2017 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including
+ * the next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Lyude Paul <lyude at redhat.com>
+ *
+ */
+
+#include "xwayland.h"
+
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <xf86drm.h>
+
+#define MESA_EGL_NO_X11_HEADERS
+#include <gbm.h>
+#include <glamor_egl.h>
+
+#include <glamor.h>
+#include <glamor_context.h>
+#include <dri3.h>
+#include "drm-client-protocol.h"
+
+struct xwl_gbm_private {
+    struct gbm_device *gbm;
+    struct wl_drm *drm;
+    char *device_name;
+    int drm_fd;
+    int fd_render_node;
+    Bool drm_authenticated;
+    uint32_t capabilities;
+};
+
+struct xwl_pixmap {
+    struct wl_buffer *buffer;
+    EGLImage image;
+    unsigned int texture;
+    struct gbm_bo *bo;
+};
+
+static DevPrivateKeyRec xwl_gbm_private_key;
+static DevPrivateKeyRec xwl_auth_state_private_key;
+
+static inline struct xwl_gbm_private *
+xwl_gbm_get(struct xwl_screen *xwl_screen)
+{
+    return dixLookupPrivate(&xwl_screen->screen->devPrivates,
+                            &xwl_gbm_private_key);
+}
+
+static uint32_t
+gbm_format_for_depth(int depth)
+{
+    switch (depth) {
+    case 16:
+        return GBM_FORMAT_RGB565;
+    case 24:
+        return GBM_FORMAT_XRGB8888;
+    default:
+        ErrorF("unexpected depth: %d\n", depth);
+    case 32:
+        return GBM_FORMAT_ARGB8888;
+    }
+}
+
+static uint32_t
+drm_format_for_depth(int depth)
+{
+    switch (depth) {
+    case 15:
+        return WL_DRM_FORMAT_XRGB1555;
+    case 16:
+        return WL_DRM_FORMAT_RGB565;
+    case 24:
+        return WL_DRM_FORMAT_XRGB8888;
+    default:
+        ErrorF("unexpected depth: %d\n", depth);
+    case 32:
+        return WL_DRM_FORMAT_ARGB8888;
+    }
+}
+
+static char
+is_fd_render_node(int fd)
+{
+    struct stat render;
+
+    if (fstat(fd, &render))
+        return 0;
+    if (!S_ISCHR(render.st_mode))
+        return 0;
+    if (render.st_rdev & 0x80)
+        return 1;
+
+    return 0;
+}
+
+static PixmapPtr
+xwl_glamor_gbm_create_pixmap_for_bo(ScreenPtr screen, struct gbm_bo *bo,
+                                    int depth)
+{
+    PixmapPtr pixmap;
+    struct xwl_pixmap *xwl_pixmap;
+    struct xwl_screen *xwl_screen = xwl_screen_get(screen);
+
+    xwl_pixmap = malloc(sizeof *xwl_pixmap);
+    if (xwl_pixmap == NULL)
+        return NULL;
+
+    pixmap = glamor_create_pixmap(screen,
+                                  gbm_bo_get_width(bo),
+                                  gbm_bo_get_height(bo),
+                                  depth,
+                                  GLAMOR_CREATE_PIXMAP_NO_TEXTURE);
+    if (!pixmap) {
+        free(xwl_pixmap);
+        return NULL;
+    }
+
+    if (lastGLContext != xwl_screen->glamor_ctx) {
+        lastGLContext = xwl_screen->glamor_ctx;
+        xwl_screen->glamor_ctx->make_current(xwl_screen->glamor_ctx);
+    }
+
+    xwl_pixmap->bo = bo;
+    xwl_pixmap->buffer = NULL;
+    xwl_pixmap->image = eglCreateImageKHR(xwl_screen->egl_display,
+                                          xwl_screen->egl_context,
+                                          EGL_NATIVE_PIXMAP_KHR,
+                                          xwl_pixmap->bo, NULL);
+
+    glGenTextures(1, &xwl_pixmap->texture);
+    glBindTexture(GL_TEXTURE_2D, xwl_pixmap->texture);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+
+    glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, xwl_pixmap->image);
+    glBindTexture(GL_TEXTURE_2D, 0);
+
+    xwl_pixmap_set_private(pixmap, xwl_pixmap);
+
+    glamor_set_pixmap_texture(pixmap, xwl_pixmap->texture);
+    glamor_set_pixmap_type(pixmap, GLAMOR_TEXTURE_DRM);
+
+    return pixmap;
+}
+
+static PixmapPtr
+xwl_glamor_gbm_create_pixmap(ScreenPtr screen,
+                             int width, int height, int depth,
+                             unsigned int hint)
+{
+    struct xwl_screen *xwl_screen = xwl_screen_get(screen);
+    struct xwl_gbm_private *xwl_gbm = xwl_gbm_get(xwl_screen);
+    struct gbm_bo *bo;
+
+    if (width > 0 && height > 0 && depth >= 15 &&
+        (hint == 0 ||
+         hint == CREATE_PIXMAP_USAGE_BACKING_PIXMAP ||
+         hint == CREATE_PIXMAP_USAGE_SHARED)) {
+        bo = gbm_bo_create(xwl_gbm->gbm, width, height,
+                           gbm_format_for_depth(depth),
+                           GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING);
+
+        if (bo)
+            return xwl_glamor_gbm_create_pixmap_for_bo(screen, bo, depth);
+    }
+
+    return glamor_create_pixmap(screen, width, height, depth, hint);
+}
+
+static Bool
+xwl_glamor_gbm_destroy_pixmap(PixmapPtr pixmap)
+{
+    struct xwl_screen *xwl_screen = xwl_screen_get(pixmap->drawable.pScreen);
+    struct xwl_pixmap *xwl_pixmap = xwl_pixmap_get(pixmap);
+
+    if (xwl_pixmap && pixmap->refcnt == 1) {
+        if (xwl_pixmap->buffer)
+            wl_buffer_destroy(xwl_pixmap->buffer);
+
+        eglDestroyImageKHR(xwl_screen->egl_display, xwl_pixmap->image);
+        gbm_bo_destroy(xwl_pixmap->bo);
+        free(xwl_pixmap);
+    }
+
+    return glamor_destroy_pixmap(pixmap);
+}
+
+static struct wl_buffer *
+xwl_glamor_gbm_get_wl_buffer_for_pixmap(PixmapPtr pixmap)
+{
+    struct xwl_screen *xwl_screen = xwl_screen_get(pixmap->drawable.pScreen);
+    struct xwl_pixmap *xwl_pixmap = xwl_pixmap_get(pixmap);
+    struct xwl_gbm_private *xwl_gbm = xwl_gbm_get(xwl_screen);
+    struct wl_buffer *buffer;
+    int prime_fd;
+
+    if (xwl_pixmap->buffer)
+        return xwl_pixmap->buffer;
+
+    prime_fd = gbm_bo_get_fd(xwl_pixmap->bo);
+    if (prime_fd == -1)
+        return NULL;
+
+    buffer = wl_drm_create_prime_buffer(
+        xwl_gbm->drm, prime_fd,
+        pixmap->drawable.width, pixmap->drawable.height,
+        drm_format_for_depth(pixmap->drawable.depth),
+        0, gbm_bo_get_stride(xwl_pixmap->bo), 0, 0, 0, 0);
+
+    close(prime_fd);
+
+    return buffer;
+}
+
+static void
+xwl_glamor_gbm_cleanup(struct xwl_screen *xwl_screen)
+{
+    struct xwl_gbm_private *xwl_gbm = xwl_gbm_get(xwl_screen);
+
+    if (xwl_gbm->device_name)
+        free(xwl_gbm->device_name);
+    if (xwl_gbm->drm_fd)
+        close(xwl_gbm->drm_fd);
+    if (xwl_gbm->drm)
+        wl_drm_destroy(xwl_gbm->drm);
+    if (xwl_gbm->gbm)
+        gbm_device_destroy(xwl_gbm->gbm);
+
+    free(xwl_gbm);
+}
+
+struct xwl_auth_state {
+    int fd;
+    ClientPtr client;
+    struct wl_callback *callback;
+};
+
+static void
+free_xwl_auth_state(ClientPtr pClient, struct xwl_auth_state *state)
+{
+    dixSetPrivate(&pClient->devPrivates, &xwl_auth_state_private_key, NULL);
+    if (state) {
+        wl_callback_destroy(state->callback);
+        free(state);
+    }
+}
+
+static void
+xwl_auth_state_client_callback(CallbackListPtr *pcbl, void *unused, void *data)
+{
+    NewClientInfoRec *clientinfo = (NewClientInfoRec *) data;
+    ClientPtr pClient = clientinfo->client;
+    struct xwl_auth_state *state;
+
+    switch (pClient->clientState) {
+    case ClientStateGone:
+    case ClientStateRetained:
+        state = dixLookupPrivate(&pClient->devPrivates,
+                                 &xwl_auth_state_private_key);
+        free_xwl_auth_state(pClient, state);
+        break;
+    default:
+        break;
+    }
+}
+
+static void
+sync_callback(void *data, struct wl_callback *callback, uint32_t serial)
+{
+    struct xwl_auth_state *state = data;
+    ClientPtr client = state->client;
+
+    /* if the client is gone, the callback is cancelled so it's safe to
+     * assume the client is still in ClientStateRunning at this point...
+     */
+    dri3_send_open_reply(client, state->fd);
+    AttendClient(client);
+    free_xwl_auth_state(client, state);
+}
+
+static const struct wl_callback_listener sync_listener = {
+   sync_callback
+};
+
+static int
+xwl_dri3_open_client(ClientPtr client,
+                     ScreenPtr screen,
+                     RRProviderPtr provider,
+                     int *pfd)
+{
+    struct xwl_screen *xwl_screen = xwl_screen_get(screen);
+    struct xwl_gbm_private *xwl_gbm = xwl_gbm_get(xwl_screen);
+    struct xwl_auth_state *state;
+    drm_magic_t magic;
+    int fd;
+
+    fd = open(xwl_gbm->device_name, O_RDWR | O_CLOEXEC);
+    if (fd < 0)
+        return BadAlloc;
+    if (xwl_gbm->fd_render_node) {
+        *pfd = fd;
+        return Success;
+    }
+
+    state = malloc(sizeof *state);
+    if (state == NULL) {
+        close(fd);
+        return BadAlloc;
+    }
+
+    state->client = client;
+    state->fd = fd;
+
+    if (drmGetMagic(state->fd, &magic) < 0) {
+        close(state->fd);
+        free(state);
+        return BadMatch;
+    }
+
+    wl_drm_authenticate(xwl_gbm->drm, magic);
+    state->callback = wl_display_sync(xwl_screen->display);
+    wl_callback_add_listener(state->callback, &sync_listener, state);
+    dixSetPrivate(&client->devPrivates, &xwl_auth_state_private_key, state);
+
+    IgnoreClient(client);
+
+    return Success;
+}
+
+static PixmapPtr
+xwl_dri3_pixmap_from_fd(ScreenPtr screen, int fd,
+                        CARD16 width, CARD16 height, CARD16 stride,
+                        CARD8 depth, CARD8 bpp)
+{
+    struct xwl_screen *xwl_screen = xwl_screen_get(screen);
+    struct xwl_gbm_private *xwl_gbm = xwl_gbm_get(xwl_screen);
+    struct gbm_import_fd_data data;
+    struct gbm_bo *bo;
+    PixmapPtr pixmap;
+
+    if (width == 0 || height == 0 ||
+        depth < 15 || bpp != BitsPerPixel(depth) || stride < width * bpp / 8)
+        return NULL;
+
+    data.fd = fd;
+    data.width = width;
+    data.height = height;
+    data.stride = stride;
+    data.format = gbm_format_for_depth(depth);
+    bo = gbm_bo_import(xwl_gbm->gbm, GBM_BO_IMPORT_FD, &data,
+                       GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING);
+    if (bo == NULL)
+        return NULL;
+
+    pixmap = xwl_glamor_gbm_create_pixmap_for_bo(screen, bo, depth);
+    if (pixmap == NULL) {
+        gbm_bo_destroy(bo);
+        return NULL;
+    }
+
+    return pixmap;
+}
+
+static int
+xwl_dri3_fd_from_pixmap(ScreenPtr screen, PixmapPtr pixmap,
+                        CARD16 *stride, CARD32 *size)
+{
+    struct xwl_pixmap *xwl_pixmap;
+
+    xwl_pixmap = xwl_pixmap_get(pixmap);
+
+    *stride = gbm_bo_get_stride(xwl_pixmap->bo);
+    *size = pixmap->drawable.width * *stride;
+
+    return gbm_bo_get_fd(xwl_pixmap->bo);
+}
+
+static dri3_screen_info_rec xwl_dri3_info = {
+    .version = 1,
+    .open = NULL,
+    .pixmap_from_fd = xwl_dri3_pixmap_from_fd,
+    .fd_from_pixmap = xwl_dri3_fd_from_pixmap,
+    .open_client = xwl_dri3_open_client,
+};
+
+static void
+xwl_drm_handle_device(void *data, struct wl_drm *drm, const char *device)
+{
+   struct xwl_screen *xwl_screen = data;
+   struct xwl_gbm_private *xwl_gbm = xwl_gbm_get(xwl_screen);
+   drm_magic_t magic;
+
+   xwl_gbm->device_name = strdup(device);
+   if (!xwl_gbm->device_name) {
+       xwl_glamor_gbm_cleanup(xwl_screen);
+       return;
+   }
+
+   xwl_gbm->drm_fd = open(xwl_gbm->device_name, O_RDWR | O_CLOEXEC);
+   if (xwl_gbm->drm_fd == -1) {
+       ErrorF("wayland-egl: could not open %s (%s)\n",
+              xwl_gbm->device_name, strerror(errno));
+       xwl_glamor_gbm_cleanup(xwl_screen);
+       return;
+   }
+
+   if (is_fd_render_node(xwl_gbm->drm_fd)) {
+       xwl_gbm->fd_render_node = 1;
+       xwl_screen->expecting_event--;
+   } else {
+       drmGetMagic(xwl_gbm->drm_fd, &magic);
+       wl_drm_authenticate(xwl_gbm->drm, magic);
+   }
+}
+
+static void
+xwl_drm_handle_format(void *data, struct wl_drm *drm, uint32_t format)
+{
+   struct xwl_screen *xwl_screen = data;
+
+   switch (format) {
+   case WL_DRM_FORMAT_ARGB8888:
+      xwl_screen->formats |= XWL_FORMAT_ARGB8888;
+      break;
+   case WL_DRM_FORMAT_XRGB8888:
+      xwl_screen->formats |= XWL_FORMAT_XRGB8888;
+      break;
+   case WL_DRM_FORMAT_RGB565:
+      xwl_screen->formats |= XWL_FORMAT_RGB565;
+      break;
+   }
+}
+
+static void
+xwl_drm_handle_authenticated(void *data, struct wl_drm *drm)
+{
+    struct xwl_screen *xwl_screen = data;
+    struct xwl_gbm_private *xwl_gbm = xwl_gbm_get(xwl_screen);
+
+    xwl_gbm->drm_authenticated = TRUE;
+    xwl_screen->expecting_event--;
+}
+
+static void
+xwl_drm_handle_capabilities(void *data, struct wl_drm *drm, uint32_t value)
+{
+    xwl_gbm_get(data)->capabilities = value;
+}
+
+static const struct wl_drm_listener xwl_drm_listener = {
+    xwl_drm_handle_device,
+    xwl_drm_handle_format,
+    xwl_drm_handle_authenticated,
+    xwl_drm_handle_capabilities
+};
+
+static void
+xwl_glamor_gbm_init_wl_registry(struct xwl_screen *xwl_screen,
+                                struct wl_registry *wl_registry,
+                                const char *name,
+                                uint32_t id, uint32_t version)
+{
+    struct xwl_gbm_private *xwl_gbm = xwl_gbm_get(xwl_screen);
+
+    if (strcmp(name, "wl_drm") != 0)
+        return;
+
+    if (version < 2) {
+        ErrorF("glamor gbm: wl_drm version %d is too old, we require at least v2\n",
+               version);
+        xwl_glamor_gbm_cleanup(xwl_screen);
+        return;
+    }
+
+    xwl_gbm->drm = wl_registry_bind(xwl_screen->registry,
+                                    id, &wl_drm_interface, 2);
+    wl_drm_add_listener(xwl_gbm->drm, &xwl_drm_listener, xwl_screen);
+    xwl_screen->expecting_event++;
+}
+
+static Bool
+xwl_glamor_gbm_init_egl(struct xwl_screen *xwl_screen)
+{
+    struct xwl_gbm_private *xwl_gbm = xwl_gbm_get(xwl_screen);
+    EGLint major, minor;
+    Bool egl_initialized = FALSE;
+    static const EGLint config_attribs_core[] = {
+        EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR,
+        EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR,
+        EGL_CONTEXT_MAJOR_VERSION_KHR,
+        GLAMOR_GL_CORE_VER_MAJOR,
+        EGL_CONTEXT_MINOR_VERSION_KHR,
+        GLAMOR_GL_CORE_VER_MINOR,
+        EGL_NONE
+    };
+
+    xwl_gbm->gbm = gbm_create_device(xwl_gbm->drm_fd);
+    if (!xwl_gbm->gbm) {
+        ErrorF("couldn't create gbm device\n");
+        goto error;
+    }
+
+    xwl_screen->egl_display = glamor_egl_get_display(EGL_PLATFORM_GBM_MESA,
+                                                     xwl_gbm->gbm);
+    if (xwl_screen->egl_display == EGL_NO_DISPLAY) {
+        ErrorF("glamor_egl_get_display() failed\n");
+        goto error;
+    }
+
+    egl_initialized = eglInitialize(xwl_screen->egl_display, &major, &minor);
+    if (!egl_initialized) {
+        ErrorF("eglInitialize() failed\n");
+        goto error;
+    }
+
+    eglBindAPI(EGL_OPENGL_API);
+
+    xwl_screen->egl_context = eglCreateContext(
+        xwl_screen->egl_display, NULL, EGL_NO_CONTEXT, config_attribs_core);
+    if (xwl_screen->egl_context == EGL_NO_CONTEXT) {
+        xwl_screen->egl_context = eglCreateContext(
+            xwl_screen->egl_display, NULL, EGL_NO_CONTEXT, NULL);
+    }
+
+    if (xwl_screen->egl_context == EGL_NO_CONTEXT) {
+        ErrorF("Failed to create EGL context\n");
+        goto error;
+    }
+
+    if (!eglMakeCurrent(xwl_screen->egl_display,
+                        EGL_NO_SURFACE, EGL_NO_SURFACE,
+                        xwl_screen->egl_context)) {
+        ErrorF("Failed to make EGL context current\n");
+        goto error;
+    }
+
+    if (!epoxy_has_gl_extension("GL_OES_EGL_image"))
+        ErrorF("GL_OES_EGL_image not available\n");
+
+    return TRUE;
+error:
+    if (xwl_screen->egl_context != EGL_NO_CONTEXT) {
+        eglDestroyContext(xwl_screen->egl_display, xwl_screen->egl_context);
+        xwl_screen->egl_context = EGL_NO_CONTEXT;
+    }
+
+    if (xwl_screen->egl_display != EGL_NO_DISPLAY) {
+        eglTerminate(xwl_screen->egl_display);
+        xwl_screen->egl_display = EGL_NO_DISPLAY;
+    }
+
+    xwl_glamor_gbm_cleanup(xwl_screen);
+    return FALSE;
+}
+
+static Bool
+xwl_glamor_gbm_init_screen(struct xwl_screen *xwl_screen)
+{
+    if (!dri3_screen_init(xwl_screen->screen, &xwl_dri3_info)) {
+        ErrorF("Failed to initialize dri3\n");
+        goto error;
+    }
+
+    if (!dixRegisterPrivateKey(&xwl_auth_state_private_key, PRIVATE_CLIENT,
+                               0)) {
+        ErrorF("Failed to register private key\n");
+        goto error;
+    }
+
+    if (!AddCallback(&ClientStateCallback, xwl_auth_state_client_callback,
+                     NULL)) {
+        ErrorF("Failed to add client state callback\n");
+        goto error;
+    }
+
+    xwl_screen->screen->CreatePixmap = xwl_glamor_gbm_create_pixmap;
+    xwl_screen->screen->DestroyPixmap = xwl_glamor_gbm_destroy_pixmap;
+
+    return TRUE;
+error:
+    xwl_glamor_gbm_cleanup(xwl_screen);
+    return FALSE;
+}
+
+Bool
+xwl_glamor_init_gbm(struct xwl_screen *xwl_screen)
+{
+    struct xwl_gbm_private *xwl_gbm;
+
+    if (!dixRegisterPrivateKey(&xwl_gbm_private_key, PRIVATE_SCREEN, 0))
+        return FALSE;
+
+    xwl_gbm = calloc(sizeof(*xwl_gbm), 1);
+    if (!xwl_gbm) {
+        ErrorF("glamor: Not enough memory to setup GBM, disabling\n");
+        return FALSE;
+    }
+
+    dixSetPrivate(&xwl_screen->screen->devPrivates, &xwl_gbm_private_key,
+                  xwl_gbm);
+
+    xwl_screen->egl_backend.init_wl_registry = xwl_glamor_gbm_init_wl_registry;
+    xwl_screen->egl_backend.init_egl = xwl_glamor_gbm_init_egl;
+    xwl_screen->egl_backend.init_screen = xwl_glamor_gbm_init_screen;
+    xwl_screen->egl_backend.get_wl_buffer_for_pixmap = xwl_glamor_gbm_get_wl_buffer_for_pixmap;
+
+    return TRUE;
+}
diff --git a/hw/xwayland/xwayland-glamor.c b/hw/xwayland/xwayland-glamor.c
index 8ffb40d6f..2089c2848 100644
--- a/hw/xwayland/xwayland-glamor.c
+++ b/hw/xwayland/xwayland-glamor.c
@@ -35,17 +35,6 @@
 
 #include <glamor.h>
 #include <glamor_context.h>
-#include <dri3.h>
-#include "drm-client-protocol.h"
-
-static DevPrivateKeyRec xwl_auth_state_private_key;
-
-struct xwl_pixmap {
-    struct wl_buffer *buffer;
-    struct gbm_bo *bo;
-    void *image;
-    unsigned int texture;
-};
 
 static void
 xwl_glamor_egl_make_current(struct glamor_context *glamor_ctx)
@@ -58,38 +47,6 @@ xwl_glamor_egl_make_current(struct glamor_context *glamor_ctx)
         FatalError("Failed to make EGL context current\n");
 }
 
-static uint32_t
-drm_format_for_depth(int depth)
-{
-    switch (depth) {
-    case 15:
-        return WL_DRM_FORMAT_XRGB1555;
-    case 16:
-        return WL_DRM_FORMAT_RGB565;
-    case 24:
-        return WL_DRM_FORMAT_XRGB8888;
-    default:
-        ErrorF("unexpected depth: %d\n", depth);
-    case 32:
-        return WL_DRM_FORMAT_ARGB8888;
-    }
-}
-
-static uint32_t
-gbm_format_for_depth(int depth)
-{
-    switch (depth) {
-    case 16:
-        return GBM_FORMAT_RGB565;
-    case 24:
-        return GBM_FORMAT_XRGB8888;
-    default:
-        ErrorF("unexpected depth: %d\n", depth);
-    case 32:
-        return GBM_FORMAT_ARGB8888;
-    }
-}
-
 void
 glamor_egl_screen_init(ScreenPtr screen, struct glamor_context *glamor_ctx)
 {
@@ -103,121 +60,23 @@ glamor_egl_screen_init(ScreenPtr screen, struct glamor_context *glamor_ctx)
     xwl_screen->glamor_ctx = glamor_ctx;
 }
 
-static PixmapPtr
-xwl_glamor_create_pixmap_for_bo(ScreenPtr screen, struct gbm_bo *bo, int depth)
-{
-    PixmapPtr pixmap;
-    struct xwl_pixmap *xwl_pixmap;
-    struct xwl_screen *xwl_screen = xwl_screen_get(screen);
-
-    xwl_pixmap = malloc(sizeof *xwl_pixmap);
-    if (xwl_pixmap == NULL)
-        return NULL;
-
-    pixmap = glamor_create_pixmap(screen,
-                                  gbm_bo_get_width(bo),
-                                  gbm_bo_get_height(bo),
-                                  depth,
-                                  GLAMOR_CREATE_PIXMAP_NO_TEXTURE);
-    if (pixmap == NULL) {
-        free(xwl_pixmap);
-        return NULL;
-    }
-
-    if (lastGLContext != xwl_screen->glamor_ctx) {
-        lastGLContext = xwl_screen->glamor_ctx;
-        xwl_glamor_egl_make_current(xwl_screen->glamor_ctx);
-    }
-
-    xwl_pixmap->bo = bo;
-    xwl_pixmap->buffer = NULL;
-    xwl_pixmap->image = eglCreateImageKHR(xwl_screen->egl_display,
-                                          xwl_screen->egl_context,
-                                          EGL_NATIVE_PIXMAP_KHR,
-                                          xwl_pixmap->bo, NULL);
-
-    glGenTextures(1, &xwl_pixmap->texture);
-    glBindTexture(GL_TEXTURE_2D, xwl_pixmap->texture);
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-
-    glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, xwl_pixmap->image);
-    glBindTexture(GL_TEXTURE_2D, 0);
-
-    xwl_pixmap_set_private(pixmap, xwl_pixmap);
-
-    glamor_set_pixmap_texture(pixmap, xwl_pixmap->texture);
-    glamor_set_pixmap_type(pixmap, GLAMOR_TEXTURE_DRM);
-
-    return pixmap;
-}
-
 struct wl_buffer *
 xwl_glamor_pixmap_get_wl_buffer(PixmapPtr pixmap)
 {
     struct xwl_screen *xwl_screen = xwl_screen_get(pixmap->drawable.pScreen);
-    struct xwl_pixmap *xwl_pixmap = xwl_pixmap_get(pixmap);
-    int prime_fd;
 
-    if (xwl_pixmap->buffer)
-        return xwl_pixmap->buffer;
-
-    prime_fd = gbm_bo_get_fd(xwl_pixmap->bo);
-    if (prime_fd == -1)
-        return NULL;
-
-    xwl_pixmap->buffer =
-        wl_drm_create_prime_buffer(xwl_screen->drm, prime_fd,
-                                   pixmap->drawable.width,
-                                   pixmap->drawable.height,
-                                   drm_format_for_depth(pixmap->drawable.depth),
-                                   0, gbm_bo_get_stride(xwl_pixmap->bo),
-                                   0, 0,
-                                   0, 0);
-
-    close(prime_fd);
-
-    return xwl_pixmap->buffer;
+    return xwl_screen->egl_backend.get_wl_buffer_for_pixmap(pixmap);
 }
 
-static PixmapPtr
-xwl_glamor_create_pixmap(ScreenPtr screen,
-                         int width, int height, int depth, unsigned int hint)
+void
+xwl_glamor_init_wl_registry(struct xwl_screen *xwl_screen,
+                            struct wl_registry *registry,
+                            uint32_t id, const char *interface,
+                            uint32_t version)
 {
-    struct xwl_screen *xwl_screen = xwl_screen_get(screen);
-    struct gbm_bo *bo;
-
-    if (width > 0 && height > 0 && depth >= 15 &&
-        (hint == 0 ||
-         hint == CREATE_PIXMAP_USAGE_BACKING_PIXMAP ||
-         hint == CREATE_PIXMAP_USAGE_SHARED)) {
-        bo = gbm_bo_create(xwl_screen->gbm, width, height,
-                           gbm_format_for_depth(depth),
-                           GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING);
-
-        if (bo)
-            return xwl_glamor_create_pixmap_for_bo(screen, bo, depth);
-    }
-
-    return glamor_create_pixmap(screen, width, height, depth, hint);
-}
-
-static Bool
-xwl_glamor_destroy_pixmap(PixmapPtr pixmap)
-{
-    struct xwl_screen *xwl_screen = xwl_screen_get(pixmap->drawable.pScreen);
-    struct xwl_pixmap *xwl_pixmap = xwl_pixmap_get(pixmap);
-
-    if (xwl_pixmap && pixmap->refcnt == 1) {
-        if (xwl_pixmap->buffer)
-            wl_buffer_destroy(xwl_pixmap->buffer);
-
-        eglDestroyImageKHR(xwl_screen->egl_display, xwl_pixmap->image);
-        gbm_bo_destroy(xwl_pixmap->bo);
-        free(xwl_pixmap);
-    }
-
-    return glamor_destroy_pixmap(pixmap);
+    if (xwl_screen->egl_backend.init_wl_registry)
+        xwl_screen->egl_backend.init_wl_registry(xwl_screen, registry,
+                                                 interface, id, version);
 }
 
 static Bool
@@ -239,10 +98,9 @@ xwl_glamor_create_screen_resources(ScreenPtr screen)
             fbCreatePixmap(screen, 0, 0, screen->rootDepth, 0);
     }
     else {
-        screen->devPrivate =
-            xwl_glamor_create_pixmap(screen, screen->width, screen->height,
-                                     screen->rootDepth,
-                                     CREATE_PIXMAP_USAGE_BACKING_PIXMAP);
+        screen->devPrivate = screen->CreatePixmap(
+            screen, screen->width, screen->height, screen->rootDepth,
+            CREATE_PIXMAP_USAGE_BACKING_PIXMAP);
     }
 
     SetRootClip(screen, xwl_screen->root_clip_mode);
@@ -250,169 +108,6 @@ xwl_glamor_create_screen_resources(ScreenPtr screen)
     return screen->devPrivate != NULL;
 }
 
-static char
-is_fd_render_node(int fd)
-{
-    struct stat render;
-
-    if (fstat(fd, &render))
-        return 0;
-    if (!S_ISCHR(render.st_mode))
-        return 0;
-    if (render.st_rdev & 0x80)
-        return 1;
-
-    return 0;
-}
-
-static void
-xwl_drm_init_egl(struct xwl_screen *xwl_screen)
-{
-    EGLint major, minor;
-    static const EGLint config_attribs_core[] = {
-        EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR,
-        EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR,
-        EGL_CONTEXT_MAJOR_VERSION_KHR,
-        GLAMOR_GL_CORE_VER_MAJOR,
-        EGL_CONTEXT_MINOR_VERSION_KHR,
-        GLAMOR_GL_CORE_VER_MINOR,
-        EGL_NONE
-    };
-
-    if (xwl_screen->egl_display)
-        return;
-
-    xwl_screen->expecting_event--;
-
-    xwl_screen->gbm = gbm_create_device(xwl_screen->drm_fd);
-    if (xwl_screen->gbm == NULL) {
-        ErrorF("couldn't get display device\n");
-        return;
-    }
-
-    xwl_screen->egl_display = glamor_egl_get_display(EGL_PLATFORM_GBM_MESA,
-                                                     xwl_screen->gbm);
-    if (xwl_screen->egl_display == EGL_NO_DISPLAY) {
-        ErrorF("glamor_egl_get_display() failed\n");
-        return;
-    }
-
-    if (!eglInitialize(xwl_screen->egl_display, &major, &minor)) {
-        ErrorF("eglInitialize() failed\n");
-        return;
-    }
-
-    eglBindAPI(EGL_OPENGL_API);
-
-    xwl_screen->egl_context = eglCreateContext(xwl_screen->egl_display,
-                                               NULL, EGL_NO_CONTEXT, config_attribs_core);
-    if (!xwl_screen->egl_context)
-        xwl_screen->egl_context = eglCreateContext(xwl_screen->egl_display,
-                                                   NULL, EGL_NO_CONTEXT, NULL);
-
-    if (xwl_screen->egl_context == EGL_NO_CONTEXT) {
-        ErrorF("Failed to create EGL context\n");
-        return;
-    }
-
-    if (!eglMakeCurrent(xwl_screen->egl_display,
-                        EGL_NO_SURFACE, EGL_NO_SURFACE,
-                        xwl_screen->egl_context)) {
-        ErrorF("Failed to make EGL context current\n");
-        return;
-    }
-
-    if (!epoxy_has_gl_extension("GL_OES_EGL_image")) {
-        ErrorF("GL_OES_EGL_image not available\n");
-        return;
-    }
-
-    return;
-}
-
-static void
-xwl_drm_handle_device(void *data, struct wl_drm *drm, const char *device)
-{
-   struct xwl_screen *xwl_screen = data;
-   drm_magic_t magic;
-
-   xwl_screen->device_name = strdup(device);
-   if (!xwl_screen->device_name)
-      return;
-
-   xwl_screen->drm_fd = open(xwl_screen->device_name, O_RDWR | O_CLOEXEC);
-   if (xwl_screen->drm_fd == -1) {
-       ErrorF("wayland-egl: could not open %s (%s)\n",
-              xwl_screen->device_name, strerror(errno));
-       return;
-   }
-
-   if (is_fd_render_node(xwl_screen->drm_fd)) {
-       xwl_screen->fd_render_node = 1;
-       xwl_drm_init_egl(xwl_screen);
-   } else {
-       drmGetMagic(xwl_screen->drm_fd, &magic);
-       wl_drm_authenticate(xwl_screen->drm, magic);
-   }
-}
-
-static void
-xwl_drm_handle_format(void *data, struct wl_drm *drm, uint32_t format)
-{
-   struct xwl_screen *xwl_screen = data;
-
-   switch (format) {
-   case WL_DRM_FORMAT_ARGB8888:
-      xwl_screen->formats |= XWL_FORMAT_ARGB8888;
-      break;
-   case WL_DRM_FORMAT_XRGB8888:
-      xwl_screen->formats |= XWL_FORMAT_XRGB8888;
-      break;
-   case WL_DRM_FORMAT_RGB565:
-      xwl_screen->formats |= XWL_FORMAT_RGB565;
-      break;
-   }
-}
-
-static void
-xwl_drm_handle_authenticated(void *data, struct wl_drm *drm)
-{
-    struct xwl_screen *xwl_screen = data;
-
-    if (!xwl_screen->egl_display)
-        xwl_drm_init_egl(xwl_screen);
-}
-
-static void
-xwl_drm_handle_capabilities(void *data, struct wl_drm *drm, uint32_t value)
-{
-   struct xwl_screen *xwl_screen = data;
-
-   xwl_screen->capabilities = value;
-}
-
-static const struct wl_drm_listener xwl_drm_listener = {
-    xwl_drm_handle_device,
-    xwl_drm_handle_format,
-    xwl_drm_handle_authenticated,
-    xwl_drm_handle_capabilities
-};
-
-Bool
-xwl_screen_init_glamor(struct xwl_screen *xwl_screen,
-                       uint32_t id, uint32_t version)
-{
-    if (version < 2)
-        return FALSE;
-
-    xwl_screen->drm =
-        wl_registry_bind(xwl_screen->registry, id, &wl_drm_interface, 2);
-    wl_drm_add_listener(xwl_screen->drm, &xwl_drm_listener, xwl_screen);
-    xwl_screen->expecting_event++;
-
-    return TRUE;
-}
-
 int
 glamor_egl_dri3_fd_name_from_tex(ScreenPtr screen,
                                  PixmapPtr pixmap,
@@ -422,157 +117,6 @@ glamor_egl_dri3_fd_name_from_tex(ScreenPtr screen,
     return 0;
 }
 
-struct xwl_auth_state {
-    int fd;
-    ClientPtr client;
-    struct wl_callback *callback;
-};
-
-static void
-free_xwl_auth_state(ClientPtr pClient, struct xwl_auth_state *state)
-{
-    dixSetPrivate(&pClient->devPrivates, &xwl_auth_state_private_key, NULL);
-    if (state) {
-        wl_callback_destroy(state->callback);
-        free(state);
-    }
-}
-
-static void
-xwl_auth_state_client_callback(CallbackListPtr *pcbl, void *unused, void *data)
-{
-    NewClientInfoRec *clientinfo = (NewClientInfoRec *) data;
-    ClientPtr pClient = clientinfo->client;
-    struct xwl_auth_state *state;
-
-    switch (pClient->clientState) {
-    case ClientStateGone:
-    case ClientStateRetained:
-        state = dixLookupPrivate(&pClient->devPrivates, &xwl_auth_state_private_key);
-        free_xwl_auth_state(pClient, state);
-        break;
-    default:
-        break;
-    }
-}
-
-static void
-sync_callback(void *data, struct wl_callback *callback, uint32_t serial)
-{
-    struct xwl_auth_state *state = data;
-    ClientPtr client = state->client;
-
-    /* if the client is gone, the callback is cancelled so it's safe to
-     * assume the client is still in ClientStateRunning at this point...
-     */
-    dri3_send_open_reply(client, state->fd);
-    AttendClient(client);
-    free_xwl_auth_state(client, state);
-}
-
-static const struct wl_callback_listener sync_listener = {
-   sync_callback
-};
-
-static int
-xwl_dri3_open_client(ClientPtr client,
-                     ScreenPtr screen,
-                     RRProviderPtr provider,
-                     int *pfd)
-{
-    struct xwl_screen *xwl_screen = xwl_screen_get(screen);
-    struct xwl_auth_state *state;
-    drm_magic_t magic;
-    int fd;
-
-    fd = open(xwl_screen->device_name, O_RDWR | O_CLOEXEC);
-    if (fd < 0)
-        return BadAlloc;
-    if (xwl_screen->fd_render_node) {
-        *pfd = fd;
-        return Success;
-    }
-
-    state = malloc(sizeof *state);
-    if (state == NULL) {
-        close(fd);
-        return BadAlloc;
-    }
-
-    state->client = client;
-    state->fd = fd;
-
-    if (drmGetMagic(state->fd, &magic) < 0) {
-        close(state->fd);
-        free(state);
-        return BadMatch;
-    }
-
-    wl_drm_authenticate(xwl_screen->drm, magic);
-    state->callback = wl_display_sync(xwl_screen->display);
-    wl_callback_add_listener(state->callback, &sync_listener, state);
-    dixSetPrivate(&client->devPrivates, &xwl_auth_state_private_key, state);
-
-    IgnoreClient(client);
-
-    return Success;
-}
-
-static PixmapPtr
-xwl_dri3_pixmap_from_fd(ScreenPtr screen, int fd,
-                        CARD16 width, CARD16 height, CARD16 stride,
-                        CARD8 depth, CARD8 bpp)
-{
-    struct xwl_screen *xwl_screen = xwl_screen_get(screen);
-    struct gbm_import_fd_data data;
-    struct gbm_bo *bo;
-    PixmapPtr pixmap;
-
-    if (width == 0 || height == 0 ||
-        depth < 15 || bpp != BitsPerPixel(depth) || stride < width * bpp / 8)
-        return NULL;
-
-    data.fd = fd;
-    data.width = width;
-    data.height = height;
-    data.stride = stride;
-    data.format = gbm_format_for_depth(depth);
-    bo = gbm_bo_import(xwl_screen->gbm, GBM_BO_IMPORT_FD, &data,
-                       GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING);
-    if (bo == NULL)
-        return NULL;
-
-    pixmap = xwl_glamor_create_pixmap_for_bo(screen, bo, depth);
-    if (pixmap == NULL) {
-        gbm_bo_destroy(bo);
-        return NULL;
-    }
-
-    return pixmap;
-}
-
-static int
-xwl_dri3_fd_from_pixmap(ScreenPtr screen, PixmapPtr pixmap,
-                        CARD16 *stride, CARD32 *size)
-{
-    struct xwl_pixmap *xwl_pixmap;
-
-    xwl_pixmap = xwl_pixmap_get(pixmap);
-
-    *stride = gbm_bo_get_stride(xwl_pixmap->bo);
-    *size = pixmap->drawable.width * *stride;
-
-    return gbm_bo_get_fd(xwl_pixmap->bo);
-}
-
-static dri3_screen_info_rec xwl_dri3_info = {
-    .version = 1,
-    .open = NULL,
-    .pixmap_from_fd = xwl_dri3_pixmap_from_fd,
-    .fd_from_pixmap = xwl_dri3_fd_from_pixmap,
-    .open_client = xwl_dri3_open_client,
-};
-
 Bool
 xwl_glamor_init(struct xwl_screen *xwl_screen)
 {
@@ -585,8 +129,8 @@ xwl_glamor_init(struct xwl_screen *xwl_screen)
         return FALSE;
     }
 
-    if (xwl_screen->egl_context == EGL_NO_CONTEXT) {
-        ErrorF("Disabling glamor and dri3, EGL setup failed\n");
+    if (!xwl_screen->egl_backend.init_egl(xwl_screen)) {
+        ErrorF("EGL setup failed, disabling glamor\n");
         return FALSE;
     }
 
@@ -595,25 +139,13 @@ xwl_glamor_init(struct xwl_screen *xwl_screen)
         return FALSE;
     }
 
-    if (!dri3_screen_init(xwl_screen->screen, &xwl_dri3_info)) {
-        ErrorF("Failed to initialize dri3\n");
-        return FALSE;
-    }
-
-    if (!dixRegisterPrivateKey(&xwl_auth_state_private_key, PRIVATE_CLIENT, 0)) {
-        ErrorF("Failed to register private key\n");
-        return FALSE;
-    }
-
-    if (!AddCallback(&ClientStateCallback, xwl_auth_state_client_callback, NULL)) {
-        ErrorF("Failed to add client state callback\n");
+    if (!xwl_screen->egl_backend.init_screen(xwl_screen)) {
+        ErrorF("EGL backend init_screen() failed, disabling glamor\n");
         return FALSE;
     }
 
     xwl_screen->CreateScreenResources = screen->CreateScreenResources;
     screen->CreateScreenResources = xwl_glamor_create_screen_resources;
-    screen->CreatePixmap = xwl_glamor_create_pixmap;
-    screen->DestroyPixmap = xwl_glamor_destroy_pixmap;
 
 #ifdef XV
     if (!xwl_glamor_xv_init(screen))
diff --git a/hw/xwayland/xwayland.c b/hw/xwayland/xwayland.c
index 9b1d85674..979b72918 100644
--- a/hw/xwayland/xwayland.c
+++ b/hw/xwayland/xwayland.c
@@ -726,9 +726,9 @@ registry_global(void *data, struct wl_registry *registry, uint32_t id,
         xwl_screen_init_xdg_output(xwl_screen);
     }
 #ifdef GLAMOR_HAS_GBM
-    else if (xwl_screen->glamor &&
-             strcmp(interface, "wl_drm") == 0 && version >= 2) {
-        xwl_screen_init_glamor(xwl_screen, id, version);
+    else if (xwl_screen->glamor) {
+        xwl_glamor_init_wl_registry(xwl_screen, registry, id, interface,
+                                    version);
     }
 #endif
 }
@@ -937,6 +937,13 @@ xwl_screen_init(ScreenPtr pScreen, int argc, char **argv)
         }
     }
 
+    if (xwl_screen->glamor) {
+        if (!xwl_glamor_init_gbm(xwl_screen)) {
+            ErrorF("xwayland glamor: failed to setup GBM backend, falling back to sw accel\n");
+            xwl_screen->glamor = 0;
+        }
+    }
+
     /* In rootless mode, we don't have any screen storage, and the only
      * rendering should be to redirected mode. */
     if (xwl_screen->rootless)
diff --git a/hw/xwayland/xwayland.h b/hw/xwayland/xwayland.h
index ffa0d7297..88e9ec832 100644
--- a/hw/xwayland/xwayland.h
+++ b/hw/xwayland/xwayland.h
@@ -48,6 +48,9 @@
 #include "xwayland-keyboard-grab-unstable-v1-client-protocol.h"
 #include "xdg-output-unstable-v1-client-protocol.h"
 
+struct xwl_pixmap;
+struct xwl_window;
+
 struct xwl_screen {
     int width;
     int height;
@@ -93,14 +96,41 @@ struct xwl_screen {
     int prepare_read;
     int wait_flush;
 
-    char *device_name;
-    int drm_fd;
-    int fd_render_node;
-    struct wl_drm *drm;
     uint32_t formats;
-    uint32_t capabilities;
     void *egl_display, *egl_context;
-    struct gbm_device *gbm;
+
+    /* the current backend for creating pixmaps on wayland */
+    struct {
+        /* Called once for each interface in the global registry. Backends
+         * should use this to bind to any wayland interfaces they need. This
+         * callback is optional.
+         */
+        void (*init_wl_registry)(struct xwl_screen *xwl_screen,
+                                 struct wl_registry *wl_registry,
+                                 const char *name, uint32_t id,
+                                 uint32_t version);
+
+        /* Called before glamor has been initialized. Backends should setup a
+         * valid, glamor compatible EGL context in this hook.
+         */
+        Bool (*init_egl)(struct xwl_screen *xwl_screen);
+
+        /* Called after glamor has been initialized, and after all of the
+         * common Xwayland DDX hooks have been connected. Backends should use
+         * this to setup any required wraps around X server callbacks like
+         * CreatePixmap.
+         */
+        Bool (*init_screen)(struct xwl_screen *xwl_screen);
+
+        /* Called by Xwayland to retrieve a pointer to a valid wl_buffer for
+         * the given window/pixmap combo so that damage to the pixmap may be
+         * displayed on-screen. Backends should use this to create a new
+         * wl_buffer for a currently buffer-less pixmap, or simply return the
+         * pixmap they've prepared beforehand.
+         */
+        struct wl_buffer *(*get_wl_buffer_for_pixmap)(PixmapPtr pixmap);
+    } egl_backend;
+
     struct glamor_context *glamor_ctx;
 
     Atom allow_commits_prop;
@@ -272,8 +302,6 @@ struct xwl_output {
     Bool xdg_output_done;
 };
 
-struct xwl_pixmap;
-
 void xwl_sync_events (struct xwl_screen *xwl_screen);
 
 Bool xwl_screen_init_cursor(struct xwl_screen *xwl_screen);
@@ -326,9 +354,11 @@ struct wl_buffer *xwl_shm_pixmap_get_wl_buffer(PixmapPtr pixmap);
 
 Bool xwl_glamor_init(struct xwl_screen *xwl_screen);
 
-Bool xwl_screen_init_glamor(struct xwl_screen *xwl_screen,
-                         uint32_t id, uint32_t version);
 struct wl_buffer *xwl_glamor_pixmap_get_wl_buffer(PixmapPtr pixmap);
+void xwl_glamor_init_wl_registry(struct xwl_screen *xwl_screen,
+                                 struct wl_registry *registry,
+                                 uint32_t id, const char *interface,
+                                 uint32_t version);
 
 void xwl_screen_release_tablet_manager(struct xwl_screen *xwl_screen);
 
@@ -344,4 +374,8 @@ Bool xwl_glamor_xv_init(ScreenPtr pScreen);
 void xwlVidModeExtensionInit(void);
 #endif
 
+#ifdef GLAMOR_HAS_GBM
+Bool xwl_glamor_init_gbm(struct xwl_screen *xwl_screen);
+#endif
+
 #endif
-- 
2.14.3



More information about the xorg-devel mailing list