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