summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--configure.ac2
-rw-r--r--dri3/dri3.c19
-rw-r--r--dri3/dri3.h44
-rw-r--r--dri3/dri3_priv.h27
-rw-r--r--dri3/dri3_request.c294
-rw-r--r--dri3/dri3_screen.c196
-rw-r--r--hw/xwayland/xwayland-glamor.c4
-rw-r--r--meson.build2
8 files changed, 559 insertions, 29 deletions
diff --git a/configure.ac b/configure.ac
index 0ba7550a1..47bf17452 100644
--- a/configure.ac
+++ b/configure.ac
@@ -729,7 +729,7 @@ SCRNSAVERPROTO="scrnsaverproto >= 1.1"
RESOURCEPROTO="resourceproto >= 1.2.0"
DRIPROTO="xf86driproto >= 2.1.0"
DRI2PROTO="dri2proto >= 2.8"
-DRI3PROTO="dri3proto >= 1.0"
+DRI3PROTO="dri3proto >= 1.2"
XINERAMAPROTO="xineramaproto"
BIGFONTPROTO="xf86bigfontproto >= 1.2.0"
DGAPROTO="xf86dgaproto >= 2.0.99.1"
diff --git a/dri3/dri3.c b/dri3/dri3.c
index d042b8b7d..8ac0f3ae2 100644
--- a/dri3/dri3.c
+++ b/dri3/dri3.c
@@ -26,6 +26,8 @@
#include "dri3_priv.h"
+#include <drm_fourcc.h>
+
static int dri3_request;
DevPrivateKeyRec dri3_screen_private_key;
@@ -99,3 +101,20 @@ dri3_extension_init(void)
bail:
FatalError("Cannot initialize DRI3 extension");
}
+
+uint32_t
+drm_format_for_depth(uint32_t depth, uint32_t bpp)
+{
+ switch (bpp) {
+ case 16:
+ return DRM_FORMAT_RGB565;
+ case 24:
+ return DRM_FORMAT_XRGB8888;
+ case 30:
+ return DRM_FORMAT_XRGB2101010;
+ case 32:
+ return DRM_FORMAT_ARGB8888;
+ default:
+ return 0;
+ }
+}
diff --git a/dri3/dri3.h b/dri3/dri3.h
index 7562352ff..89ad13ad9 100644
--- a/dri3/dri3.h
+++ b/dri3/dri3.h
@@ -28,7 +28,7 @@
#include <X11/extensions/dri3proto.h>
#include <randrstr.h>
-#define DRI3_SCREEN_INFO_VERSION 1
+#define DRI3_SCREEN_INFO_VERSION 2
typedef int (*dri3_open_proc)(ScreenPtr screen,
RRProviderPtr provider,
@@ -47,11 +47,43 @@ typedef PixmapPtr (*dri3_pixmap_from_fd_proc) (ScreenPtr screen,
CARD8 depth,
CARD8 bpp);
+typedef PixmapPtr (*dri3_pixmap_from_fds_proc) (ScreenPtr screen,
+ CARD8 num_fds,
+ int *fds,
+ CARD16 width,
+ CARD16 height,
+ CARD32 *strides,
+ CARD32 *offsets,
+ CARD8 depth,
+ CARD8 bpp,
+ CARD64 modifier);
+
typedef int (*dri3_fd_from_pixmap_proc) (ScreenPtr screen,
PixmapPtr pixmap,
CARD16 *stride,
CARD32 *size);
+typedef int (*dri3_fds_from_pixmap_proc) (ScreenPtr screen,
+ PixmapPtr pixmap,
+ int *fds,
+ CARD32 *strides,
+ CARD32 *offsets,
+ CARD64 *modifier);
+
+typedef int (*dri3_get_formats_proc) (ScreenPtr screen,
+ CARD32 *num_formats,
+ CARD32 **formats);
+
+typedef int (*dri3_get_modifiers_proc) (ScreenPtr screen,
+ CARD32 format,
+ CARD32 *num_modifiers,
+ CARD64 **modifiers);
+
+typedef int (*dri3_get_drawable_modifiers_proc) (DrawablePtr draw,
+ CARD32 format,
+ CARD32 *num_modifiers,
+ CARD64 **modifiers);
+
typedef struct dri3_screen_info {
uint32_t version;
@@ -62,6 +94,13 @@ typedef struct dri3_screen_info {
/* Version 1 */
dri3_open_client_proc open_client;
+ /* Version 2 */
+ dri3_pixmap_from_fds_proc pixmap_from_fds;
+ dri3_fds_from_pixmap_proc fds_from_pixmap;
+ dri3_get_formats_proc get_formats;
+ dri3_get_modifiers_proc get_modifiers;
+ dri3_get_drawable_modifiers_proc get_drawable_modifiers;
+
} dri3_screen_info_rec, *dri3_screen_info_ptr;
extern _X_EXPORT Bool
@@ -70,6 +109,9 @@ dri3_screen_init(ScreenPtr screen, dri3_screen_info_ptr info);
extern _X_EXPORT int
dri3_send_open_reply(ClientPtr client, int fd);
+extern _X_EXPORT uint32_t
+drm_format_for_depth(uint32_t depth, uint32_t bpp);
+
#endif
#endif /* _DRI3_H_ */
diff --git a/dri3/dri3_priv.h b/dri3/dri3_priv.h
index e61ef226c..8447680ba 100644
--- a/dri3/dri3_priv.h
+++ b/dri3/dri3_priv.h
@@ -34,11 +34,21 @@
extern DevPrivateKeyRec dri3_screen_private_key;
+typedef struct dri3_dmabuf_format {
+ uint32_t format;
+ uint32_t num_modifiers;
+ uint64_t *modifiers;
+} dri3_dmabuf_format_rec, *dri3_dmabuf_format_ptr;
+
typedef struct dri3_screen_priv {
CloseScreenProcPtr CloseScreen;
ConfigNotifyProcPtr ConfigNotify;
DestroyWindowProcPtr DestroyWindow;
+ Bool formats_cached;
+ CARD32 num_formats;
+ dri3_dmabuf_format_ptr formats;
+
dri3_screen_info_ptr info;
} dri3_screen_priv_rec, *dri3_screen_priv_ptr;
@@ -69,10 +79,21 @@ int
dri3_open(ClientPtr client, ScreenPtr screen, RRProviderPtr provider, int *fd);
int
-dri3_pixmap_from_fd(PixmapPtr *ppixmap, ScreenPtr screen, int fd,
- CARD16 width, CARD16 height, CARD16 stride, CARD8 depth, CARD8 bpp);
+dri3_pixmap_from_fds(PixmapPtr *ppixmap, ScreenPtr screen, CARD8 num_fds, int *fds,
+ CARD16 width, CARD16 height, CARD32 *strides, CARD32 *offsets,
+ CARD8 depth, CARD8 bpp, CARD64 modifier);
+
+int
+dri3_fds_from_pixmap(PixmapPtr pixmap, int *fds,
+ CARD32 *strides, CARD32 *offsets,
+ CARD64 *modifier);
int
-dri3_fd_from_pixmap(int *pfd, PixmapPtr pixmap, CARD16 *stride, CARD32 *size);
+dri3_get_supported_modifiers(ScreenPtr screen, DrawablePtr drawable,
+ CARD8 depth, CARD8 bpp,
+ CARD32 *num_drawable_modifiers,
+ CARD64 **drawable_modifiers,
+ CARD32 *num_screen_modifiers,
+ CARD64 **screen_modifiers);
#endif /* _DRI3PRIV_H_ */
diff --git a/dri3/dri3_request.c b/dri3/dri3_request.c
index b28d883a5..7f3f0d08c 100644
--- a/dri3/dri3_request.c
+++ b/dri3/dri3_request.c
@@ -30,6 +30,7 @@
#include <xace.h>
#include "../Xext/syncsdk.h"
#include <protocol-versions.h>
+#include <drm_fourcc.h>
static int
proc_dri3_query_version(ClientPtr client)
@@ -124,6 +125,7 @@ proc_dri3_pixmap_from_buffer(ClientPtr client)
int fd;
DrawablePtr drawable;
PixmapPtr pixmap;
+ CARD32 stride, offset;
int rc;
SetReqFds(client, 1);
@@ -159,11 +161,14 @@ proc_dri3_pixmap_from_buffer(ClientPtr client)
if (fd < 0)
return BadValue;
- rc = dri3_pixmap_from_fd(&pixmap,
- drawable->pScreen, fd,
- stuff->width, stuff->height,
- stuff->stride, stuff->depth,
- stuff->bpp);
+ offset = 0;
+ stride = stuff->stride;
+ rc = dri3_pixmap_from_fds(&pixmap,
+ drawable->pScreen, 1, &fd,
+ stuff->width, stuff->height,
+ &stride, &offset,
+ stuff->depth, stuff->bpp,
+ DRM_FORMAT_MOD_INVALID);
close (fd);
if (rc != Success)
return rc;
@@ -195,7 +200,10 @@ proc_dri3_buffer_from_pixmap(ClientPtr client)
.length = 0,
};
int rc;
- int fd;
+ int num_fds;
+ int fds[4];
+ uint32_t strides[4], offsets[4];
+ uint64_t modifier;
PixmapPtr pixmap;
REQUEST_SIZE_MATCH(xDRI3BufferFromPixmapReq);
@@ -211,9 +219,12 @@ proc_dri3_buffer_from_pixmap(ClientPtr client)
rep.depth = pixmap->drawable.depth;
rep.bpp = pixmap->drawable.bitsPerPixel;
- rc = dri3_fd_from_pixmap(&fd, pixmap, &rep.stride, &rep.size);
- if (rc != Success)
- return rc;
+ num_fds = dri3_fds_from_pixmap(pixmap, fds, strides, offsets, &modifier);
+ if (num_fds != 1)
+ return BadPixmap;
+
+ rep.stride = (CARD16) strides[0];
+ rep.size = rep.stride * rep.height;
if (client->swapped) {
swaps(&rep.sequenceNumber);
@@ -223,8 +234,8 @@ proc_dri3_buffer_from_pixmap(ClientPtr client)
swaps(&rep.height);
swaps(&rep.stride);
}
- if (WriteFdToClient(client, fd, TRUE) < 0) {
- close(fd);
+ if (WriteFdToClient(client, fds[0], TRUE) < 0) {
+ close(fds[0]);
return BadAlloc;
}
@@ -299,6 +310,216 @@ proc_dri3_fd_from_fence(ClientPtr client)
return Success;
}
+static int
+proc_dri3_get_supported_modifiers(ClientPtr client)
+{
+ REQUEST(xDRI3GetSupportedModifiersReq);
+ xDRI3GetSupportedModifiersReply rep = {
+ .type = X_Reply,
+ .sequenceNumber = client->sequence,
+ };
+ WindowPtr window;
+ ScreenPtr pScreen;
+ CARD64 *window_modifiers = NULL;
+ CARD64 *screen_modifiers = NULL;
+ CARD32 nwindowmodifiers = 0;
+ CARD32 nscreenmodifiers = 0;
+ int status;
+ int i;
+
+ REQUEST_SIZE_MATCH(xDRI3GetSupportedModifiersReq);
+
+ status = dixLookupWindow(&window, stuff->window, client, DixReadAccess);
+ if (status != Success)
+ return status;
+ pScreen = window->drawable.pScreen;
+
+ dri3_get_supported_modifiers(pScreen, &window->drawable,
+ stuff->depth, stuff->bpp,
+ &nwindowmodifiers, &window_modifiers,
+ &nscreenmodifiers, &screen_modifiers);
+
+ rep.numWindowModifiers = nwindowmodifiers;
+ rep.numScreenModifiers = nscreenmodifiers;
+ rep.length = bytes_to_int32(rep.numWindowModifiers * sizeof(CARD64)) +
+ bytes_to_int32(rep.numScreenModifiers * sizeof(CARD64));
+
+ if (client->swapped) {
+ swaps(&rep.sequenceNumber);
+ swapl(&rep.length);
+ swapl(&rep.numWindowModifiers);
+ swapl(&rep.numScreenModifiers);
+ for (i = 0; i < nwindowmodifiers; i++)
+ swapll(&window_modifiers[i]);
+ for (i = 0; i < nscreenmodifiers; i++)
+ swapll(&screen_modifiers[i]);
+ }
+
+ WriteToClient(client, sizeof(rep), &rep);
+ WriteToClient(client, nwindowmodifiers * sizeof(CARD64), window_modifiers);
+ WriteToClient(client, nscreenmodifiers * sizeof(CARD64), screen_modifiers);
+
+ free(window_modifiers);
+ free(screen_modifiers);
+
+ return Success;
+}
+
+static int
+proc_dri3_pixmap_from_buffers(ClientPtr client)
+{
+ REQUEST(xDRI3PixmapFromBuffersReq);
+ int fds[4];
+ CARD32 strides[4], offsets[4];
+ ScreenPtr screen;
+ WindowPtr window;
+ PixmapPtr pixmap;
+ int rc;
+ int i;
+
+ SetReqFds(client, stuff->num_buffers);
+ REQUEST_SIZE_MATCH(xDRI3PixmapFromBuffersReq);
+ LEGAL_NEW_RESOURCE(stuff->pixmap, client);
+ rc = dixLookupWindow(&window, stuff->window, client, DixGetAttrAccess);
+ if (rc != Success) {
+ client->errorValue = stuff->window;
+ return rc;
+ }
+ screen = window->drawable.pScreen;
+
+ if (!stuff->width || !stuff->height || !stuff->bpp || !stuff->depth) {
+ client->errorValue = 0;
+ return BadValue;
+ }
+
+ if (stuff->width > 32767 || stuff->height > 32767)
+ return BadAlloc;
+
+ if (stuff->depth != 1) {
+ DepthPtr depth = screen->allowedDepths;
+ int j;
+ for (j = 0; j < screen->numDepths; j++, depth++)
+ if (depth->depth == stuff->depth)
+ break;
+ if (j == screen->numDepths) {
+ client->errorValue = stuff->depth;
+ return BadValue;
+ }
+ }
+
+ if (!stuff->num_buffers || stuff->num_buffers > 4) {
+ client->errorValue = stuff->num_buffers;
+ return BadValue;
+ }
+
+ for (i = 0; i < stuff->num_buffers; i++) {
+ fds[i] = ReadFdFromClient(client);
+ if (fds[i] < 0) {
+ while (--i >= 0)
+ close(fds[i]);
+ return BadValue;
+ }
+ }
+
+ strides[0] = stuff->stride0;
+ strides[1] = stuff->stride1;
+ strides[2] = stuff->stride2;
+ strides[3] = stuff->stride3;
+ offsets[0] = stuff->offset0;
+ offsets[1] = stuff->offset1;
+ offsets[2] = stuff->offset2;
+ offsets[3] = stuff->offset3;
+
+ rc = dri3_pixmap_from_fds(&pixmap, screen,
+ stuff->num_buffers, fds,
+ stuff->width, stuff->height,
+ strides, offsets,
+ stuff->depth, stuff->bpp,
+ stuff->modifier);
+
+ for (i = 0; i < stuff->num_buffers; i++)
+ close (fds[i]);
+
+ if (rc != Success)
+ return rc;
+
+ pixmap->drawable.id = stuff->pixmap;
+
+ /* security creation/labeling check */
+ rc = XaceHook(XACE_RESOURCE_ACCESS, client, stuff->pixmap, RT_PIXMAP,
+ pixmap, RT_NONE, NULL, DixCreateAccess);
+
+ if (rc != Success) {
+ (*screen->DestroyPixmap) (pixmap);
+ return rc;
+ }
+ if (!AddResource(stuff->pixmap, RT_PIXMAP, (void *) pixmap))
+ return BadAlloc;
+
+ return Success;
+}
+
+static int
+proc_dri3_buffers_from_pixmap(ClientPtr client)
+{
+ REQUEST(xDRI3BuffersFromPixmapReq);
+ xDRI3BuffersFromPixmapReply rep = {
+ .type = X_Reply,
+ .sequenceNumber = client->sequence,
+ };
+ int rc;
+ int fds[4];
+ int num_fds;
+ uint32_t strides[4], offsets[4];
+ uint64_t modifier;
+ int i;
+ PixmapPtr pixmap;
+
+ REQUEST_SIZE_MATCH(xDRI3BufferFromPixmapReq);
+ rc = dixLookupResourceByType((void **) &pixmap, stuff->pixmap, RT_PIXMAP,
+ client, DixWriteAccess);
+ if (rc != Success) {
+ client->errorValue = stuff->pixmap;
+ return rc;
+ }
+
+ num_fds = dri3_fds_from_pixmap(pixmap, fds, strides, offsets, &modifier);
+ if (num_fds == 0)
+ return BadPixmap;
+
+ rep.nfd = num_fds;
+ rep.length = bytes_to_int32(num_fds * 2 * sizeof(CARD32));
+ rep.width = pixmap->drawable.width;
+ rep.height = pixmap->drawable.height;
+ rep.modifier = modifier;
+
+ if (client->swapped) {
+ swaps(&rep.sequenceNumber);
+ swapl(&rep.length);
+ swaps(&rep.width);
+ swaps(&rep.height);
+ swapll(&rep.modifier);
+ for (i = 0; i < num_fds; i++) {
+ swapl(&strides[i]);
+ swapl(&offsets[i]);
+ }
+ }
+
+ for (i = 0; i < num_fds; i++) {
+ if (WriteFdToClient(client, fds[i], TRUE) < 0) {
+ while (i--)
+ close(fds[i]);
+ return BadAlloc;
+ }
+ }
+
+ WriteToClient(client, sizeof(rep), &rep);
+ WriteToClient(client, num_fds * sizeof(CARD32), strides);
+ WriteToClient(client, num_fds * sizeof(CARD32), offsets);
+
+ return Success;
+}
+
int (*proc_dri3_vector[DRI3NumberRequests]) (ClientPtr) = {
proc_dri3_query_version, /* 0 */
proc_dri3_open, /* 1 */
@@ -306,6 +527,9 @@ int (*proc_dri3_vector[DRI3NumberRequests]) (ClientPtr) = {
proc_dri3_buffer_from_pixmap, /* 3 */
proc_dri3_fence_from_fd, /* 4 */
proc_dri3_fd_from_fence, /* 5 */
+ proc_dri3_get_supported_modifiers, /* 6 */
+ proc_dri3_pixmap_from_buffers, /* 7 */
+ proc_dri3_buffers_from_pixmap, /* 8 */
};
int
@@ -394,6 +618,51 @@ sproc_dri3_fd_from_fence(ClientPtr client)
return (*proc_dri3_vector[stuff->dri3ReqType]) (client);
}
+static int _X_COLD
+sproc_dri3_get_supported_modifiers(ClientPtr client)
+{
+ REQUEST(xDRI3GetSupportedModifiersReq);
+ REQUEST_SIZE_MATCH(xDRI3GetSupportedModifiersReq);
+
+ swaps(&stuff->length);
+ swapl(&stuff->window);
+ return (*proc_dri3_vector[stuff->dri3ReqType]) (client);
+}
+
+static int _X_COLD
+sproc_dri3_pixmap_from_buffers(ClientPtr client)
+{
+ REQUEST(xDRI3PixmapFromBuffersReq);
+ REQUEST_SIZE_MATCH(xDRI3PixmapFromBuffersReq);
+
+ swaps(&stuff->length);
+ swapl(&stuff->pixmap);
+ swapl(&stuff->window);
+ swaps(&stuff->width);
+ swaps(&stuff->height);
+ swapl(&stuff->stride0);
+ swapl(&stuff->offset0);
+ swapl(&stuff->stride1);
+ swapl(&stuff->offset1);
+ swapl(&stuff->stride2);
+ swapl(&stuff->offset2);
+ swapl(&stuff->stride3);
+ swapl(&stuff->offset3);
+ swapll(&stuff->modifier);
+ return (*proc_dri3_vector[stuff->dri3ReqType]) (client);
+}
+
+static int _X_COLD
+sproc_dri3_buffers_from_pixmap(ClientPtr client)
+{
+ REQUEST(xDRI3BuffersFromPixmapReq);
+ REQUEST_SIZE_MATCH(xDRI3BuffersFromPixmapReq);
+
+ swaps(&stuff->length);
+ swapl(&stuff->pixmap);
+ return (*proc_dri3_vector[stuff->dri3ReqType]) (client);
+}
+
int (*sproc_dri3_vector[DRI3NumberRequests]) (ClientPtr) = {
sproc_dri3_query_version, /* 0 */
sproc_dri3_open, /* 1 */
@@ -401,6 +670,9 @@ int (*sproc_dri3_vector[DRI3NumberRequests]) (ClientPtr) = {
sproc_dri3_buffer_from_pixmap, /* 3 */
sproc_dri3_fence_from_fd, /* 4 */
sproc_dri3_fd_from_fence, /* 5 */
+ sproc_dri3_get_supported_modifiers, /* 6 */
+ sproc_dri3_pixmap_from_buffers, /* 7 */
+ sproc_dri3_buffers_from_pixmap, /* 8 */
};
int _X_COLD
diff --git a/dri3/dri3_screen.c b/dri3/dri3_screen.c
index 6c0c60cbf..df40f8281 100644
--- a/dri3/dri3_screen.c
+++ b/dri3/dri3_screen.c
@@ -29,6 +29,7 @@
#include <misync.h>
#include <misyncshm.h>
#include <randrstr.h>
+#include <drm_fourcc.h>
static inline Bool has_open(dri3_screen_info_ptr info) {
if (info == NULL)
@@ -60,17 +61,30 @@ dri3_open(ClientPtr client, ScreenPtr screen, RRProviderPtr provider, int *fd)
}
int
-dri3_pixmap_from_fd(PixmapPtr *ppixmap, ScreenPtr screen, int fd,
- CARD16 width, CARD16 height, CARD16 stride, CARD8 depth, CARD8 bpp)
+dri3_pixmap_from_fds(PixmapPtr *ppixmap, ScreenPtr screen,
+ CARD8 num_fds, int *fds,
+ CARD16 width, CARD16 height,
+ CARD32 *strides, CARD32 *offsets,
+ CARD8 depth, CARD8 bpp, CARD64 modifier)
{
dri3_screen_priv_ptr ds = dri3_screen_priv(screen);
dri3_screen_info_ptr info = ds->info;
PixmapPtr pixmap;
- if (!info || !info->pixmap_from_fd)
+ if (!info)
return BadImplementation;
- pixmap = (*info->pixmap_from_fd) (screen, fd, width, height, stride, depth, bpp);
+ if (info->version >= 2 && info->pixmap_from_fds != NULL) {
+ pixmap = (*info->pixmap_from_fds) (screen, num_fds, fds, width, height,
+ strides, offsets, depth, bpp, modifier);
+ } else if (info->pixmap_from_fd != NULL && num_fds == 1 &&
+ modifier == DRM_FORMAT_MOD_INVALID) {
+ pixmap = (*info->pixmap_from_fd) (screen, fds[0], width, height,
+ strides[0], depth, bpp);
+ } else {
+ return BadImplementation;
+ }
+
if (!pixmap)
return BadAlloc;
@@ -79,20 +93,182 @@ dri3_pixmap_from_fd(PixmapPtr *ppixmap, ScreenPtr screen, int fd,
}
int
-dri3_fd_from_pixmap(int *pfd, PixmapPtr pixmap, CARD16 *stride, CARD32 *size)
+dri3_fds_from_pixmap(PixmapPtr pixmap, int *fds,
+ CARD32 *strides, CARD32 *offsets,
+ CARD64 *modifier)
{
ScreenPtr screen = pixmap->drawable.pScreen;
dri3_screen_priv_ptr ds = dri3_screen_priv(screen);
dri3_screen_info_ptr info = ds->info;
- int fd;
- if (!info || !info->fd_from_pixmap)
+ if (!info)
+ return 0;
+
+ if (info->version >= 2 && info->fds_from_pixmap != NULL) {
+ return (*info->fds_from_pixmap)(screen, pixmap, fds, strides, offsets,
+ modifier);
+ } else if (info->fd_from_pixmap != NULL) {
+ CARD16 stride;
+ CARD32 size;
+
+ fds[0] = (*info->fd_from_pixmap)(screen, pixmap, &stride, &size);
+ if (fds[0] < 0)
+ return 0;
+
+ strides[0] = stride;
+ offsets[0] = 0;
+ *modifier = DRM_FORMAT_MOD_INVALID;
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+static int
+cache_formats_and_modifiers(ScreenPtr screen)
+{
+ dri3_screen_priv_ptr ds = dri3_screen_priv(screen);
+ dri3_screen_info_ptr info = ds->info;
+ CARD32 *formats = NULL;
+ CARD64 *modifiers = NULL;
+ int i;
+
+ if (ds->formats_cached)
+ return Success;
+
+ if (!info)
return BadImplementation;
- fd = (*info->fd_from_pixmap)(screen, pixmap, stride, size);
- if (fd < 0)
+ if (!info->get_formats || !info->get_modifiers) {
+ ds->formats = NULL;
+ ds->num_formats = 0;
+ ds->formats_cached = TRUE;
+ return Success;
+ }
+
+ (*info->get_formats) (screen, &ds->num_formats, &formats);
+ ds->formats = calloc(ds->num_formats, sizeof(dri3_dmabuf_format_rec));
+ if (!ds->formats)
return BadAlloc;
- *pfd = fd;
+
+ for (i = 0; i < ds->num_formats; i++) {
+ dri3_dmabuf_format_ptr iter = &ds->formats[i];
+
+ iter->format = formats[i];
+ (*info->get_modifiers) (screen, formats[i],
+ &iter->num_modifiers,
+ &modifiers);
+
+ iter->modifiers = malloc(iter->num_modifiers * sizeof(CARD64));
+ if (iter->modifiers == NULL)
+ goto error;
+
+ memcpy(iter->modifiers, modifiers,
+ iter->num_modifiers * sizeof(CARD64));
+ goto done;
+
+error:
+ iter->num_modifiers = 0;
+ free(iter->modifiers);
+done:
+ free(modifiers);
+ }
+ free(formats);
+ ds->formats_cached = TRUE;
+
return Success;
}
+int
+dri3_get_supported_modifiers(ScreenPtr screen, DrawablePtr drawable,
+ CARD8 depth, CARD8 bpp,
+ CARD32 *num_intersect_modifiers,
+ CARD64 **intersect_modifiers,
+ CARD32 *num_screen_modifiers,
+ CARD64 **screen_modifiers)
+{
+ dri3_screen_priv_ptr ds = dri3_screen_priv(screen);
+ dri3_screen_info_ptr info = ds->info;
+ int i, j;
+ int ret;
+ CARD32 num_drawable_mods;
+ CARD64 *drawable_mods;
+ CARD64 *intersect_mods = NULL;
+ CARD64 *screen_mods = NULL;
+ CARD32 format;
+ dri3_dmabuf_format_ptr screen_format = NULL;
+
+ ret = cache_formats_and_modifiers(screen);
+ if (ret != Success)
+ return ret;
+
+ format = drm_format_for_depth(depth, bpp);
+ if (format == 0)
+ return BadValue;
+
+ /* Find screen-global modifiers from cache
+ */
+ for (i = 0; i < ds->num_formats; i++) {
+ if (ds->formats[i].format == format) {
+ screen_format = &ds->formats[i];
+ break;
+ }
+ }
+ if (screen_format == NULL)
+ return BadMatch;
+
+ if (screen_format->num_modifiers == 0) {
+ *num_screen_modifiers = 0;
+ *num_intersect_modifiers = 0;
+ return Success;
+ }
+
+ if (info->get_drawable_modifiers)
+ (*info->get_drawable_modifiers) (drawable, format,
+ &num_drawable_mods,
+ &drawable_mods);
+
+ /* We're allocating slightly more memory than necessary but it reduces
+ * the complexity of finding the intersection set.
+ */
+ screen_mods = malloc(screen_format->num_modifiers * sizeof(CARD64));
+ if (!screen_mods)
+ return BadAlloc;
+ if (num_drawable_mods > 0) {
+ intersect_mods = malloc(screen_format->num_modifiers * sizeof(CARD64));
+ if (!intersect_mods) {
+ free(screen_mods);
+ return BadAlloc;
+ }
+ }
+
+ *num_screen_modifiers = 0;
+ *num_intersect_modifiers = 0;
+ for (i = 0; i < screen_format->num_modifiers; i++) {
+ CARD64 modifier = screen_format->modifiers[i];
+ Bool intersect = FALSE;
+
+ for (j = 0; j < num_drawable_mods; j++) {
+ if (drawable_mods[j] == modifier) {
+ intersect = TRUE;
+ break;
+ }
+ }
+
+ if (intersect) {
+ intersect_mods[*num_intersect_modifiers] = modifier;
+ *num_intersect_modifiers += 1;
+ } else {
+ screen_mods[*num_screen_modifiers] = modifier;
+ *num_screen_modifiers += 1;
+ }
+ }
+
+ assert(*num_intersect_modifiers + *num_screen_modifiers == screen_format->num_modifiers);
+
+ *intersect_modifiers = intersect_mods;
+ *screen_modifiers = screen_mods;
+ free(drawable_mods);
+
+ return Success;
+}
diff --git a/hw/xwayland/xwayland-glamor.c b/hw/xwayland/xwayland-glamor.c
index 8ffb40d6f..0933e9411 100644
--- a/hw/xwayland/xwayland-glamor.c
+++ b/hw/xwayland/xwayland-glamor.c
@@ -59,7 +59,7 @@ xwl_glamor_egl_make_current(struct glamor_context *glamor_ctx)
}
static uint32_t
-drm_format_for_depth(int depth)
+wl_drm_format_for_depth(int depth)
{
switch (depth) {
case 15:
@@ -170,7 +170,7 @@ xwl_glamor_pixmap_get_wl_buffer(PixmapPtr pixmap)
wl_drm_create_prime_buffer(xwl_screen->drm, prime_fd,
pixmap->drawable.width,
pixmap->drawable.height,
- drm_format_for_depth(pixmap->drawable.depth),
+ wl_drm_format_for_depth(pixmap->drawable.depth),
0, gbm_bo_get_stride(xwl_pixmap->bo),
0, 0,
0, 0);
diff --git a/meson.build b/meson.build
index 430c770cb..d64fb0ca3 100644
--- a/meson.build
+++ b/meson.build
@@ -78,7 +78,7 @@ scrnsaverproto_dep = dependency('scrnsaverproto', version: '>= 1.1')
resourceproto_dep = dependency('resourceproto', version: '>= 1.2.0')
xf86driproto_dep = dependency('xf86driproto', version: '>= 2.1.0', required: get_option('dri1') == 'true')
dri2proto_dep = dependency('dri2proto', version: '>= 2.8', required: get_option('dri2') == 'true')
-dri3proto_dep = dependency('dri3proto', version: '>= 1.0', required: get_option('dri3') == 'true')
+dri3proto_dep = dependency('dri3proto', version: '>= 1.2', required: get_option('dri3') == 'true')
xineramaproto_dep = dependency('xineramaproto')
xf86bigfontproto_dep = dependency('xf86bigfontproto', version: '>= 1.2.0')
xf86vidmodeproto_dep = dependency('xf86vidmodeproto', version: '>= 2.2.99.1', required: false)