xwayland: Decouple GBM from glamor
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@redhat.com> Reviewed-by: Lyude Paul <lyude@redhat.com> Reviewed-by: Daniel Stone <daniels@collabora.com> Reviewed-by: Adam Jackson <ajax@redhat.com>
This commit is contained in:
parent
d2d664df97
commit
1545e2dbad
|
@ -35,6 +35,7 @@ Xwayland_built_sources =
|
||||||
if GLAMOR_EGL
|
if GLAMOR_EGL
|
||||||
Xwayland_SOURCES += \
|
Xwayland_SOURCES += \
|
||||||
xwayland-glamor.c \
|
xwayland-glamor.c \
|
||||||
|
xwayland-glamor-gbm.c \
|
||||||
xwayland-present.c
|
xwayland-present.c
|
||||||
if XV
|
if XV
|
||||||
Xwayland_SOURCES += \
|
Xwayland_SOURCES += \
|
||||||
|
|
|
@ -52,7 +52,11 @@ srcs += code.process(dmabuf_xml)
|
||||||
|
|
||||||
xwayland_glamor = []
|
xwayland_glamor = []
|
||||||
if gbm_dep.found()
|
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
|
if build_xv
|
||||||
srcs += 'xwayland-glamor-xv.c'
|
srcs += 'xwayland-glamor-xv.c'
|
||||||
endif
|
endif
|
||||||
|
|
891
hw/xwayland/xwayland-glamor-gbm.c
Normal file
891
hw/xwayland/xwayland-glamor-gbm.c
Normal file
|
@ -0,0 +1,891 @@
|
||||||
|
/*
|
||||||
|
* 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@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;
|
||||||
|
|
||||||
|
/* Explicitly zero the count as the caller may ignore the return value */
|
||||||
|
*num_formats = 0;
|
||||||
|
|
||||||
|
if (!xwl_gbm->dmabuf_capable || !xwl_gbm->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_gbm_private *xwl_gbm = xwl_gbm_get(xwl_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_gbm->dmabuf_capable || !xwl_gbm->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,
|
||||||
|
};
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
|
@ -25,28 +25,11 @@
|
||||||
|
|
||||||
#include "xwayland.h"
|
#include "xwayland.h"
|
||||||
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <xf86drm.h>
|
|
||||||
#include <drm_fourcc.h>
|
|
||||||
|
|
||||||
#define MESA_EGL_NO_X11_HEADERS
|
#define MESA_EGL_NO_X11_HEADERS
|
||||||
#include <gbm.h>
|
|
||||||
#include <glamor_egl.h>
|
#include <glamor_egl.h>
|
||||||
|
|
||||||
#include <glamor.h>
|
#include <glamor.h>
|
||||||
#include <glamor_context.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
|
static void
|
||||||
xwl_glamor_egl_make_current(struct glamor_context *glamor_ctx)
|
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");
|
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
|
void
|
||||||
glamor_egl_screen_init(ScreenPtr screen, struct glamor_context *glamor_ctx)
|
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;
|
xwl_screen->glamor_ctx = glamor_ctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
static PixmapPtr
|
void
|
||||||
xwl_glamor_create_pixmap_for_bo(ScreenPtr screen, struct gbm_bo *bo, int depth)
|
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;
|
if (xwl_screen->egl_backend.init_wl_registry)
|
||||||
struct xwl_pixmap *xwl_pixmap;
|
xwl_screen->egl_backend.init_wl_registry(xwl_screen, registry,
|
||||||
struct xwl_screen *xwl_screen = xwl_screen_get(screen);
|
interface, id, version);
|
||||||
|
|
||||||
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 *
|
struct wl_buffer *
|
||||||
|
@ -164,133 +73,14 @@ xwl_glamor_pixmap_get_wl_buffer(PixmapPtr pixmap,
|
||||||
Bool *created)
|
Bool *created)
|
||||||
{
|
{
|
||||||
struct xwl_screen *xwl_screen = xwl_screen_get(pixmap->drawable.pScreen);
|
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) {
|
if (xwl_screen->egl_backend.get_wl_buffer_for_pixmap)
|
||||||
/* Buffer already exists. Return it and inform caller if interested. */
|
return xwl_screen->egl_backend.get_wl_buffer_for_pixmap(pixmap,
|
||||||
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_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,
|
width,
|
||||||
height,
|
height,
|
||||||
wl_drm_format_for_depth(pixmap->drawable.depth),
|
created);
|
||||||
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 NULL;
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static Bool
|
static Bool
|
||||||
|
@ -312,9 +102,8 @@ xwl_glamor_create_screen_resources(ScreenPtr screen)
|
||||||
fbCreatePixmap(screen, 0, 0, screen->rootDepth, 0);
|
fbCreatePixmap(screen, 0, 0, screen->rootDepth, 0);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
screen->devPrivate =
|
screen->devPrivate = screen->CreatePixmap(
|
||||||
xwl_glamor_create_pixmap(screen, screen->width, screen->height,
|
screen, screen->width, screen->height, screen->rootDepth,
|
||||||
screen->rootDepth,
|
|
||||||
CREATE_PIXMAP_USAGE_BACKING_PIXMAP);
|
CREATE_PIXMAP_USAGE_BACKING_PIXMAP);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -323,224 +112,6 @@ xwl_glamor_create_screen_resources(ScreenPtr screen)
|
||||||
return screen->devPrivate != NULL;
|
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
|
int
|
||||||
glamor_egl_fd_name_from_pixmap(ScreenPtr screen,
|
glamor_egl_fd_name_from_pixmap(ScreenPtr screen,
|
||||||
PixmapPtr pixmap,
|
PixmapPtr pixmap,
|
||||||
|
@ -549,277 +120,6 @@ glamor_egl_fd_name_from_pixmap(ScreenPtr screen,
|
||||||
return 0;
|
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
|
Bool
|
||||||
xwl_glamor_init(struct xwl_screen *xwl_screen)
|
xwl_glamor_init(struct xwl_screen *xwl_screen)
|
||||||
{
|
{
|
||||||
|
@ -832,14 +132,8 @@ xwl_glamor_init(struct xwl_screen *xwl_screen)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!xwl_screen->fd_render_node && !xwl_screen->drm_authenticated) {
|
if (!xwl_screen->egl_backend.init_egl(xwl_screen)) {
|
||||||
ErrorF("Failed to get wl_drm, disabling Glamor and DRI3\n");
|
ErrorF("EGL setup failed, disabling glamor\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");
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -848,25 +142,13 @@ xwl_glamor_init(struct xwl_screen *xwl_screen)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!dri3_screen_init(xwl_screen->screen, &xwl_dri3_info)) {
|
if (!xwl_screen->egl_backend.init_screen(xwl_screen)) {
|
||||||
ErrorF("Failed to initialize dri3\n");
|
ErrorF("EGL backend init_screen() failed, disabling glamor\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");
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
xwl_screen->CreateScreenResources = screen->CreateScreenResources;
|
xwl_screen->CreateScreenResources = screen->CreateScreenResources;
|
||||||
screen->CreateScreenResources = xwl_glamor_create_screen_resources;
|
screen->CreateScreenResources = xwl_glamor_create_screen_resources;
|
||||||
screen->CreatePixmap = xwl_glamor_create_pixmap;
|
|
||||||
screen->DestroyPixmap = xwl_glamor_destroy_pixmap;
|
|
||||||
|
|
||||||
#ifdef XV
|
#ifdef XV
|
||||||
if (!xwl_glamor_xv_init(screen))
|
if (!xwl_glamor_xv_init(screen))
|
||||||
|
|
|
@ -755,13 +755,9 @@ registry_global(void *data, struct wl_registry *registry, uint32_t id,
|
||||||
xwl_screen_init_xdg_output(xwl_screen);
|
xwl_screen_init_xdg_output(xwl_screen);
|
||||||
}
|
}
|
||||||
#ifdef GLAMOR_HAS_GBM
|
#ifdef GLAMOR_HAS_GBM
|
||||||
else if (xwl_screen->glamor &&
|
else if (xwl_screen->glamor) {
|
||||||
strcmp(interface, "wl_drm") == 0 && version >= 2) {
|
xwl_glamor_init_wl_registry(xwl_screen, registry, id, interface,
|
||||||
xwl_screen_set_drm_interface(xwl_screen, id, version);
|
version);
|
||||||
}
|
|
||||||
else if (xwl_screen->glamor &&
|
|
||||||
strcmp(interface, "zwp_linux_dmabuf_v1") == 0 && version >= 3) {
|
|
||||||
xwl_screen_set_dmabuf_interface(xwl_screen, id, version);
|
|
||||||
}
|
}
|
||||||
#endif
|
#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
|
/* In rootless mode, we don't have any screen storage, and the only
|
||||||
* rendering should be to redirected mode. */
|
* rendering should be to redirected mode. */
|
||||||
if (xwl_screen->rootless)
|
if (xwl_screen->rootless)
|
||||||
|
|
|
@ -55,6 +55,9 @@ struct xwl_format {
|
||||||
uint64_t *modifiers;
|
uint64_t *modifiers;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct xwl_pixmap;
|
||||||
|
struct xwl_window;
|
||||||
|
|
||||||
struct xwl_screen {
|
struct xwl_screen {
|
||||||
int width;
|
int width;
|
||||||
int height;
|
int height;
|
||||||
|
@ -101,19 +104,46 @@ struct xwl_screen {
|
||||||
int prepare_read;
|
int prepare_read;
|
||||||
int wait_flush;
|
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;
|
uint32_t num_formats;
|
||||||
struct xwl_format *formats;
|
struct xwl_format *formats;
|
||||||
uint32_t capabilities;
|
|
||||||
void *egl_display, *egl_context;
|
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;
|
struct glamor_context *glamor_ctx;
|
||||||
int dmabuf_capable;
|
|
||||||
|
|
||||||
Atom allow_commits_prop;
|
Atom allow_commits_prop;
|
||||||
};
|
};
|
||||||
|
@ -318,8 +348,6 @@ struct xwl_output {
|
||||||
Bool xdg_output_done;
|
Bool xdg_output_done;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct xwl_pixmap;
|
|
||||||
|
|
||||||
void xwl_sync_events (struct xwl_screen *xwl_screen);
|
void xwl_sync_events (struct xwl_screen *xwl_screen);
|
||||||
|
|
||||||
Bool xwl_screen_init_cursor(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 width,
|
||||||
unsigned short height,
|
unsigned short height,
|
||||||
Bool *created);
|
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
|
#ifdef GLAMOR_HAS_GBM
|
||||||
Bool xwl_present_init(ScreenPtr screen);
|
Bool xwl_present_init(ScreenPtr screen);
|
||||||
|
@ -400,4 +432,8 @@ Bool xwl_glamor_xv_init(ScreenPtr pScreen);
|
||||||
void xwlVidModeExtensionInit(void);
|
void xwlVidModeExtensionInit(void);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef GLAMOR_HAS_GBM
|
||||||
|
Bool xwl_glamor_init_gbm(struct xwl_screen *xwl_screen);
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue
Block a user