diff options
Diffstat (limited to 'xorg-server/hw/xfree86/dri2/dri2ext.c')
-rw-r--r-- | xorg-server/hw/xfree86/dri2/dri2ext.c | 217 |
1 files changed, 217 insertions, 0 deletions
diff --git a/xorg-server/hw/xfree86/dri2/dri2ext.c b/xorg-server/hw/xfree86/dri2/dri2ext.c index 7d6064acb..3e6b03e4e 100644 --- a/xorg-server/hw/xfree86/dri2/dri2ext.c +++ b/xorg-server/hw/xfree86/dri2/dri2ext.c @@ -259,6 +259,9 @@ ProcDRI2GetBuffers(ClientPtr client) &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); @@ -283,6 +286,9 @@ ProcDRI2GetBuffersWithFormat(ClientPtr client) &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); @@ -329,6 +335,204 @@ ProcDRI2CopyRegion(ClientPtr client) 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; + + event.type = DRI2EventBase + DRI2_BufferSwapComplete; + event.sequenceNumber = client->sequence; + event.event_type = type; + 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; + + 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) { @@ -357,6 +561,16 @@ ProcDRI2Dispatch (ClientPtr client) 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; } @@ -413,6 +627,8 @@ static int DRI2DrawableGone(pointer p, XID id) return Success; } +int DRI2EventBase; + static void DRI2ExtensionInit(void) { @@ -429,6 +645,7 @@ DRI2ExtensionInit(void) NULL, StandardMinorOpcode); + DRI2EventBase = dri2Extension->eventBase; } extern Bool noDRI2Extension; |