mirror of
https://github.com/X11Libre/xserver.git
synced 2026-03-24 05:54:08 +00:00
dri3: Add DRI3 extension
Adds DRM compatible fences using futexes. Uses FD passing to get pixmaps from DRM applications. Signed-off-by: Keith Packard <keithp@keithp.com> Reviewed-by: Adam Jackson <ajax@redhat.com>
This commit is contained in:
394
dri3/dri3_request.c
Normal file
394
dri3/dri3_request.c
Normal file
@@ -0,0 +1,394 @@
|
||||
/*
|
||||
* Copyright © 2013 Keith Packard
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that copyright
|
||||
* notice and this permission notice appear in supporting documentation, and
|
||||
* that the name of the copyright holders not be used in advertising or
|
||||
* publicity pertaining to distribution of the software without specific,
|
||||
* written prior permission. The copyright holders make no representations
|
||||
* about the suitability of this software for any purpose. It is provided "as
|
||||
* is" without express or implied warranty.
|
||||
*
|
||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||
* OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_XORG_CONFIG_H
|
||||
#include <xorg-config.h>
|
||||
#endif
|
||||
|
||||
#include "dri3_priv.h"
|
||||
#include <syncsrv.h>
|
||||
#include <unistd.h>
|
||||
#include <xace.h>
|
||||
#include "../Xext/syncsdk.h"
|
||||
|
||||
static int
|
||||
proc_dri3_query_version(ClientPtr client)
|
||||
{
|
||||
REQUEST(xDRI3QueryVersionReq);
|
||||
xDRI3QueryVersionReply rep = {
|
||||
.type = X_Reply,
|
||||
.sequenceNumber = client->sequence,
|
||||
.length = 0,
|
||||
.majorVersion = DRI3_MAJOR,
|
||||
.minorVersion = DRI3_MINOR
|
||||
};
|
||||
|
||||
REQUEST_SIZE_MATCH(xDRI3QueryVersionReq);
|
||||
(void) stuff;
|
||||
if (client->swapped) {
|
||||
swaps(&rep.sequenceNumber);
|
||||
swapl(&rep.length);
|
||||
swapl(&rep.majorVersion);
|
||||
swapl(&rep.minorVersion);
|
||||
}
|
||||
WriteToClient(client, sizeof(rep), &rep);
|
||||
return Success;
|
||||
}
|
||||
|
||||
static int
|
||||
proc_dri3_open(ClientPtr client)
|
||||
{
|
||||
REQUEST(xDRI3OpenReq);
|
||||
xDRI3OpenReply rep = {
|
||||
.type = X_Reply,
|
||||
.nfd = 1,
|
||||
.sequenceNumber = client->sequence,
|
||||
.length = 0,
|
||||
};
|
||||
RRProviderPtr provider;
|
||||
DrawablePtr drawable;
|
||||
ScreenPtr screen;
|
||||
int fd;
|
||||
int status;
|
||||
|
||||
REQUEST_SIZE_MATCH(xDRI3OpenReq);
|
||||
|
||||
status = dixLookupDrawable(&drawable, stuff->drawable, client, 0, DixReadAccess);
|
||||
if (status != Success)
|
||||
return status;
|
||||
|
||||
if (stuff->provider == None)
|
||||
provider = NULL;
|
||||
else if (!RRProviderType) {
|
||||
return BadMatch;
|
||||
} else {
|
||||
VERIFY_RR_PROVIDER(stuff->provider, provider, DixReadAccess);
|
||||
if (drawable->pScreen != provider->pScreen)
|
||||
return BadMatch;
|
||||
}
|
||||
screen = drawable->pScreen;
|
||||
|
||||
status = dri3_open(client, screen, provider, &fd);
|
||||
if (status != Success)
|
||||
return status;
|
||||
|
||||
if (client->swapped) {
|
||||
swaps(&rep.sequenceNumber);
|
||||
swapl(&rep.length);
|
||||
}
|
||||
|
||||
if (WriteFdToClient(client, fd, TRUE) < 0) {
|
||||
close(fd);
|
||||
return BadAlloc;
|
||||
}
|
||||
|
||||
WriteToClient(client, sizeof (rep), &rep);
|
||||
|
||||
return Success;
|
||||
}
|
||||
|
||||
static int
|
||||
proc_dri3_pixmap_from_buffer(ClientPtr client)
|
||||
{
|
||||
REQUEST(xDRI3PixmapFromBufferReq);
|
||||
int fd;
|
||||
DrawablePtr drawable;
|
||||
PixmapPtr pixmap;
|
||||
int rc;
|
||||
|
||||
SetReqFds(client, 1);
|
||||
REQUEST_SIZE_MATCH(xDRI3PixmapFromBufferReq);
|
||||
LEGAL_NEW_RESOURCE(stuff->pixmap, client);
|
||||
rc = dixLookupDrawable(&drawable, stuff->drawable, client, M_ANY, DixGetAttrAccess);
|
||||
if (rc != Success) {
|
||||
client->errorValue = stuff->drawable;
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (!stuff->width || !stuff->height) {
|
||||
client->errorValue = 0;
|
||||
return BadValue;
|
||||
}
|
||||
|
||||
if (stuff->width > 32767 || stuff->height > 32767)
|
||||
return BadAlloc;
|
||||
|
||||
if (stuff->depth != 1) {
|
||||
DepthPtr depth = drawable->pScreen->allowedDepths;
|
||||
int i;
|
||||
for (i = 0; i < drawable->pScreen->numDepths; i++, depth++)
|
||||
if (depth->depth == stuff->depth)
|
||||
break;
|
||||
if (i == drawable->pScreen->numDepths) {
|
||||
client->errorValue = stuff->depth;
|
||||
return BadValue;
|
||||
}
|
||||
}
|
||||
|
||||
fd = ReadFdFromClient(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);
|
||||
close (fd);
|
||||
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) {
|
||||
(*drawable->pScreen->DestroyPixmap) (pixmap);
|
||||
return rc;
|
||||
}
|
||||
if (AddResource(stuff->pixmap, RT_PIXMAP, (pointer) pixmap))
|
||||
return Success;
|
||||
|
||||
return Success;
|
||||
}
|
||||
|
||||
static int
|
||||
proc_dri3_buffer_from_pixmap(ClientPtr client)
|
||||
{
|
||||
REQUEST(xDRI3BufferFromPixmapReq);
|
||||
xDRI3BufferFromPixmapReply rep = {
|
||||
.type = X_Reply,
|
||||
.nfd = 1,
|
||||
.sequenceNumber = client->sequence,
|
||||
.length = 0,
|
||||
};
|
||||
int rc;
|
||||
int fd;
|
||||
PixmapPtr pixmap;
|
||||
|
||||
REQUEST_SIZE_MATCH(xDRI3BufferFromPixmapReq);
|
||||
rc = dixLookupResourceByType((pointer *) &pixmap, stuff->pixmap, RT_PIXMAP,
|
||||
client, DixWriteAccess);
|
||||
if (rc != Success) {
|
||||
client->errorValue = stuff->pixmap;
|
||||
return rc;
|
||||
}
|
||||
|
||||
rep.width = pixmap->drawable.width;
|
||||
rep.height = pixmap->drawable.height;
|
||||
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;
|
||||
|
||||
if (client->swapped) {
|
||||
swaps(&rep.sequenceNumber);
|
||||
swapl(&rep.length);
|
||||
swapl(&rep.size);
|
||||
swaps(&rep.width);
|
||||
swaps(&rep.height);
|
||||
swaps(&rep.stride);
|
||||
}
|
||||
if (WriteFdToClient(client, fd, TRUE) < 0) {
|
||||
close(fd);
|
||||
return BadAlloc;
|
||||
}
|
||||
|
||||
WriteToClient(client, sizeof(rep), &rep);
|
||||
|
||||
return client->noClientException;
|
||||
}
|
||||
|
||||
static int
|
||||
proc_dri3_fence_from_fd(ClientPtr client)
|
||||
{
|
||||
REQUEST(xDRI3FenceFromFDReq);
|
||||
DrawablePtr drawable;
|
||||
int fd;
|
||||
int status;
|
||||
|
||||
SetReqFds(client, 1);
|
||||
REQUEST_SIZE_MATCH(xDRI3FenceFromFDReq);
|
||||
LEGAL_NEW_RESOURCE(stuff->fence, client);
|
||||
|
||||
status = dixLookupDrawable(&drawable, stuff->drawable, client, M_ANY, DixGetAttrAccess);
|
||||
if (status != Success)
|
||||
return status;
|
||||
|
||||
fd = ReadFdFromClient(client);
|
||||
if (fd < 0)
|
||||
return BadValue;
|
||||
|
||||
status = SyncCreateFenceFromFD(client, drawable, stuff->fence,
|
||||
fd, stuff->initially_triggered);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static int
|
||||
proc_dri3_fd_from_fence(ClientPtr client)
|
||||
{
|
||||
REQUEST(xDRI3FDFromFenceReq);
|
||||
xDRI3FDFromFenceReply rep = {
|
||||
.type = X_Reply,
|
||||
.nfd = 1,
|
||||
.sequenceNumber = client->sequence,
|
||||
.length = 0,
|
||||
};
|
||||
DrawablePtr drawable;
|
||||
int fd;
|
||||
int status;
|
||||
SyncFence *fence;
|
||||
|
||||
REQUEST_SIZE_MATCH(xDRI3FDFromFenceReq);
|
||||
|
||||
status = dixLookupDrawable(&drawable, stuff->drawable, client, M_ANY, DixGetAttrAccess);
|
||||
if (status != Success)
|
||||
return status;
|
||||
status = SyncVerifyFence(&fence, stuff->fence, client, DixWriteAccess);
|
||||
if (status != Success)
|
||||
return status;
|
||||
|
||||
fd = SyncFDFromFence(client, drawable, fence);
|
||||
if (fd < 0)
|
||||
return BadMatch;
|
||||
|
||||
if (client->swapped) {
|
||||
swaps(&rep.sequenceNumber);
|
||||
swapl(&rep.length);
|
||||
}
|
||||
if (WriteFdToClient(client, fd, FALSE) < 0)
|
||||
return BadAlloc;
|
||||
|
||||
WriteToClient(client, sizeof(rep), &rep);
|
||||
|
||||
return client->noClientException;
|
||||
}
|
||||
|
||||
int (*proc_dri3_vector[DRI3NumberRequests]) (ClientPtr) = {
|
||||
proc_dri3_query_version, /* 0 */
|
||||
proc_dri3_open, /* 1 */
|
||||
proc_dri3_pixmap_from_buffer, /* 2 */
|
||||
proc_dri3_buffer_from_pixmap, /* 3 */
|
||||
proc_dri3_fence_from_fd, /* 4 */
|
||||
proc_dri3_fd_from_fence, /* 5 */
|
||||
};
|
||||
|
||||
int
|
||||
proc_dri3_dispatch(ClientPtr client)
|
||||
{
|
||||
REQUEST(xReq);
|
||||
if (stuff->data >= DRI3NumberRequests || !proc_dri3_vector[stuff->data])
|
||||
return BadRequest;
|
||||
return (*proc_dri3_vector[stuff->data]) (client);
|
||||
}
|
||||
|
||||
static int
|
||||
sproc_dri3_query_version(ClientPtr client)
|
||||
{
|
||||
REQUEST(xDRI3QueryVersionReq);
|
||||
|
||||
swaps(&stuff->length);
|
||||
swapl(&stuff->majorVersion);
|
||||
swapl(&stuff->minorVersion);
|
||||
return (*proc_dri3_vector[stuff->dri3ReqType]) (client);
|
||||
}
|
||||
|
||||
static int
|
||||
sproc_dri3_open(ClientPtr client)
|
||||
{
|
||||
REQUEST(xDRI3OpenReq);
|
||||
|
||||
swaps(&stuff->length);
|
||||
swapl(&stuff->drawable);
|
||||
swapl(&stuff->provider);
|
||||
return (*proc_dri3_vector[stuff->dri3ReqType]) (client);
|
||||
}
|
||||
|
||||
static int
|
||||
sproc_dri3_pixmap_from_buffer(ClientPtr client)
|
||||
{
|
||||
REQUEST(xDRI3PixmapFromBufferReq);
|
||||
|
||||
swaps(&stuff->length);
|
||||
swapl(&stuff->pixmap);
|
||||
swapl(&stuff->drawable);
|
||||
swapl(&stuff->size);
|
||||
swaps(&stuff->width);
|
||||
swaps(&stuff->height);
|
||||
swaps(&stuff->stride);
|
||||
return (*proc_dri3_vector[stuff->dri3ReqType]) (client);
|
||||
}
|
||||
|
||||
static int
|
||||
sproc_dri3_buffer_from_pixmap(ClientPtr client)
|
||||
{
|
||||
REQUEST(xDRI3BufferFromPixmapReq);
|
||||
|
||||
swaps(&stuff->length);
|
||||
swapl(&stuff->pixmap);
|
||||
return (*proc_dri3_vector[stuff->dri3ReqType]) (client);
|
||||
}
|
||||
|
||||
static int
|
||||
sproc_dri3_fence_from_fd(ClientPtr client)
|
||||
{
|
||||
REQUEST(xDRI3FenceFromFDReq);
|
||||
|
||||
swaps(&stuff->length);
|
||||
swapl(&stuff->drawable);
|
||||
swapl(&stuff->fence);
|
||||
return (*proc_dri3_vector[stuff->dri3ReqType]) (client);
|
||||
}
|
||||
|
||||
static int
|
||||
sproc_dri3_fd_from_fence(ClientPtr client)
|
||||
{
|
||||
REQUEST(xDRI3FDFromFenceReq);
|
||||
|
||||
swaps(&stuff->length);
|
||||
swapl(&stuff->drawable);
|
||||
swapl(&stuff->fence);
|
||||
return (*proc_dri3_vector[stuff->dri3ReqType]) (client);
|
||||
}
|
||||
|
||||
int (*sproc_dri3_vector[DRI3NumberRequests]) (ClientPtr) = {
|
||||
sproc_dri3_query_version, /* 0 */
|
||||
sproc_dri3_open, /* 1 */
|
||||
sproc_dri3_pixmap_from_buffer, /* 2 */
|
||||
sproc_dri3_buffer_from_pixmap, /* 3 */
|
||||
sproc_dri3_fence_from_fd, /* 4 */
|
||||
sproc_dri3_fd_from_fence, /* 5 */
|
||||
};
|
||||
|
||||
int
|
||||
sproc_dri3_dispatch(ClientPtr client)
|
||||
{
|
||||
REQUEST(xReq);
|
||||
if (stuff->data >= DRI3NumberRequests || !sproc_dri3_vector[stuff->data])
|
||||
return BadRequest;
|
||||
return (*sproc_dri3_vector[stuff->data]) (client);
|
||||
}
|
||||
Reference in New Issue
Block a user