| 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 |
| |