diff options
Diffstat (limited to 'xorg-server/hw/xfree86/dri2/dri2ext.c')
-rw-r--r-- | xorg-server/hw/xfree86/dri2/dri2ext.c | 1292 |
1 files changed, 646 insertions, 646 deletions
diff --git a/xorg-server/hw/xfree86/dri2/dri2ext.c b/xorg-server/hw/xfree86/dri2/dri2ext.c index 17df1304e..8bed02055 100644 --- a/xorg-server/hw/xfree86/dri2/dri2ext.c +++ b/xorg-server/hw/xfree86/dri2/dri2ext.c @@ -1,646 +1,646 @@ -/* - * Copyright © 2008 Red Hat, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Soft- - * ware"), to deal in the Software without restriction, including without - * limitation the rights to use, copy, modify, merge, publish, distribute, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, provided that the above copyright - * notice(s) and this permission notice appear in all copies of the Soft- - * ware and that both the above copyright notice(s) and this permission - * notice appear in supporting documentation. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- - * ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY - * RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN - * THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSE- - * QUENTIAL 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 PERFOR- - * MANCE OF THIS SOFTWARE. - * - * Except as contained in this notice, the name of a copyright holder shall - * not be used in advertising or otherwise to promote the sale, use or - * other dealings in this Software without prior written authorization of - * the copyright holder. - * - * Authors: - * Kristian Høgsberg (krh@redhat.com) - */ - -#ifdef HAVE_XORG_CONFIG_H -#include <xorg-config.h> -#endif - -#include <X11/X.h> -#include <X11/Xproto.h> -#include <X11/extensions/dri2proto.h> -#include <X11/extensions/xfixeswire.h> -#include "dixstruct.h" -#include "scrnintstr.h" -#include "pixmapstr.h" -#include "extnsionst.h" -#include "xf86drm.h" -#include "xfixes.h" -#include "dri2.h" -#include "protocol-versions.h" - -/* The only xf86 include */ -#include "xf86Module.h" - -static ExtensionEntry *dri2Extension; - -static Bool -validDrawable(ClientPtr client, XID drawable, Mask access_mode, - DrawablePtr *pDrawable, int *status) -{ - *status = dixLookupDrawable(pDrawable, drawable, client, 0, access_mode); - if (*status != Success) { - client->errorValue = drawable; - return FALSE; - } - - return TRUE; -} - -static int -ProcDRI2QueryVersion(ClientPtr client) -{ - REQUEST(xDRI2QueryVersionReq); - xDRI2QueryVersionReply rep; - int n; - - if (client->swapped) - swaps(&stuff->length, n); - - REQUEST_SIZE_MATCH(xDRI2QueryVersionReq); - rep.type = X_Reply; - rep.length = 0; - rep.sequenceNumber = client->sequence; - rep.majorVersion = dri2_major; - rep.minorVersion = dri2_minor; - - if (client->swapped) { - swaps(&rep.sequenceNumber, n); - swapl(&rep.length, n); - swapl(&rep.majorVersion, n); - swapl(&rep.minorVersion, n); - } - - WriteToClient(client, sizeof(xDRI2QueryVersionReply), &rep); - - return client->noClientException; -} - -static int -ProcDRI2Connect(ClientPtr client) -{ - REQUEST(xDRI2ConnectReq); - xDRI2ConnectReply rep; - DrawablePtr pDraw; - int fd, status; - const char *driverName; - const char *deviceName; - - REQUEST_SIZE_MATCH(xDRI2ConnectReq); - if (!validDrawable(client, stuff->window, DixGetAttrAccess, - &pDraw, &status)) - return status; - - rep.type = X_Reply; - rep.length = 0; - rep.sequenceNumber = client->sequence; - rep.driverNameLength = 0; - rep.deviceNameLength = 0; - - if (!DRI2Connect(pDraw->pScreen, - stuff->driverType, &fd, &driverName, &deviceName)) - goto fail; - - rep.driverNameLength = strlen(driverName); - rep.deviceNameLength = strlen(deviceName); - rep.length = (rep.driverNameLength + 3) / 4 + - (rep.deviceNameLength + 3) / 4; - - fail: - WriteToClient(client, sizeof(xDRI2ConnectReply), &rep); - WriteToClient(client, rep.driverNameLength, driverName); - WriteToClient(client, rep.deviceNameLength, deviceName); - - return client->noClientException; -} - -static int -ProcDRI2Authenticate(ClientPtr client) -{ - REQUEST(xDRI2AuthenticateReq); - xDRI2AuthenticateReply rep; - DrawablePtr pDraw; - int status; - - REQUEST_SIZE_MATCH(xDRI2AuthenticateReq); - if (!validDrawable(client, stuff->window, DixGetAttrAccess, - &pDraw, &status)) - return status; - - rep.type = X_Reply; - rep.sequenceNumber = client->sequence; - rep.length = 0; - rep.authenticated = DRI2Authenticate(pDraw->pScreen, stuff->magic); - WriteToClient(client, sizeof(xDRI2AuthenticateReply), &rep); - - return client->noClientException; -} - -static int -ProcDRI2CreateDrawable(ClientPtr client) -{ - REQUEST(xDRI2CreateDrawableReq); - DrawablePtr pDrawable; - int status; - - REQUEST_SIZE_MATCH(xDRI2CreateDrawableReq); - - if (!validDrawable(client, stuff->drawable, DixAddAccess, - &pDrawable, &status)) - return status; - - status = DRI2CreateDrawable(pDrawable); - if (status != Success) - return status; - - return client->noClientException; -} - -static int -ProcDRI2DestroyDrawable(ClientPtr client) -{ - REQUEST(xDRI2DestroyDrawableReq); - DrawablePtr pDrawable; - int status; - - REQUEST_SIZE_MATCH(xDRI2DestroyDrawableReq); - if (!validDrawable(client, stuff->drawable, DixRemoveAccess, - &pDrawable, &status)) - return status; - - return client->noClientException; -} - - -static void -send_buffers_reply(ClientPtr client, DrawablePtr pDrawable, - DRI2BufferPtr *buffers, int count, int width, int height) -{ - xDRI2GetBuffersReply rep; - int skip = 0; - int i; - - if (pDrawable->type == DRAWABLE_WINDOW) { - for (i = 0; i < count; i++) { - /* Do not send the real front buffer of a window to the client. - */ - if (buffers[i]->attachment == DRI2BufferFrontLeft) { - skip++; - continue; - } - } - } - - rep.type = X_Reply; - rep.length = (count - skip) * sizeof(xDRI2Buffer) / 4; - rep.sequenceNumber = client->sequence; - rep.width = width; - rep.height = height; - rep.count = count - skip; - WriteToClient(client, sizeof(xDRI2GetBuffersReply), &rep); - - for (i = 0; i < count; i++) { - xDRI2Buffer buffer; - - /* Do not send the real front buffer of a window to the client. - */ - if ((pDrawable->type == DRAWABLE_WINDOW) - && (buffers[i]->attachment == DRI2BufferFrontLeft)) { - continue; - } - - buffer.attachment = buffers[i]->attachment; - buffer.name = buffers[i]->name; - buffer.pitch = buffers[i]->pitch; - buffer.cpp = buffers[i]->cpp; - buffer.flags = buffers[i]->flags; - WriteToClient(client, sizeof(xDRI2Buffer), &buffer); - } -} - - -static int -ProcDRI2GetBuffers(ClientPtr client) -{ - REQUEST(xDRI2GetBuffersReq); - DrawablePtr pDrawable; - DRI2BufferPtr *buffers; - int status, width, height, count; - unsigned int *attachments; - - REQUEST_FIXED_SIZE(xDRI2GetBuffersReq, stuff->count * 4); - if (!validDrawable(client, stuff->drawable, DixReadAccess | DixWriteAccess, - &pDrawable, &status)) - return status; - - if (DRI2ThrottleClient(client, pDrawable)) - return client->noClientException; - - attachments = (unsigned int *) &stuff[1]; - buffers = DRI2GetBuffers(pDrawable, &width, &height, - attachments, stuff->count, &count); - - - send_buffers_reply(client, pDrawable, buffers, count, width, height); - - return client->noClientException; -} - -static int -ProcDRI2GetBuffersWithFormat(ClientPtr client) -{ - REQUEST(xDRI2GetBuffersReq); - DrawablePtr pDrawable; - DRI2BufferPtr *buffers; - int status, width, height, count; - unsigned int *attachments; - - REQUEST_FIXED_SIZE(xDRI2GetBuffersReq, stuff->count * (2 * 4)); - if (!validDrawable(client, stuff->drawable, DixReadAccess | DixWriteAccess, - &pDrawable, &status)) - return status; - - if (DRI2ThrottleClient(client, pDrawable)) - return client->noClientException; - - attachments = (unsigned int *) &stuff[1]; - buffers = DRI2GetBuffersWithFormat(pDrawable, &width, &height, - attachments, stuff->count, &count); - - send_buffers_reply(client, pDrawable, buffers, count, width, height); - - return client->noClientException; -} - -static int -ProcDRI2CopyRegion(ClientPtr client) -{ - REQUEST(xDRI2CopyRegionReq); - xDRI2CopyRegionReply rep; - DrawablePtr pDrawable; - int status; - RegionPtr pRegion; - - REQUEST_SIZE_MATCH(xDRI2CopyRegionReq); - - if (!validDrawable(client, stuff->drawable, DixWriteAccess, - &pDrawable, &status)) - return status; - - VERIFY_REGION(pRegion, stuff->region, client, DixReadAccess); - - status = DRI2CopyRegion(pDrawable, pRegion, stuff->dest, stuff->src); - if (status != Success) - return status; - - /* CopyRegion needs to be a round trip to make sure the X server - * queues the swap buffer rendering commands before the DRI client - * continues rendering. The reply has a bitmask to signal the - * presense of optional return values as well, but we're not using - * that yet. - */ - - rep.type = X_Reply; - rep.length = 0; - rep.sequenceNumber = client->sequence; - - WriteToClient(client, sizeof(xDRI2CopyRegionReply), &rep); - - return client->noClientException; -} - -static void -load_swap_reply(xDRI2SwapBuffersReply *rep, CARD64 sbc) -{ - rep->swap_hi = sbc >> 32; - rep->swap_lo = sbc & 0xffffffff; -} - -static CARD64 -vals_to_card64(CARD32 lo, CARD32 hi) -{ - return (CARD64)hi << 32 | lo; -} - -static void -DRI2SwapEvent(ClientPtr client, void *data, int type, CARD64 ust, CARD64 msc, - CARD64 sbc) -{ - xDRI2BufferSwapComplete event; - DrawablePtr pDrawable = data; - - event.type = DRI2EventBase + DRI2_BufferSwapComplete; - event.sequenceNumber = client->sequence; - event.event_type = type; - event.drawable = pDrawable->id; - event.ust_hi = (CARD64)ust >> 32; - event.ust_lo = ust & 0xffffffff; - event.msc_hi = (CARD64)msc >> 32; - event.msc_lo = msc & 0xffffffff; - event.sbc_hi = (CARD64)sbc >> 32; - event.sbc_lo = sbc & 0xffffffff; - - WriteEventsToClient(client, 1, (xEvent *)&event); -} - -static int -ProcDRI2SwapBuffers(ClientPtr client) -{ - REQUEST(xDRI2SwapBuffersReq); - xDRI2SwapBuffersReply rep; - DrawablePtr pDrawable; - CARD64 target_msc, divisor, remainder, swap_target; - int status; - - REQUEST_SIZE_MATCH(xDRI2SwapBuffersReq); - - if (!validDrawable(client, stuff->drawable, - DixReadAccess | DixWriteAccess, &pDrawable, &status)) - return status; - - /* - * Ensures an out of control client can't exhaust our swap queue, and - * also orders swaps. - */ - if (DRI2ThrottleClient(client, pDrawable)) - return client->noClientException; - - target_msc = vals_to_card64(stuff->target_msc_lo, stuff->target_msc_hi); - divisor = vals_to_card64(stuff->divisor_lo, stuff->divisor_hi); - remainder = vals_to_card64(stuff->remainder_lo, stuff->remainder_hi); - - status = DRI2SwapBuffers(client, pDrawable, target_msc, divisor, remainder, - &swap_target, DRI2SwapEvent, pDrawable); - if (status != Success) - return BadDrawable; - - rep.type = X_Reply; - rep.length = 0; - rep.sequenceNumber = client->sequence; - load_swap_reply(&rep, swap_target); - - WriteToClient(client, sizeof(xDRI2SwapBuffersReply), &rep); - - return client->noClientException; -} - -static void -load_msc_reply(xDRI2MSCReply *rep, CARD64 ust, CARD64 msc, CARD64 sbc) -{ - rep->ust_hi = ust >> 32; - rep->ust_lo = ust & 0xffffffff; - rep->msc_hi = msc >> 32; - rep->msc_lo = msc & 0xffffffff; - rep->sbc_hi = sbc >> 32; - rep->sbc_lo = sbc & 0xffffffff; -} - -static int -ProcDRI2GetMSC(ClientPtr client) -{ - REQUEST(xDRI2GetMSCReq); - xDRI2MSCReply rep; - DrawablePtr pDrawable; - CARD64 ust, msc, sbc; - int status; - - REQUEST_SIZE_MATCH(xDRI2GetMSCReq); - - if (!validDrawable(client, stuff->drawable, DixReadAccess, &pDrawable, - &status)) - return status; - - status = DRI2GetMSC(pDrawable, &ust, &msc, &sbc); - if (status != Success) - return status; - - rep.type = X_Reply; - rep.length = 0; - rep.sequenceNumber = client->sequence; - load_msc_reply(&rep, ust, msc, sbc); - - WriteToClient(client, sizeof(xDRI2MSCReply), &rep); - - return client->noClientException; -} - -static int -ProcDRI2WaitMSC(ClientPtr client) -{ - REQUEST(xDRI2WaitMSCReq); - DrawablePtr pDrawable; - CARD64 target, divisor, remainder; - int status; - - /* FIXME: in restart case, client may be gone at this point */ - - REQUEST_SIZE_MATCH(xDRI2WaitMSCReq); - - if (!validDrawable(client, stuff->drawable, DixReadAccess, &pDrawable, - &status)) - return status; - - target = vals_to_card64(stuff->target_msc_lo, stuff->target_msc_hi); - divisor = vals_to_card64(stuff->divisor_lo, stuff->divisor_hi); - remainder = vals_to_card64(stuff->remainder_lo, stuff->remainder_hi); - - status = DRI2WaitMSC(client, pDrawable, target, divisor, remainder); - if (status != Success) - return status; - - return client->noClientException; -} - -int -ProcDRI2WaitMSCReply(ClientPtr client, CARD64 ust, CARD64 msc, CARD64 sbc) -{ - xDRI2MSCReply rep; - - rep.type = X_Reply; - rep.length = 0; - rep.sequenceNumber = client->sequence; - load_msc_reply(&rep, ust, msc, sbc); - - WriteToClient(client, sizeof(xDRI2MSCReply), &rep); - - return client->noClientException; -} - -static int -ProcDRI2SwapInterval(ClientPtr client) -{ - REQUEST(xDRI2SwapIntervalReq); - DrawablePtr pDrawable; - int status; - - /* FIXME: in restart case, client may be gone at this point */ - - REQUEST_SIZE_MATCH(xDRI2SwapIntervalReq); - - if (!validDrawable(client, stuff->drawable, DixReadAccess | DixWriteAccess, - &pDrawable, &status)) - return status; - - DRI2SwapInterval(pDrawable, stuff->interval); - - return client->noClientException; -} - -static int -ProcDRI2WaitSBC(ClientPtr client) -{ - REQUEST(xDRI2WaitSBCReq); - xDRI2MSCReply rep; - DrawablePtr pDrawable; - CARD64 target, ust, msc, sbc; - int status; - - REQUEST_SIZE_MATCH(xDRI2WaitSBCReq); - - if (!validDrawable(client, stuff->drawable, DixReadAccess, &pDrawable, - &status)) - return status; - - target = vals_to_card64(stuff->target_sbc_lo, stuff->target_sbc_hi); - status = DRI2WaitSBC(client, pDrawable, target, &ust, &msc, &sbc); - if (status != Success) - return status; - - rep.type = X_Reply; - rep.length = 0; - rep.sequenceNumber = client->sequence; - load_msc_reply(&rep, ust, msc, sbc); - - WriteToClient(client, sizeof(xDRI2MSCReply), &rep); - - return client->noClientException; -} - -static int -ProcDRI2Dispatch (ClientPtr client) -{ - REQUEST(xReq); - - switch (stuff->data) { - case X_DRI2QueryVersion: - return ProcDRI2QueryVersion(client); - } - - if (!LocalClient(client)) - return BadRequest; - - switch (stuff->data) { - case X_DRI2Connect: - return ProcDRI2Connect(client); - case X_DRI2Authenticate: - return ProcDRI2Authenticate(client); - case X_DRI2CreateDrawable: - return ProcDRI2CreateDrawable(client); - case X_DRI2DestroyDrawable: - return ProcDRI2DestroyDrawable(client); - case X_DRI2GetBuffers: - return ProcDRI2GetBuffers(client); - case X_DRI2CopyRegion: - return ProcDRI2CopyRegion(client); - case X_DRI2GetBuffersWithFormat: - return ProcDRI2GetBuffersWithFormat(client); - case X_DRI2SwapBuffers: - return ProcDRI2SwapBuffers(client); - case X_DRI2GetMSC: - return ProcDRI2GetMSC(client); - case X_DRI2WaitMSC: - return ProcDRI2WaitMSC(client); - case X_DRI2WaitSBC: - return ProcDRI2WaitSBC(client); - case X_DRI2SwapInterval: - return ProcDRI2SwapInterval(client); - default: - return BadRequest; - } -} - -static int -SProcDRI2Connect(ClientPtr client) -{ - REQUEST(xDRI2ConnectReq); - xDRI2ConnectReply rep; - int n; - - /* If the client is swapped, it's not local. Talk to the hand. */ - - swaps(&stuff->length, n); - if (sizeof(*stuff) / 4 != client->req_len) - return BadLength; - - rep.sequenceNumber = client->sequence; - swaps(&rep.sequenceNumber, n); - rep.length = 0; - rep.driverNameLength = 0; - rep.deviceNameLength = 0; - - return client->noClientException; -} - -static int -SProcDRI2Dispatch (ClientPtr client) -{ - REQUEST(xReq); - - /* - * Only local clients are allowed DRI access, but remote clients - * still need these requests to find out cleanly. - */ - switch (stuff->data) - { - case X_DRI2QueryVersion: - return ProcDRI2QueryVersion(client); - case X_DRI2Connect: - return SProcDRI2Connect(client); - default: - return BadRequest; - } -} - -int DRI2EventBase; - -static void -DRI2ExtensionInit(void) -{ - dri2Extension = AddExtension(DRI2_NAME, - DRI2NumberEvents, - DRI2NumberErrors, - ProcDRI2Dispatch, - SProcDRI2Dispatch, - NULL, - StandardMinorOpcode); - - DRI2EventBase = dri2Extension->eventBase; -} - -extern Bool noDRI2Extension; - -_X_HIDDEN ExtensionModule dri2ExtensionModule = { - DRI2ExtensionInit, - DRI2_NAME, - &noDRI2Extension, - NULL, - NULL -}; +/*
+ * Copyright © 2008 Red Hat, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Soft-
+ * ware"), to deal in the Software without restriction, including without
+ * limitation the rights to use, copy, modify, merge, publish, distribute,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, provided that the above copyright
+ * notice(s) and this permission notice appear in all copies of the Soft-
+ * ware and that both the above copyright notice(s) and this permission
+ * notice appear in supporting documentation.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
+ * ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY
+ * RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN
+ * THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSE-
+ * QUENTIAL 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 PERFOR-
+ * MANCE OF THIS SOFTWARE.
+ *
+ * Except as contained in this notice, the name of a copyright holder shall
+ * not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization of
+ * the copyright holder.
+ *
+ * Authors:
+ * Kristian Høgsberg (krh@redhat.com)
+ */
+
+#ifdef HAVE_XORG_CONFIG_H
+#include <xorg-config.h>
+#endif
+
+#include <X11/X.h>
+#include <X11/Xproto.h>
+#include <X11/extensions/dri2proto.h>
+#include <X11/extensions/xfixeswire.h>
+#include "dixstruct.h"
+#include "scrnintstr.h"
+#include "pixmapstr.h"
+#include "extnsionst.h"
+#include "xf86drm.h"
+#include "xfixes.h"
+#include "dri2.h"
+#include "protocol-versions.h"
+
+/* The only xf86 include */
+#include "xf86Module.h"
+
+static ExtensionEntry *dri2Extension;
+
+static Bool
+validDrawable(ClientPtr client, XID drawable, Mask access_mode,
+ DrawablePtr *pDrawable, int *status)
+{
+ *status = dixLookupDrawable(pDrawable, drawable, client, 0, access_mode);
+ if (*status != Success) {
+ client->errorValue = drawable;
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static int
+ProcDRI2QueryVersion(ClientPtr client)
+{
+ REQUEST(xDRI2QueryVersionReq);
+ xDRI2QueryVersionReply rep;
+ int n;
+
+ if (client->swapped)
+ swaps(&stuff->length, n);
+
+ REQUEST_SIZE_MATCH(xDRI2QueryVersionReq);
+ rep.type = X_Reply;
+ rep.length = 0;
+ rep.sequenceNumber = client->sequence;
+ rep.majorVersion = dri2_major;
+ rep.minorVersion = dri2_minor;
+
+ if (client->swapped) {
+ swaps(&rep.sequenceNumber, n);
+ swapl(&rep.length, n);
+ swapl(&rep.majorVersion, n);
+ swapl(&rep.minorVersion, n);
+ }
+
+ WriteToClient(client, sizeof(xDRI2QueryVersionReply), &rep);
+
+ return client->noClientException;
+}
+
+static int
+ProcDRI2Connect(ClientPtr client)
+{
+ REQUEST(xDRI2ConnectReq);
+ xDRI2ConnectReply rep;
+ DrawablePtr pDraw;
+ int fd, status;
+ const char *driverName;
+ const char *deviceName;
+
+ REQUEST_SIZE_MATCH(xDRI2ConnectReq);
+ if (!validDrawable(client, stuff->window, DixGetAttrAccess,
+ &pDraw, &status))
+ return status;
+
+ rep.type = X_Reply;
+ rep.length = 0;
+ rep.sequenceNumber = client->sequence;
+ rep.driverNameLength = 0;
+ rep.deviceNameLength = 0;
+
+ if (!DRI2Connect(pDraw->pScreen,
+ stuff->driverType, &fd, &driverName, &deviceName))
+ goto fail;
+
+ rep.driverNameLength = strlen(driverName);
+ rep.deviceNameLength = strlen(deviceName);
+ rep.length = (rep.driverNameLength + 3) / 4 +
+ (rep.deviceNameLength + 3) / 4;
+
+ fail:
+ WriteToClient(client, sizeof(xDRI2ConnectReply), &rep);
+ WriteToClient(client, rep.driverNameLength, driverName);
+ WriteToClient(client, rep.deviceNameLength, deviceName);
+
+ return client->noClientException;
+}
+
+static int
+ProcDRI2Authenticate(ClientPtr client)
+{
+ REQUEST(xDRI2AuthenticateReq);
+ xDRI2AuthenticateReply rep;
+ DrawablePtr pDraw;
+ int status;
+
+ REQUEST_SIZE_MATCH(xDRI2AuthenticateReq);
+ if (!validDrawable(client, stuff->window, DixGetAttrAccess,
+ &pDraw, &status))
+ return status;
+
+ rep.type = X_Reply;
+ rep.sequenceNumber = client->sequence;
+ rep.length = 0;
+ rep.authenticated = DRI2Authenticate(pDraw->pScreen, stuff->magic);
+ WriteToClient(client, sizeof(xDRI2AuthenticateReply), &rep);
+
+ return client->noClientException;
+}
+
+static int
+ProcDRI2CreateDrawable(ClientPtr client)
+{
+ REQUEST(xDRI2CreateDrawableReq);
+ DrawablePtr pDrawable;
+ int status;
+
+ REQUEST_SIZE_MATCH(xDRI2CreateDrawableReq);
+
+ if (!validDrawable(client, stuff->drawable, DixAddAccess,
+ &pDrawable, &status))
+ return status;
+
+ status = DRI2CreateDrawable(client, pDrawable, stuff->drawable);
+ if (status != Success)
+ return status;
+
+ return client->noClientException;
+}
+
+static int
+ProcDRI2DestroyDrawable(ClientPtr client)
+{
+ REQUEST(xDRI2DestroyDrawableReq);
+ DrawablePtr pDrawable;
+ int status;
+
+ REQUEST_SIZE_MATCH(xDRI2DestroyDrawableReq);
+ if (!validDrawable(client, stuff->drawable, DixRemoveAccess,
+ &pDrawable, &status))
+ return status;
+
+ return client->noClientException;
+}
+
+
+static void
+send_buffers_reply(ClientPtr client, DrawablePtr pDrawable,
+ DRI2BufferPtr *buffers, int count, int width, int height)
+{
+ xDRI2GetBuffersReply rep;
+ int skip = 0;
+ int i;
+
+ if (pDrawable->type == DRAWABLE_WINDOW) {
+ for (i = 0; i < count; i++) {
+ /* Do not send the real front buffer of a window to the client.
+ */
+ if (buffers[i]->attachment == DRI2BufferFrontLeft) {
+ skip++;
+ continue;
+ }
+ }
+ }
+
+ rep.type = X_Reply;
+ rep.length = (count - skip) * sizeof(xDRI2Buffer) / 4;
+ rep.sequenceNumber = client->sequence;
+ rep.width = width;
+ rep.height = height;
+ rep.count = count - skip;
+ WriteToClient(client, sizeof(xDRI2GetBuffersReply), &rep);
+
+ for (i = 0; i < count; i++) {
+ xDRI2Buffer buffer;
+
+ /* Do not send the real front buffer of a window to the client.
+ */
+ if ((pDrawable->type == DRAWABLE_WINDOW)
+ && (buffers[i]->attachment == DRI2BufferFrontLeft)) {
+ continue;
+ }
+
+ buffer.attachment = buffers[i]->attachment;
+ buffer.name = buffers[i]->name;
+ buffer.pitch = buffers[i]->pitch;
+ buffer.cpp = buffers[i]->cpp;
+ buffer.flags = buffers[i]->flags;
+ WriteToClient(client, sizeof(xDRI2Buffer), &buffer);
+ }
+}
+
+
+static int
+ProcDRI2GetBuffers(ClientPtr client)
+{
+ REQUEST(xDRI2GetBuffersReq);
+ DrawablePtr pDrawable;
+ DRI2BufferPtr *buffers;
+ int status, width, height, count;
+ unsigned int *attachments;
+
+ REQUEST_FIXED_SIZE(xDRI2GetBuffersReq, stuff->count * 4);
+ if (!validDrawable(client, stuff->drawable, DixReadAccess | DixWriteAccess,
+ &pDrawable, &status))
+ return status;
+
+ if (DRI2ThrottleClient(client, pDrawable))
+ return client->noClientException;
+
+ attachments = (unsigned int *) &stuff[1];
+ buffers = DRI2GetBuffers(pDrawable, &width, &height,
+ attachments, stuff->count, &count);
+
+
+ send_buffers_reply(client, pDrawable, buffers, count, width, height);
+
+ return client->noClientException;
+}
+
+static int
+ProcDRI2GetBuffersWithFormat(ClientPtr client)
+{
+ REQUEST(xDRI2GetBuffersReq);
+ DrawablePtr pDrawable;
+ DRI2BufferPtr *buffers;
+ int status, width, height, count;
+ unsigned int *attachments;
+
+ REQUEST_FIXED_SIZE(xDRI2GetBuffersReq, stuff->count * (2 * 4));
+ if (!validDrawable(client, stuff->drawable, DixReadAccess | DixWriteAccess,
+ &pDrawable, &status))
+ return status;
+
+ if (DRI2ThrottleClient(client, pDrawable))
+ return client->noClientException;
+
+ attachments = (unsigned int *) &stuff[1];
+ buffers = DRI2GetBuffersWithFormat(pDrawable, &width, &height,
+ attachments, stuff->count, &count);
+
+ send_buffers_reply(client, pDrawable, buffers, count, width, height);
+
+ return client->noClientException;
+}
+
+static int
+ProcDRI2CopyRegion(ClientPtr client)
+{
+ REQUEST(xDRI2CopyRegionReq);
+ xDRI2CopyRegionReply rep;
+ DrawablePtr pDrawable;
+ int status;
+ RegionPtr pRegion;
+
+ REQUEST_SIZE_MATCH(xDRI2CopyRegionReq);
+
+ if (!validDrawable(client, stuff->drawable, DixWriteAccess,
+ &pDrawable, &status))
+ return status;
+
+ VERIFY_REGION(pRegion, stuff->region, client, DixReadAccess);
+
+ status = DRI2CopyRegion(pDrawable, pRegion, stuff->dest, stuff->src);
+ if (status != Success)
+ return status;
+
+ /* CopyRegion needs to be a round trip to make sure the X server
+ * queues the swap buffer rendering commands before the DRI client
+ * continues rendering. The reply has a bitmask to signal the
+ * presense of optional return values as well, but we're not using
+ * that yet.
+ */
+
+ rep.type = X_Reply;
+ rep.length = 0;
+ rep.sequenceNumber = client->sequence;
+
+ WriteToClient(client, sizeof(xDRI2CopyRegionReply), &rep);
+
+ return client->noClientException;
+}
+
+static void
+load_swap_reply(xDRI2SwapBuffersReply *rep, CARD64 sbc)
+{
+ rep->swap_hi = sbc >> 32;
+ rep->swap_lo = sbc & 0xffffffff;
+}
+
+static CARD64
+vals_to_card64(CARD32 lo, CARD32 hi)
+{
+ return (CARD64)hi << 32 | lo;
+}
+
+static void
+DRI2SwapEvent(ClientPtr client, void *data, int type, CARD64 ust, CARD64 msc,
+ CARD64 sbc)
+{
+ xDRI2BufferSwapComplete event;
+ DrawablePtr pDrawable = data;
+
+ event.type = DRI2EventBase + DRI2_BufferSwapComplete;
+ event.sequenceNumber = client->sequence;
+ event.event_type = type;
+ event.drawable = pDrawable->id;
+ event.ust_hi = (CARD64)ust >> 32;
+ event.ust_lo = ust & 0xffffffff;
+ event.msc_hi = (CARD64)msc >> 32;
+ event.msc_lo = msc & 0xffffffff;
+ event.sbc_hi = (CARD64)sbc >> 32;
+ event.sbc_lo = sbc & 0xffffffff;
+
+ WriteEventsToClient(client, 1, (xEvent *)&event);
+}
+
+static int
+ProcDRI2SwapBuffers(ClientPtr client)
+{
+ REQUEST(xDRI2SwapBuffersReq);
+ xDRI2SwapBuffersReply rep;
+ DrawablePtr pDrawable;
+ CARD64 target_msc, divisor, remainder, swap_target;
+ int status;
+
+ REQUEST_SIZE_MATCH(xDRI2SwapBuffersReq);
+
+ if (!validDrawable(client, stuff->drawable,
+ DixReadAccess | DixWriteAccess, &pDrawable, &status))
+ return status;
+
+ /*
+ * Ensures an out of control client can't exhaust our swap queue, and
+ * also orders swaps.
+ */
+ if (DRI2ThrottleClient(client, pDrawable))
+ return client->noClientException;
+
+ target_msc = vals_to_card64(stuff->target_msc_lo, stuff->target_msc_hi);
+ divisor = vals_to_card64(stuff->divisor_lo, stuff->divisor_hi);
+ remainder = vals_to_card64(stuff->remainder_lo, stuff->remainder_hi);
+
+ status = DRI2SwapBuffers(client, pDrawable, target_msc, divisor, remainder,
+ &swap_target, DRI2SwapEvent, pDrawable);
+ if (status != Success)
+ return BadDrawable;
+
+ rep.type = X_Reply;
+ rep.length = 0;
+ rep.sequenceNumber = client->sequence;
+ load_swap_reply(&rep, swap_target);
+
+ WriteToClient(client, sizeof(xDRI2SwapBuffersReply), &rep);
+
+ return client->noClientException;
+}
+
+static void
+load_msc_reply(xDRI2MSCReply *rep, CARD64 ust, CARD64 msc, CARD64 sbc)
+{
+ rep->ust_hi = ust >> 32;
+ rep->ust_lo = ust & 0xffffffff;
+ rep->msc_hi = msc >> 32;
+ rep->msc_lo = msc & 0xffffffff;
+ rep->sbc_hi = sbc >> 32;
+ rep->sbc_lo = sbc & 0xffffffff;
+}
+
+static int
+ProcDRI2GetMSC(ClientPtr client)
+{
+ REQUEST(xDRI2GetMSCReq);
+ xDRI2MSCReply rep;
+ DrawablePtr pDrawable;
+ CARD64 ust, msc, sbc;
+ int status;
+
+ REQUEST_SIZE_MATCH(xDRI2GetMSCReq);
+
+ if (!validDrawable(client, stuff->drawable, DixReadAccess, &pDrawable,
+ &status))
+ return status;
+
+ status = DRI2GetMSC(pDrawable, &ust, &msc, &sbc);
+ if (status != Success)
+ return status;
+
+ rep.type = X_Reply;
+ rep.length = 0;
+ rep.sequenceNumber = client->sequence;
+ load_msc_reply(&rep, ust, msc, sbc);
+
+ WriteToClient(client, sizeof(xDRI2MSCReply), &rep);
+
+ return client->noClientException;
+}
+
+static int
+ProcDRI2WaitMSC(ClientPtr client)
+{
+ REQUEST(xDRI2WaitMSCReq);
+ DrawablePtr pDrawable;
+ CARD64 target, divisor, remainder;
+ int status;
+
+ /* FIXME: in restart case, client may be gone at this point */
+
+ REQUEST_SIZE_MATCH(xDRI2WaitMSCReq);
+
+ if (!validDrawable(client, stuff->drawable, DixReadAccess, &pDrawable,
+ &status))
+ return status;
+
+ target = vals_to_card64(stuff->target_msc_lo, stuff->target_msc_hi);
+ divisor = vals_to_card64(stuff->divisor_lo, stuff->divisor_hi);
+ remainder = vals_to_card64(stuff->remainder_lo, stuff->remainder_hi);
+
+ status = DRI2WaitMSC(client, pDrawable, target, divisor, remainder);
+ if (status != Success)
+ return status;
+
+ return client->noClientException;
+}
+
+int
+ProcDRI2WaitMSCReply(ClientPtr client, CARD64 ust, CARD64 msc, CARD64 sbc)
+{
+ xDRI2MSCReply rep;
+
+ rep.type = X_Reply;
+ rep.length = 0;
+ rep.sequenceNumber = client->sequence;
+ load_msc_reply(&rep, ust, msc, sbc);
+
+ WriteToClient(client, sizeof(xDRI2MSCReply), &rep);
+
+ return client->noClientException;
+}
+
+static int
+ProcDRI2SwapInterval(ClientPtr client)
+{
+ REQUEST(xDRI2SwapIntervalReq);
+ DrawablePtr pDrawable;
+ int status;
+
+ /* FIXME: in restart case, client may be gone at this point */
+
+ REQUEST_SIZE_MATCH(xDRI2SwapIntervalReq);
+
+ if (!validDrawable(client, stuff->drawable, DixReadAccess | DixWriteAccess,
+ &pDrawable, &status))
+ return status;
+
+ DRI2SwapInterval(pDrawable, stuff->interval);
+
+ return client->noClientException;
+}
+
+static int
+ProcDRI2WaitSBC(ClientPtr client)
+{
+ REQUEST(xDRI2WaitSBCReq);
+ xDRI2MSCReply rep;
+ DrawablePtr pDrawable;
+ CARD64 target, ust, msc, sbc;
+ int status;
+
+ REQUEST_SIZE_MATCH(xDRI2WaitSBCReq);
+
+ if (!validDrawable(client, stuff->drawable, DixReadAccess, &pDrawable,
+ &status))
+ return status;
+
+ target = vals_to_card64(stuff->target_sbc_lo, stuff->target_sbc_hi);
+ status = DRI2WaitSBC(client, pDrawable, target, &ust, &msc, &sbc);
+ if (status != Success)
+ return status;
+
+ rep.type = X_Reply;
+ rep.length = 0;
+ rep.sequenceNumber = client->sequence;
+ load_msc_reply(&rep, ust, msc, sbc);
+
+ WriteToClient(client, sizeof(xDRI2MSCReply), &rep);
+
+ return client->noClientException;
+}
+
+static int
+ProcDRI2Dispatch (ClientPtr client)
+{
+ REQUEST(xReq);
+
+ switch (stuff->data) {
+ case X_DRI2QueryVersion:
+ return ProcDRI2QueryVersion(client);
+ }
+
+ if (!LocalClient(client))
+ return BadRequest;
+
+ switch (stuff->data) {
+ case X_DRI2Connect:
+ return ProcDRI2Connect(client);
+ case X_DRI2Authenticate:
+ return ProcDRI2Authenticate(client);
+ case X_DRI2CreateDrawable:
+ return ProcDRI2CreateDrawable(client);
+ case X_DRI2DestroyDrawable:
+ return ProcDRI2DestroyDrawable(client);
+ case X_DRI2GetBuffers:
+ return ProcDRI2GetBuffers(client);
+ case X_DRI2CopyRegion:
+ return ProcDRI2CopyRegion(client);
+ case X_DRI2GetBuffersWithFormat:
+ return ProcDRI2GetBuffersWithFormat(client);
+ case X_DRI2SwapBuffers:
+ return ProcDRI2SwapBuffers(client);
+ case X_DRI2GetMSC:
+ return ProcDRI2GetMSC(client);
+ case X_DRI2WaitMSC:
+ return ProcDRI2WaitMSC(client);
+ case X_DRI2WaitSBC:
+ return ProcDRI2WaitSBC(client);
+ case X_DRI2SwapInterval:
+ return ProcDRI2SwapInterval(client);
+ default:
+ return BadRequest;
+ }
+}
+
+static int
+SProcDRI2Connect(ClientPtr client)
+{
+ REQUEST(xDRI2ConnectReq);
+ xDRI2ConnectReply rep;
+ int n;
+
+ /* If the client is swapped, it's not local. Talk to the hand. */
+
+ swaps(&stuff->length, n);
+ if (sizeof(*stuff) / 4 != client->req_len)
+ return BadLength;
+
+ rep.sequenceNumber = client->sequence;
+ swaps(&rep.sequenceNumber, n);
+ rep.length = 0;
+ rep.driverNameLength = 0;
+ rep.deviceNameLength = 0;
+
+ return client->noClientException;
+}
+
+static int
+SProcDRI2Dispatch (ClientPtr client)
+{
+ REQUEST(xReq);
+
+ /*
+ * Only local clients are allowed DRI access, but remote clients
+ * still need these requests to find out cleanly.
+ */
+ switch (stuff->data)
+ {
+ case X_DRI2QueryVersion:
+ return ProcDRI2QueryVersion(client);
+ case X_DRI2Connect:
+ return SProcDRI2Connect(client);
+ default:
+ return BadRequest;
+ }
+}
+
+int DRI2EventBase;
+
+static void
+DRI2ExtensionInit(void)
+{
+ dri2Extension = AddExtension(DRI2_NAME,
+ DRI2NumberEvents,
+ DRI2NumberErrors,
+ ProcDRI2Dispatch,
+ SProcDRI2Dispatch,
+ NULL,
+ StandardMinorOpcode);
+
+ DRI2EventBase = dri2Extension->eventBase;
+}
+
+extern Bool noDRI2Extension;
+
+_X_HIDDEN ExtensionModule dri2ExtensionModule = {
+ DRI2ExtensionInit,
+ DRI2_NAME,
+ &noDRI2Extension,
+ NULL,
+ NULL
+};
|