From: Louis-Francis Ratté-Boulianne <[email protected]> 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 <[email protected]> Signed-off-by: Daniel Stone <[email protected]> --- 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 _______________________________________________ [email protected]: X.Org development Archives: http://lists.x.org/archives/xorg-devel Info: https://lists.x.org/mailman/listinfo/xorg-devel
