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 <daniels@collabora.com>
Reported-by: Adam Jackson <ajax@redhat.com>
Reviewed-by: Adam Jackson <ajax@redhat.com>
This commit is contained in:
Daniel Stone 2018-04-04 16:16:32 +01:00 committed by Adam Jackson
parent 574069c291
commit 75bba3aedc
3 changed files with 48 additions and 11 deletions

View File

@ -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,

View File

@ -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;
}

View File

@ -30,6 +30,7 @@
#include <misyncshm.h>
#include <randrstr.h>
#include <drm_fourcc.h>
#include <unistd.h>
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)
{