1706f2543Smrg/* 2706f2543Smrg * Copyright © 2008 Red Hat, Inc. 3706f2543Smrg * 4706f2543Smrg * Permission is hereby granted, free of charge, to any person obtaining a 5706f2543Smrg * copy of this software and associated documentation files (the "Soft- 6706f2543Smrg * ware"), to deal in the Software without restriction, including without 7706f2543Smrg * limitation the rights to use, copy, modify, merge, publish, distribute, 8706f2543Smrg * and/or sell copies of the Software, and to permit persons to whom the 9706f2543Smrg * Software is furnished to do so, provided that the above copyright 10706f2543Smrg * notice(s) and this permission notice appear in all copies of the Soft- 11706f2543Smrg * ware and that both the above copyright notice(s) and this permission 12706f2543Smrg * notice appear in supporting documentation. 13706f2543Smrg * 14706f2543Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15706f2543Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- 16706f2543Smrg * ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY 17706f2543Smrg * RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN 18706f2543Smrg * THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSE- 19706f2543Smrg * QUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 20706f2543Smrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 21706f2543Smrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFOR- 22706f2543Smrg * MANCE OF THIS SOFTWARE. 23706f2543Smrg * 24706f2543Smrg * Except as contained in this notice, the name of a copyright holder shall 25706f2543Smrg * not be used in advertising or otherwise to promote the sale, use or 26706f2543Smrg * other dealings in this Software without prior written authorization of 27706f2543Smrg * the copyright holder. 28706f2543Smrg * 29706f2543Smrg * Authors: 30706f2543Smrg * Kristian Høgsberg (krh@redhat.com) 31706f2543Smrg */ 32706f2543Smrg 33706f2543Smrg#ifdef HAVE_XORG_CONFIG_H 34706f2543Smrg#include <xorg-config.h> 35706f2543Smrg#endif 36706f2543Smrg 37706f2543Smrg#include <X11/X.h> 38706f2543Smrg#include <X11/Xproto.h> 39706f2543Smrg#include <X11/extensions/dri2proto.h> 40706f2543Smrg#include <X11/extensions/xfixeswire.h> 41706f2543Smrg#include "dixstruct.h" 42706f2543Smrg#include "scrnintstr.h" 43706f2543Smrg#include "pixmapstr.h" 44706f2543Smrg#include "extnsionst.h" 45706f2543Smrg#include "xfixes.h" 46706f2543Smrg#include "dri2.h" 47706f2543Smrg#include "protocol-versions.h" 48706f2543Smrg 49706f2543Smrg/* The only xf86 include */ 50706f2543Smrg#include "xf86Module.h" 51706f2543Smrg 52706f2543Smrgstatic ExtensionEntry *dri2Extension; 53706f2543Smrgextern Bool DRI2ModuleSetup(void); 54706f2543Smrg 55706f2543Smrgstatic Bool 56706f2543SmrgvalidDrawable(ClientPtr client, XID drawable, Mask access_mode, 57706f2543Smrg DrawablePtr *pDrawable, int *status) 58706f2543Smrg{ 59706f2543Smrg *status = dixLookupDrawable(pDrawable, drawable, client, 60706f2543Smrg M_DRAWABLE_WINDOW | M_DRAWABLE_PIXMAP, 61706f2543Smrg access_mode); 62706f2543Smrg if (*status != Success) { 63706f2543Smrg client->errorValue = drawable; 64706f2543Smrg return FALSE; 65706f2543Smrg } 66706f2543Smrg 67706f2543Smrg return TRUE; 68706f2543Smrg} 69706f2543Smrg 70706f2543Smrgstatic int 71706f2543SmrgProcDRI2QueryVersion(ClientPtr client) 72706f2543Smrg{ 73706f2543Smrg REQUEST(xDRI2QueryVersionReq); 74706f2543Smrg xDRI2QueryVersionReply rep; 75706f2543Smrg int n; 76706f2543Smrg 77706f2543Smrg if (client->swapped) 78706f2543Smrg swaps(&stuff->length, n); 79706f2543Smrg 80706f2543Smrg REQUEST_SIZE_MATCH(xDRI2QueryVersionReq); 81706f2543Smrg rep.type = X_Reply; 82706f2543Smrg rep.length = 0; 83706f2543Smrg rep.sequenceNumber = client->sequence; 84706f2543Smrg rep.majorVersion = dri2_major; 85706f2543Smrg rep.minorVersion = dri2_minor; 86706f2543Smrg 87706f2543Smrg if (client->swapped) { 88706f2543Smrg swaps(&rep.sequenceNumber, n); 89706f2543Smrg swapl(&rep.length, n); 90706f2543Smrg swapl(&rep.majorVersion, n); 91706f2543Smrg swapl(&rep.minorVersion, n); 92706f2543Smrg } 93706f2543Smrg 94706f2543Smrg WriteToClient(client, sizeof(xDRI2QueryVersionReply), &rep); 95706f2543Smrg 96706f2543Smrg return Success; 97706f2543Smrg} 98706f2543Smrg 99706f2543Smrgstatic int 100706f2543SmrgProcDRI2Connect(ClientPtr client) 101706f2543Smrg{ 102706f2543Smrg REQUEST(xDRI2ConnectReq); 103706f2543Smrg xDRI2ConnectReply rep; 104706f2543Smrg DrawablePtr pDraw; 105706f2543Smrg int fd, status; 106706f2543Smrg const char *driverName; 107706f2543Smrg const char *deviceName; 108706f2543Smrg 109706f2543Smrg REQUEST_SIZE_MATCH(xDRI2ConnectReq); 110706f2543Smrg if (!validDrawable(client, stuff->window, DixGetAttrAccess, 111706f2543Smrg &pDraw, &status)) 112706f2543Smrg return status; 113706f2543Smrg 114706f2543Smrg rep.type = X_Reply; 115706f2543Smrg rep.length = 0; 116706f2543Smrg rep.sequenceNumber = client->sequence; 117706f2543Smrg rep.driverNameLength = 0; 118706f2543Smrg rep.deviceNameLength = 0; 119706f2543Smrg 120706f2543Smrg if (!DRI2Connect(pDraw->pScreen, 121706f2543Smrg stuff->driverType, &fd, &driverName, &deviceName)) 122706f2543Smrg goto fail; 123706f2543Smrg 124706f2543Smrg rep.driverNameLength = strlen(driverName); 125706f2543Smrg rep.deviceNameLength = strlen(deviceName); 126706f2543Smrg rep.length = (rep.driverNameLength + 3) / 4 + 127706f2543Smrg (rep.deviceNameLength + 3) / 4; 128706f2543Smrg 129706f2543Smrg fail: 130706f2543Smrg WriteToClient(client, sizeof(xDRI2ConnectReply), &rep); 131706f2543Smrg WriteToClient(client, rep.driverNameLength, driverName); 132706f2543Smrg WriteToClient(client, rep.deviceNameLength, deviceName); 133706f2543Smrg 134706f2543Smrg return Success; 135706f2543Smrg} 136706f2543Smrg 137706f2543Smrgstatic int 138706f2543SmrgProcDRI2Authenticate(ClientPtr client) 139706f2543Smrg{ 140706f2543Smrg REQUEST(xDRI2AuthenticateReq); 141706f2543Smrg xDRI2AuthenticateReply rep; 142706f2543Smrg DrawablePtr pDraw; 143706f2543Smrg int status; 144706f2543Smrg 145706f2543Smrg REQUEST_SIZE_MATCH(xDRI2AuthenticateReq); 146706f2543Smrg if (!validDrawable(client, stuff->window, DixGetAttrAccess, 147706f2543Smrg &pDraw, &status)) 148706f2543Smrg return status; 149706f2543Smrg 150706f2543Smrg rep.type = X_Reply; 151706f2543Smrg rep.sequenceNumber = client->sequence; 152706f2543Smrg rep.length = 0; 153706f2543Smrg rep.authenticated = DRI2Authenticate(pDraw->pScreen, stuff->magic); 154706f2543Smrg WriteToClient(client, sizeof(xDRI2AuthenticateReply), &rep); 155706f2543Smrg 156706f2543Smrg return Success; 157706f2543Smrg} 158706f2543Smrg 159706f2543Smrgstatic void 160706f2543SmrgDRI2InvalidateBuffersEvent(DrawablePtr pDraw, void *priv) 161706f2543Smrg{ 162706f2543Smrg xDRI2InvalidateBuffers event; 163706f2543Smrg ClientPtr client = priv; 164706f2543Smrg 165706f2543Smrg event.type = DRI2EventBase + DRI2_InvalidateBuffers; 166706f2543Smrg event.drawable = pDraw->id; 167706f2543Smrg 168706f2543Smrg WriteEventsToClient(client, 1, (xEvent *)&event); 169706f2543Smrg} 170706f2543Smrg 171706f2543Smrgstatic int 172706f2543SmrgProcDRI2CreateDrawable(ClientPtr client) 173706f2543Smrg{ 174706f2543Smrg REQUEST(xDRI2CreateDrawableReq); 175706f2543Smrg DrawablePtr pDrawable; 176706f2543Smrg int status; 177706f2543Smrg 178706f2543Smrg REQUEST_SIZE_MATCH(xDRI2CreateDrawableReq); 179706f2543Smrg 180706f2543Smrg if (!validDrawable(client, stuff->drawable, DixAddAccess, 181706f2543Smrg &pDrawable, &status)) 182706f2543Smrg return status; 183706f2543Smrg 184706f2543Smrg status = DRI2CreateDrawable(client, pDrawable, stuff->drawable, 185706f2543Smrg DRI2InvalidateBuffersEvent, client); 186706f2543Smrg if (status != Success) 187706f2543Smrg return status; 188706f2543Smrg 189706f2543Smrg return Success; 190706f2543Smrg} 191706f2543Smrg 192706f2543Smrgstatic int 193706f2543SmrgProcDRI2DestroyDrawable(ClientPtr client) 194706f2543Smrg{ 195706f2543Smrg REQUEST(xDRI2DestroyDrawableReq); 196706f2543Smrg DrawablePtr pDrawable; 197706f2543Smrg int status; 198706f2543Smrg 199706f2543Smrg REQUEST_SIZE_MATCH(xDRI2DestroyDrawableReq); 200706f2543Smrg if (!validDrawable(client, stuff->drawable, DixRemoveAccess, 201706f2543Smrg &pDrawable, &status)) 202706f2543Smrg return status; 203706f2543Smrg 204706f2543Smrg return Success; 205706f2543Smrg} 206706f2543Smrg 207706f2543Smrg 208706f2543Smrgstatic int 209706f2543Smrgsend_buffers_reply(ClientPtr client, DrawablePtr pDrawable, 210706f2543Smrg DRI2BufferPtr *buffers, int count, int width, int height) 211706f2543Smrg{ 212706f2543Smrg xDRI2GetBuffersReply rep; 213706f2543Smrg int skip = 0; 214706f2543Smrg int i; 215706f2543Smrg 216706f2543Smrg if (buffers == NULL) 217706f2543Smrg return BadAlloc; 218706f2543Smrg 219706f2543Smrg if (pDrawable->type == DRAWABLE_WINDOW) { 220706f2543Smrg for (i = 0; i < count; i++) { 221706f2543Smrg /* Do not send the real front buffer of a window to the client. 222706f2543Smrg */ 223706f2543Smrg if (buffers[i]->attachment == DRI2BufferFrontLeft) { 224706f2543Smrg skip++; 225706f2543Smrg continue; 226706f2543Smrg } 227706f2543Smrg } 228706f2543Smrg } 229706f2543Smrg 230706f2543Smrg rep.type = X_Reply; 231706f2543Smrg rep.length = (count - skip) * sizeof(xDRI2Buffer) / 4; 232706f2543Smrg rep.sequenceNumber = client->sequence; 233706f2543Smrg rep.width = width; 234706f2543Smrg rep.height = height; 235706f2543Smrg rep.count = count - skip; 236706f2543Smrg WriteToClient(client, sizeof(xDRI2GetBuffersReply), &rep); 237706f2543Smrg 238706f2543Smrg for (i = 0; i < count; i++) { 239706f2543Smrg xDRI2Buffer buffer; 240706f2543Smrg 241706f2543Smrg /* Do not send the real front buffer of a window to the client. 242706f2543Smrg */ 243706f2543Smrg if ((pDrawable->type == DRAWABLE_WINDOW) 244706f2543Smrg && (buffers[i]->attachment == DRI2BufferFrontLeft)) { 245706f2543Smrg continue; 246706f2543Smrg } 247706f2543Smrg 248706f2543Smrg buffer.attachment = buffers[i]->attachment; 249706f2543Smrg buffer.name = buffers[i]->name; 250706f2543Smrg buffer.pitch = buffers[i]->pitch; 251706f2543Smrg buffer.cpp = buffers[i]->cpp; 252706f2543Smrg buffer.flags = buffers[i]->flags; 253706f2543Smrg WriteToClient(client, sizeof(xDRI2Buffer), &buffer); 254706f2543Smrg } 255706f2543Smrg return Success; 256706f2543Smrg} 257706f2543Smrg 258706f2543Smrg 259706f2543Smrgstatic int 260706f2543SmrgProcDRI2GetBuffers(ClientPtr client) 261706f2543Smrg{ 262706f2543Smrg REQUEST(xDRI2GetBuffersReq); 263706f2543Smrg DrawablePtr pDrawable; 264706f2543Smrg DRI2BufferPtr *buffers; 265706f2543Smrg int status, width, height, count; 266706f2543Smrg unsigned int *attachments; 267706f2543Smrg 268706f2543Smrg REQUEST_FIXED_SIZE(xDRI2GetBuffersReq, stuff->count * 4); 269706f2543Smrg if (stuff->count > (INT_MAX / 4)) 270706f2543Smrg return BadLength; 271706f2543Smrg 272706f2543Smrg if (!validDrawable(client, stuff->drawable, DixReadAccess | DixWriteAccess, 273706f2543Smrg &pDrawable, &status)) 274706f2543Smrg return status; 275706f2543Smrg 276706f2543Smrg if (DRI2ThrottleClient(client, pDrawable)) 277706f2543Smrg return Success; 278706f2543Smrg 279706f2543Smrg attachments = (unsigned int *) &stuff[1]; 280706f2543Smrg buffers = DRI2GetBuffers(pDrawable, &width, &height, 281706f2543Smrg attachments, stuff->count, &count); 282706f2543Smrg 283706f2543Smrg 284706f2543Smrg return send_buffers_reply(client, pDrawable, buffers, count, width, height); 285706f2543Smrg 286706f2543Smrg} 287706f2543Smrg 288706f2543Smrgstatic int 289706f2543SmrgProcDRI2GetBuffersWithFormat(ClientPtr client) 290706f2543Smrg{ 291706f2543Smrg REQUEST(xDRI2GetBuffersReq); 292706f2543Smrg DrawablePtr pDrawable; 293706f2543Smrg DRI2BufferPtr *buffers; 294706f2543Smrg int status, width, height, count; 295706f2543Smrg unsigned int *attachments; 296706f2543Smrg 297706f2543Smrg REQUEST_FIXED_SIZE(xDRI2GetBuffersReq, stuff->count * (2 * 4)); 298706f2543Smrg if (!validDrawable(client, stuff->drawable, DixReadAccess | DixWriteAccess, 299706f2543Smrg &pDrawable, &status)) 300706f2543Smrg return status; 301706f2543Smrg 302706f2543Smrg if (DRI2ThrottleClient(client, pDrawable)) 303706f2543Smrg return Success; 304706f2543Smrg 305706f2543Smrg attachments = (unsigned int *) &stuff[1]; 306706f2543Smrg buffers = DRI2GetBuffersWithFormat(pDrawable, &width, &height, 307706f2543Smrg attachments, stuff->count, &count); 308706f2543Smrg 309706f2543Smrg return send_buffers_reply(client, pDrawable, buffers, count, width, height); 310706f2543Smrg} 311706f2543Smrg 312706f2543Smrgstatic int 313706f2543SmrgProcDRI2CopyRegion(ClientPtr client) 314706f2543Smrg{ 315706f2543Smrg REQUEST(xDRI2CopyRegionReq); 316706f2543Smrg xDRI2CopyRegionReply rep; 317706f2543Smrg DrawablePtr pDrawable; 318706f2543Smrg int status; 319706f2543Smrg RegionPtr pRegion; 320706f2543Smrg 321706f2543Smrg REQUEST_SIZE_MATCH(xDRI2CopyRegionReq); 322706f2543Smrg 323706f2543Smrg if (!validDrawable(client, stuff->drawable, DixWriteAccess, 324706f2543Smrg &pDrawable, &status)) 325706f2543Smrg return status; 326706f2543Smrg 327706f2543Smrg VERIFY_REGION(pRegion, stuff->region, client, DixReadAccess); 328706f2543Smrg 329706f2543Smrg status = DRI2CopyRegion(pDrawable, pRegion, stuff->dest, stuff->src); 330706f2543Smrg if (status != Success) 331706f2543Smrg return status; 332706f2543Smrg 333706f2543Smrg /* CopyRegion needs to be a round trip to make sure the X server 334706f2543Smrg * queues the swap buffer rendering commands before the DRI client 335706f2543Smrg * continues rendering. The reply has a bitmask to signal the 336706f2543Smrg * presense of optional return values as well, but we're not using 337706f2543Smrg * that yet. 338706f2543Smrg */ 339706f2543Smrg 340706f2543Smrg rep.type = X_Reply; 341706f2543Smrg rep.length = 0; 342706f2543Smrg rep.sequenceNumber = client->sequence; 343706f2543Smrg 344706f2543Smrg WriteToClient(client, sizeof(xDRI2CopyRegionReply), &rep); 345706f2543Smrg 346706f2543Smrg return Success; 347706f2543Smrg} 348706f2543Smrg 349706f2543Smrgstatic void 350706f2543Smrgload_swap_reply(xDRI2SwapBuffersReply *rep, CARD64 sbc) 351706f2543Smrg{ 352706f2543Smrg rep->swap_hi = sbc >> 32; 353706f2543Smrg rep->swap_lo = sbc & 0xffffffff; 354706f2543Smrg} 355706f2543Smrg 356706f2543Smrgstatic CARD64 357706f2543Smrgvals_to_card64(CARD32 lo, CARD32 hi) 358706f2543Smrg{ 359706f2543Smrg return (CARD64)hi << 32 | lo; 360706f2543Smrg} 361706f2543Smrg 362706f2543Smrgstatic void 363706f2543SmrgDRI2SwapEvent(ClientPtr client, void *data, int type, CARD64 ust, CARD64 msc, 364706f2543Smrg CARD64 sbc) 365706f2543Smrg{ 366706f2543Smrg xDRI2BufferSwapComplete event; 367706f2543Smrg DrawablePtr pDrawable = data; 368706f2543Smrg 369706f2543Smrg event.type = DRI2EventBase + DRI2_BufferSwapComplete; 370706f2543Smrg event.event_type = type; 371706f2543Smrg event.drawable = pDrawable->id; 372706f2543Smrg event.ust_hi = (CARD64)ust >> 32; 373706f2543Smrg event.ust_lo = ust & 0xffffffff; 374706f2543Smrg event.msc_hi = (CARD64)msc >> 32; 375706f2543Smrg event.msc_lo = msc & 0xffffffff; 376706f2543Smrg event.sbc_hi = (CARD64)sbc >> 32; 377706f2543Smrg event.sbc_lo = sbc & 0xffffffff; 378706f2543Smrg 379706f2543Smrg WriteEventsToClient(client, 1, (xEvent *)&event); 380706f2543Smrg} 381706f2543Smrg 382706f2543Smrgstatic int 383706f2543SmrgProcDRI2SwapBuffers(ClientPtr client) 384706f2543Smrg{ 385706f2543Smrg REQUEST(xDRI2SwapBuffersReq); 386706f2543Smrg xDRI2SwapBuffersReply rep; 387706f2543Smrg DrawablePtr pDrawable; 388706f2543Smrg CARD64 target_msc, divisor, remainder, swap_target; 389706f2543Smrg int status; 390706f2543Smrg 391706f2543Smrg REQUEST_SIZE_MATCH(xDRI2SwapBuffersReq); 392706f2543Smrg 393706f2543Smrg if (!validDrawable(client, stuff->drawable, 394706f2543Smrg DixReadAccess | DixWriteAccess, &pDrawable, &status)) 395706f2543Smrg return status; 396706f2543Smrg 397706f2543Smrg /* 398706f2543Smrg * Ensures an out of control client can't exhaust our swap queue, and 399706f2543Smrg * also orders swaps. 400706f2543Smrg */ 401706f2543Smrg if (DRI2ThrottleClient(client, pDrawable)) 402706f2543Smrg return Success; 403706f2543Smrg 404706f2543Smrg target_msc = vals_to_card64(stuff->target_msc_lo, stuff->target_msc_hi); 405706f2543Smrg divisor = vals_to_card64(stuff->divisor_lo, stuff->divisor_hi); 406706f2543Smrg remainder = vals_to_card64(stuff->remainder_lo, stuff->remainder_hi); 407706f2543Smrg 408706f2543Smrg status = DRI2SwapBuffers(client, pDrawable, target_msc, divisor, remainder, 409706f2543Smrg &swap_target, DRI2SwapEvent, pDrawable); 410706f2543Smrg if (status != Success) 411706f2543Smrg return BadDrawable; 412706f2543Smrg 413706f2543Smrg rep.type = X_Reply; 414706f2543Smrg rep.length = 0; 415706f2543Smrg rep.sequenceNumber = client->sequence; 416706f2543Smrg load_swap_reply(&rep, swap_target); 417706f2543Smrg 418706f2543Smrg WriteToClient(client, sizeof(xDRI2SwapBuffersReply), &rep); 419706f2543Smrg 420706f2543Smrg return Success; 421706f2543Smrg} 422706f2543Smrg 423706f2543Smrgstatic void 424706f2543Smrgload_msc_reply(xDRI2MSCReply *rep, CARD64 ust, CARD64 msc, CARD64 sbc) 425706f2543Smrg{ 426706f2543Smrg rep->ust_hi = ust >> 32; 427706f2543Smrg rep->ust_lo = ust & 0xffffffff; 428706f2543Smrg rep->msc_hi = msc >> 32; 429706f2543Smrg rep->msc_lo = msc & 0xffffffff; 430706f2543Smrg rep->sbc_hi = sbc >> 32; 431706f2543Smrg rep->sbc_lo = sbc & 0xffffffff; 432706f2543Smrg} 433706f2543Smrg 434706f2543Smrgstatic int 435706f2543SmrgProcDRI2GetMSC(ClientPtr client) 436706f2543Smrg{ 437706f2543Smrg REQUEST(xDRI2GetMSCReq); 438706f2543Smrg xDRI2MSCReply rep; 439706f2543Smrg DrawablePtr pDrawable; 440706f2543Smrg CARD64 ust, msc, sbc; 441706f2543Smrg int status; 442706f2543Smrg 443706f2543Smrg REQUEST_SIZE_MATCH(xDRI2GetMSCReq); 444706f2543Smrg 445706f2543Smrg if (!validDrawable(client, stuff->drawable, DixReadAccess, &pDrawable, 446706f2543Smrg &status)) 447706f2543Smrg return status; 448706f2543Smrg 449706f2543Smrg status = DRI2GetMSC(pDrawable, &ust, &msc, &sbc); 450706f2543Smrg if (status != Success) 451706f2543Smrg return status; 452706f2543Smrg 453706f2543Smrg rep.type = X_Reply; 454706f2543Smrg rep.length = 0; 455706f2543Smrg rep.sequenceNumber = client->sequence; 456706f2543Smrg load_msc_reply(&rep, ust, msc, sbc); 457706f2543Smrg 458706f2543Smrg WriteToClient(client, sizeof(xDRI2MSCReply), &rep); 459706f2543Smrg 460706f2543Smrg return Success; 461706f2543Smrg} 462706f2543Smrg 463706f2543Smrgstatic int 464706f2543SmrgProcDRI2WaitMSC(ClientPtr client) 465706f2543Smrg{ 466706f2543Smrg REQUEST(xDRI2WaitMSCReq); 467706f2543Smrg DrawablePtr pDrawable; 468706f2543Smrg CARD64 target, divisor, remainder; 469706f2543Smrg int status; 470706f2543Smrg 471706f2543Smrg /* FIXME: in restart case, client may be gone at this point */ 472706f2543Smrg 473706f2543Smrg REQUEST_SIZE_MATCH(xDRI2WaitMSCReq); 474706f2543Smrg 475706f2543Smrg if (!validDrawable(client, stuff->drawable, DixReadAccess, &pDrawable, 476706f2543Smrg &status)) 477706f2543Smrg return status; 478706f2543Smrg 479706f2543Smrg target = vals_to_card64(stuff->target_msc_lo, stuff->target_msc_hi); 480706f2543Smrg divisor = vals_to_card64(stuff->divisor_lo, stuff->divisor_hi); 481706f2543Smrg remainder = vals_to_card64(stuff->remainder_lo, stuff->remainder_hi); 482706f2543Smrg 483706f2543Smrg status = DRI2WaitMSC(client, pDrawable, target, divisor, remainder); 484706f2543Smrg if (status != Success) 485706f2543Smrg return status; 486706f2543Smrg 487706f2543Smrg return Success; 488706f2543Smrg} 489706f2543Smrg 490706f2543Smrgint 491706f2543SmrgProcDRI2WaitMSCReply(ClientPtr client, CARD64 ust, CARD64 msc, CARD64 sbc) 492706f2543Smrg{ 493706f2543Smrg xDRI2MSCReply rep; 494706f2543Smrg 495706f2543Smrg rep.type = X_Reply; 496706f2543Smrg rep.length = 0; 497706f2543Smrg rep.sequenceNumber = client->sequence; 498706f2543Smrg load_msc_reply(&rep, ust, msc, sbc); 499706f2543Smrg 500706f2543Smrg WriteToClient(client, sizeof(xDRI2MSCReply), &rep); 501706f2543Smrg 502706f2543Smrg return Success; 503706f2543Smrg} 504706f2543Smrg 505706f2543Smrgstatic int 506706f2543SmrgProcDRI2SwapInterval(ClientPtr client) 507706f2543Smrg{ 508706f2543Smrg REQUEST(xDRI2SwapIntervalReq); 509706f2543Smrg DrawablePtr pDrawable; 510706f2543Smrg int status; 511706f2543Smrg 512706f2543Smrg /* FIXME: in restart case, client may be gone at this point */ 513706f2543Smrg 514706f2543Smrg REQUEST_SIZE_MATCH(xDRI2SwapIntervalReq); 515706f2543Smrg 516706f2543Smrg if (!validDrawable(client, stuff->drawable, DixReadAccess | DixWriteAccess, 517706f2543Smrg &pDrawable, &status)) 518706f2543Smrg return status; 519706f2543Smrg 520706f2543Smrg DRI2SwapInterval(pDrawable, stuff->interval); 521706f2543Smrg 522706f2543Smrg return Success; 523706f2543Smrg} 524706f2543Smrg 525706f2543Smrgstatic int 526706f2543SmrgProcDRI2WaitSBC(ClientPtr client) 527706f2543Smrg{ 528706f2543Smrg REQUEST(xDRI2WaitSBCReq); 529706f2543Smrg DrawablePtr pDrawable; 530706f2543Smrg CARD64 target; 531706f2543Smrg int status; 532706f2543Smrg 533706f2543Smrg REQUEST_SIZE_MATCH(xDRI2WaitSBCReq); 534706f2543Smrg 535706f2543Smrg if (!validDrawable(client, stuff->drawable, DixReadAccess, &pDrawable, 536706f2543Smrg &status)) 537706f2543Smrg return status; 538706f2543Smrg 539706f2543Smrg target = vals_to_card64(stuff->target_sbc_lo, stuff->target_sbc_hi); 540706f2543Smrg status = DRI2WaitSBC(client, pDrawable, target); 541706f2543Smrg 542706f2543Smrg return status; 543706f2543Smrg} 544706f2543Smrg 545706f2543Smrgstatic int 546706f2543SmrgProcDRI2Dispatch (ClientPtr client) 547706f2543Smrg{ 548706f2543Smrg REQUEST(xReq); 549706f2543Smrg 550706f2543Smrg switch (stuff->data) { 551706f2543Smrg case X_DRI2QueryVersion: 552706f2543Smrg return ProcDRI2QueryVersion(client); 553706f2543Smrg } 554706f2543Smrg 555706f2543Smrg if (!LocalClient(client)) 556706f2543Smrg return BadRequest; 557706f2543Smrg 558706f2543Smrg switch (stuff->data) { 559706f2543Smrg case X_DRI2Connect: 560706f2543Smrg return ProcDRI2Connect(client); 561706f2543Smrg case X_DRI2Authenticate: 562706f2543Smrg return ProcDRI2Authenticate(client); 563706f2543Smrg case X_DRI2CreateDrawable: 564706f2543Smrg return ProcDRI2CreateDrawable(client); 565706f2543Smrg case X_DRI2DestroyDrawable: 566706f2543Smrg return ProcDRI2DestroyDrawable(client); 567706f2543Smrg case X_DRI2GetBuffers: 568706f2543Smrg return ProcDRI2GetBuffers(client); 569706f2543Smrg case X_DRI2CopyRegion: 570706f2543Smrg return ProcDRI2CopyRegion(client); 571706f2543Smrg case X_DRI2GetBuffersWithFormat: 572706f2543Smrg return ProcDRI2GetBuffersWithFormat(client); 573706f2543Smrg case X_DRI2SwapBuffers: 574706f2543Smrg return ProcDRI2SwapBuffers(client); 575706f2543Smrg case X_DRI2GetMSC: 576706f2543Smrg return ProcDRI2GetMSC(client); 577706f2543Smrg case X_DRI2WaitMSC: 578706f2543Smrg return ProcDRI2WaitMSC(client); 579706f2543Smrg case X_DRI2WaitSBC: 580706f2543Smrg return ProcDRI2WaitSBC(client); 581706f2543Smrg case X_DRI2SwapInterval: 582706f2543Smrg return ProcDRI2SwapInterval(client); 583706f2543Smrg default: 584706f2543Smrg return BadRequest; 585706f2543Smrg } 586706f2543Smrg} 587706f2543Smrg 588706f2543Smrgstatic int 589706f2543SmrgSProcDRI2Connect(ClientPtr client) 590706f2543Smrg{ 591706f2543Smrg REQUEST(xDRI2ConnectReq); 592706f2543Smrg xDRI2ConnectReply rep; 593706f2543Smrg int n; 594706f2543Smrg 595706f2543Smrg /* If the client is swapped, it's not local. Talk to the hand. */ 596706f2543Smrg 597706f2543Smrg swaps(&stuff->length, n); 598706f2543Smrg if (sizeof(*stuff) / 4 != client->req_len) 599706f2543Smrg return BadLength; 600706f2543Smrg 601706f2543Smrg rep.sequenceNumber = client->sequence; 602706f2543Smrg swaps(&rep.sequenceNumber, n); 603706f2543Smrg rep.length = 0; 604706f2543Smrg rep.driverNameLength = 0; 605706f2543Smrg rep.deviceNameLength = 0; 606706f2543Smrg 607706f2543Smrg return Success; 608706f2543Smrg} 609706f2543Smrg 610706f2543Smrgstatic int 611706f2543SmrgSProcDRI2Dispatch (ClientPtr client) 612706f2543Smrg{ 613706f2543Smrg REQUEST(xReq); 614706f2543Smrg 615706f2543Smrg /* 616706f2543Smrg * Only local clients are allowed DRI access, but remote clients 617706f2543Smrg * still need these requests to find out cleanly. 618706f2543Smrg */ 619706f2543Smrg switch (stuff->data) 620706f2543Smrg { 621706f2543Smrg case X_DRI2QueryVersion: 622706f2543Smrg return ProcDRI2QueryVersion(client); 623706f2543Smrg case X_DRI2Connect: 624706f2543Smrg return SProcDRI2Connect(client); 625706f2543Smrg default: 626706f2543Smrg return BadRequest; 627706f2543Smrg } 628706f2543Smrg} 629706f2543Smrg 630706f2543Smrgint DRI2EventBase; 631706f2543Smrg 632706f2543Smrgstatic void 633706f2543SmrgDRI2ExtensionInit(void) 634706f2543Smrg{ 635706f2543Smrg dri2Extension = AddExtension(DRI2_NAME, 636706f2543Smrg DRI2NumberEvents, 637706f2543Smrg DRI2NumberErrors, 638706f2543Smrg ProcDRI2Dispatch, 639706f2543Smrg SProcDRI2Dispatch, 640706f2543Smrg NULL, 641706f2543Smrg StandardMinorOpcode); 642706f2543Smrg 643706f2543Smrg DRI2EventBase = dri2Extension->eventBase; 644706f2543Smrg 645706f2543Smrg DRI2ModuleSetup(); 646706f2543Smrg} 647706f2543Smrg 648706f2543Smrgextern Bool noDRI2Extension; 649706f2543Smrg 650706f2543Smrg_X_HIDDEN ExtensionModule dri2ExtensionModule = { 651706f2543Smrg DRI2ExtensionInit, 652706f2543Smrg DRI2_NAME, 653706f2543Smrg &noDRI2Extension, 654706f2543Smrg NULL, 655706f2543Smrg NULL 656706f2543Smrg}; 657