[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