From c5fbfbce654b95058b4a1046df8f49436dceaef6 Mon Sep 17 00:00:00 2001 From: Louis-Francis Ratté-Boulianne Date: Wed, 30 Aug 2017 00:45:35 -0400 Subject: glamor: Implement PixmapFromBuffers and BuffersFromPixmap MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It relies on GBM >= 17.1.0 where we can import BO with multiple planes and a format modifier (GBM_BO_IMPORT_FD_MODIFIER). Signed-off-by: Louis-Francis Ratté-Boulianne --- configure.ac | 4 + glamor/glamor.c | 34 +++++--- glamor/glamor.h | 65 ++++++++------ glamor/glamor_egl.c | 121 +++++++++++++++++++++----- glamor/glamor_egl.h | 1 + glamor/glamor_egl_ext.h | 65 ++++++++++++++ glamor/glamor_egl_stubs.c | 7 +- hw/xwayland/.gitignore | 2 + hw/xwayland/Makefile.am | 9 +- hw/xwayland/xwayland-glamor.c | 194 ++++++++++++++++++++++++++++++++---------- hw/xwayland/xwayland.c | 6 +- hw/xwayland/xwayland.h | 9 +- include/dix-config.h.in | 3 + 13 files changed, 407 insertions(+), 113 deletions(-) create mode 100644 glamor/glamor_egl_ext.h diff --git a/configure.ac b/configure.ac index 8d3c3b55b..d8d9aa441 100644 --- a/configure.ac +++ b/configure.ac @@ -2094,6 +2094,10 @@ if test "x$GLAMOR" = xyes; then [AC_DEFINE(GLAMOR_HAS_GBM_LINEAR, 1, [Have GBM_BO_USE_LINEAR])], [], [#include #include ]) + dnl 17.1.0 is required for gbm_bo_create_with_modifiers + PKG_CHECK_EXISTS(gbm >= 17.1.0, + [AC_DEFINE(GBM_BO_WITH_MODIFIERS, 1, [Have gbm_bo_create_with_modifiers])], + []) else if test "x$XORG" = xyes; then AC_MSG_ERROR([Glamor for Xorg requires $LIBGBM]) diff --git a/glamor/glamor.c b/glamor/glamor.c index 91236e29c..f0113534e 100644 --- a/glamor/glamor.c +++ b/glamor/glamor.c @@ -32,6 +32,7 @@ */ #include +#include #include "glamor_priv.h" #include "mipict.h" @@ -804,8 +805,9 @@ glamor_supports_pixmap_import_export(ScreenPtr screen) } _X_EXPORT int -glamor_fd_from_pixmap(ScreenPtr screen, - PixmapPtr pixmap, CARD16 *stride, CARD32 *size) +glamor_fds_from_pixmap(ScreenPtr screen, PixmapPtr pixmap, int *fds, + uint32_t *strides, uint32_t *offsets, + uint64_t *modifier) { glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); glamor_screen_private *glamor_priv = @@ -818,10 +820,9 @@ glamor_fd_from_pixmap(ScreenPtr screen, case GLAMOR_TEXTURE_ONLY: if (!glamor_pixmap_ensure_fbo(pixmap, GL_RGBA, 0)) return -1; - return glamor_egl_dri3_fd_name_from_tex(screen, - pixmap, - pixmap_priv->fbo->tex, - FALSE, stride, size); + return glamor_egl_fds_from_pixmap(screen, pixmap, fds, + strides, offsets, + modifier); default: break; } @@ -834,6 +835,9 @@ glamor_shareable_fd_from_pixmap(ScreenPtr screen, { unsigned orig_usage_hint = pixmap->usage_hint; int ret; + int fds[4]; + uint32_t strides[4], offsets[4]; + uint64_t modifier; /* * The actual difference between a sharable and non sharable buffer @@ -842,7 +846,17 @@ glamor_shareable_fd_from_pixmap(ScreenPtr screen, * 2 of those calls are also exported API, so we cannot just add a flag. */ pixmap->usage_hint = CREATE_PIXMAP_USAGE_SHARED; - ret = glamor_fd_from_pixmap(screen, pixmap, stride, size); + ret = glamor_fds_from_pixmap(screen, pixmap, fds, strides, offsets, + &modifier); + + /* Pixmaps with multi-planes/modifier are not shareable */ + if (ret > 1) + return -1; + + ret = fds[0]; + *stride = strides[0]; + *size = pixmap->drawable.height * *stride; + pixmap->usage_hint = orig_usage_hint; return ret; @@ -858,10 +872,8 @@ glamor_name_from_pixmap(PixmapPtr pixmap, CARD16 *stride, CARD32 *size) case GLAMOR_TEXTURE_ONLY: if (!glamor_pixmap_ensure_fbo(pixmap, GL_RGBA, 0)) return -1; - return glamor_egl_dri3_fd_name_from_tex(pixmap->drawable.pScreen, - pixmap, - pixmap_priv->fbo->tex, - TRUE, stride, size); + return glamor_egl_fd_name_from_pixmap(pixmap->drawable.pScreen, + pixmap, stride, size); default: break; } diff --git a/glamor/glamor.h b/glamor/glamor.h index 5b15a46e5..8f8c31b45 100644 --- a/glamor/glamor.h +++ b/glamor/glamor.h @@ -138,15 +138,17 @@ extern _X_EXPORT void glamor_pixmap_exchange_fbos(PixmapPtr front, /* The DDX is not supposed to call these three functions */ extern _X_EXPORT void glamor_enable_dri3(ScreenPtr screen); -extern _X_EXPORT int glamor_egl_dri3_fd_name_from_tex(ScreenPtr, PixmapPtr, - unsigned int, Bool, - CARD16 *, CARD32 *); +extern _X_EXPORT int glamor_egl_fds_from_pixmap(ScreenPtr, PixmapPtr, int *, + uint32_t *, uint32_t *, + uint64_t *); +extern _X_EXPORT int glamor_egl_fd_name_from_pixmap(ScreenPtr, PixmapPtr, + CARD16 *, CARD32 *); extern _X_EXPORT struct gbm_device *glamor_egl_get_gbm_device(ScreenPtr screen); /* @glamor_supports_pixmap_import_export: Returns whether - * glamor_fd_from_pixmap(), glamor_name_from_pixmap(), and - * glamor_pixmap_from_fd() are supported. + * glamor_fds_from_pixmap(), glamor_name_from_pixmap(), and + * glamor_pixmap_from_fds() are supported. * * @screen: Current screen pointer. * @@ -159,20 +161,22 @@ extern _X_EXPORT struct gbm_device *glamor_egl_get_gbm_device(ScreenPtr screen); * */ extern _X_EXPORT Bool glamor_supports_pixmap_import_export(ScreenPtr screen); -/* @glamor_fd_from_pixmap: Get a dma-buf fd from a pixmap. +/* @glamor_fds_from_pixmap: Get a dma-buf fd from a pixmap. * * @screen: Current screen pointer. * @pixmap: The pixmap from which we want the fd. - * @stride, @size: Pointers to fill the stride and size of the - * buffer associated to the fd. + * @fds, @strides, @offsets: Pointers to fill info of each plane. + * @modifier: Pointer to fill the modifier of the buffer. * - * the pixmap and the buffer associated by the fd will share the same - * content. - * Returns the fd on success, -1 on error. + * the pixmap and the buffer associated by the fds will share the same + * content. The caller is responsible to close the returned file descriptors. + * Returns the number of planes, -1 on error. * */ -extern _X_EXPORT int glamor_fd_from_pixmap(ScreenPtr screen, - PixmapPtr pixmap, - CARD16 *stride, CARD32 *size); +extern _X_EXPORT int glamor_fds_from_pixmap(ScreenPtr screen, + PixmapPtr pixmap, + int *fds, + uint32_t *strides, uint32_t *offsets, + uint64_t *modifier); /* @glamor_shareable_fd_from_pixmap: Get a dma-buf fd suitable for sharing * with other GPUs from a pixmap. @@ -224,25 +228,30 @@ extern _X_EXPORT int glamor_name_from_pixmap(PixmapPtr pixmap, extern _X_EXPORT struct gbm_bo *glamor_gbm_bo_from_pixmap(ScreenPtr screen, PixmapPtr pixmap); -/* @glamor_pixmap_from_fd: Creates a pixmap to wrap a dma-buf fd. +/* @glamor_pixmap_from_fds: Creates a pixmap to wrap a dma-buf fds. * * @screen: Current screen pointer. - * @fd: The dma-buf fd to import. - * @width: The width of the buffer. - * @height: The height of the buffer. - * @stride: The stride of the buffer. - * @depth: The depth of the buffer. - * @bpp: The number of bpp of the buffer. + * @num_fds: Number of fds to import + * @fds: The dma-buf fds to import. + * @width: The width of the buffers. + * @height: The height of the buffers. + * @stride: The stride of the buffers. + * @depth: The depth of the buffers. + * @bpp: The bpp of the buffers. + * @modifier: The modifier of the buffers. * * Returns a valid pixmap if the import succeeded, else NULL. * */ -extern _X_EXPORT PixmapPtr glamor_pixmap_from_fd(ScreenPtr screen, - int fd, - CARD16 width, - CARD16 height, - CARD16 stride, - CARD8 depth, - CARD8 bpp); +extern _X_EXPORT PixmapPtr glamor_pixmap_from_fds(ScreenPtr screen, + CARD8 num_fds, + int *fds, + CARD16 width, + CARD16 height, + CARD32 *strides, + CARD32 *offsets, + CARD8 depth, + CARD8 bpp, + uint64_t modifier); /* @glamor_back_pixmap_from_fd: Backs an existing pixmap with a dma-buf fd. * diff --git a/glamor/glamor_egl.c b/glamor/glamor_egl.c index 53a74b8da..5708170a9 100644 --- a/glamor/glamor_egl.c +++ b/glamor/glamor_egl.c @@ -56,6 +56,7 @@ struct glamor_egl_screen_private { CloseScreenProcPtr CloseScreen; int fd; struct gbm_device *gbm; + int dmabuf_capable; CloseScreenProcPtr saved_close_screen; DestroyPixmapProcPtr saved_destroy_pixmap; @@ -329,10 +330,49 @@ glamor_gbm_bo_from_pixmap(ScreenPtr screen, PixmapPtr pixmap) } int -glamor_egl_dri3_fd_name_from_tex(ScreenPtr screen, - PixmapPtr pixmap, - unsigned int tex, - Bool want_name, CARD16 *stride, CARD32 *size) +glamor_egl_fds_from_pixmap(ScreenPtr screen, PixmapPtr pixmap, int *fds, + uint32_t *strides, uint32_t *offsets, + uint64_t *modifier) +{ +#ifdef GLAMOR_HAS_GBM + struct gbm_bo *bo; +#ifdef GBM_BO_WITH_MODIFIERS + int num_fds, i; +#endif + + if (!glamor_make_pixmap_exportable(pixmap)) + return 0; + + bo = glamor_gbm_bo_from_pixmap(screen, pixmap); + if (!bo) + return 0; + +#ifdef GBM_BO_WITH_MODIFIERS + num_fds = gbm_bo_get_plane_count(bo); + for (i = 0; i < num_fds; i++) { + fds[i] = gbm_bo_get_fd(bo); + strides[i] = gbm_bo_get_stride_for_plane(bo, i); + offsets[i] = gbm_bo_get_offset(bo, i); + } + *modifier = gbm_bo_get_modifier(bo); +#else + fds[0] = gbm_bo_get_fd(bo); + strides[0] = gbm_bo_get_stride(bo); + offsets[0] = 0; + *modifier = 0; +#endif + + gbm_bo_destroy(bo); + return 1; +#else + return 0; +#endif +} + +int +glamor_egl_fd_name_from_pixmap(ScreenPtr screen, + PixmapPtr pixmap, + CARD16 *stride, CARD32 *size) { struct glamor_egl_screen_private *glamor_egl; struct gbm_bo *bo; @@ -346,12 +386,7 @@ glamor_egl_dri3_fd_name_from_tex(ScreenPtr screen, pixmap->devKind = gbm_bo_get_stride(bo); - if (want_name) { - glamor_get_name_from_bo(glamor_egl->fd, bo, &fd); - } - else { - fd = gbm_bo_get_fd(bo); - } + glamor_get_name_from_bo(glamor_egl->fd, bo, &fd); *stride = pixmap->devKind; *size = pixmap->devKind * gbm_bo_get_height(bo); @@ -396,19 +431,55 @@ glamor_back_pixmap_from_fd(PixmapPtr pixmap, } _X_EXPORT PixmapPtr -glamor_pixmap_from_fd(ScreenPtr screen, - int fd, - CARD16 width, - CARD16 height, - CARD16 stride, CARD8 depth, CARD8 bpp) +glamor_pixmap_from_fds(ScreenPtr screen, + CARD8 num_fds, int *fds, + CARD16 width, CARD16 height, + CARD32 *strides, CARD32 *offsets, + CARD8 depth, CARD8 bpp, + uint64_t modifier) { PixmapPtr pixmap; - Bool ret; + struct glamor_egl_screen_private *glamor_egl; + Bool ret = FALSE; + int i; + + glamor_egl = glamor_egl_get_screen_private(xf86ScreenToScrn(screen)); pixmap = screen->CreatePixmap(screen, 0, 0, depth, 0); - ret = glamor_back_pixmap_from_fd(pixmap, fd, width, height, - stride, depth, bpp); + +#ifdef GBM_BO_WITH_MODIFIERS + if (glamor_egl->dmabuf_capable) { + struct gbm_import_fd_modifier_data import_data = { 0 }; + struct gbm_bo *bo; + + import_data.width = width; + import_data.height = height; + import_data.num_fds = num_fds; + import_data.modifier = modifier; + for (i = 0; i < num_fds; i++) { + import_data.fds[i] = fds[i]; + import_data.strides[i] = strides[i]; + import_data.offsets[i] = offsets[i]; + } + import_data.format = GBM_FORMAT_ARGB8888; + bo = gbm_bo_import(glamor_egl->gbm, GBM_BO_IMPORT_FD_MODIFIER, &import_data, 0); + if (bo) { + screen->ModifyPixmapHeader(pixmap, width, height, 0, 0, strides[0], NULL); + ret = glamor_egl_create_textured_pixmap_from_gbm_bo(pixmap, bo); + gbm_bo_destroy(bo); + } + } else +#endif + { + if (num_fds == 1) { + ret = glamor_back_pixmap_from_fd(pixmap, fds[0], width, height, + strides[0], depth, bpp); + } + } + if (ret == FALSE) { + for (i = 0; i < num_fds; i++) + close(fds[i]); screen->DestroyPixmap(pixmap); return NULL; } @@ -532,10 +603,10 @@ glamor_dri3_open_client(ClientPtr client, } static dri3_screen_info_rec glamor_dri3_info = { - .version = 1, + .version = 2, .open_client = glamor_dri3_open_client, - .pixmap_from_fd = glamor_pixmap_from_fd, - .fd_from_pixmap = glamor_fd_from_pixmap, + .pixmap_from_fds = glamor_pixmap_from_fds, + .fds_from_pixmap = glamor_egl_fds_from_pixmap, }; #endif /* DRI3 */ @@ -733,6 +804,14 @@ glamor_egl_init(ScrnInfoPtr scrn, int fd) xf86DrvMsg(scrn->scrnIndex, X_INFO, "glamor X acceleration enabled on %s\n", glGetString(GL_RENDERER)); +#ifdef GBM_BO_WITH_MODIFIERS + if (epoxy_has_egl_extension(glamor_egl->display, + "EGL_EXT_image_dma_buf_import") && + epoxy_has_egl_extension(glamor_egl->display, + "EGL_EXT_image_dma_buf_import_modifiers")) + glamor_egl->dmabuf_capable = TRUE; +#endif + glamor_egl->saved_free_screen = scrn->FreeScreen; scrn->FreeScreen = glamor_egl_free_screen; return TRUE; diff --git a/glamor/glamor_egl.h b/glamor/glamor_egl.h index 6bb1185bf..2f7566b24 100644 --- a/glamor/glamor_egl.h +++ b/glamor/glamor_egl.h @@ -30,6 +30,7 @@ #define MESA_EGL_NO_X11_HEADERS #include #include +#include /* * Create an EGLDisplay from a native display type. This is a little quirky diff --git a/glamor/glamor_egl_ext.h b/glamor/glamor_egl_ext.h new file mode 100644 index 000000000..436e52137 --- /dev/null +++ b/glamor/glamor_egl_ext.h @@ -0,0 +1,65 @@ +/* + * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +/* Extensions used by Glamor, copied from Mesa's eglmesaext.h, */ + +#ifndef GLAMOR_EGL_EXT_H +#define GLAMOR_EGL_EXT_H + +/* Define needed tokens from EGL_EXT_image_dma_buf_import extension + * here to avoid having to add ifdefs everywhere.*/ +#ifndef EGL_EXT_image_dma_buf_import +#define EGL_LINUX_DMA_BUF_EXT 0x3270 +#define EGL_LINUX_DRM_FOURCC_EXT 0x3271 +#define EGL_DMA_BUF_PLANE0_FD_EXT 0x3272 +#define EGL_DMA_BUF_PLANE0_OFFSET_EXT 0x3273 +#define EGL_DMA_BUF_PLANE0_PITCH_EXT 0x3274 +#define EGL_DMA_BUF_PLANE1_FD_EXT 0x3275 +#define EGL_DMA_BUF_PLANE1_OFFSET_EXT 0x3276 +#define EGL_DMA_BUF_PLANE1_PITCH_EXT 0x3277 +#define EGL_DMA_BUF_PLANE2_FD_EXT 0x3278 +#define EGL_DMA_BUF_PLANE2_OFFSET_EXT 0x3279 +#define EGL_DMA_BUF_PLANE2_PITCH_EXT 0x327A +#endif + +/* Define tokens from EGL_EXT_image_dma_buf_import_modifiers */ +#ifndef EGL_EXT_image_dma_buf_import_modifiers +#define EGL_EXT_image_dma_buf_import_modifiers 1 +#define EGL_DMA_BUF_PLANE3_FD_EXT 0x3440 +#define EGL_DMA_BUF_PLANE3_OFFSET_EXT 0x3441 +#define EGL_DMA_BUF_PLANE3_PITCH_EXT 0x3442 +#define EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT 0x3443 +#define EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT 0x3444 +#define EGL_DMA_BUF_PLANE1_MODIFIER_LO_EXT 0x3445 +#define EGL_DMA_BUF_PLANE1_MODIFIER_HI_EXT 0x3446 +#define EGL_DMA_BUF_PLANE2_MODIFIER_LO_EXT 0x3447 +#define EGL_DMA_BUF_PLANE2_MODIFIER_HI_EXT 0x3448 +#define EGL_DMA_BUF_PLANE3_MODIFIER_LO_EXT 0x3449 +#define EGL_DMA_BUF_PLANE3_MODIFIER_HI_EXT 0x344A +typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYDMABUFFORMATSEXTPROC) (EGLDisplay dpy, EGLint max_formats, EGLint *formats, EGLint *num_formats); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYDMABUFMODIFIERSEXTPROC) (EGLDisplay dpy, EGLint format, EGLint max_modifiers, EGLuint64KHR *modifiers, EGLBoolean *external_only, EGLint *num_modifiers); +#endif + +#endif /* GLAMOR_EGL_EXT_H */ diff --git a/glamor/glamor_egl_stubs.c b/glamor/glamor_egl_stubs.c index 40f7fcc01..4af1c13d5 100644 --- a/glamor/glamor_egl_stubs.c +++ b/glamor/glamor_egl_stubs.c @@ -36,10 +36,9 @@ glamor_egl_screen_init(ScreenPtr screen, struct glamor_context *glamor_ctx) } int -glamor_egl_dri3_fd_name_from_tex(ScreenPtr screen, - PixmapPtr pixmap, - unsigned int tex, - Bool want_name, CARD16 *stride, CARD32 *size) +glamor_egl_fds_from_pixmap(ScreenPtr screen, PixmapPtr pixmap, int *fds, + uint32_t *offsets, uint32_t *strides, + uint64_t *modifier) { return 0; } diff --git a/hw/xwayland/.gitignore b/hw/xwayland/.gitignore index 38ada56d1..c0320b555 100644 --- a/hw/xwayland/.gitignore +++ b/hw/xwayland/.gitignore @@ -5,3 +5,5 @@ 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 eda49799e..e438d8306 100644 --- a/hw/xwayland/Makefile.am +++ b/hw/xwayland/Makefile.am @@ -59,7 +59,9 @@ Xwayland_built_sources += \ tablet-unstable-v2-client-protocol.h \ tablet-unstable-v2-protocol.c \ xwayland-keyboard-grab-unstable-v1-protocol.c \ - xwayland-keyboard-grab-unstable-v1-client-protocol.h + xwayland-keyboard-grab-unstable-v1-client-protocol.h \ + linux-dmabuf-unstable-v1-client-protocol.h \ + linux-dmabuf-unstable-v1-protocol.c nodist_Xwayland_SOURCES = $(Xwayland_built_sources) CLEANFILES = $(Xwayland_built_sources) @@ -92,6 +94,11 @@ xwayland-keyboard-grab-unstable-v1-protocol.c : $(WAYLAND_PROTOCOLS_DATADIR)/uns xwayland-keyboard-grab-unstable-v1-client-protocol.h : $(WAYLAND_PROTOCOLS_DATADIR)/unstable/xwayland-keyboard-grab/xwayland-keyboard-grab-unstable-v1.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 87622839e..5c0c408ab 100644 --- a/hw/xwayland/xwayland-glamor.c +++ b/hw/xwayland/xwayland-glamor.c @@ -59,7 +59,7 @@ xwl_glamor_egl_make_current(struct glamor_context *glamor_ctx) } static uint32_t -drm_format_for_depth(int depth) +wl_drm_format_for_depth(int depth) { switch (depth) { case 15: @@ -158,25 +158,64 @@ 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; + int num_planes; + uint32_t strides[4]; + uint32_t offsets[4]; + uint64_t modifier; + int i; if (xwl_pixmap->buffer) return xwl_pixmap->buffer; + if (!xwl_pixmap->bo) + 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); +#ifdef GBM_BO_WITH_MODIFIERS + num_planes = gbm_bo_get_plane_count(xwl_pixmap->bo); + modifier = gbm_bo_get_modifier(xwl_pixmap->bo); + for (i = 0; i < num_planes; i++) { + strides[i] = gbm_bo_get_stride_for_plane(xwl_pixmap->bo, i); + offsets[i] = gbm_bo_get_offset(xwl_pixmap->bo, i); + } +#else + num_planes = 1; + modifier = 0; + strides[0] = gbm_go_get_stride(xwl_pixmap->bo); + offsets[0] = 0; +#endif - close(prime_fd); + if (xwl_screen->dmabuf) { + struct zwp_linux_buffer_params_v1 *params; + + 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, prime_fd, i, + offsets[i], strides[i] + modifier >> 32, modifier & 0xffffffff); + } + + xwl_pixmap->buffer = + zwp_linux_buffer_params_v1_create_immed(params, + pixmap->drawable.width, + pixmap->drawable.height, + wl_drm_format_for_depth(pixmap->drawable.depth), + 0); + } else if (num_planes == 1 && modifier == 0) { + xwl_pixmap->buffer = + wl_drm_create_prime_buffer(xwl_screen->drm, prime_fd, + pixmap->drawable.width, + pixmap->drawable.height, + wl_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; } @@ -213,7 +252,8 @@ xwl_glamor_destroy_pixmap(PixmapPtr pixmap) wl_buffer_destroy(xwl_pixmap->buffer); eglDestroyImageKHR(xwl_screen->egl_display, xwl_pixmap->image); - gbm_bo_destroy(xwl_pixmap->bo); + if (xwl_pixmap->bo) + gbm_bo_destroy(xwl_pixmap->bo); free(xwl_pixmap); } @@ -331,6 +371,12 @@ xwl_drm_init_egl(struct xwl_screen *xwl_screen) return; } + if (epoxy_has_egl_extension(xwl_screen->egl_display, + "EXT_image_dma_buf_import") && + epoxy_has_egl_extension(xwl_screen->egl_display, + "EXT_image_dma_buf_import_modifiers")) + xwl_screen->dmabuf_capable = TRUE; + return; } @@ -403,8 +449,8 @@ static const struct wl_drm_listener xwl_drm_listener = { }; 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; @@ -417,11 +463,23 @@ 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); + + return TRUE; +} + int -glamor_egl_dri3_fd_name_from_tex(ScreenPtr screen, - PixmapPtr pixmap, - unsigned int tex, - Bool want_name, CARD16 *stride, CARD32 *size) +glamor_egl_fd_name_from_pixmap(ScreenPtr screen, + PixmapPtr pixmap, + CARD16 *stride, CARD32 *size) { return 0; } @@ -522,58 +580,104 @@ xwl_dri3_open_client(ClientPtr client, return Success; } -static PixmapPtr -xwl_dri3_pixmap_from_fd(ScreenPtr screen, int fd, - CARD16 width, CARD16 height, CARD16 stride, - CARD8 depth, CARD8 bpp) +_X_EXPORT PixmapPtr +glamor_pixmap_from_fds(ScreenPtr screen, + CARD8 num_fds, int *fds, + CARD16 width, CARD16 height, + CARD32 *strides, CARD32 *offsets, + CARD8 depth, CARD8 bpp, uint64_t modifier) { struct xwl_screen *xwl_screen = xwl_screen_get(screen); - struct gbm_import_fd_data data; struct gbm_bo *bo; PixmapPtr pixmap; + int i; + + if (width == 0 || height == 0 || num_fds == 0 || + depth < 15 || bpp != BitsPerPixel(depth) || + strides[0] < width * bpp / 8) + goto error; + + if (xwl_screen->dmabuf_capable) { +#ifdef GBM_BO_WITH_MODIFIERS + struct gbm_import_fd_modifier_data data; + + data.width = width; + data.height = height; + data.num_fds = num_fds; + data.format = gbm_format_for_depth(depth); + data.modifier = modifier + for (i = 0; i < num_fds; i++) { + data.fds[i] = fds[i]; + data.strides[i] = strides[i]; + data.offsets[i] = offsets[i]; + } + bo = gbm_bo_import(xwl_screen->gbm, GBM_BO_IMPORT_FD_MODIFIER, &data, + GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING); +#endif + } else if (num_fds == 1) { + struct gbm_import_fd_data data; + + data.fd = fds[0]; + data.width = width; + data.height = height; + data.stride = strides[0]; + 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); + } else { + goto error; + } - 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; + goto error; pixmap = xwl_glamor_create_pixmap_for_bo(screen, bo, depth); if (pixmap == NULL) { - gbm_bo_destroy(bo); - return NULL; + gbm_bo_destroy(bo); + goto error; } return pixmap; + +error: + for (i = 0; i < num_fds; i++) + close(fds[i]); + return NULL; } -static int -xwl_dri3_fd_from_pixmap(ScreenPtr screen, PixmapPtr pixmap, - CARD16 *stride, CARD32 *size) +_X_EXPORT int +glamor_egl_fds_from_pixmap(ScreenPtr screen, PixmapPtr pixmap, int *fds, + uint32_t *strides, uint32_t *offsets, + uint64_t *modifier) { struct xwl_pixmap *xwl_pixmap; + int i; xwl_pixmap = xwl_pixmap_get(pixmap); - *stride = gbm_bo_get_stride(xwl_pixmap->bo); - *size = pixmap->drawable.width * *stride; + if (xwl_pixmap->bo) { + fds[0] = gbm_bo_get_fd(xwl_pixmap->bo); + strides[0] = gbm_bo_get_stride(xwl_pixmap->bo); + offsets[0] = 0; + *modifier = 0; + return 1; + } + + for (i = 0; i < xwl_pixmap->num_fds; i++) { + fds[i] = xwl_pixmap->fds[i]; + strides[i] = xwl_pixmap->strides[i]; + offsets[i] = xwl_pixmap->offsets[i]; + } + *modifier = xwl_pixmap->modifier; - return gbm_bo_get_fd(xwl_pixmap->bo); + return xwl_pixmap->num_fds; } static dri3_screen_info_rec xwl_dri3_info = { - .version = 1, + .version = 2, .open = NULL, - .pixmap_from_fd = xwl_dri3_pixmap_from_fd, - .fd_from_pixmap = xwl_dri3_fd_from_pixmap, + .pixmap_from_fds = glamor_pixmap_from_fds, + .fds_from_pixmap = glamor_fds_from_pixmap, .open_client = xwl_dri3_open_client, }; diff --git a/hw/xwayland/xwayland.c b/hw/xwayland/xwayland.c index cb929cad5..92088cdce 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 6d3edf33b..ec77d10f9 100644 --- a/hw/xwayland/xwayland.h +++ b/hw/xwayland/xwayland.h @@ -46,6 +46,7 @@ #include "pointer-constraints-unstable-v1-client-protocol.h" #include "tablet-unstable-v2-client-protocol.h" #include "xwayland-keyboard-grab-unstable-v1-client-protocol.h" +#include "linux-dmabuf-unstable-v1-client-protocol.h" struct xwl_screen { int width; @@ -95,11 +96,13 @@ struct xwl_screen { int drm_fd; int fd_render_node; struct wl_drm *drm; + struct zwp_linux_dmabuf_v1 *dmabuf; uint32_t formats; uint32_t capabilities; void *egl_display, *egl_context; struct gbm_device *gbm; struct glamor_context *glamor_ctx; + int dmabuf_capable; Atom allow_commits_prop; }; @@ -320,8 +323,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); diff --git a/include/dix-config.h.in b/include/dix-config.h.in index ad1ab20a6..57aee61fd 100644 --- a/include/dix-config.h.in +++ b/include/dix-config.h.in @@ -497,6 +497,9 @@ /* Build glamor/gbm has linear support */ #undef GLAMOR_HAS_GBM_LINEAR +/* GBM has modifiers support */ +#undef GBM_BO_WITH_MODIFIERS + /* Build glamor use new drmGetDeviceNameFromFD2 */ #undef GLAMOR_HAS_DRM_NAME_FROM_FD_2 -- cgit v1.2.3