Commit 75bba3ae authored by Daniel Stone's avatar Daniel Stone Committed by Adam Jackson
Browse files

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's avatarDaniel Stone <>
Reported-by: Adam Jackson's avatarAdam Jackson <>
Reviewed-by: Adam Jackson's avatarAdam Jackson <>
parent 574069c2
......@@ -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);
dri3_fd_from_pixmap(PixmapPtr pixmap, CARD16 *stride, CARD32 *size);
dri3_fds_from_pixmap(PixmapPtr pixmap, int *fds,
CARD32 *strides, CARD32 *offsets,
......@@ -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;
......@@ -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) {
......@@ -246,8 +240,8 @@ proc_dri3_buffer_from_pixmap(ClientPtr client)
if (WriteFdToClient(client, fds[0], TRUE) < 0) {
if (WriteFdToClient(client, fd, TRUE) < 0) {
return BadAlloc;
......@@ -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,
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,
if (num_fds != 1 || offsets[0] != 0) {
int i;
for (i = 0; i < num_fds; i++)
return -1;
return fds[0];
static int
cache_formats_and_modifiers(ScreenPtr screen)
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment