14642e01fSmrg/* 24642e01fSmrg * Copyright © 2008 Red Hat, Inc. 34642e01fSmrg * 44642e01fSmrg * Permission is hereby granted, free of charge, to any person obtaining a 54642e01fSmrg * copy of this software and associated documentation files (the "Soft- 64642e01fSmrg * ware"), to deal in the Software without restriction, including without 74642e01fSmrg * limitation the rights to use, copy, modify, merge, publish, distribute, 84642e01fSmrg * and/or sell copies of the Software, and to permit persons to whom the 94642e01fSmrg * Software is furnished to do so, provided that the above copyright 104642e01fSmrg * notice(s) and this permission notice appear in all copies of the Soft- 114642e01fSmrg * ware and that both the above copyright notice(s) and this permission 124642e01fSmrg * notice appear in supporting documentation. 134642e01fSmrg * 144642e01fSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 154642e01fSmrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- 164642e01fSmrg * ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY 174642e01fSmrg * RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN 184642e01fSmrg * THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSE- 194642e01fSmrg * QUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 204642e01fSmrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 214642e01fSmrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFOR- 224642e01fSmrg * MANCE OF THIS SOFTWARE. 234642e01fSmrg * 244642e01fSmrg * Except as contained in this notice, the name of a copyright holder shall 254642e01fSmrg * not be used in advertising or otherwise to promote the sale, use or 264642e01fSmrg * other dealings in this Software without prior written authorization of 274642e01fSmrg * the copyright holder. 284642e01fSmrg * 294642e01fSmrg * Authors: 304642e01fSmrg * Kristian Høgsberg (krh@redhat.com) 314642e01fSmrg */ 324642e01fSmrg 334642e01fSmrg#ifdef HAVE_XORG_CONFIG_H 344642e01fSmrg#include <xorg-config.h> 354642e01fSmrg#endif 364642e01fSmrg 374642e01fSmrg#include <X11/X.h> 384642e01fSmrg#include <X11/Xproto.h> 394642e01fSmrg#include <X11/extensions/dri2proto.h> 404642e01fSmrg#include <X11/extensions/xfixeswire.h> 414642e01fSmrg#include "dixstruct.h" 424642e01fSmrg#include "scrnintstr.h" 434642e01fSmrg#include "pixmapstr.h" 444642e01fSmrg#include "extnsionst.h" 454642e01fSmrg#include "xfixes.h" 464642e01fSmrg#include "dri2.h" 47f7df2e56Smrg#include "dri2int.h" 486747b715Smrg#include "protocol-versions.h" 494642e01fSmrg 50f7df2e56Smrg/* The only xf86 includes */ 514642e01fSmrg#include "xf86Module.h" 52f7df2e56Smrg#include "xf86Extensions.h" 53f7df2e56Smrg 54f7df2e56Smrgstatic int DRI2EventBase; 554642e01fSmrg 564642e01fSmrg 574642e01fSmrgstatic Bool 586747b715SmrgvalidDrawable(ClientPtr client, XID drawable, Mask access_mode, 59f7df2e56Smrg DrawablePtr *pDrawable, int *status) 604642e01fSmrg{ 616747b715Smrg *status = dixLookupDrawable(pDrawable, drawable, client, 62f7df2e56Smrg M_DRAWABLE_WINDOW | M_DRAWABLE_PIXMAP, 63f7df2e56Smrg access_mode); 644642e01fSmrg if (*status != Success) { 65f7df2e56Smrg client->errorValue = drawable; 66f7df2e56Smrg return FALSE; 674642e01fSmrg } 684642e01fSmrg 694642e01fSmrg return TRUE; 704642e01fSmrg} 714642e01fSmrg 724642e01fSmrgstatic int 734642e01fSmrgProcDRI2QueryVersion(ClientPtr client) 744642e01fSmrg{ 754642e01fSmrg REQUEST(xDRI2QueryVersionReq); 76f7df2e56Smrg xDRI2QueryVersionReply rep = { 77f7df2e56Smrg .type = X_Reply, 78f7df2e56Smrg .sequenceNumber = client->sequence, 79f7df2e56Smrg .length = 0, 80f7df2e56Smrg .majorVersion = dri2_major, 81f7df2e56Smrg .minorVersion = dri2_minor 82f7df2e56Smrg }; 834642e01fSmrg 844642e01fSmrg if (client->swapped) 85f7df2e56Smrg swaps(&stuff->length); 864642e01fSmrg 874642e01fSmrg REQUEST_SIZE_MATCH(xDRI2QueryVersionReq); 884642e01fSmrg 894642e01fSmrg if (client->swapped) { 90f7df2e56Smrg swaps(&rep.sequenceNumber); 91f7df2e56Smrg swapl(&rep.length); 92f7df2e56Smrg swapl(&rep.majorVersion); 93f7df2e56Smrg swapl(&rep.minorVersion); 944642e01fSmrg } 954642e01fSmrg 964642e01fSmrg WriteToClient(client, sizeof(xDRI2QueryVersionReply), &rep); 974642e01fSmrg 986747b715Smrg return Success; 994642e01fSmrg} 1004642e01fSmrg 1014642e01fSmrgstatic int 1024642e01fSmrgProcDRI2Connect(ClientPtr client) 1034642e01fSmrg{ 1044642e01fSmrg REQUEST(xDRI2ConnectReq); 105f7df2e56Smrg xDRI2ConnectReply rep = { 106f7df2e56Smrg .type = X_Reply, 107f7df2e56Smrg .sequenceNumber = client->sequence, 108f7df2e56Smrg .length = 0, 109f7df2e56Smrg .driverNameLength = 0, 110f7df2e56Smrg .deviceNameLength = 0 111f7df2e56Smrg }; 1124642e01fSmrg DrawablePtr pDraw; 1134642e01fSmrg int fd, status; 1144642e01fSmrg const char *driverName; 1154642e01fSmrg const char *deviceName; 1164642e01fSmrg 1174642e01fSmrg REQUEST_SIZE_MATCH(xDRI2ConnectReq); 1186747b715Smrg if (!validDrawable(client, stuff->window, DixGetAttrAccess, 119f7df2e56Smrg &pDraw, &status)) 120f7df2e56Smrg return status; 121f7df2e56Smrg 122f7df2e56Smrg if (!DRI2Connect(client, pDraw->pScreen, 123f7df2e56Smrg stuff->driverType, &fd, &driverName, &deviceName)) 124f7df2e56Smrg goto fail; 1254642e01fSmrg 1264642e01fSmrg rep.driverNameLength = strlen(driverName); 1274642e01fSmrg rep.deviceNameLength = strlen(deviceName); 1284642e01fSmrg rep.length = (rep.driverNameLength + 3) / 4 + 129f7df2e56Smrg (rep.deviceNameLength + 3) / 4; 1304642e01fSmrg 1314642e01fSmrg fail: 1324642e01fSmrg WriteToClient(client, sizeof(xDRI2ConnectReply), &rep); 1334642e01fSmrg WriteToClient(client, rep.driverNameLength, driverName); 1344642e01fSmrg WriteToClient(client, rep.deviceNameLength, deviceName); 1354642e01fSmrg 1366747b715Smrg return Success; 1374642e01fSmrg} 1384642e01fSmrg 1394642e01fSmrgstatic int 1404642e01fSmrgProcDRI2Authenticate(ClientPtr client) 1414642e01fSmrg{ 1424642e01fSmrg REQUEST(xDRI2AuthenticateReq); 1434642e01fSmrg xDRI2AuthenticateReply rep; 1444642e01fSmrg DrawablePtr pDraw; 1454642e01fSmrg int status; 1464642e01fSmrg 1474642e01fSmrg REQUEST_SIZE_MATCH(xDRI2AuthenticateReq); 1486747b715Smrg if (!validDrawable(client, stuff->window, DixGetAttrAccess, 149f7df2e56Smrg &pDraw, &status)) 150f7df2e56Smrg return status; 151f7df2e56Smrg 152f7df2e56Smrg rep = (xDRI2AuthenticateReply) { 153f7df2e56Smrg .type = X_Reply, 154f7df2e56Smrg .sequenceNumber = client->sequence, 155f7df2e56Smrg .length = 0, 156f7df2e56Smrg .authenticated = DRI2Authenticate(client, pDraw->pScreen, stuff->magic) 157f7df2e56Smrg }; 1584642e01fSmrg WriteToClient(client, sizeof(xDRI2AuthenticateReply), &rep); 1594642e01fSmrg 1606747b715Smrg return Success; 1616747b715Smrg} 1626747b715Smrg 1636747b715Smrgstatic void 164f7df2e56SmrgDRI2InvalidateBuffersEvent(DrawablePtr pDraw, void *priv, XID id) 1656747b715Smrg{ 1666747b715Smrg ClientPtr client = priv; 167f7df2e56Smrg xDRI2InvalidateBuffers event = { 168f7df2e56Smrg .type = DRI2EventBase + DRI2_InvalidateBuffers, 169f7df2e56Smrg .drawable = id 170f7df2e56Smrg }; 1716747b715Smrg 172f7df2e56Smrg WriteEventsToClient(client, 1, (xEvent *) &event); 1734642e01fSmrg} 1744642e01fSmrg 1754642e01fSmrgstatic int 1764642e01fSmrgProcDRI2CreateDrawable(ClientPtr client) 1774642e01fSmrg{ 1784642e01fSmrg REQUEST(xDRI2CreateDrawableReq); 1794642e01fSmrg DrawablePtr pDrawable; 1804642e01fSmrg int status; 1814642e01fSmrg 1824642e01fSmrg REQUEST_SIZE_MATCH(xDRI2CreateDrawableReq); 1834642e01fSmrg 1846747b715Smrg if (!validDrawable(client, stuff->drawable, DixAddAccess, 185f7df2e56Smrg &pDrawable, &status)) 186f7df2e56Smrg return status; 1874642e01fSmrg 1886747b715Smrg status = DRI2CreateDrawable(client, pDrawable, stuff->drawable, 189f7df2e56Smrg DRI2InvalidateBuffersEvent, client); 1904642e01fSmrg if (status != Success) 191f7df2e56Smrg return status; 1924642e01fSmrg 1936747b715Smrg return Success; 1944642e01fSmrg} 1954642e01fSmrg 1964642e01fSmrgstatic int 1974642e01fSmrgProcDRI2DestroyDrawable(ClientPtr client) 1984642e01fSmrg{ 1994642e01fSmrg REQUEST(xDRI2DestroyDrawableReq); 2004642e01fSmrg DrawablePtr pDrawable; 2014642e01fSmrg int status; 2024642e01fSmrg 2034642e01fSmrg REQUEST_SIZE_MATCH(xDRI2DestroyDrawableReq); 2046747b715Smrg if (!validDrawable(client, stuff->drawable, DixRemoveAccess, 205f7df2e56Smrg &pDrawable, &status)) 206f7df2e56Smrg return status; 2074642e01fSmrg 2086747b715Smrg return Success; 2094642e01fSmrg} 2104642e01fSmrg 2116747b715Smrgstatic int 21252397711Smrgsend_buffers_reply(ClientPtr client, DrawablePtr pDrawable, 213f7df2e56Smrg DRI2BufferPtr * buffers, int count, int width, int height) 21452397711Smrg{ 21552397711Smrg xDRI2GetBuffersReply rep; 21652397711Smrg int skip = 0; 21752397711Smrg int i; 21852397711Smrg 2196747b715Smrg if (buffers == NULL) 220f7df2e56Smrg return BadAlloc; 2216747b715Smrg 22252397711Smrg if (pDrawable->type == DRAWABLE_WINDOW) { 223f7df2e56Smrg for (i = 0; i < count; i++) { 224f7df2e56Smrg /* Do not send the real front buffer of a window to the client. 225f7df2e56Smrg */ 226f7df2e56Smrg if (buffers[i]->attachment == DRI2BufferFrontLeft) { 227f7df2e56Smrg skip++; 228f7df2e56Smrg continue; 229f7df2e56Smrg } 230f7df2e56Smrg } 23152397711Smrg } 23252397711Smrg 233f7df2e56Smrg rep = (xDRI2GetBuffersReply) { 234f7df2e56Smrg .type = X_Reply, 235f7df2e56Smrg .sequenceNumber = client->sequence, 236f7df2e56Smrg .length = (count - skip) * sizeof(xDRI2Buffer) / 4, 237f7df2e56Smrg .width = width, 238f7df2e56Smrg .height = height, 239f7df2e56Smrg .count = count - skip 240f7df2e56Smrg }; 24152397711Smrg WriteToClient(client, sizeof(xDRI2GetBuffersReply), &rep); 24252397711Smrg 24352397711Smrg for (i = 0; i < count; i++) { 244f7df2e56Smrg xDRI2Buffer buffer; 245f7df2e56Smrg 246f7df2e56Smrg /* Do not send the real front buffer of a window to the client. 247f7df2e56Smrg */ 248f7df2e56Smrg if ((pDrawable->type == DRAWABLE_WINDOW) 249f7df2e56Smrg && (buffers[i]->attachment == DRI2BufferFrontLeft)) { 250f7df2e56Smrg continue; 251f7df2e56Smrg } 252f7df2e56Smrg 253f7df2e56Smrg buffer.attachment = buffers[i]->attachment; 254f7df2e56Smrg buffer.name = buffers[i]->name; 255f7df2e56Smrg buffer.pitch = buffers[i]->pitch; 256f7df2e56Smrg buffer.cpp = buffers[i]->cpp; 257f7df2e56Smrg buffer.flags = buffers[i]->flags; 258f7df2e56Smrg WriteToClient(client, sizeof(xDRI2Buffer), &buffer); 25952397711Smrg } 2606747b715Smrg return Success; 26152397711Smrg} 26252397711Smrg 2634642e01fSmrgstatic int 2644642e01fSmrgProcDRI2GetBuffers(ClientPtr client) 2654642e01fSmrg{ 2664642e01fSmrg REQUEST(xDRI2GetBuffersReq); 2674642e01fSmrg DrawablePtr pDrawable; 2686747b715Smrg DRI2BufferPtr *buffers; 26952397711Smrg int status, width, height, count; 2704642e01fSmrg unsigned int *attachments; 2714642e01fSmrg 272f7df2e56Smrg REQUEST_AT_LEAST_SIZE(xDRI2GetBuffersReq); 273f7df2e56Smrg /* stuff->count is a count of CARD32 attachments that follows */ 274f7df2e56Smrg if (stuff->count > (INT_MAX / sizeof(CARD32))) 2750b0d8713Smrg return BadLength; 276f7df2e56Smrg REQUEST_FIXED_SIZE(xDRI2GetBuffersReq, stuff->count * sizeof(CARD32)); 2770b0d8713Smrg 2786747b715Smrg if (!validDrawable(client, stuff->drawable, DixReadAccess | DixWriteAccess, 279f7df2e56Smrg &pDrawable, &status)) 280f7df2e56Smrg return status; 2814642e01fSmrg 2826747b715Smrg if (DRI2ThrottleClient(client, pDrawable)) 283f7df2e56Smrg return Success; 2846747b715Smrg 2854642e01fSmrg attachments = (unsigned int *) &stuff[1]; 2864642e01fSmrg buffers = DRI2GetBuffers(pDrawable, &width, &height, 287f7df2e56Smrg attachments, stuff->count, &count); 2884642e01fSmrg 2896747b715Smrg return send_buffers_reply(client, pDrawable, buffers, count, width, height); 29052397711Smrg 29152397711Smrg} 29252397711Smrg 29352397711Smrgstatic int 29452397711SmrgProcDRI2GetBuffersWithFormat(ClientPtr client) 29552397711Smrg{ 29652397711Smrg REQUEST(xDRI2GetBuffersReq); 29752397711Smrg DrawablePtr pDrawable; 2986747b715Smrg DRI2BufferPtr *buffers; 29952397711Smrg int status, width, height, count; 30052397711Smrg unsigned int *attachments; 30152397711Smrg 302f7df2e56Smrg REQUEST_AT_LEAST_SIZE(xDRI2GetBuffersReq); 303f7df2e56Smrg /* stuff->count is a count of pairs of CARD32s (attachments & formats) 304f7df2e56Smrg that follows */ 305f7df2e56Smrg if (stuff->count > (INT_MAX / (2 * sizeof(CARD32)))) 306f7df2e56Smrg return BadLength; 307f7df2e56Smrg REQUEST_FIXED_SIZE(xDRI2GetBuffersReq, 308f7df2e56Smrg stuff->count * (2 * sizeof(CARD32))); 3096747b715Smrg if (!validDrawable(client, stuff->drawable, DixReadAccess | DixWriteAccess, 310f7df2e56Smrg &pDrawable, &status)) 311f7df2e56Smrg return status; 31252397711Smrg 3136747b715Smrg if (DRI2ThrottleClient(client, pDrawable)) 314f7df2e56Smrg return Success; 3156747b715Smrg 31652397711Smrg attachments = (unsigned int *) &stuff[1]; 31752397711Smrg buffers = DRI2GetBuffersWithFormat(pDrawable, &width, &height, 318f7df2e56Smrg attachments, stuff->count, &count); 31952397711Smrg 3206747b715Smrg return send_buffers_reply(client, pDrawable, buffers, count, width, height); 3214642e01fSmrg} 3224642e01fSmrg 3234642e01fSmrgstatic int 3244642e01fSmrgProcDRI2CopyRegion(ClientPtr client) 3254642e01fSmrg{ 3264642e01fSmrg REQUEST(xDRI2CopyRegionReq); 3274642e01fSmrg xDRI2CopyRegionReply rep; 3284642e01fSmrg DrawablePtr pDrawable; 3294642e01fSmrg int status; 3304642e01fSmrg RegionPtr pRegion; 3314642e01fSmrg 3324642e01fSmrg REQUEST_SIZE_MATCH(xDRI2CopyRegionReq); 3334642e01fSmrg 3346747b715Smrg if (!validDrawable(client, stuff->drawable, DixWriteAccess, 335f7df2e56Smrg &pDrawable, &status)) 336f7df2e56Smrg return status; 3374642e01fSmrg 3384642e01fSmrg VERIFY_REGION(pRegion, stuff->region, client, DixReadAccess); 3394642e01fSmrg 3404642e01fSmrg status = DRI2CopyRegion(pDrawable, pRegion, stuff->dest, stuff->src); 3414642e01fSmrg if (status != Success) 342f7df2e56Smrg return status; 3434642e01fSmrg 3444642e01fSmrg /* CopyRegion needs to be a round trip to make sure the X server 3454642e01fSmrg * queues the swap buffer rendering commands before the DRI client 3464642e01fSmrg * continues rendering. The reply has a bitmask to signal the 3475a112b11Smrg * presence of optional return values as well, but we're not using 3484642e01fSmrg * that yet. 3494642e01fSmrg */ 3504642e01fSmrg 351f7df2e56Smrg rep = (xDRI2CopyRegionReply) { 352f7df2e56Smrg .type = X_Reply, 353f7df2e56Smrg .sequenceNumber = client->sequence, 354f7df2e56Smrg .length = 0 355f7df2e56Smrg }; 3564642e01fSmrg 3574642e01fSmrg WriteToClient(client, sizeof(xDRI2CopyRegionReply), &rep); 3584642e01fSmrg 3596747b715Smrg return Success; 3606747b715Smrg} 3616747b715Smrg 3626747b715Smrgstatic void 363f7df2e56Smrgload_swap_reply(xDRI2SwapBuffersReply * rep, CARD64 sbc) 3646747b715Smrg{ 3656747b715Smrg rep->swap_hi = sbc >> 32; 3666747b715Smrg rep->swap_lo = sbc & 0xffffffff; 3676747b715Smrg} 3686747b715Smrg 3696747b715Smrgstatic CARD64 3706747b715Smrgvals_to_card64(CARD32 lo, CARD32 hi) 3716747b715Smrg{ 372f7df2e56Smrg return (CARD64) hi << 32 | lo; 3736747b715Smrg} 3746747b715Smrg 3756747b715Smrgstatic void 3766747b715SmrgDRI2SwapEvent(ClientPtr client, void *data, int type, CARD64 ust, CARD64 msc, 377f7df2e56Smrg CARD32 sbc) 3786747b715Smrg{ 3796747b715Smrg DrawablePtr pDrawable = data; 380f7df2e56Smrg xDRI2BufferSwapComplete2 event = { 381f7df2e56Smrg .type = DRI2EventBase + DRI2_BufferSwapComplete, 382f7df2e56Smrg .event_type = type, 383f7df2e56Smrg .drawable = pDrawable->id, 384f7df2e56Smrg .ust_hi = (CARD64) ust >> 32, 385f7df2e56Smrg .ust_lo = ust & 0xffffffff, 386f7df2e56Smrg .msc_hi = (CARD64) msc >> 32, 387f7df2e56Smrg .msc_lo = msc & 0xffffffff, 388f7df2e56Smrg .sbc = sbc 389f7df2e56Smrg }; 390f7df2e56Smrg 391f7df2e56Smrg WriteEventsToClient(client, 1, (xEvent *) &event); 3926747b715Smrg} 3936747b715Smrg 3946747b715Smrgstatic int 3956747b715SmrgProcDRI2SwapBuffers(ClientPtr client) 3966747b715Smrg{ 3976747b715Smrg REQUEST(xDRI2SwapBuffersReq); 398f7df2e56Smrg xDRI2SwapBuffersReply rep = { 399f7df2e56Smrg .type = X_Reply, 400f7df2e56Smrg .sequenceNumber = client->sequence, 401f7df2e56Smrg .length = 0 402f7df2e56Smrg }; 4036747b715Smrg DrawablePtr pDrawable; 4046747b715Smrg CARD64 target_msc, divisor, remainder, swap_target; 4056747b715Smrg int status; 4066747b715Smrg 4076747b715Smrg REQUEST_SIZE_MATCH(xDRI2SwapBuffersReq); 4086747b715Smrg 4096747b715Smrg if (!validDrawable(client, stuff->drawable, 410f7df2e56Smrg DixReadAccess | DixWriteAccess, &pDrawable, &status)) 411f7df2e56Smrg return status; 4126747b715Smrg 4136747b715Smrg /* 4146747b715Smrg * Ensures an out of control client can't exhaust our swap queue, and 4156747b715Smrg * also orders swaps. 4166747b715Smrg */ 4176747b715Smrg if (DRI2ThrottleClient(client, pDrawable)) 418f7df2e56Smrg return Success; 4196747b715Smrg 4206747b715Smrg target_msc = vals_to_card64(stuff->target_msc_lo, stuff->target_msc_hi); 4216747b715Smrg divisor = vals_to_card64(stuff->divisor_lo, stuff->divisor_hi); 4226747b715Smrg remainder = vals_to_card64(stuff->remainder_lo, stuff->remainder_hi); 4236747b715Smrg 4246747b715Smrg status = DRI2SwapBuffers(client, pDrawable, target_msc, divisor, remainder, 425f7df2e56Smrg &swap_target, DRI2SwapEvent, pDrawable); 4266747b715Smrg if (status != Success) 427f7df2e56Smrg return BadDrawable; 4286747b715Smrg 4296747b715Smrg load_swap_reply(&rep, swap_target); 4306747b715Smrg 4316747b715Smrg WriteToClient(client, sizeof(xDRI2SwapBuffersReply), &rep); 4326747b715Smrg 4336747b715Smrg return Success; 4346747b715Smrg} 4356747b715Smrg 4366747b715Smrgstatic void 437f7df2e56Smrgload_msc_reply(xDRI2MSCReply * rep, CARD64 ust, CARD64 msc, CARD64 sbc) 4386747b715Smrg{ 4396747b715Smrg rep->ust_hi = ust >> 32; 4406747b715Smrg rep->ust_lo = ust & 0xffffffff; 4416747b715Smrg rep->msc_hi = msc >> 32; 4426747b715Smrg rep->msc_lo = msc & 0xffffffff; 4436747b715Smrg rep->sbc_hi = sbc >> 32; 4446747b715Smrg rep->sbc_lo = sbc & 0xffffffff; 4456747b715Smrg} 4466747b715Smrg 4476747b715Smrgstatic int 4486747b715SmrgProcDRI2GetMSC(ClientPtr client) 4496747b715Smrg{ 4506747b715Smrg REQUEST(xDRI2GetMSCReq); 451f7df2e56Smrg xDRI2MSCReply rep = { 452f7df2e56Smrg .type = X_Reply, 453f7df2e56Smrg .sequenceNumber = client->sequence, 454f7df2e56Smrg .length = 0 455f7df2e56Smrg }; 4566747b715Smrg DrawablePtr pDrawable; 4576747b715Smrg CARD64 ust, msc, sbc; 4586747b715Smrg int status; 4596747b715Smrg 4606747b715Smrg REQUEST_SIZE_MATCH(xDRI2GetMSCReq); 4616747b715Smrg 4626747b715Smrg if (!validDrawable(client, stuff->drawable, DixReadAccess, &pDrawable, 463f7df2e56Smrg &status)) 464f7df2e56Smrg return status; 4656747b715Smrg 4666747b715Smrg status = DRI2GetMSC(pDrawable, &ust, &msc, &sbc); 4676747b715Smrg if (status != Success) 468f7df2e56Smrg return status; 4696747b715Smrg 4706747b715Smrg load_msc_reply(&rep, ust, msc, sbc); 4716747b715Smrg 4726747b715Smrg WriteToClient(client, sizeof(xDRI2MSCReply), &rep); 4736747b715Smrg 4746747b715Smrg return Success; 4756747b715Smrg} 4766747b715Smrg 4776747b715Smrgstatic int 4786747b715SmrgProcDRI2WaitMSC(ClientPtr client) 4796747b715Smrg{ 4806747b715Smrg REQUEST(xDRI2WaitMSCReq); 4816747b715Smrg DrawablePtr pDrawable; 4826747b715Smrg CARD64 target, divisor, remainder; 4836747b715Smrg int status; 4846747b715Smrg 4856747b715Smrg /* FIXME: in restart case, client may be gone at this point */ 4866747b715Smrg 4876747b715Smrg REQUEST_SIZE_MATCH(xDRI2WaitMSCReq); 4886747b715Smrg 4896747b715Smrg if (!validDrawable(client, stuff->drawable, DixReadAccess, &pDrawable, 490f7df2e56Smrg &status)) 491f7df2e56Smrg return status; 4926747b715Smrg 4936747b715Smrg target = vals_to_card64(stuff->target_msc_lo, stuff->target_msc_hi); 4946747b715Smrg divisor = vals_to_card64(stuff->divisor_lo, stuff->divisor_hi); 4956747b715Smrg remainder = vals_to_card64(stuff->remainder_lo, stuff->remainder_hi); 4966747b715Smrg 4976747b715Smrg status = DRI2WaitMSC(client, pDrawable, target, divisor, remainder); 4986747b715Smrg if (status != Success) 499f7df2e56Smrg return status; 5006747b715Smrg 5016747b715Smrg return Success; 5026747b715Smrg} 5036747b715Smrg 5046747b715Smrgint 5056747b715SmrgProcDRI2WaitMSCReply(ClientPtr client, CARD64 ust, CARD64 msc, CARD64 sbc) 5066747b715Smrg{ 507f7df2e56Smrg xDRI2MSCReply rep = { 508f7df2e56Smrg .type = X_Reply, 509f7df2e56Smrg .sequenceNumber = client->sequence, 510f7df2e56Smrg .length = 0 511f7df2e56Smrg }; 5126747b715Smrg 5136747b715Smrg load_msc_reply(&rep, ust, msc, sbc); 5146747b715Smrg 5156747b715Smrg WriteToClient(client, sizeof(xDRI2MSCReply), &rep); 5166747b715Smrg 5176747b715Smrg return Success; 5186747b715Smrg} 5196747b715Smrg 5206747b715Smrgstatic int 5216747b715SmrgProcDRI2SwapInterval(ClientPtr client) 5226747b715Smrg{ 5236747b715Smrg REQUEST(xDRI2SwapIntervalReq); 5246747b715Smrg DrawablePtr pDrawable; 5256747b715Smrg int status; 5266747b715Smrg 5276747b715Smrg /* FIXME: in restart case, client may be gone at this point */ 5286747b715Smrg 5296747b715Smrg REQUEST_SIZE_MATCH(xDRI2SwapIntervalReq); 5306747b715Smrg 5316747b715Smrg if (!validDrawable(client, stuff->drawable, DixReadAccess | DixWriteAccess, 532f7df2e56Smrg &pDrawable, &status)) 533f7df2e56Smrg return status; 5346747b715Smrg 5356747b715Smrg DRI2SwapInterval(pDrawable, stuff->interval); 5366747b715Smrg 5376747b715Smrg return Success; 5386747b715Smrg} 5396747b715Smrg 5406747b715Smrgstatic int 5416747b715SmrgProcDRI2WaitSBC(ClientPtr client) 5426747b715Smrg{ 5436747b715Smrg REQUEST(xDRI2WaitSBCReq); 5446747b715Smrg DrawablePtr pDrawable; 5456747b715Smrg CARD64 target; 5466747b715Smrg int status; 5476747b715Smrg 5486747b715Smrg REQUEST_SIZE_MATCH(xDRI2WaitSBCReq); 5496747b715Smrg 5506747b715Smrg if (!validDrawable(client, stuff->drawable, DixReadAccess, &pDrawable, 551f7df2e56Smrg &status)) 552f7df2e56Smrg return status; 5536747b715Smrg 5546747b715Smrg target = vals_to_card64(stuff->target_sbc_lo, stuff->target_sbc_hi); 5556747b715Smrg status = DRI2WaitSBC(client, pDrawable, target); 5566747b715Smrg 5576747b715Smrg return status; 5584642e01fSmrg} 5594642e01fSmrg 5604642e01fSmrgstatic int 561f7df2e56SmrgProcDRI2GetParam(ClientPtr client) 562f7df2e56Smrg{ 563f7df2e56Smrg REQUEST(xDRI2GetParamReq); 564f7df2e56Smrg xDRI2GetParamReply rep = { 565f7df2e56Smrg .type = X_Reply, 566f7df2e56Smrg .sequenceNumber = client->sequence, 567f7df2e56Smrg .length = 0 568f7df2e56Smrg }; 569f7df2e56Smrg DrawablePtr pDrawable; 570f7df2e56Smrg CARD64 value; 571f7df2e56Smrg int status; 572f7df2e56Smrg 573f7df2e56Smrg REQUEST_SIZE_MATCH(xDRI2GetParamReq); 574f7df2e56Smrg 575f7df2e56Smrg if (!validDrawable(client, stuff->drawable, DixReadAccess, 576f7df2e56Smrg &pDrawable, &status)) 577f7df2e56Smrg return status; 578f7df2e56Smrg 579f7df2e56Smrg status = DRI2GetParam(client, pDrawable, stuff->param, 580f7df2e56Smrg &rep.is_param_recognized, &value); 581f7df2e56Smrg rep.value_hi = value >> 32; 582f7df2e56Smrg rep.value_lo = value & 0xffffffff; 583f7df2e56Smrg 584f7df2e56Smrg if (status != Success) 585f7df2e56Smrg return status; 586f7df2e56Smrg 587f7df2e56Smrg WriteToClient(client, sizeof(xDRI2GetParamReply), &rep); 588f7df2e56Smrg 589f7df2e56Smrg return status; 590f7df2e56Smrg} 591f7df2e56Smrg 592f7df2e56Smrgstatic int 593f7df2e56SmrgProcDRI2Dispatch(ClientPtr client) 5944642e01fSmrg{ 5954642e01fSmrg REQUEST(xReq); 596f7df2e56Smrg 5974642e01fSmrg switch (stuff->data) { 5984642e01fSmrg case X_DRI2QueryVersion: 599f7df2e56Smrg return ProcDRI2QueryVersion(client); 6004642e01fSmrg } 6014642e01fSmrg 602f7df2e56Smrg if (!client->local) 603f7df2e56Smrg return BadRequest; 6044642e01fSmrg 6054642e01fSmrg switch (stuff->data) { 6064642e01fSmrg case X_DRI2Connect: 607f7df2e56Smrg return ProcDRI2Connect(client); 6084642e01fSmrg case X_DRI2Authenticate: 609f7df2e56Smrg return ProcDRI2Authenticate(client); 6104642e01fSmrg case X_DRI2CreateDrawable: 611f7df2e56Smrg return ProcDRI2CreateDrawable(client); 6124642e01fSmrg case X_DRI2DestroyDrawable: 613f7df2e56Smrg return ProcDRI2DestroyDrawable(client); 6144642e01fSmrg case X_DRI2GetBuffers: 615f7df2e56Smrg return ProcDRI2GetBuffers(client); 6164642e01fSmrg case X_DRI2CopyRegion: 617f7df2e56Smrg return ProcDRI2CopyRegion(client); 61852397711Smrg case X_DRI2GetBuffersWithFormat: 619f7df2e56Smrg return ProcDRI2GetBuffersWithFormat(client); 6206747b715Smrg case X_DRI2SwapBuffers: 621f7df2e56Smrg return ProcDRI2SwapBuffers(client); 6226747b715Smrg case X_DRI2GetMSC: 623f7df2e56Smrg return ProcDRI2GetMSC(client); 6246747b715Smrg case X_DRI2WaitMSC: 625f7df2e56Smrg return ProcDRI2WaitMSC(client); 6266747b715Smrg case X_DRI2WaitSBC: 627f7df2e56Smrg return ProcDRI2WaitSBC(client); 6286747b715Smrg case X_DRI2SwapInterval: 629f7df2e56Smrg return ProcDRI2SwapInterval(client); 630f7df2e56Smrg case X_DRI2GetParam: 631f7df2e56Smrg return ProcDRI2GetParam(client); 6324642e01fSmrg default: 633f7df2e56Smrg return BadRequest; 6344642e01fSmrg } 6354642e01fSmrg} 6364642e01fSmrg 6377e31ba66Smrgstatic int _X_COLD 6384642e01fSmrgSProcDRI2Connect(ClientPtr client) 6394642e01fSmrg{ 6404642e01fSmrg REQUEST(xDRI2ConnectReq); 641f7df2e56Smrg xDRI2ConnectReply rep = { 642f7df2e56Smrg .type = X_Reply, 643f7df2e56Smrg .sequenceNumber = client->sequence, 644f7df2e56Smrg .length = 0, 645f7df2e56Smrg .driverNameLength = 0, 646f7df2e56Smrg .deviceNameLength = 0 647f7df2e56Smrg }; 6484642e01fSmrg 6494642e01fSmrg /* If the client is swapped, it's not local. Talk to the hand. */ 6504642e01fSmrg 651f7df2e56Smrg swaps(&stuff->length); 6524642e01fSmrg if (sizeof(*stuff) / 4 != client->req_len) 653f7df2e56Smrg return BadLength; 6544642e01fSmrg 655f7df2e56Smrg swaps(&rep.sequenceNumber); 656f7df2e56Smrg 657f7df2e56Smrg WriteToClient(client, sizeof(xDRI2ConnectReply), &rep); 6584642e01fSmrg 6596747b715Smrg return Success; 6604642e01fSmrg} 6614642e01fSmrg 6627e31ba66Smrgstatic int _X_COLD 663f7df2e56SmrgSProcDRI2Dispatch(ClientPtr client) 6644642e01fSmrg{ 6654642e01fSmrg REQUEST(xReq); 6664642e01fSmrg 6674642e01fSmrg /* 6684642e01fSmrg * Only local clients are allowed DRI access, but remote clients 6694642e01fSmrg * still need these requests to find out cleanly. 6704642e01fSmrg */ 671f7df2e56Smrg switch (stuff->data) { 6724642e01fSmrg case X_DRI2QueryVersion: 673f7df2e56Smrg return ProcDRI2QueryVersion(client); 6744642e01fSmrg case X_DRI2Connect: 675f7df2e56Smrg return SProcDRI2Connect(client); 6764642e01fSmrg default: 677f7df2e56Smrg return BadRequest; 6784642e01fSmrg } 6794642e01fSmrg} 6804642e01fSmrg 681f7df2e56Smrgvoid 6824642e01fSmrgDRI2ExtensionInit(void) 6834642e01fSmrg{ 684f7df2e56Smrg ExtensionEntry *dri2Extension; 685f7df2e56Smrg 686f7df2e56Smrg#ifdef PANORAMIX 687f7df2e56Smrg if (!noPanoramiXExtension) 688f7df2e56Smrg return; 689f7df2e56Smrg#endif 690f7df2e56Smrg 6914642e01fSmrg dri2Extension = AddExtension(DRI2_NAME, 692f7df2e56Smrg DRI2NumberEvents, 693f7df2e56Smrg DRI2NumberErrors, 694f7df2e56Smrg ProcDRI2Dispatch, 695f7df2e56Smrg SProcDRI2Dispatch, NULL, StandardMinorOpcode); 6964642e01fSmrg 6976747b715Smrg DRI2EventBase = dri2Extension->eventBase; 698475c125cSmrg 699475c125cSmrg DRI2ModuleSetup(); 7004642e01fSmrg} 701