[PATCH xserver 1/3] xwayland: Decouple GBM from glamor

Lyude Paul lyude at redhat.com
Fri Apr 20 21:23:57 UTC 2018


lgtm! for the whole series:

Reviewed-by: Lyude Paul <lyude at redhat.com>

On Fri, 2018-04-20 at 14:38 -0400, Adam Jackson wrote:
> From: Lyude Paul <lyude at redhat.com>
> 
> 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           |   1 +
>  hw/xwayland/meson.build           |   6 +-
>  hw/xwayland/xwayland-glamor-gbm.c | 892 ++++++++++++++++++++++++++++++
>  hw/xwayland/xwayland-glamor.c     | 760 +------------------------
>  hw/xwayland/xwayland.c            |  17 +-
>  hw/xwayland/xwayland.h            |  58 +-
>  6 files changed, 976 insertions(+), 758 deletions(-)
>  create mode 100644 hw/xwayland/xwayland-glamor-gbm.c
> 
> diff --git a/hw/xwayland/Makefile.am b/hw/xwayland/Makefile.am
> index 80d3a1f199..3fd980d0ee 100644
> --- a/hw/xwayland/Makefile.am
> +++ b/hw/xwayland/Makefile.am
> @@ -35,6 +35,7 @@ Xwayland_built_sources =
>  if GLAMOR_EGL
>  Xwayland_SOURCES += 				\
>  	xwayland-glamor.c			\
> +	xwayland-glamor-gbm.c			\
>  	xwayland-present.c
>  if XV
>  Xwayland_SOURCES += 				\
> diff --git a/hw/xwayland/meson.build b/hw/xwayland/meson.build
> index 8d178825e7..ef4379aab0 100644
> --- a/hw/xwayland/meson.build
> +++ b/hw/xwayland/meson.build
> @@ -52,7 +52,11 @@ srcs += code.process(dmabuf_xml)
>  
>  xwayland_glamor = []
>  if gbm_dep.found()
> -    srcs += [ 'xwayland-glamor.c', 'xwayland-present.c' ]
> +    srcs += [
> +        'xwayland-glamor.c',
> +        'xwayland-glamor-gbm.c',
> +        'xwayland-present.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 0000000000..7be1437e86
> --- /dev/null
> +++ b/hw/xwayland/xwayland-glamor-gbm.c
> @@ -0,0 +1,892 @@
> +/*
> + * 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>
> +#include <drm_fourcc.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 {
> +    char *device_name;
> +    struct gbm_device *gbm;
> +    struct wl_drm *drm;
> +    struct zwp_linux_dmabuf_v1 *dmabuf;
> +    int drm_fd;
> +    int fd_render_node;
> +    Bool drm_authenticated;
> +    uint32_t capabilities;
> +    int dmabuf_capable;
> +};
> +
> +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;
> +    case 30:
> +        return GBM_FORMAT_ARGB2101010;
> +    default:
> +        ErrorF("unexpected depth: %d\n", depth);
> +    case 32:
> +        return GBM_FORMAT_ARGB8888;
> +    }
> +}
> +
> +static uint32_t
> +wl_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;
> +    case 30:
> +        return WL_DRM_FORMAT_ARGB2101010;
> +    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)) {
> +        uint32_t format = gbm_format_for_depth(depth);
> +
> +#ifdef GBM_BO_WITH_MODIFIERS
> +        if (xwl_gbm->dmabuf_capable) {
> +            uint32_t num_modifiers;
> +            uint64_t *modifiers = NULL;
> +
> +            glamor_get_modifiers(screen, format, &num_modifiers,
> &modifiers);
> +            bo = gbm_bo_create_with_modifiers(xwl_gbm->gbm, width, height,
> +                                              format, modifiers,
> num_modifiers);
> +            free(modifiers);
> +        }
> +        else
> +#endif
> +        {
> +            bo = gbm_bo_create(xwl_gbm->gbm, width, height, format,
> +                               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);
> +        if (xwl_pixmap->bo)
> +           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,
> +                                        unsigned short width,
> +                                        unsigned short height,
> +                                        Bool *created)
> +{
> +    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);
> +    int prime_fd;
> +    int num_planes;
> +    uint32_t strides[4];
> +    uint32_t offsets[4];
> +    uint64_t modifier;
> +    int i;
> +
> +    if (xwl_pixmap->buffer) {
> +        /* Buffer already exists. Return it and inform caller if
> interested. */
> +        if (created)
> +            *created = FALSE;
> +        return xwl_pixmap->buffer;
> +    }
> +
> +    /* Buffer does not exist yet. Create now and inform caller if
> interested. */
> +    if (created)
> +        *created = TRUE;
> +
> +    if (!xwl_pixmap->bo)
> +       return NULL;
> +
> +    prime_fd = gbm_bo_get_fd(xwl_pixmap->bo);
> +    if (prime_fd == -1)
> +        return NULL;
> +
> +#ifdef GBM_BO_WITH_MODIFIERS
> +    num_planes = gbm_bo_get_plane_count(xwl_pixmap->bo);
> +    modifier = gbm_bo_get_modifier(xwl_pixmap->bo);
> +    for (i = 0; i < num_planes; i++) {
> +        strides[i] = gbm_bo_get_stride_for_plane(xwl_pixmap->bo, i);
> +        offsets[i] = gbm_bo_get_offset(xwl_pixmap->bo, i);
> +    }
> +#else
> +    num_planes = 1;
> +    modifier = DRM_FORMAT_MOD_INVALID;
> +    strides[0] = gbm_go_get_stride(xwl_pixmap->bo);
> +    offsets[0] = 0;
> +#endif
> +
> +    if (xwl_gbm->dmabuf && modifier != DRM_FORMAT_MOD_INVALID) {
> +        struct zwp_linux_buffer_params_v1 *params;
> +
> +        params = zwp_linux_dmabuf_v1_create_params(xwl_gbm->dmabuf);
> +        for (i = 0; i < num_planes; i++) {
> +            zwp_linux_buffer_params_v1_add(params, prime_fd, i,
> +                                           offsets[i], strides[i],
> +                                           modifier >> 32, modifier &
> 0xffffffff);
> +        }
> +
> +        xwl_pixmap->buffer =
> +           zwp_linux_buffer_params_v1_create_immed(params, width, height,
> +                                                   wl_drm_format_for_depth(
> pixmap->drawable.depth),
> +                                                   0);
> +        zwp_linux_buffer_params_v1_destroy(params);
> +    } else if (num_planes == 1) {
> +        xwl_pixmap->buffer =
> +            wl_drm_create_prime_buffer(xwl_gbm->drm, prime_fd, width,
> height,
> +                                       wl_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;
> +}
> +
> +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;
> +}
> +
> +_X_EXPORT PixmapPtr
> +glamor_pixmap_from_fds(ScreenPtr screen, CARD8 num_fds, const int *fds,
> +                       CARD16 width, CARD16 height,
> +                       const CARD32 *strides, const CARD32 *offsets,
> +                       CARD8 depth, CARD8 bpp, uint64_t modifier)
> +{
> +    struct xwl_screen *xwl_screen = xwl_screen_get(screen);
> +    struct xwl_gbm_private *xwl_gbm = xwl_gbm_get(xwl_screen);
> +    struct gbm_bo *bo = NULL;
> +    PixmapPtr pixmap;
> +    int i;
> +
> +    if (width == 0 || height == 0 || num_fds == 0 ||
> +        depth < 15 || bpp != BitsPerPixel(depth) ||
> +        strides[0] < width * bpp / 8)
> +       goto error;
> +
> +    if (xwl_gbm->dmabuf_capable && modifier != DRM_FORMAT_MOD_INVALID) {
> +#ifdef GBM_BO_WITH_MODIFIERS
> +       struct gbm_import_fd_modifier_data data;
> +
> +       data.width = width;
> +       data.height = height;
> +       data.num_fds = num_fds;
> +       data.format = gbm_format_for_depth(depth);
> +       data.modifier = modifier;
> +       for (i = 0; i < num_fds; i++) {
> +          data.fds[i] = fds[i];
> +          data.strides[i] = strides[i];
> +          data.offsets[i] = offsets[i];
> +       }
> +       bo = gbm_bo_import(xwl_gbm->gbm, GBM_BO_IMPORT_FD_MODIFIER, &data,
> 0);
> +#endif
> +    } else if (num_fds == 1) {
> +       struct gbm_import_fd_data data;
> +
> +       data.fd = fds[0];
> +       data.width = width;
> +       data.height = height;
> +       data.stride = strides[0];
> +       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);
> +    } else {
> +       goto error;
> +    }
> +
> +    if (bo == NULL)
> +       goto error;
> +
> +    pixmap = xwl_glamor_gbm_create_pixmap_for_bo(screen, bo, depth);
> +    if (pixmap == NULL) {
> +       gbm_bo_destroy(bo);
> +       goto error;
> +    }
> +
> +    return pixmap;
> +
> +error:
> +    return NULL;
> +}
> +
> +_X_EXPORT int
> +glamor_egl_fds_from_pixmap(ScreenPtr screen, PixmapPtr pixmap, int *fds,
> +                           uint32_t *strides, uint32_t *offsets,
> +                           uint64_t *modifier)
> +{
> +    struct xwl_pixmap *xwl_pixmap;
> +#ifdef GBM_BO_WITH_MODIFIERS
> +    uint32_t num_fds;
> +    int i;
> +#endif
> +
> +    xwl_pixmap = xwl_pixmap_get(pixmap);
> +
> +    if (!xwl_pixmap->bo)
> +       return 0;
> +
> +#ifdef GBM_BO_WITH_MODIFIERS
> +    num_fds = gbm_bo_get_plane_count(xwl_pixmap->bo);
> +    *modifier = gbm_bo_get_modifier(xwl_pixmap->bo);
> +
> +    for (i = 0; i < num_fds; i++) {
> +        fds[i] = gbm_bo_get_fd(xwl_pixmap->bo);
> +        strides[i] = gbm_bo_get_stride_for_plane(xwl_pixmap->bo, i);
> +        offsets[i] = gbm_bo_get_offset(xwl_pixmap->bo, i);
> +    }
> +
> +    return num_fds;
> +#else
> +    *modifier = DRM_FORMAT_MOD_INVALID;
> +    fds[0] = gbm_bo_get_fd(xwl_pixmap->bo);
> +    strides[0] = gbm_bo_get_stride(xwl_pixmap->bo);
> +    offsets[0] = 0;
> +    return 1;
> +#endif
> +}
> +
> +_X_EXPORT Bool
> +glamor_get_formats(ScreenPtr screen,
> +                   CARD32 *num_formats, CARD32 **formats)
> +{
> +    struct xwl_screen *xwl_screen = xwl_screen_get(screen);
> +    struct xwl_gbm_private *xwl_gbm = xwl_gbm_get(xwl_screen);
> +    int i;
> +
> +    if (!xwl_gbm->dmabuf_capable || !xwl_gbm->dmabuf)
> +        return FALSE;
> +
> +    if (xwl_screen->num_formats == 0) {
> +       *num_formats = 0;
> +       return TRUE;
> +    }
> +
> +    *formats = calloc(xwl_screen->num_formats, sizeof(CARD32));
> +    if (*formats == NULL) {
> +        *num_formats = 0;
> +        return FALSE;
> +    }
> +
> +    for (i = 0; i < xwl_screen->num_formats; i++)
> +       (*formats)[i] = xwl_screen->formats[i].format;
> +    *num_formats = xwl_screen->num_formats;
> +
> +    return TRUE;
> +}
> +
> +_X_EXPORT Bool
> +glamor_get_modifiers(ScreenPtr screen, CARD32 format,
> +                     CARD32 *num_modifiers, uint64_t **modifiers)
> +{
> +    struct xwl_screen *xwl_screen = xwl_screen_get(screen);
> +    struct xwl_gbm_private *xwl_gbm = xwl_gbm_get(xwl_screen);
> +    struct xwl_format *xwl_format = NULL;
> +    int i;
> +
> +    if (!xwl_gbm->dmabuf_capable || !xwl_gbm->dmabuf)
> +        return FALSE;
> +
> +    /* Explicitly zero the count as the caller may ignore the return value
> */
> +    *num_modifiers = 0;
> +
> +    if (xwl_screen->num_formats == 0)
> +       return TRUE;
> +
> +    for (i = 0; i < xwl_screen->num_formats; i++) {
> +       if (xwl_screen->formats[i].format == format) {
> +          xwl_format = &xwl_screen->formats[i];
> +          break;
> +       }
> +    }
> +
> +    if (!xwl_format)
> +        return FALSE;
> +
> +    *modifiers = calloc(xwl_format->num_modifiers, sizeof(uint64_t));
> +    if (*modifiers == NULL)
> +        return FALSE;
> +
> +    for (i = 0; i < xwl_format->num_modifiers; i++)
> +       (*modifiers)[i] = xwl_format->modifiers[i];
> +    *num_modifiers = xwl_format->num_modifiers;
> +
> +    return TRUE;
> +}
> +
> +static const dri3_screen_info_rec xwl_dri3_info = {
> +    .version = 2,
> +    .open = NULL,
> +    .pixmap_from_fds = glamor_pixmap_from_fds,
> +    .fds_from_pixmap = glamor_fds_from_pixmap,
> +    .open_client = xwl_dri3_open_client,
> +    .get_formats = glamor_get_formats,
> +    .get_modifiers = glamor_get_modifiers,
> +    .get_drawable_modifiers = glamor_get_drawable_modifiers,
> +};
> +
> +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)
> +{
> +}
> +
> +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_dmabuf_handle_format(void *data, struct zwp_linux_dmabuf_v1 *dmabuf,
> +                         uint32_t format)
> +{
> +}
> +
> +static void
> +xwl_dmabuf_handle_modifier(void *data, struct zwp_linux_dmabuf_v1 *dmabuf,
> +                           uint32_t format, uint32_t modifier_hi,
> +                           uint32_t modifier_lo)
> +{
> +   struct xwl_screen *xwl_screen = data;
> +    struct xwl_format *xwl_format = NULL;
> +    int i;
> +
> +    for (i = 0; i < xwl_screen->num_formats; i++) {
> +        if (xwl_screen->formats[i].format == format) {
> +            xwl_format = &xwl_screen->formats[i];
> +            break;
> +        }
> +    }
> +
> +    if (xwl_format == NULL) {
> +       xwl_screen->num_formats++;
> +       xwl_screen->formats = realloc(xwl_screen->formats,
> +                                     xwl_screen->num_formats *
> sizeof(*xwl_format));
> +       if (!xwl_screen->formats)
> +          return;
> +       xwl_format = &xwl_screen->formats[xwl_screen->num_formats - 1];
> +       xwl_format->format = format;
> +       xwl_format->num_modifiers = 0;
> +       xwl_format->modifiers = NULL;
> +    }
> +
> +    xwl_format->num_modifiers++;
> +    xwl_format->modifiers = realloc(xwl_format->modifiers,
> +                                    xwl_format->num_modifiers *
> sizeof(uint64_t));
> +    if (!xwl_format->modifiers)
> +       return;
> +    xwl_format->modifiers[xwl_format->num_modifiers - 1]  = (uint64_t)
> modifier_lo;
> +    xwl_format->modifiers[xwl_format->num_modifiers - 1] |= (uint64_t)
> modifier_hi << 32;
> +}
> +
> +static const struct zwp_linux_dmabuf_v1_listener xwl_dmabuf_listener = {
> +    .format   = xwl_dmabuf_handle_format,
> +    .modifier = xwl_dmabuf_handle_modifier
> +};
> +
> +Bool
> +xwl_screen_set_drm_interface(struct xwl_screen *xwl_screen,
> +                             uint32_t id, uint32_t version)
> +{
> +    struct xwl_gbm_private *xwl_gbm = xwl_gbm_get(xwl_screen);
> +
> +    if (version < 2)
> +        return FALSE;
> +
> +    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++;
> +
> +    return TRUE;
> +}
> +
> +Bool
> +xwl_screen_set_dmabuf_interface(struct xwl_screen *xwl_screen,
> +                                uint32_t id, uint32_t version)
> +{
> +    struct xwl_gbm_private *xwl_gbm = xwl_gbm_get(xwl_screen);
> +
> +    if (version < 3)
> +        return FALSE;
> +
> +    xwl_gbm->dmabuf =
> +        wl_registry_bind(xwl_screen->registry, id,
> &zwp_linux_dmabuf_v1_interface, 3);
> +    zwp_linux_dmabuf_v1_add_listener(xwl_gbm->dmabuf, &xwl_dmabuf_listener,
> xwl_screen);
> +
> +    return TRUE;
> +}
> +
> +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)
> +{
> +    if (strcmp(name, "wl_drm") == 0)
> +        xwl_screen_set_drm_interface(xwl_screen, id, version);
> +    else if (strcmp(name, "zwp_linux_dmabuf_v1") == 0)
> +        xwl_screen_set_dmabuf_interface(xwl_screen, id, version);
> +}
> +
> +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
> +    };
> +
> +    if (!xwl_gbm->fd_render_node && !xwl_gbm->drm_authenticated) {
> +        ErrorF("Failed to get wl_drm, disabling Glamor and DRI3\n");
> +	return FALSE;
> +    }
> +
> +    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");
> +
> +    if (epoxy_has_egl_extension(xwl_screen->egl_display,
> +                                "EXT_image_dma_buf_import") &&
> +        epoxy_has_egl_extension(xwl_screen->egl_display,
> +                                "EXT_image_dma_buf_import_modifiers"))
> +       xwl_gbm->dmabuf_capable = TRUE;
> +
> +    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 1b9a6b0309..7b24ce7e40 100644
> --- a/hw/xwayland/xwayland-glamor.c
> +++ b/hw/xwayland/xwayland-glamor.c
> @@ -25,28 +25,11 @@
>  
>  #include "xwayland.h"
>  
> -#include <fcntl.h>
> -#include <sys/stat.h>
> -#include <xf86drm.h>
> -#include <drm_fourcc.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"
> -
> -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)
> @@ -59,42 +42,6 @@ xwl_glamor_egl_make_current(struct glamor_context
> *glamor_ctx)
>          FatalError("Failed to make EGL context current\n");
>  }
>  
> -static uint32_t
> -wl_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;
> -    case 30:
> -        return WL_DRM_FORMAT_ARGB2101010;
> -    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;
> -    case 30:
> -        return GBM_FORMAT_ARGB2101010;
> -    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)
>  {
> @@ -108,53 +55,15 @@ 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)
> +void
> +xwl_glamor_init_wl_registry(struct xwl_screen *xwl_screen,
> +                            struct wl_registry *registry,
> +                            uint32_t id, const char *interface,
> +                            uint32_t version)
>  {
> -    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;
> +    if (xwl_screen->egl_backend.init_wl_registry)
> +        xwl_screen->egl_backend.init_wl_registry(xwl_screen, registry,
> +                                                 interface, id, version);
>  }
>  
>  struct wl_buffer *
> @@ -164,133 +73,14 @@ xwl_glamor_pixmap_get_wl_buffer(PixmapPtr pixmap,
>                                  Bool *created)
>  {
>      struct xwl_screen *xwl_screen = xwl_screen_get(pixmap-
> >drawable.pScreen);
> -    struct xwl_pixmap *xwl_pixmap = xwl_pixmap_get(pixmap);
> -    int prime_fd;
> -    int num_planes;
> -    uint32_t strides[4];
> -    uint32_t offsets[4];
> -    uint64_t modifier;
> -    int i;
>  
> -    if (xwl_pixmap->buffer) {
> -        /* Buffer already exists. Return it and inform caller if
> interested. */
> -        if (created)
> -            *created = FALSE;
> -        return xwl_pixmap->buffer;
> -    }
> +    if (xwl_screen->egl_backend.get_wl_buffer_for_pixmap)
> +        return xwl_screen->egl_backend.get_wl_buffer_for_pixmap(pixmap,
> +                                                                width,
> +                                                                height,
> +                                                                created);
>  
> -    /* Buffer does not exist yet. Create now and inform caller if
> interested. */
> -    if (created)
> -        *created = TRUE;
> -
> -    if (!xwl_pixmap->bo)
> -       return NULL;
> -
> -    prime_fd = gbm_bo_get_fd(xwl_pixmap->bo);
> -    if (prime_fd == -1)
> -        return NULL;
> -
> -#ifdef GBM_BO_WITH_MODIFIERS
> -    num_planes = gbm_bo_get_plane_count(xwl_pixmap->bo);
> -    modifier = gbm_bo_get_modifier(xwl_pixmap->bo);
> -    for (i = 0; i < num_planes; i++) {
> -        strides[i] = gbm_bo_get_stride_for_plane(xwl_pixmap->bo, i);
> -        offsets[i] = gbm_bo_get_offset(xwl_pixmap->bo, i);
> -    }
> -#else
> -    num_planes = 1;
> -    modifier = DRM_FORMAT_MOD_INVALID;
> -    strides[0] = gbm_go_get_stride(xwl_pixmap->bo);
> -    offsets[0] = 0;
> -#endif
> -
> -    if (xwl_screen->dmabuf && modifier != DRM_FORMAT_MOD_INVALID) {
> -        struct zwp_linux_buffer_params_v1 *params;
> -
> -        params = zwp_linux_dmabuf_v1_create_params(xwl_screen->dmabuf);
> -        for (i = 0; i < num_planes; i++) {
> -            zwp_linux_buffer_params_v1_add(params, prime_fd, i,
> -                                           offsets[i], strides[i],
> -                                           modifier >> 32, modifier &
> 0xffffffff);
> -        }
> -
> -        xwl_pixmap->buffer =
> -           zwp_linux_buffer_params_v1_create_immed(params,
> -                                                   width,
> -                                                   height,
> -                                                   wl_drm_format_for_depth(
> pixmap->drawable.depth),
> -                                                   0);
> -        zwp_linux_buffer_params_v1_destroy(params);
> -    } else if (num_planes == 1) {
> -        xwl_pixmap->buffer =
> -            wl_drm_create_prime_buffer(xwl_screen->drm, prime_fd,
> -                                       width,
> -                                       height,
> -                                       wl_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;
> -}
> -
> -static PixmapPtr
> -xwl_glamor_create_pixmap(ScreenPtr screen,
> -                         int width, int height, int depth, unsigned int
> hint)
> -{
> -    struct xwl_screen *xwl_screen = xwl_screen_get(screen);
> -    struct gbm_bo *bo;
> -    uint32_t format;
> -
> -    if (width > 0 && height > 0 && depth >= 15 &&
> -        (hint == 0 ||
> -         hint == CREATE_PIXMAP_USAGE_BACKING_PIXMAP ||
> -         hint == CREATE_PIXMAP_USAGE_SHARED)) {
> -        format = gbm_format_for_depth(depth);
> -
> -#ifdef GBM_BO_WITH_MODIFIERS
> -        if (xwl_screen->dmabuf_capable) {
> -            uint32_t num_modifiers;
> -            uint64_t *modifiers = NULL;
> -
> -            glamor_get_modifiers(screen, format, &num_modifiers,
> &modifiers);
> -            bo = gbm_bo_create_with_modifiers(xwl_screen->gbm, width,
> height,
> -                                              format, modifiers,
> num_modifiers);
> -            free(modifiers);
> -        }
> -        else
> -#endif
> -        {
> -            bo = gbm_bo_create(xwl_screen->gbm, width, height, format,
> -                               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);
> -        if (xwl_pixmap->bo)
> -           gbm_bo_destroy(xwl_pixmap->bo);
> -        free(xwl_pixmap);
> -    }
> -
> -    return glamor_destroy_pixmap(pixmap);
> +    return NULL;
>  }
>  
>  static Bool
> @@ -312,10 +102,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);
> @@ -323,224 +112,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->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;
> -    }
> -
> -    if (epoxy_has_egl_extension(xwl_screen->egl_display,
> -                                "EXT_image_dma_buf_import") &&
> -        epoxy_has_egl_extension(xwl_screen->egl_display,
> -                                "EXT_image_dma_buf_import_modifiers"))
> -       xwl_screen->dmabuf_capable = TRUE;
> -
> -    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;
> -   }
> -
> -   xwl_screen->expecting_event--;
> -
> -   if (is_fd_render_node(xwl_screen->drm_fd)) {
> -       xwl_screen->fd_render_node = 1;
> -   } else {
> -       drmGetMagic(xwl_screen->drm_fd, &magic);
> -       wl_drm_authenticate(xwl_screen->drm, magic);
> -       xwl_screen->expecting_event++; /* wait for 'authenticated' */
> -   }
> -}
> -
> -static void
> -xwl_drm_handle_format(void *data, struct wl_drm *drm, uint32_t format)
> -{
> -}
> -
> -static void
> -xwl_drm_handle_authenticated(void *data, struct wl_drm *drm)
> -{
> -    struct xwl_screen *xwl_screen = data;
> -
> -    xwl_screen->drm_authenticated = 1;
> -    xwl_screen->expecting_event--;
> -}
> -
> -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
> -};
> -
> -static void
> -xwl_dmabuf_handle_format(void *data, struct zwp_linux_dmabuf_v1 *dmabuf,
> -                         uint32_t format)
> -{
> -}
> -
> -static void
> -xwl_dmabuf_handle_modifier(void *data, struct zwp_linux_dmabuf_v1 *dmabuf,
> -                           uint32_t format, uint32_t modifier_hi,
> -                           uint32_t modifier_lo)
> -{
> -   struct xwl_screen *xwl_screen = data;
> -    struct xwl_format *xwl_format = NULL;
> -    int i;
> -
> -    for (i = 0; i < xwl_screen->num_formats; i++) {
> -        if (xwl_screen->formats[i].format == format) {
> -            xwl_format = &xwl_screen->formats[i];
> -            break;
> -        }
> -    }
> -
> -    if (xwl_format == NULL) {
> -       xwl_screen->num_formats++;
> -       xwl_screen->formats = realloc(xwl_screen->formats,
> -                                     xwl_screen->num_formats *
> sizeof(*xwl_format));
> -       if (!xwl_screen->formats)
> -          return;
> -       xwl_format = &xwl_screen->formats[xwl_screen->num_formats - 1];
> -       xwl_format->format = format;
> -       xwl_format->num_modifiers = 0;
> -       xwl_format->modifiers = NULL;
> -    }
> -
> -    xwl_format->num_modifiers++;
> -    xwl_format->modifiers = realloc(xwl_format->modifiers,
> -                                    xwl_format->num_modifiers *
> sizeof(uint64_t));
> -    if (!xwl_format->modifiers)
> -       return;
> -    xwl_format->modifiers[xwl_format->num_modifiers - 1]  = (uint64_t)
> modifier_lo;
> -    xwl_format->modifiers[xwl_format->num_modifiers - 1] |= (uint64_t)
> modifier_hi << 32;
> -}
> -
> -static const struct zwp_linux_dmabuf_v1_listener xwl_dmabuf_listener = {
> -    .format   = xwl_dmabuf_handle_format,
> -    .modifier = xwl_dmabuf_handle_modifier
> -};
> -
> -Bool
> -xwl_screen_set_drm_interface(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;
> -}
> -
> -Bool
> -xwl_screen_set_dmabuf_interface(struct xwl_screen *xwl_screen,
> -                                uint32_t id, uint32_t version)
> -{
> -    if (version < 3)
> -        return FALSE;
> -
> -    xwl_screen->dmabuf =
> -        wl_registry_bind(xwl_screen->registry, id,
> &zwp_linux_dmabuf_v1_interface, 3);
> -    zwp_linux_dmabuf_v1_add_listener(xwl_screen->dmabuf,
> &xwl_dmabuf_listener, xwl_screen);
> -
> -    return TRUE;
> -}
> -
>  int
>  glamor_egl_fd_name_from_pixmap(ScreenPtr screen,
>                                 PixmapPtr pixmap,
> @@ -549,277 +120,6 @@ glamor_egl_fd_name_from_pixmap(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;
> -}
> -
> -_X_EXPORT PixmapPtr
> -glamor_pixmap_from_fds(ScreenPtr screen,
> -                       CARD8 num_fds, const int *fds,
> -                       CARD16 width, CARD16 height,
> -                       const CARD32 *strides, const CARD32 *offsets,
> -                       CARD8 depth, CARD8 bpp, uint64_t modifier)
> -{
> -    struct xwl_screen *xwl_screen = xwl_screen_get(screen);
> -    struct gbm_bo *bo = NULL;
> -    PixmapPtr pixmap;
> -    int i;
> -
> -    if (width == 0 || height == 0 || num_fds == 0 ||
> -        depth < 15 || bpp != BitsPerPixel(depth) ||
> -        strides[0] < width * bpp / 8)
> -       goto error;
> -
> -    if (xwl_screen->dmabuf_capable && modifier != DRM_FORMAT_MOD_INVALID) {
> -#ifdef GBM_BO_WITH_MODIFIERS
> -       struct gbm_import_fd_modifier_data data;
> -
> -       data.width = width;
> -       data.height = height;
> -       data.num_fds = num_fds;
> -       data.format = gbm_format_for_depth(depth);
> -       data.modifier = modifier;
> -       for (i = 0; i < num_fds; i++) {
> -          data.fds[i] = fds[i];
> -          data.strides[i] = strides[i];
> -          data.offsets[i] = offsets[i];
> -       }
> -       bo = gbm_bo_import(xwl_screen->gbm, GBM_BO_IMPORT_FD_MODIFIER,
> &data, 0);
> -#endif
> -    } else if (num_fds == 1) {
> -       struct gbm_import_fd_data data;
> -
> -       data.fd = fds[0];
> -       data.width = width;
> -       data.height = height;
> -       data.stride = strides[0];
> -       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);
> -    } else {
> -       goto error;
> -    }
> -
> -    if (bo == NULL)
> -       goto error;
> -
> -    pixmap = xwl_glamor_create_pixmap_for_bo(screen, bo, depth);
> -    if (pixmap == NULL) {
> -       gbm_bo_destroy(bo);
> -       goto error;
> -    }
> -
> -    return pixmap;
> -
> -error:
> -    return NULL;
> -}
> -
> -_X_EXPORT int
> -glamor_egl_fds_from_pixmap(ScreenPtr screen, PixmapPtr pixmap, int *fds,
> -                           uint32_t *strides, uint32_t *offsets,
> -                           uint64_t *modifier)
> -{
> -    struct xwl_pixmap *xwl_pixmap;
> -#ifdef GBM_BO_WITH_MODIFIERS
> -    uint32_t num_fds;
> -    int i;
> -#endif
> -
> -    xwl_pixmap = xwl_pixmap_get(pixmap);
> -
> -    if (!xwl_pixmap->bo)
> -       return 0;
> -
> -#ifdef GBM_BO_WITH_MODIFIERS
> -    num_fds = gbm_bo_get_plane_count(xwl_pixmap->bo);
> -    *modifier = gbm_bo_get_modifier(xwl_pixmap->bo);
> -
> -    for (i = 0; i < num_fds; i++) {
> -        fds[i] = gbm_bo_get_fd(xwl_pixmap->bo);
> -        strides[i] = gbm_bo_get_stride_for_plane(xwl_pixmap->bo, i);
> -        offsets[i] = gbm_bo_get_offset(xwl_pixmap->bo, i);
> -    }
> -
> -    return num_fds;
> -#else
> -    *modifier = DRM_FORMAT_MOD_INVALID;
> -    fds[0] = gbm_bo_get_fd(xwl_pixmap->bo);
> -    strides[0] = gbm_bo_get_stride(xwl_pixmap->bo);
> -    offsets[0] = 0;
> -    return 1;
> -#endif
> -}
> -
> -_X_EXPORT Bool
> -glamor_get_formats(ScreenPtr screen,
> -                   CARD32 *num_formats, CARD32 **formats)
> -{
> -    struct xwl_screen *xwl_screen = xwl_screen_get(screen);
> -    int i;
> -
> -    /* Explicitly zero the count as the caller may ignore the return value
> */
> -    *num_formats = 0;
> -
> -    if (!xwl_screen->dmabuf_capable || !xwl_screen->dmabuf)
> -        return FALSE;
> -
> -    if (xwl_screen->num_formats == 0)
> -       return TRUE;
> -
> -    *formats = calloc(xwl_screen->num_formats, sizeof(CARD32));
> -    if (*formats == NULL)
> -        return FALSE;
> -
> -    for (i = 0; i < xwl_screen->num_formats; i++)
> -       (*formats)[i] = xwl_screen->formats[i].format;
> -    *num_formats = xwl_screen->num_formats;
> -
> -    return TRUE;
> -}
> -
> -_X_EXPORT Bool
> -glamor_get_modifiers(ScreenPtr screen, CARD32 format,
> -                     CARD32 *num_modifiers, uint64_t **modifiers)
> -{
> -    struct xwl_screen *xwl_screen = xwl_screen_get(screen);
> -    struct xwl_format *xwl_format = NULL;
> -    int i;
> -
> -    /* Explicitly zero the count as the caller may ignore the return value
> */
> -    *num_modifiers = 0;
> -
> -    if (!xwl_screen->dmabuf_capable || !xwl_screen->dmabuf)
> -        return FALSE;
> -
> -    if (xwl_screen->num_formats == 0)
> -        return TRUE;
> -
> -    for (i = 0; i < xwl_screen->num_formats; i++) {
> -       if (xwl_screen->formats[i].format == format) {
> -          xwl_format = &xwl_screen->formats[i];
> -          break;
> -       }
> -    }
> -
> -    if (!xwl_format)
> -        return FALSE;
> -
> -    *modifiers = calloc(xwl_format->num_modifiers, sizeof(uint64_t));
> -    if (*modifiers == NULL)
> -        return FALSE;
> -
> -    for (i = 0; i < xwl_format->num_modifiers; i++)
> -       (*modifiers)[i] = xwl_format->modifiers[i];
> -    *num_modifiers = xwl_format->num_modifiers;
> -
> -    return TRUE;
> -}
> -
> -
> -static const dri3_screen_info_rec xwl_dri3_info = {
> -    .version = 2,
> -    .open = NULL,
> -    .pixmap_from_fds = glamor_pixmap_from_fds,
> -    .fds_from_pixmap = glamor_fds_from_pixmap,
> -    .open_client = xwl_dri3_open_client,
> -    .get_formats = glamor_get_formats,
> -    .get_modifiers = glamor_get_modifiers,
> -    .get_drawable_modifiers = glamor_get_drawable_modifiers,
> -};
> -
>  Bool
>  xwl_glamor_init(struct xwl_screen *xwl_screen)
>  {
> @@ -832,14 +132,8 @@ xwl_glamor_init(struct xwl_screen *xwl_screen)
>          return FALSE;
>      }
>  
> -    if (!xwl_screen->fd_render_node && !xwl_screen->drm_authenticated) {
> -        ErrorF("Failed to get wl_drm, disabling Glamor and DRI3\n");
> -	return FALSE;
> -    }
> -
> -    xwl_drm_init_egl(xwl_screen);
> -    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;
>      }
>  
> @@ -848,25 +142,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 72493285e2..b37b62c786 100644
> --- a/hw/xwayland/xwayland.c
> +++ b/hw/xwayland/xwayland.c
> @@ -755,13 +755,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_set_drm_interface(xwl_screen, id, version);
> -    }
> -    else if (xwl_screen->glamor &&
> -             strcmp(interface, "zwp_linux_dmabuf_v1") == 0 && version >= 3)
> {
> -        xwl_screen_set_dmabuf_interface(xwl_screen, id, version);
> +    else if (xwl_screen->glamor) {
> +        xwl_glamor_init_wl_registry(xwl_screen, registry, id, interface,
> +                                    version);
>      }
>  #endif
>  }
> @@ -970,6 +966,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 11a9f48165..82cbfc9d34 100644
> --- a/hw/xwayland/xwayland.h
> +++ b/hw/xwayland/xwayland.h
> @@ -55,6 +55,9 @@ struct xwl_format {
>      uint64_t *modifiers;
>  };
>  
> +struct xwl_pixmap;
> +struct xwl_window;
> +
>  struct xwl_screen {
>      int width;
>      int height;
> @@ -101,19 +104,46 @@ struct xwl_screen {
>      int prepare_read;
>      int wait_flush;
>  
> -    char *device_name;
> -    int drm_fd;
> -    int fd_render_node;
> -    int drm_authenticated;
> -    struct wl_drm *drm;
> -    struct zwp_linux_dmabuf_v1 *dmabuf;
>      uint32_t num_formats;
>      struct xwl_format *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,
> +                                                      unsigned short width,
> +                                                      unsigned short
> height,
> +                                                      Bool *created);
> +    } egl_backend;
> +
>      struct glamor_context *glamor_ctx;
> -    int dmabuf_capable;
>  
>      Atom allow_commits_prop;
>  };
> @@ -318,8 +348,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);
> @@ -380,6 +408,10 @@ struct wl_buffer
> *xwl_glamor_pixmap_get_wl_buffer(PixmapPtr pixmap,
>                                                    unsigned short width,
>                                                    unsigned short height,
>                                                    Bool *created);
> +void xwl_glamor_init_wl_registry(struct xwl_screen *xwl_screen,
> +                                 struct wl_registry *registry,
> +                                 uint32_t id, const char *interface,
> +                                 uint32_t version);
>  
>  #ifdef GLAMOR_HAS_GBM
>  Bool xwl_present_init(ScreenPtr screen);
> @@ -400,4 +432,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
-- 
Cheers,
	Lyude Paul


More information about the xorg-devel mailing list