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