lgtm! for the whole series: Reviewed-by: Lyude Paul <ly...@redhat.com>
On Fri, 2018-04-20 at 14:38 -0400, Adam Jackson wrote: > From: Lyude Paul <ly...@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 <ly...@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 <ly...@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 _______________________________________________ xorg-devel@lists.x.org: X.Org development Archives: http://lists.x.org/archives/xorg-devel Info: https://lists.x.org/mailman/listinfo/xorg-devel