blob: 3965e489347766f63561d8a0edb97c6afde6c243 [file] [log] [blame]
From fafc053cb6a011464dc85baced22fb555ae870ce Mon Sep 17 00:00:00 2001
From: David Reveman <reveman@chromium.org>
Date: Sat, 10 Mar 2018 14:39:00 +0000
Subject: [PATCH] xwayland virtwl with dmabuf 1.19.5
---
hw/xwayland/Makefile.am | 10 +---
hw/xwayland/xwayland-cursor.c | 33 +++++++----
hw/xwayland/xwayland-shm.c | 135 +++++++++++++++++++++++++++++++++++++-----
hw/xwayland/xwayland.c | 13 ++--
hw/xwayland/xwayland.h | 2 +
5 files changed, 155 insertions(+), 38 deletions(-)
diff --git a/hw/xwayland/Makefile.am b/hw/xwayland/Makefile.am
index a3c9fce48..9c4692be2 100644
--- a/hw/xwayland/Makefile.am
+++ b/hw/xwayland/Makefile.am
@@ -40,12 +40,6 @@ Xwayland_SOURCES += \
xwayland-glamor-xv.c
endif
-glamor_built_sources = \
- drm-client-protocol.h \
- drm-protocol.c
-
-Xwayland_built_sources += $(glamor_built_sources)
-
glamor_lib = $(top_builddir)/glamor/libglamor.la
Xwayland_LDADD += $(GLAMOR_LIBS) $(GBM_LIBS) -lEGL -lGL
@@ -56,7 +50,9 @@ Xwayland_built_sources += \
relative-pointer-unstable-v1-client-protocol.h \
relative-pointer-unstable-v1-protocol.c \
pointer-constraints-unstable-v1-client-protocol.h \
- pointer-constraints-unstable-v1-protocol.c
+ pointer-constraints-unstable-v1-protocol.c \
+ drm-client-protocol.h \
+ drm-protocol.c
nodist_Xwayland_SOURCES = $(Xwayland_built_sources)
CLEANFILES = $(Xwayland_built_sources)
diff --git a/hw/xwayland/xwayland-cursor.c b/hw/xwayland/xwayland-cursor.c
index f334f1ca5..549ff7753 100644
--- a/hw/xwayland/xwayland-cursor.c
+++ b/hw/xwayland/xwayland-cursor.c
@@ -31,19 +31,19 @@
static DevPrivateKeyRec xwl_cursor_private_key;
static void
-expand_source_and_mask(CursorPtr cursor, CARD32 *data)
+expand_source_and_mask(CursorPtr cursor, CARD32 *data, int dataStride)
{
CARD32 *p, d, fg, bg;
CursorBitsPtr bits = cursor->bits;
int x, y, stride, i, bit;
- p = data;
fg = ((cursor->foreRed & 0xff00) << 8) |
(cursor->foreGreen & 0xff00) | (cursor->foreGreen >> 8);
bg = ((cursor->backRed & 0xff00) << 8) |
(cursor->backGreen & 0xff00) | (cursor->backGreen >> 8);
stride = (bits->width / 8 + 3) & ~3;
- for (y = 0; y < bits->height; y++)
+ for (y = 0; y < bits->height; y++) {
+ p = data + y * dataStride / sizeof (*p);
for (x = 0; x < bits->width; x++) {
i = y * stride + x / 8;
bit = 1 << (x & 7);
@@ -58,6 +58,7 @@ expand_source_and_mask(CursorPtr cursor, CARD32 *data)
*p++ = d;
}
+ }
}
static Bool
@@ -66,7 +67,8 @@ xwl_realize_cursor(DeviceIntPtr device, ScreenPtr screen, CursorPtr cursor)
PixmapPtr pixmap;
pixmap = xwl_shm_create_pixmap(screen, cursor->bits->width,
- cursor->bits->height, 32, 0);
+ cursor->bits->height, 32,
+ CREATE_PIXMAP_USAGE_BACKING_PIXMAP);
dixSetPrivate(&cursor->devPrivates, &xwl_cursor_private_key, pixmap);
return TRUE;
@@ -127,7 +129,7 @@ xwl_seat_set_cursor(struct xwl_seat *xwl_seat)
{
PixmapPtr pixmap;
CursorPtr cursor;
- int stride;
+ int srcStride, dstStride;
if (!xwl_seat->wl_pointer)
return;
@@ -150,12 +152,21 @@ xwl_seat_set_cursor(struct xwl_seat *xwl_seat)
if (!pixmap)
return;
- stride = cursor->bits->width * 4;
- if (cursor->bits->argb)
- memcpy(pixmap->devPrivate.ptr,
- cursor->bits->argb, cursor->bits->height * stride);
- else
- expand_source_and_mask(cursor, pixmap->devPrivate.ptr);
+ srcStride = cursor->bits->width * 4;
+ dstStride = (int) pixmap->devKind;
+ if (cursor->bits->argb) {
+ CARD8 *s = (CARD8 *) cursor->bits->argb;
+ CARD8 *d = pixmap->devPrivate.ptr;
+ int height = cursor->bits->height;
+
+ while (height--) {
+ memcpy(d, s, srcStride);
+ s += srcStride;
+ d += dstStride;
+ }
+ } else {
+ expand_source_and_mask(cursor, pixmap->devPrivate.ptr, dstStride);
+ }
wl_pointer_set_cursor(xwl_seat->wl_pointer,
xwl_seat->pointer_enter_serial,
diff --git a/hw/xwayland/xwayland-shm.c b/hw/xwayland/xwayland-shm.c
index 452d1f509..2edc95050 100644
--- a/hw/xwayland/xwayland-shm.c
+++ b/hw/xwayland/xwayland-shm.c
@@ -32,6 +32,7 @@
#include "xwayland.h"
+#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <unistd.h>
@@ -39,14 +40,23 @@
#include <errno.h>
#include <string.h>
#include <stdlib.h>
+#include <linux/virtwl.h>
+
+#include "drm-client-protocol.h"
+
+#define DMA_BUF_SYNC_READ (1 << 0)
+#define DMA_BUF_SYNC_WRITE (2 << 0)
+#define DMA_BUF_SYNC_RW (DMA_BUF_SYNC_READ | DMA_BUF_SYNC_WRITE)
+#define DMA_BUF_SYNC_START (0 << 2)
+#define DMA_BUF_SYNC_END (1 << 2)
struct xwl_pixmap {
struct wl_buffer *buffer;
void *data;
size_t size;
+ int dmabuf_fd;
};
-#ifndef HAVE_MKOSTEMP
static int
set_cloexec_or_close(int fd)
{
@@ -68,7 +78,6 @@ set_cloexec_or_close(int fd)
close(fd);
return -1;
}
-#endif
static int
create_tmpfile_cloexec(char *tmpname)
@@ -189,6 +198,27 @@ shm_format_for_depth(int depth)
}
}
+static uint32_t
+drm_format_for_depth(int depth)
+{
+ switch (depth) {
+ 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;
+ }
+}
+
+// Buffer size threshold for which DMABuf should be considered.
+#define DMABUF_SIZE_THRESHOLD 65536
+
+// Maximum number of DMABufs allowed at any given time.
+#define DMABUF_COUNT_MAX 256
+
PixmapPtr
xwl_shm_create_pixmap(ScreenPtr screen,
int width, int height, int depth, unsigned int hint)
@@ -201,7 +231,7 @@ xwl_shm_create_pixmap(ScreenPtr screen,
uint32_t format;
int fd;
- if (hint == CREATE_PIXMAP_USAGE_GLYPH_PICTURE ||
+ if ((hint != CREATE_PIXMAP_USAGE_BACKING_PIXMAP) ||
(width == 0 && height == 0) || depth < 15)
return fbCreatePixmap(screen, width, height, depth, hint);
@@ -216,11 +246,65 @@ xwl_shm_create_pixmap(ScreenPtr screen,
stride = PixmapBytePad(width, depth);
size = stride * height;
xwl_pixmap->buffer = NULL;
- xwl_pixmap->size = size;
- fd = os_create_anonymous_file(size);
- if (fd < 0)
- goto err_free_xwl_pixmap;
+ xwl_pixmap->dmabuf_fd = -1;
+ fd = -1;
+
+ if (xwl_screen->drm &&
+ size > DMABUF_SIZE_THRESHOLD &&
+ xwl_screen->dmabuf_count < DMABUF_COUNT_MAX) {
+ uint32_t drm_format = drm_format_for_depth(depth);
+ struct virtwl_ioctl_new new_alloc = {
+ .type = VIRTWL_IOCTL_NEW_DMABUF,
+ .fd = -1,
+ .flags = 0,
+ .dmabuf = {
+ .width = width,
+ .height = height,
+ .format = drm_format,
+ },
+ };
+ int ret = ioctl(xwl_screen->wl_fd, VIRTWL_IOCTL_NEW, &new_alloc);
+ if (ret == 0) {
+ fd = set_cloexec_or_close(new_alloc.fd);
+ if (fd >= 0) {
+ struct virtwl_ioctl_dmabuf_sync sync = {0};
+
+ sync.flags = DMA_BUF_SYNC_START | DMA_BUF_SYNC_RW;
+ ioctl(fd, VIRTWL_IOCTL_DMABUF_SYNC, &sync);
+
+ stride = new_alloc.dmabuf.stride0;
+ size = stride * height;
+ xwl_pixmap->dmabuf_fd = fd;
+ xwl_pixmap->buffer =
+ wl_drm_create_prime_buffer(xwl_screen->drm,
+ fd,
+ width,
+ height,
+ drm_format,
+ 0, stride,
+ 0, 0,
+ 0, 0);
+ }
+ }
+ }
+ if (!xwl_pixmap->buffer) {
+ fd = os_create_anonymous_file(size);
+ if (fd < 0)
+ goto err_free_xwl_pixmap;
+
+ format = shm_format_for_depth(depth);
+ pool = wl_shm_create_pool(xwl_screen->shm, fd, size);
+ xwl_pixmap->buffer = wl_shm_pool_create_buffer(pool,
+ 0,
+ width,
+ height,
+ stride,
+ format);
+ wl_shm_pool_destroy(pool);
+ }
+
+ xwl_pixmap->size = size;
xwl_pixmap->data = mmap(NULL, size, PROT_READ | PROT_WRITE,
MAP_SHARED, fd, 0);
if (xwl_pixmap->data == MAP_FAILED)
@@ -231,14 +315,10 @@ xwl_shm_create_pixmap(ScreenPtr screen,
stride, xwl_pixmap->data))
goto err_munmap;
- format = shm_format_for_depth(pixmap->drawable.depth);
- pool = wl_shm_create_pool(xwl_screen->shm, fd, xwl_pixmap->size);
- xwl_pixmap->buffer = wl_shm_pool_create_buffer(pool, 0,
- pixmap->drawable.width,
- pixmap->drawable.height,
- pixmap->devKind, format);
- wl_shm_pool_destroy(pool);
- close(fd);
+ if (xwl_pixmap->dmabuf_fd != -1)
+ xwl_screen->dmabuf_count++;
+ else
+ close(fd);
xwl_pixmap_set_private(pixmap, xwl_pixmap);
@@ -262,9 +342,15 @@ xwl_shm_destroy_pixmap(PixmapPtr pixmap)
struct xwl_pixmap *xwl_pixmap = xwl_pixmap_get(pixmap);
if (xwl_pixmap && pixmap->refcnt == 1) {
+ struct xwl_screen *xwl_screen =
+ xwl_screen_get(pixmap->drawable.pScreen);
if (xwl_pixmap->buffer)
wl_buffer_destroy(xwl_pixmap->buffer);
munmap(xwl_pixmap->data, xwl_pixmap->size);
+ if (xwl_pixmap->dmabuf_fd != -1) {
+ close(xwl_pixmap->dmabuf_fd);
+ xwl_screen->dmabuf_count--;
+ }
free(xwl_pixmap);
}
@@ -274,7 +360,19 @@ xwl_shm_destroy_pixmap(PixmapPtr pixmap)
struct wl_buffer *
xwl_shm_pixmap_get_wl_buffer(PixmapPtr pixmap)
{
- return xwl_pixmap_get(pixmap)->buffer;
+ struct xwl_pixmap *xwl_pixmap = xwl_pixmap_get(pixmap);
+
+ if (xwl_pixmap->dmabuf_fd != -1) {
+ struct virtwl_ioctl_dmabuf_sync sync = {0};
+
+ // Trigger a flush by stopping and starting access to buffer.
+ sync.flags = DMA_BUF_SYNC_END | DMA_BUF_SYNC_RW;
+ ioctl(xwl_pixmap->dmabuf_fd, VIRTWL_IOCTL_DMABUF_SYNC, &sync);
+ sync.flags = DMA_BUF_SYNC_START | DMA_BUF_SYNC_RW;
+ ioctl(xwl_pixmap->dmabuf_fd, VIRTWL_IOCTL_DMABUF_SYNC, &sync);
+ }
+
+ return xwl_pixmap->buffer;
}
Bool
@@ -283,6 +381,11 @@ xwl_shm_create_screen_resources(ScreenPtr screen)
struct xwl_screen *xwl_screen = xwl_screen_get(screen);
int ret;
+ xwl_screen->wl_fd = open("/dev/wl0", O_RDWR);
+ if (xwl_screen->wl_fd < 0)
+ return 0;
+ xwl_screen->dmabuf_count = 0;
+
screen->CreateScreenResources = xwl_screen->CreateScreenResources;
ret = (*screen->CreateScreenResources) (screen);
xwl_screen->CreateScreenResources = screen->CreateScreenResources;
diff --git a/hw/xwayland/xwayland.c b/hw/xwayland/xwayland.c
index 939f3392c..c762c3178 100644
--- a/hw/xwayland/xwayland.c
+++ b/hw/xwayland/xwayland.c
@@ -40,6 +40,8 @@
_X_EXPORT Bool noXFree86VidModeExtension;
#endif
+#include "drm-client-protocol.h"
+
void
ddxGiveUp(enum ExitCode error)
{
@@ -551,12 +553,15 @@ registry_global(void *data, struct wl_registry *registry, uint32_t id,
if (xwl_output_create(xwl_screen, id))
xwl_screen->expecting_event++;
}
+ else if (strcmp(interface, "wl_drm") == 0 && version >= 2) {
#ifdef GLAMOR_HAS_GBM
- else if (xwl_screen->glamor &&
- strcmp(interface, "wl_drm") == 0 && version >= 2) {
- xwl_screen_init_glamor(xwl_screen, id, version);
- }
+ if (xwl_screen->glamor)
+ xwl_screen_init_glamor(xwl_screen, id, version);
+ else
#endif
+ xwl_screen->drm =
+ wl_registry_bind(registry, id, &wl_drm_interface, 2);
+ }
}
static void
diff --git a/hw/xwayland/xwayland.h b/hw/xwayland/xwayland.h
index 5e5624be0..f0327c905 100644
--- a/hw/xwayland/xwayland.h
+++ b/hw/xwayland/xwayland.h
@@ -99,6 +99,8 @@ struct xwl_screen {
void *egl_display, *egl_context;
struct gbm_device *gbm;
struct glamor_context *glamor_ctx;
+ int wl_fd;
+ int dmabuf_count;
};
struct xwl_window {
--
2.11.0