[RFC xserver 16/16] xwayland: Use unstable dmabuf extension to support modifiers
Daniel Stone
daniels at collabora.com
Thu Jun 8 18:43:42 UTC 2017
From: Louis-Francis Ratté-Boulianne <lfrb at collabora.com>
Use linux-dmabuf-unstable-v1 extension to retrieve supported
formats and modifiers and to create wl_buffers from multi-fds
pixmaps.
Signed-off-by: Louis-Francis Ratté-Boulianne <lfrb at collabora.com>
Signed-off-by: Daniel Stone <daniels at collabora.com>
---
hw/xwayland/.gitignore | 3 +
hw/xwayland/Makefile.am | 9 ++-
hw/xwayland/xwayland-glamor.c | 175 ++++++++++++++++++++++++++++--------------
hw/xwayland/xwayland.c | 6 +-
hw/xwayland/xwayland.h | 17 +++-
5 files changed, 146 insertions(+), 64 deletions(-)
diff --git a/hw/xwayland/.gitignore b/hw/xwayland/.gitignore
index 38ada56d1..5ce020835 100644
--- a/hw/xwayland/.gitignore
+++ b/hw/xwayland/.gitignore
@@ -5,3 +5,6 @@ pointer-constraints-unstable-v1-client-protocol.h
pointer-constraints-unstable-v1-protocol.c
relative-pointer-unstable-v1-client-protocol.h
relative-pointer-unstable-v1-protocol.c
+linux-dmabuf-unstable-v1-client-protocol.h
+linux-dmabuf-unstable-v1-protocol.c
+
diff --git a/hw/xwayland/Makefile.am b/hw/xwayland/Makefile.am
index 7eda9be34..5a65de026 100644
--- a/hw/xwayland/Makefile.am
+++ b/hw/xwayland/Makefile.am
@@ -57,7 +57,9 @@ Xwayland_built_sources += \
pointer-constraints-unstable-v1-client-protocol.h \
pointer-constraints-unstable-v1-protocol.c \
tablet-unstable-v2-client-protocol.h \
- tablet-unstable-v2-protocol.c
+ tablet-unstable-v2-protocol.c \
+ linux-dmabuf-unstable-v1-client-protocol.h \
+ linux-dmabuf-unstable-v1-protocol.c
nodist_Xwayland_SOURCES = $(Xwayland_built_sources)
CLEANFILES = $(Xwayland_built_sources)
@@ -85,6 +87,11 @@ tablet-unstable-v2-protocol.c: $(WAYLAND_PROTOCOLS_DATADIR)/unstable/tablet/tabl
tablet-unstable-v2-client-protocol.h: $(WAYLAND_PROTOCOLS_DATADIR)/unstable/tablet/tablet-unstable-v2.xml
$(AM_V_GEN)$(WAYLAND_SCANNER) client-header < $< > $@
+linux-dmabuf-unstable-v1-protocol.c : $(WAYLAND_PROTOCOLS_DATADIR)/unstable/linux-dmabuf/linux-dmabuf-unstable-v1.xml
+ $(AM_V_GEN)$(WAYLAND_SCANNER) code < $< > $@
+linux-dmabuf-unstable-v1-client-protocol.h : $(WAYLAND_PROTOCOLS_DATADIR)/unstable/linux-dmabuf/linux-dmabuf-unstable-v1.xml
+ $(AM_V_GEN)$(WAYLAND_SCANNER) client-header < $< > $@
+
%-protocol.c : %.xml
$(AM_V_GEN)$(WAYLAND_SCANNER) code < $< > $@
diff --git a/hw/xwayland/xwayland-glamor.c b/hw/xwayland/xwayland-glamor.c
index de9769028..49950f997 100644
--- a/hw/xwayland/xwayland-glamor.c
+++ b/hw/xwayland/xwayland-glamor.c
@@ -307,29 +307,47 @@ 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;
- /* XXX If xwl_pimxap is not backed by a bo (dmabuf),
- * should we create a wl_buffer using the zwp_linux_dmabuf
- * interface? Is it safe to use in Xorg server? */
+ if (xwl_pixmap->bo) {
+ int prime_fd;
- prime_fd = gbm_bo_get_fd(xwl_pixmap->bo);
- if (prime_fd == -1)
- return NULL;
+ 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);
+ 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);
+ } else if (xwl_pixmap->num_fds > 0) {
+ struct zwp_linux_buffer_params_v1 *params;
+ int i;
+
+ params = zwp_linux_dmabuf_v1_create_params(xwl_screen->dmabuf);
+ for (i = 0; i < xwl_pixmap->num_fds; i++) {
+ zwp_linux_buffer_params_v1_add(params, xwl_pixmap->fds[i], i,
+ xwl_pixmap->offsets[i],
+ xwl_pixmap->strides[i],
+ xwl_pixmap->modifier >> 32,
+ xwl_pixmap->modifier & 0xffffffff);
+ }
- close(prime_fd);
+ xwl_pixmap->buffer =
+ zwp_linux_buffer_params_v1_create_immed(params,
+ pixmap->drawable.width,
+ pixmap->drawable.height,
+ drm_format_for_depth(pixmap->drawable.depth),
+ 0);
+ }
return xwl_pixmap->buffer;
}
@@ -548,19 +566,6 @@ xwl_drm_handle_device(void *data, struct wl_drm *drm, const char *device)
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
@@ -587,9 +592,57 @@ static const struct wl_drm_listener xwl_drm_listener = {
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_init_glamor(struct xwl_screen *xwl_screen,
- uint32_t id, uint32_t version)
+xwl_screen_set_drm_interface(struct xwl_screen *xwl_screen,
+ uint32_t id, uint32_t version)
{
if (version < 2)
return FALSE;
@@ -602,6 +655,20 @@ xwl_screen_init_glamor(struct xwl_screen *xwl_screen,
return TRUE;
}
+Bool
+xwl_screen_set_dmabuf_interface(struct xwl_screen *xwl_screen,
+ uint32_t id, uint32_t version)
+{
+ if (version < 2)
+ return FALSE;
+
+ xwl_screen->dmabuf =
+ wl_registry_bind(xwl_screen->registry, id, &zwp_linux_dmabuf_v1_interface, 2);
+ zwp_linux_dmabuf_v1_add_listener(xwl_screen->dmabuf, &xwl_dmabuf_listener, xwl_screen);
+
+ return TRUE;
+}
+
int
glamor_egl_fd_name_from_pixmap(ScreenPtr screen,
PixmapPtr pixmap,
@@ -800,29 +867,21 @@ xwl_dri3_get_formats(ScreenPtr screen,
return FALSE;
#else
struct xwl_screen *xwl_screen = xwl_screen_get(screen);
- EGLint num;
+ int i;
- if (!xwl_screen->modifiers_capable)
+ if (!xwl_screen->modifiers_capable || !xwl_screen->dmabuf)
return FALSE;
- if (!eglQueryDmaBufFormatsEXT(xwl_screen->egl_display, 0, NULL, &num)) {
- *num_formats = 0;
- return FALSE;
- }
-
- *formats = calloc(num, sizeof(CARD32));
+ *formats = calloc(xwl_screen->num_formats, sizeof(CARD32));
if (*formats == NULL) {
*num_formats = 0;
return FALSE;
}
- if (!eglQueryDmaBufFormatsEXT(xwl_screen->egl_display, num, (EGLint *) *formats, &num)) {
- *num_formats = 0;
- free(*formats);
- return FALSE;
- }
+ for (i = 0; i < xwl_screen->num_formats; i++)
+ (*formats)[i] = xwl_screen->formats[i].format;
+ *num_formats = xwl_screen->num_formats;
- *num_formats = num;
return TRUE;
#endif
}
@@ -835,31 +894,29 @@ xwl_dri3_get_modifiers(ScreenPtr screen, CARD32 format,
return FALSE;
#else
struct xwl_screen *xwl_screen = xwl_screen_get(screen);
- EGLint num;
+ struct xwl_format *xwl_format = NULL;
+ int i;
- if (!xwl_screen->modifiers_capable)
+ if (!xwl_screen->modifiers_capable || !xwl_screen->dmabuf)
return FALSE;
- if (!eglQueryDmaBufModifiersEXT(xwl_screen->egl_display, format, 0, NULL,
- NULL, &num)) {
- *num_modifiers = 0;
- return FALSE;
+ for (i = 0; i < xwl_screen->num_formats; i++) {
+ if (xwl_screen->formats[i].format == format) {
+ xwl_format = &xwl_screen->formats[i];
+ break;
+ }
}
- *modifiers = calloc(num, sizeof(uint64_t));
+ *modifiers = calloc(xwl_format->num_modifiers, sizeof(uint64_t));
if (*modifiers == NULL) {
*num_modifiers = 0;
return FALSE;
}
- if (!eglQueryDmaBufModifiersEXT(xwl_screen->egl_display, format, num,
- *modifiers, NULL, &num)) {
- *num_modifiers = 0;
- free(*modifiers);
- return FALSE;
- }
+ for (i = 0; i < xwl_format->num_modifiers; i++)
+ (*modifiers)[i] = xwl_format->modifiers[i];
+ *num_modifiers = xwl_format->num_modifiers;
- *num_modifiers = num;
return TRUE;
#endif
}
diff --git a/hw/xwayland/xwayland.c b/hw/xwayland/xwayland.c
index 551443f93..67c00e7e0 100644
--- a/hw/xwayland/xwayland.c
+++ b/hw/xwayland/xwayland.c
@@ -678,7 +678,11 @@ registry_global(void *data, struct wl_registry *registry, uint32_t id,
#ifdef GLAMOR_HAS_GBM
else if (xwl_screen->glamor &&
strcmp(interface, "wl_drm") == 0 && version >= 2) {
- xwl_screen_init_glamor(xwl_screen, id, version);
+ xwl_screen_set_drm_interface(xwl_screen, id, version);
+ }
+ else if (xwl_screen->glamor &&
+ strcmp(interface, "zwp_linux_dmabuf_v1") == 0 && version >= 2) {
+ xwl_screen_set_dmabuf_interface(xwl_screen, id, version);
}
#endif
}
diff --git a/hw/xwayland/xwayland.h b/hw/xwayland/xwayland.h
index df2a3087d..25fac5d6f 100644
--- a/hw/xwayland/xwayland.h
+++ b/hw/xwayland/xwayland.h
@@ -45,6 +45,13 @@
#include "relative-pointer-unstable-v1-client-protocol.h"
#include "pointer-constraints-unstable-v1-client-protocol.h"
#include "tablet-unstable-v2-client-protocol.h"
+#include "linux-dmabuf-unstable-v1-client-protocol.h"
+
+struct xwl_format {
+ uint32_t format;
+ int num_modifiers;
+ uint64_t *modifiers;
+};
struct xwl_screen {
int width;
@@ -94,7 +101,9 @@ struct xwl_screen {
int drm_fd;
int fd_render_node;
struct wl_drm *drm;
- uint32_t formats;
+ struct zwp_linux_dmabuf_v1 *dmabuf;
+ uint32_t num_formats;
+ struct xwl_format *formats;
uint32_t capabilities;
void *egl_display, *egl_context;
struct gbm_device *gbm;
@@ -317,8 +326,10 @@ struct wl_buffer *xwl_shm_pixmap_get_wl_buffer(PixmapPtr pixmap);
Bool xwl_glamor_init(struct xwl_screen *xwl_screen);
-Bool xwl_screen_init_glamor(struct xwl_screen *xwl_screen,
- uint32_t id, uint32_t version);
+Bool xwl_screen_set_drm_interface(struct xwl_screen *xwl_screen,
+ uint32_t id, uint32_t version);
+Bool xwl_screen_set_dmabuf_interface(struct xwl_screen *xwl_screen,
+ uint32_t id, uint32_t version);
struct wl_buffer *xwl_glamor_pixmap_get_wl_buffer(PixmapPtr pixmap);
void xwl_screen_release_tablet_manager(struct xwl_screen *xwl_screen);
--
2.13.0
More information about the xorg-devel
mailing list