summaryrefslogtreecommitdiff
path: root/dri3
diff options
context:
space:
mode:
authorDaniel Stone <daniels@collabora.com>2018-04-04 16:16:32 +0100
committerAdam Jackson <ajax@redhat.com>2018-04-04 13:46:57 -0400
commit75bba3aedcb04132a4fe2806680cd38a8f2bd206 (patch)
tree3c4ff254b3ccbabf1dd06a52f0f9c3296a391d41 /dri3
parent574069c2912893a9b9fd3d701eb3ad4784e31553 (diff)
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>
Diffstat (limited to 'dri3')
-rw-r--r--dri3/dri3_priv.h3
-rw-r--r--dri3/dri3_request.c16
-rw-r--r--dri3/dri3_screen.c40
3 files changed, 48 insertions, 11 deletions
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
@@ -84,6 +84,9 @@ dri3_pixmap_from_fds(PixmapPtr *ppixmap, ScreenPtr screen, CARD8 num_fds, int *f
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,
CARD64 *modifier);
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 <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)
{