2014-06-16 20:34:55 +02:00
|
|
|
/*
|
|
|
|
* Copyright © 2011-2014 Intel Corporation
|
|
|
|
*
|
|
|
|
* Permission to use, copy, modify, distribute, and sell this software
|
|
|
|
* and its documentation for any purpose is hereby granted without
|
|
|
|
* fee, provided that the above copyright notice appear in all copies
|
|
|
|
* and that both that copyright notice and this permission notice
|
|
|
|
* appear in supporting documentation, and that the name of the
|
|
|
|
* copyright holders not be used in advertising or publicity
|
|
|
|
* pertaining to distribution of the software without specific,
|
|
|
|
* written prior permission. The copyright holders make no
|
|
|
|
* representations about the suitability of this software for any
|
|
|
|
* purpose. It is provided "as is" without express or implied
|
|
|
|
* warranty.
|
|
|
|
*
|
|
|
|
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
|
|
|
|
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
|
|
|
* FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
|
|
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
|
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
|
|
|
|
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
|
|
|
|
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
|
|
|
|
* SOFTWARE.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "xwayland.h"
|
|
|
|
|
|
|
|
#include <fcntl.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <xf86drm.h>
|
|
|
|
|
|
|
|
#define MESA_EGL_NO_X11_HEADERS
|
|
|
|
#include <gbm.h>
|
|
|
|
#include <epoxy/egl.h>
|
|
|
|
#include <epoxy/gl.h>
|
|
|
|
|
|
|
|
#include <glamor.h>
|
|
|
|
#include <glamor_context.h>
|
|
|
|
#include <dri3.h>
|
|
|
|
#include "drm-client-protocol.h"
|
|
|
|
|
|
|
|
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)
|
|
|
|
{
|
|
|
|
eglMakeCurrent(glamor_ctx->display, EGL_NO_SURFACE,
|
|
|
|
EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
|
|
|
if (!eglMakeCurrent(glamor_ctx->display,
|
|
|
|
EGL_NO_SURFACE, EGL_NO_SURFACE,
|
|
|
|
glamor_ctx->ctx))
|
|
|
|
FatalError("Failed to make EGL context current\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
static uint32_t
|
|
|
|
drm_format_for_depth(int depth)
|
|
|
|
{
|
|
|
|
switch (depth) {
|
|
|
|
case 15:
|
|
|
|
return WL_DRM_FORMAT_XRGB1555;
|
|
|
|
case 16:
|
|
|
|
return WL_DRM_FORMAT_RGB565;
|
|
|
|
case 24:
|
|
|
|
return WL_DRM_FORMAT_XRGB8888;
|
|
|
|
default:
|
|
|
|
ErrorF("unexpected depth: %d\n", depth);
|
|
|
|
case 32:
|
|
|
|
return WL_DRM_FORMAT_ARGB8888;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static uint32_t
|
|
|
|
gbm_format_for_depth(int depth)
|
|
|
|
{
|
|
|
|
switch (depth) {
|
|
|
|
case 16:
|
|
|
|
return GBM_FORMAT_RGB565;
|
|
|
|
case 24:
|
|
|
|
return GBM_FORMAT_XRGB8888;
|
|
|
|
default:
|
|
|
|
ErrorF("unexpected depth: %d\n", depth);
|
|
|
|
case 32:
|
|
|
|
return GBM_FORMAT_ARGB8888;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
glamor_egl_screen_init(ScreenPtr screen, struct glamor_context *glamor_ctx)
|
|
|
|
{
|
|
|
|
struct xwl_screen *xwl_screen = xwl_screen_get(screen);
|
|
|
|
|
|
|
|
glamor_ctx->ctx = xwl_screen->egl_context;
|
|
|
|
glamor_ctx->display = xwl_screen->egl_display;
|
|
|
|
|
|
|
|
glamor_ctx->make_current = xwl_glamor_egl_make_current;
|
|
|
|
|
|
|
|
xwl_screen->glamor_ctx = glamor_ctx;
|
|
|
|
}
|
|
|
|
|
|
|
|
static PixmapPtr
|
|
|
|
xwl_glamor_create_pixmap_for_bo(ScreenPtr screen, struct gbm_bo *bo, int depth)
|
|
|
|
{
|
|
|
|
PixmapPtr pixmap;
|
|
|
|
struct xwl_pixmap *xwl_pixmap;
|
|
|
|
struct xwl_screen *xwl_screen = xwl_screen_get(screen);
|
|
|
|
|
|
|
|
xwl_pixmap = malloc(sizeof *xwl_pixmap);
|
|
|
|
if (xwl_pixmap == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
pixmap = glamor_create_pixmap(screen,
|
|
|
|
gbm_bo_get_width(bo),
|
|
|
|
gbm_bo_get_height(bo),
|
|
|
|
depth,
|
|
|
|
GLAMOR_CREATE_PIXMAP_NO_TEXTURE);
|
|
|
|
if (pixmap == NULL) {
|
|
|
|
free(xwl_pixmap);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (lastGLContext != xwl_screen->glamor_ctx) {
|
|
|
|
lastGLContext = xwl_screen->glamor_ctx;
|
|
|
|
xwl_glamor_egl_make_current(xwl_screen->glamor_ctx);
|
|
|
|
}
|
|
|
|
|
|
|
|
xwl_pixmap->bo = bo;
|
|
|
|
xwl_pixmap->buffer = NULL;
|
|
|
|
xwl_pixmap->image = eglCreateImageKHR(xwl_screen->egl_display,
|
|
|
|
xwl_screen->egl_context,
|
|
|
|
EGL_NATIVE_PIXMAP_KHR,
|
|
|
|
xwl_pixmap->bo, NULL);
|
|
|
|
|
|
|
|
glGenTextures(1, &xwl_pixmap->texture);
|
|
|
|
glBindTexture(GL_TEXTURE_2D, xwl_pixmap->texture);
|
2015-01-15 22:03:18 +01:00
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
|
|
|
|
2014-06-16 20:34:55 +02:00
|
|
|
glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, xwl_pixmap->image);
|
|
|
|
glBindTexture(GL_TEXTURE_2D, 0);
|
|
|
|
|
|
|
|
xwl_pixmap_set_private(pixmap, xwl_pixmap);
|
|
|
|
|
|
|
|
glamor_set_pixmap_texture(pixmap, xwl_pixmap->texture);
|
|
|
|
glamor_set_pixmap_type(pixmap, GLAMOR_TEXTURE_DRM);
|
|
|
|
|
|
|
|
return pixmap;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct wl_buffer *
|
|
|
|
xwl_glamor_pixmap_get_wl_buffer(PixmapPtr pixmap)
|
|
|
|
{
|
|
|
|
struct xwl_screen *xwl_screen = xwl_screen_get(pixmap->drawable.pScreen);
|
|
|
|
struct xwl_pixmap *xwl_pixmap = xwl_pixmap_get(pixmap);
|
|
|
|
int prime_fd;
|
|
|
|
|
|
|
|
if (xwl_pixmap->buffer)
|
|
|
|
return xwl_pixmap->buffer;
|
|
|
|
|
|
|
|
prime_fd = gbm_bo_get_fd(xwl_pixmap->bo);
|
|
|
|
if (prime_fd == -1)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
xwl_pixmap->buffer =
|
|
|
|
wl_drm_create_prime_buffer(xwl_screen->drm, prime_fd,
|
|
|
|
pixmap->drawable.width,
|
|
|
|
pixmap->drawable.height,
|
|
|
|
drm_format_for_depth(pixmap->drawable.depth),
|
|
|
|
0, gbm_bo_get_stride(xwl_pixmap->bo),
|
|
|
|
0, 0,
|
|
|
|
0, 0);
|
|
|
|
|
|
|
|
close(prime_fd);
|
|
|
|
|
|
|
|
return xwl_pixmap->buffer;
|
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
if (width > 0 && height > 0 && depth >= 15 &&
|
|
|
|
(hint == 0 ||
|
|
|
|
hint == CREATE_PIXMAP_USAGE_BACKING_PIXMAP ||
|
|
|
|
hint == CREATE_PIXMAP_USAGE_SHARED)) {
|
|
|
|
bo = gbm_bo_create(xwl_screen->gbm, width, height,
|
|
|
|
gbm_format_for_depth(depth),
|
|
|
|
GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING);
|
|
|
|
|
|
|
|
if (bo)
|
|
|
|
return xwl_glamor_create_pixmap_for_bo(screen, bo, depth);
|
|
|
|
}
|
|
|
|
|
|
|
|
return glamor_create_pixmap(screen, width, height, depth, hint);
|
|
|
|
}
|
|
|
|
|
|
|
|
static Bool
|
|
|
|
xwl_glamor_destroy_pixmap(PixmapPtr pixmap)
|
|
|
|
{
|
|
|
|
struct xwl_screen *xwl_screen = xwl_screen_get(pixmap->drawable.pScreen);
|
|
|
|
struct xwl_pixmap *xwl_pixmap = xwl_pixmap_get(pixmap);
|
|
|
|
|
|
|
|
if (xwl_pixmap && pixmap->refcnt == 1) {
|
|
|
|
if (xwl_pixmap->buffer)
|
|
|
|
wl_buffer_destroy(xwl_pixmap->buffer);
|
|
|
|
|
|
|
|
eglDestroyImageKHR(xwl_screen->egl_display, xwl_pixmap->image);
|
|
|
|
gbm_bo_destroy(xwl_pixmap->bo);
|
|
|
|
free(xwl_pixmap);
|
|
|
|
}
|
|
|
|
|
|
|
|
return glamor_destroy_pixmap(pixmap);
|
|
|
|
}
|
|
|
|
|
|
|
|
static Bool
|
|
|
|
xwl_glamor_create_screen_resources(ScreenPtr screen)
|
|
|
|
{
|
|
|
|
struct xwl_screen *xwl_screen = xwl_screen_get(screen);
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
screen->CreateScreenResources = xwl_screen->CreateScreenResources;
|
|
|
|
ret = (*screen->CreateScreenResources) (screen);
|
|
|
|
xwl_screen->CreateScreenResources = screen->CreateScreenResources;
|
|
|
|
screen->CreateScreenResources = xwl_glamor_create_screen_resources;
|
|
|
|
|
|
|
|
if (!ret)
|
|
|
|
return ret;
|
|
|
|
|
2015-11-23 08:51:48 +01:00
|
|
|
if (xwl_screen->rootless) {
|
2014-06-16 20:34:55 +02:00
|
|
|
screen->devPrivate =
|
|
|
|
fbCreatePixmap(screen, 0, 0, screen->rootDepth, 0);
|
2015-11-23 08:51:48 +01:00
|
|
|
}
|
2014-06-16 20:34:55 +02:00
|
|
|
else {
|
|
|
|
screen->devPrivate =
|
|
|
|
xwl_glamor_create_pixmap(screen, screen->width, screen->height,
|
|
|
|
screen->rootDepth,
|
|
|
|
CREATE_PIXMAP_USAGE_BACKING_PIXMAP);
|
|
|
|
if (screen->devPrivate)
|
|
|
|
glamor_set_screen_pixmap(screen->devPrivate, NULL);
|
|
|
|
}
|
|
|
|
|
dix: Add hybrid full-size/empty-clip mode to SetRootClip
216bdbc735 removed the SetRootClip call in the XWayland output-hotplug
handler when running rootless (e.g. as a part of Weston/Mutter), since
the root window has no storage, so generating exposures will result in
writes to invalid memory.
Unfortunately, preventing the segfault also breaks sprite confinement.
SetRootClip updates winSize and borderSize for the root window, which
when combined with RRScreenSizeChanged calling ScreenRestructured,
generates a new sprite-confinment area to update it to the whole screen.
Removing this call results in the window geometry being reported
correctly, but winSize/borderSize never changing from their values at
startup, i.e. out of sync with the root window geometry / screen
information in the connection info / XRandR.
This patch introduces a hybrid mode, where we update winSize and
borderSize for the root window, enabling sprite confinement to work
correctly, but keep the clip emptied so exposures are never generated.
Signed-off-by: Daniel Stone <daniels@collabora.com>
Tested-by: Olivier Fourdan <ofourdan@redhat.com>
Reviewed-by: Adam Jackson <ajax@redhat.com>
2016-02-12 17:36:59 +01:00
|
|
|
SetRootClip(screen, xwl_screen->root_clip_mode);
|
|
|
|
|
2014-06-16 20:34:55 +02:00
|
|
|
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;
|
|
|
|
const char *version;
|
2016-01-18 23:06:25 +01:00
|
|
|
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
|
|
|
|
};
|
2014-06-16 20:34:55 +02:00
|
|
|
|
|
|
|
if (xwl_screen->egl_display)
|
|
|
|
return;
|
|
|
|
|
|
|
|
xwl_screen->expecting_event--;
|
|
|
|
|
|
|
|
xwl_screen->gbm = gbm_create_device(xwl_screen->drm_fd);
|
|
|
|
if (xwl_screen->gbm == NULL) {
|
|
|
|
ErrorF("couldn't get display device\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
xwl_screen->egl_display = eglGetDisplay(xwl_screen->gbm);
|
|
|
|
if (xwl_screen->egl_display == EGL_NO_DISPLAY) {
|
|
|
|
ErrorF("eglGetDisplay() failed\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
eglBindAPI(EGL_OPENGL_API);
|
|
|
|
if (!eglInitialize(xwl_screen->egl_display, &major, &minor)) {
|
|
|
|
ErrorF("eglInitialize() failed\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
version = eglQueryString(xwl_screen->egl_display, EGL_VERSION);
|
|
|
|
ErrorF("glamor: EGL version %s:\n", version);
|
|
|
|
|
|
|
|
xwl_screen->egl_context = eglCreateContext(xwl_screen->egl_display,
|
2016-01-18 23:06:25 +01:00
|
|
|
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);
|
|
|
|
|
2014-06-16 20:34:55 +02:00
|
|
|
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")) {
|
2015-05-06 05:07:21 +02:00
|
|
|
ErrorF("GL_OES_EGL_image not available\n");
|
2014-06-16 20:34:55 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
xwl_drm_handle_device(void *data, struct wl_drm *drm, const char *device)
|
|
|
|
{
|
|
|
|
struct xwl_screen *xwl_screen = data;
|
|
|
|
drm_magic_t magic;
|
|
|
|
|
|
|
|
xwl_screen->device_name = strdup(device);
|
|
|
|
if (!xwl_screen->device_name)
|
|
|
|
return;
|
|
|
|
|
|
|
|
xwl_screen->drm_fd = open(xwl_screen->device_name, O_RDWR | O_CLOEXEC);
|
|
|
|
if (xwl_screen->drm_fd == -1) {
|
2015-05-06 05:07:21 +02:00
|
|
|
ErrorF("wayland-egl: could not open %s (%s)\n",
|
2014-06-16 20:34:55 +02:00
|
|
|
xwl_screen->device_name, strerror(errno));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (is_fd_render_node(xwl_screen->drm_fd)) {
|
|
|
|
xwl_screen->fd_render_node = 1;
|
|
|
|
xwl_drm_init_egl(xwl_screen);
|
|
|
|
} else {
|
|
|
|
drmGetMagic(xwl_screen->drm_fd, &magic);
|
|
|
|
wl_drm_authenticate(xwl_screen->drm, magic);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
xwl_drm_handle_format(void *data, struct wl_drm *drm, uint32_t format)
|
|
|
|
{
|
|
|
|
struct xwl_screen *xwl_screen = data;
|
|
|
|
|
|
|
|
switch (format) {
|
|
|
|
case WL_DRM_FORMAT_ARGB8888:
|
|
|
|
xwl_screen->formats |= XWL_FORMAT_ARGB8888;
|
|
|
|
break;
|
|
|
|
case WL_DRM_FORMAT_XRGB8888:
|
|
|
|
xwl_screen->formats |= XWL_FORMAT_XRGB8888;
|
|
|
|
break;
|
|
|
|
case WL_DRM_FORMAT_RGB565:
|
|
|
|
xwl_screen->formats |= XWL_FORMAT_RGB565;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
xwl_drm_handle_authenticated(void *data, struct wl_drm *drm)
|
|
|
|
{
|
|
|
|
struct xwl_screen *xwl_screen = data;
|
|
|
|
|
|
|
|
if (!xwl_screen->egl_display)
|
|
|
|
xwl_drm_init_egl(xwl_screen);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
xwl_drm_handle_capabilities(void *data, struct wl_drm *drm, uint32_t value)
|
|
|
|
{
|
|
|
|
struct xwl_screen *xwl_screen = data;
|
|
|
|
|
|
|
|
xwl_screen->capabilities = value;
|
|
|
|
}
|
|
|
|
|
|
|
|
static const struct wl_drm_listener xwl_drm_listener = {
|
|
|
|
xwl_drm_handle_device,
|
|
|
|
xwl_drm_handle_format,
|
|
|
|
xwl_drm_handle_authenticated,
|
|
|
|
xwl_drm_handle_capabilities
|
|
|
|
};
|
|
|
|
|
|
|
|
Bool
|
|
|
|
xwl_screen_init_glamor(struct xwl_screen *xwl_screen,
|
|
|
|
uint32_t id, uint32_t version)
|
|
|
|
{
|
|
|
|
if (version < 2)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
xwl_screen->drm =
|
|
|
|
wl_registry_bind(xwl_screen->registry, id, &wl_drm_interface, 2);
|
|
|
|
wl_drm_add_listener(xwl_screen->drm, &xwl_drm_listener, xwl_screen);
|
|
|
|
xwl_screen->expecting_event++;
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
glamor_egl_dri3_fd_name_from_tex(ScreenPtr screen,
|
|
|
|
PixmapPtr pixmap,
|
|
|
|
unsigned int tex,
|
|
|
|
Bool want_name, CARD16 *stride, CARD32 *size)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct xwl_auth_state {
|
|
|
|
int fd;
|
|
|
|
ClientPtr client;
|
|
|
|
};
|
|
|
|
|
|
|
|
static void
|
|
|
|
sync_callback(void *data, struct wl_callback *callback, uint32_t serial)
|
|
|
|
{
|
|
|
|
struct xwl_auth_state *state = data;
|
|
|
|
|
|
|
|
dri3_send_open_reply(state->client, state->fd);
|
|
|
|
AttendClient(state->client);
|
|
|
|
free(state);
|
|
|
|
wl_callback_destroy(callback);
|
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
struct wl_callback *callback;
|
|
|
|
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);
|
|
|
|
callback = wl_display_sync(xwl_screen->display);
|
|
|
|
wl_callback_add_listener(callback, &sync_listener, state);
|
|
|
|
|
|
|
|
IgnoreClient(client);
|
|
|
|
|
|
|
|
return Success;
|
|
|
|
}
|
|
|
|
|
|
|
|
static PixmapPtr
|
|
|
|
xwl_dri3_pixmap_from_fd(ScreenPtr screen, int fd,
|
|
|
|
CARD16 width, CARD16 height, CARD16 stride,
|
|
|
|
CARD8 depth, CARD8 bpp)
|
|
|
|
{
|
|
|
|
struct xwl_screen *xwl_screen = xwl_screen_get(screen);
|
|
|
|
struct gbm_import_fd_data data;
|
|
|
|
struct gbm_bo *bo;
|
|
|
|
PixmapPtr pixmap;
|
|
|
|
|
|
|
|
if (width == 0 || height == 0 ||
|
|
|
|
depth < 15 || bpp != BitsPerPixel(depth) || stride < width * bpp / 8)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
data.fd = fd;
|
|
|
|
data.width = width;
|
|
|
|
data.height = height;
|
|
|
|
data.stride = stride;
|
|
|
|
data.format = gbm_format_for_depth(depth);
|
|
|
|
bo = gbm_bo_import(xwl_screen->gbm, GBM_BO_IMPORT_FD, &data,
|
|
|
|
GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING);
|
|
|
|
if (bo == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
pixmap = xwl_glamor_create_pixmap_for_bo(screen, bo, depth);
|
|
|
|
if (pixmap == NULL) {
|
|
|
|
gbm_bo_destroy(bo);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return pixmap;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
xwl_dri3_fd_from_pixmap(ScreenPtr screen, PixmapPtr pixmap,
|
|
|
|
CARD16 *stride, CARD32 *size)
|
|
|
|
{
|
|
|
|
struct xwl_pixmap *xwl_pixmap;
|
|
|
|
|
|
|
|
xwl_pixmap = xwl_pixmap_get(pixmap);
|
|
|
|
|
|
|
|
*stride = gbm_bo_get_stride(xwl_pixmap->bo);
|
|
|
|
*size = pixmap->drawable.width * *stride;
|
|
|
|
|
|
|
|
return gbm_bo_get_fd(xwl_pixmap->bo);
|
|
|
|
}
|
|
|
|
|
|
|
|
static dri3_screen_info_rec xwl_dri3_info = {
|
|
|
|
.version = 1,
|
|
|
|
.open = NULL,
|
|
|
|
.pixmap_from_fd = xwl_dri3_pixmap_from_fd,
|
|
|
|
.fd_from_pixmap = xwl_dri3_fd_from_pixmap,
|
|
|
|
.open_client = xwl_dri3_open_client,
|
|
|
|
};
|
|
|
|
|
|
|
|
Bool
|
|
|
|
xwl_glamor_init(struct xwl_screen *xwl_screen)
|
|
|
|
{
|
|
|
|
ScreenPtr screen = xwl_screen->screen;
|
|
|
|
|
|
|
|
if (xwl_screen->egl_context == EGL_NO_CONTEXT) {
|
|
|
|
ErrorF("Disabling glamor and dri3, EGL setup failed\n");
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2014-10-30 04:30:12 +01:00
|
|
|
if (!glamor_init(xwl_screen->screen, GLAMOR_USE_EGL_SCREEN)) {
|
2014-06-16 20:34:55 +02:00
|
|
|
ErrorF("Failed to initialize glamor\n");
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!dri3_screen_init(xwl_screen->screen, &xwl_dri3_info)) {
|
|
|
|
ErrorF("Failed to initialize dri3\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;
|
|
|
|
|
2016-03-09 16:21:18 +01:00
|
|
|
#ifdef XV
|
|
|
|
if (!xwl_glamor_xv_init(screen))
|
|
|
|
ErrorF("Failed to initialize glamor Xv extension\n");
|
|
|
|
#endif
|
|
|
|
|
2014-06-16 20:34:55 +02:00
|
|
|
return TRUE;
|
|
|
|
}
|