From 75bba3aedcb04132a4fe2806680cd38a8f2bd206 Mon Sep 17 00:00:00 2001 From: Daniel Stone Date: Wed, 4 Apr 2018 16:16:32 +0100 Subject: dri3: Use single-FD screen call for single-FD request When importing client buffers into Pixmaps, we can use the fds_to_pixmap hook for both single-FD and multi-FD client requests without any harm. For the other direction of exporting Pixmap buffers to client FDs, create a new helper which calls the old pixmap_to_fd hook if available. This allows the implementation to ensure that the Pixmap storage is accessible to clients not aware of multiple planes or modifiers, e.g. by reallocating and copying. This makes it possible to run a compositing manager on an old GLX/EGL stack on top of an X server which allocates internal buffer storage using exotic modifiers from modifier-aware GBM/EGL/KMS. Signed-off-by: Daniel Stone Reported-by: Adam Jackson Reviewed-by: Adam Jackson --- dri3/dri3_priv.h | 3 +++ dri3/dri3_request.c | 16 +++++----------- dri3/dri3_screen.c | 40 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 48 insertions(+), 11 deletions(-) (limited to 'dri3') diff --git a/dri3/dri3_priv.h b/dri3/dri3_priv.h index 8447680ba..d86f06be0 100644 --- a/dri3/dri3_priv.h +++ b/dri3/dri3_priv.h @@ -83,6 +83,9 @@ dri3_pixmap_from_fds(PixmapPtr *ppixmap, ScreenPtr screen, CARD8 num_fds, int *f CARD16 width, CARD16 height, CARD32 *strides, CARD32 *offsets, CARD8 depth, CARD8 bpp, CARD64 modifier); +int +dri3_fd_from_pixmap(PixmapPtr pixmap, CARD16 *stride, CARD32 *size); + int dri3_fds_from_pixmap(PixmapPtr pixmap, int *fds, CARD32 *strides, CARD32 *offsets, diff --git a/dri3/dri3_request.c b/dri3/dri3_request.c index fc258711b..2d3deb282 100644 --- a/dri3/dri3_request.c +++ b/dri3/dri3_request.c @@ -212,10 +212,7 @@ proc_dri3_buffer_from_pixmap(ClientPtr client) .length = 0, }; int rc; - int num_fds; - int fds[4]; - uint32_t strides[4], offsets[4]; - uint64_t modifier; + int fd; PixmapPtr pixmap; REQUEST_SIZE_MATCH(xDRI3BufferFromPixmapReq); @@ -231,13 +228,10 @@ proc_dri3_buffer_from_pixmap(ClientPtr client) rep.depth = pixmap->drawable.depth; rep.bpp = pixmap->drawable.bitsPerPixel; - num_fds = dri3_fds_from_pixmap(pixmap, fds, strides, offsets, &modifier); - if (num_fds != 1) + fd = dri3_fd_from_pixmap(pixmap, &rep.stride, &rep.size); + if (fd == -1) return BadPixmap; - rep.stride = (CARD16) strides[0]; - rep.size = rep.stride * rep.height; - if (client->swapped) { swaps(&rep.sequenceNumber); swapl(&rep.length); @@ -246,8 +240,8 @@ proc_dri3_buffer_from_pixmap(ClientPtr client) swaps(&rep.height); swaps(&rep.stride); } - if (WriteFdToClient(client, fds[0], TRUE) < 0) { - close(fds[0]); + if (WriteFdToClient(client, fd, TRUE) < 0) { + close(fd); return BadAlloc; } diff --git a/dri3/dri3_screen.c b/dri3/dri3_screen.c index df40f8281..41595f412 100644 --- a/dri3/dri3_screen.c +++ b/dri3/dri3_screen.c @@ -30,6 +30,7 @@ #include #include #include +#include static inline Bool has_open(dri3_screen_info_ptr info) { if (info == NULL) @@ -124,6 +125,45 @@ dri3_fds_from_pixmap(PixmapPtr pixmap, int *fds, } } +int +dri3_fd_from_pixmap(PixmapPtr pixmap, CARD16 *stride, CARD32 *size) +{ + ScreenPtr screen = pixmap->drawable.pScreen; + dri3_screen_priv_ptr ds = dri3_screen_priv(screen); + dri3_screen_info_ptr info = ds->info; + CARD32 strides[4]; + CARD32 offsets[4]; + CARD64 modifier; + int fds[4]; + int num_fds; + + if (!info) + return -1; + + /* Preferentially use the old interface, allowing the implementation to + * ensure the buffer is in a single-plane format which doesn't need + * modifiers. */ + if (info->fd_from_pixmap != NULL) + return (*info->fd_from_pixmap)(screen, pixmap, stride, size); + + if (info->version < 2 || info->fds_from_pixmap == NULL) + return -1; + + /* If using the new interface, make sure that it's a single plane starting + * at 0 within the BO. We don't check the modifier, as the client may + * have an auxiliary mechanism for determining the modifier itself. */ + num_fds = info->fds_from_pixmap(screen, pixmap, fds, strides, offsets, + &modifier); + if (num_fds != 1 || offsets[0] != 0) { + int i; + for (i = 0; i < num_fds; i++) + close(fds[i]); + return -1; + } + + return fds[0]; +} + static int cache_formats_and_modifiers(ScreenPtr screen) { -- cgit v1.2.3