summaryrefslogtreecommitdiff
path: root/xserver/dri3/dri3_request.c
diff options
context:
space:
mode:
authorMatthieu Herrb <matthieu@cvs.openbsd.org>2019-07-27 07:57:27 +0000
committerMatthieu Herrb <matthieu@cvs.openbsd.org>2019-07-27 07:57:27 +0000
commitd4a0bed4b91da9de86c311c7fef9a8aa9a6f500c (patch)
treea1b439049dee87bc951e190db93f5bbe8b43b0b5 /xserver/dri3/dri3_request.c
parentb6bc775539a31f663f9e22ce3ccaf0aa96adf3b6 (diff)
Update to xserver 1.20.5. Tested by jsg@
Diffstat (limited to 'xserver/dri3/dri3_request.c')
-rw-r--r--xserver/dri3/dri3_request.c344
1 files changed, 327 insertions, 17 deletions
diff --git a/xserver/dri3/dri3_request.c b/xserver/dri3/dri3_request.c
index 8c15dbe16..958877efa 100644
--- a/xserver/dri3/dri3_request.c
+++ b/xserver/dri3/dri3_request.c
@@ -30,6 +30,21 @@
#include <xace.h>
#include "../Xext/syncsdk.h"
#include <protocol-versions.h>
+#include <drm_fourcc.h>
+
+static Bool
+dri3_screen_can_one_point_two(ScreenPtr screen)
+{
+ dri3_screen_priv_ptr dri3 = dri3_screen_priv(screen);
+
+ if (dri3 && dri3->info && dri3->info->version >= 2 &&
+ dri3->info->pixmap_from_fds && dri3->info->fds_from_pixmap &&
+ dri3->info->get_formats && dri3->info->get_modifiers &&
+ dri3->info->get_drawable_modifiers)
+ return TRUE;
+
+ return FALSE;
+}
static int
proc_dri3_query_version(ClientPtr client)
@@ -44,7 +59,35 @@ proc_dri3_query_version(ClientPtr client)
};
REQUEST_SIZE_MATCH(xDRI3QueryVersionReq);
- (void) stuff;
+
+ for (int i = 0; i < screenInfo.numScreens; i++) {
+ if (!dri3_screen_can_one_point_two(screenInfo.screens[i])) {
+ rep.minorVersion = 0;
+ break;
+ }
+ }
+
+ for (int i = 0; i < screenInfo.numGPUScreens; i++) {
+ if (!dri3_screen_can_one_point_two(screenInfo.gpuscreens[i])) {
+ rep.minorVersion = 0;
+ break;
+ }
+ }
+
+ /* From DRI3 proto:
+ *
+ * The client sends the highest supported version to the server
+ * and the server sends the highest version it supports, but no
+ * higher than the requested version.
+ */
+
+ if (rep.majorVersion > stuff->majorVersion ||
+ (rep.majorVersion == stuff->majorVersion &&
+ rep.minorVersion > stuff->minorVersion)) {
+ rep.majorVersion = stuff->majorVersion;
+ rep.minorVersion = stuff->minorVersion;
+ }
+
if (client->swapped) {
swaps(&rep.sequenceNumber);
swapl(&rep.length);
@@ -92,7 +135,7 @@ proc_dri3_open(ClientPtr client)
REQUEST_SIZE_MATCH(xDRI3OpenReq);
- status = dixLookupDrawable(&drawable, stuff->drawable, client, 0, DixReadAccess);
+ status = dixLookupDrawable(&drawable, stuff->drawable, client, 0, DixGetAttrAccess);
if (status != Success)
return status;
@@ -124,6 +167,7 @@ proc_dri3_pixmap_from_buffer(ClientPtr client)
int fd;
DrawablePtr drawable;
PixmapPtr pixmap;
+ CARD32 stride, offset;
int rc;
SetReqFds(client, 1);
@@ -159,11 +203,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;
@@ -211,9 +258,9 @@ 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;
+ fd = dri3_fd_from_pixmap(pixmap, &rep.stride, &rep.size);
+ if (fd < 0)
+ return BadPixmap;
if (client->swapped) {
swaps(&rep.sequenceNumber);
@@ -299,6 +346,218 @@ 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, DixGetAttrAccess);
+ 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(xDRI3BuffersFromPixmapReq);
+ 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.depth = pixmap->drawable.depth;
+ rep.bpp = pixmap->drawable.bitsPerPixel;
+ 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 +565,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
@@ -319,7 +581,7 @@ proc_dri3_dispatch(ClientPtr client)
return (*proc_dri3_vector[stuff->data]) (client);
}
-static int
+static int _X_COLD
sproc_dri3_query_version(ClientPtr client)
{
REQUEST(xDRI3QueryVersionReq);
@@ -331,7 +593,7 @@ sproc_dri3_query_version(ClientPtr client)
return (*proc_dri3_vector[stuff->dri3ReqType]) (client);
}
-static int
+static int _X_COLD
sproc_dri3_open(ClientPtr client)
{
REQUEST(xDRI3OpenReq);
@@ -343,7 +605,7 @@ sproc_dri3_open(ClientPtr client)
return (*proc_dri3_vector[stuff->dri3ReqType]) (client);
}
-static int
+static int _X_COLD
sproc_dri3_pixmap_from_buffer(ClientPtr client)
{
REQUEST(xDRI3PixmapFromBufferReq);
@@ -359,7 +621,7 @@ sproc_dri3_pixmap_from_buffer(ClientPtr client)
return (*proc_dri3_vector[stuff->dri3ReqType]) (client);
}
-static int
+static int _X_COLD
sproc_dri3_buffer_from_pixmap(ClientPtr client)
{
REQUEST(xDRI3BufferFromPixmapReq);
@@ -370,7 +632,7 @@ sproc_dri3_buffer_from_pixmap(ClientPtr client)
return (*proc_dri3_vector[stuff->dri3ReqType]) (client);
}
-static int
+static int _X_COLD
sproc_dri3_fence_from_fd(ClientPtr client)
{
REQUEST(xDRI3FenceFromFDReq);
@@ -382,7 +644,7 @@ sproc_dri3_fence_from_fd(ClientPtr client)
return (*proc_dri3_vector[stuff->dri3ReqType]) (client);
}
-static int
+static int _X_COLD
sproc_dri3_fd_from_fence(ClientPtr client)
{
REQUEST(xDRI3FDFromFenceReq);
@@ -394,6 +656,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,9 +708,12 @@ 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
+int _X_COLD
sproc_dri3_dispatch(ClientPtr client)
{
REQUEST(xReq);