dri2.c revision fbc2fcf685d22ec9bc9465e1f731529979497eaa
1/* 2 * Copyright © 2008 Red Hat, Inc. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Soft- 6 * ware"), to deal in the Software without restriction, including without 7 * limitation the rights to use, copy, modify, merge, publish, distribute, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, provided that the above copyright 10 * notice(s) and this permission notice appear in all copies of the Soft- 11 * ware and that both the above copyright notice(s) and this permission 12 * notice appear in supporting documentation. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- 16 * ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY 17 * RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN 18 * THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSE- 19 * QUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 20 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 21 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFOR- 22 * MANCE OF THIS SOFTWARE. 23 * 24 * Except as contained in this notice, the name of a copyright holder shall 25 * not be used in advertising or otherwise to promote the sale, use or 26 * other dealings in this Software without prior written authorization of 27 * the copyright holder. 28 * 29 * Authors: 30 * Kristian Høgsberg (krh@redhat.com) 31 */ 32 33 34#ifdef GLX_DIRECT_RENDERING 35 36#include <stdio.h> 37#include <X11/Xlibint.h> 38#include <X11/extensions/Xext.h> 39#include <X11/extensions/extutil.h> 40#include <X11/extensions/dri2proto.h> 41#include "xf86drm.h" 42#include "dri2.h" 43#include "glxclient.h" 44#include "GL/glxext.h" 45 46/* Allow the build to work with an older versions of dri2proto.h and 47 * dri2tokens.h. 48 */ 49#if DRI2_MINOR < 1 50#undef DRI2_MINOR 51#define DRI2_MINOR 1 52#define X_DRI2GetBuffersWithFormat 7 53#endif 54 55 56static char dri2ExtensionName[] = DRI2_NAME; 57static XExtensionInfo *dri2Info; 58static XEXT_GENERATE_CLOSE_DISPLAY (DRI2CloseDisplay, dri2Info) 59 60static Bool 61DRI2WireToEvent(Display *dpy, XEvent *event, xEvent *wire); 62static Status 63DRI2EventToWire(Display *dpy, XEvent *event, xEvent *wire); 64static int 65DRI2Error(Display *display, xError *err, XExtCodes *codes, int *ret_code); 66 67static /* const */ XExtensionHooks dri2ExtensionHooks = { 68 NULL, /* create_gc */ 69 NULL, /* copy_gc */ 70 NULL, /* flush_gc */ 71 NULL, /* free_gc */ 72 NULL, /* create_font */ 73 NULL, /* free_font */ 74 DRI2CloseDisplay, /* close_display */ 75 DRI2WireToEvent, /* wire_to_event */ 76 DRI2EventToWire, /* event_to_wire */ 77 DRI2Error, /* error */ 78 NULL, /* error_string */ 79}; 80 81static XEXT_GENERATE_FIND_DISPLAY (DRI2FindDisplay, 82 dri2Info, 83 dri2ExtensionName, 84 &dri2ExtensionHooks, 85 0, NULL) 86 87static Bool 88DRI2WireToEvent(Display *dpy, XEvent *event, xEvent *wire) 89{ 90 XExtDisplayInfo *info = DRI2FindDisplay(dpy); 91 struct glx_drawable *glxDraw; 92 93 XextCheckExtension(dpy, info, dri2ExtensionName, False); 94 95 switch ((wire->u.u.type & 0x7f) - info->codes->first_event) { 96 97#ifdef X_DRI2SwapBuffers 98 case DRI2_BufferSwapComplete: 99 { 100 GLXBufferSwapComplete *aevent = (GLXBufferSwapComplete *)event; 101 xDRI2BufferSwapComplete2 *awire = (xDRI2BufferSwapComplete2 *)wire; 102 __GLXDRIdrawable *pdraw; 103 104 pdraw = dri2GetGlxDrawableFromXDrawableId(dpy, awire->drawable); 105 106 /* Ignore swap events if we're not looking for them */ 107 aevent->type = dri2GetSwapEventType(dpy, awire->drawable); 108 if(!aevent->type) 109 return False; 110 111 aevent->serial = _XSetLastRequestRead(dpy, (xGenericReply *) wire); 112 aevent->send_event = (awire->type & 0x80) != 0; 113 aevent->display = dpy; 114 aevent->drawable = awire->drawable; 115 switch (awire->event_type) { 116 case DRI2_EXCHANGE_COMPLETE: 117 aevent->event_type = GLX_EXCHANGE_COMPLETE_INTEL; 118 break; 119 case DRI2_BLIT_COMPLETE: 120 aevent->event_type = GLX_COPY_COMPLETE_INTEL; 121 break; 122 case DRI2_FLIP_COMPLETE: 123 aevent->event_type = GLX_FLIP_COMPLETE_INTEL; 124 break; 125 default: 126 /* unknown swap completion type */ 127 return False; 128 } 129 aevent->ust = ((CARD64)awire->ust_hi << 32) | awire->ust_lo; 130 aevent->msc = ((CARD64)awire->msc_hi << 32) | awire->msc_lo; 131 132 glxDraw = GetGLXDrawable(dpy, pdraw->drawable); 133 if (awire->sbc < glxDraw->lastEventSbc) 134 glxDraw->eventSbcWrap += 0x100000000; 135 glxDraw->lastEventSbc = awire->sbc; 136 aevent->sbc = awire->sbc + glxDraw->eventSbcWrap; 137 138 return True; 139 } 140#endif 141#ifdef DRI2_InvalidateBuffers 142 case DRI2_InvalidateBuffers: 143 { 144 xDRI2InvalidateBuffers *awire = (xDRI2InvalidateBuffers *)wire; 145 146 dri2InvalidateBuffers(dpy, awire->drawable); 147 return False; 148 } 149#endif 150 default: 151 /* client doesn't support server event */ 152 break; 153 } 154 155 return False; 156} 157 158/* We don't actually support this. It doesn't make sense for clients to 159 * send each other DRI2 events. 160 */ 161static Status 162DRI2EventToWire(Display *dpy, XEvent *event, xEvent *wire) 163{ 164 XExtDisplayInfo *info = DRI2FindDisplay(dpy); 165 166 XextCheckExtension(dpy, info, dri2ExtensionName, False); 167 168 switch (event->type) { 169 default: 170 /* client doesn't support server event */ 171 break; 172 } 173 174 return Success; 175} 176 177static int 178DRI2Error(Display *display, xError *err, XExtCodes *codes, int *ret_code) 179{ 180 if (err->majorCode == codes->major_opcode && 181 err->errorCode == BadDrawable && 182 err->minorCode == X_DRI2CopyRegion) 183 return True; 184 185 /* If the X drawable was destroyed before the GLX drawable, the 186 * DRI2 drawble will be gone by the time we call 187 * DRI2DestroyDrawable. So just ignore BadDrawable here. */ 188 if (err->majorCode == codes->major_opcode && 189 err->errorCode == BadDrawable && 190 err->minorCode == X_DRI2DestroyDrawable) 191 return True; 192 193 /* If the server is non-local DRI2Connect will raise BadRequest. 194 * Swallow this so that DRI2Connect can signal this in its return code */ 195 if (err->majorCode == codes->major_opcode && 196 err->minorCode == X_DRI2Connect && 197 err->errorCode == BadRequest) { 198 *ret_code = False; 199 return True; 200 } 201 202 return False; 203} 204 205Bool 206DRI2QueryExtension(Display * dpy, int *eventBase, int *errorBase) 207{ 208 XExtDisplayInfo *info = DRI2FindDisplay(dpy); 209 210 if (XextHasExtension(info)) { 211 *eventBase = info->codes->first_event; 212 *errorBase = info->codes->first_error; 213 return True; 214 } 215 216 return False; 217} 218 219Bool 220DRI2QueryVersion(Display * dpy, int *major, int *minor) 221{ 222 XExtDisplayInfo *info = DRI2FindDisplay(dpy); 223 xDRI2QueryVersionReply rep; 224 xDRI2QueryVersionReq *req; 225 int i, nevents; 226 227 XextCheckExtension(dpy, info, dri2ExtensionName, False); 228 229 LockDisplay(dpy); 230 GetReq(DRI2QueryVersion, req); 231 req->reqType = info->codes->major_opcode; 232 req->dri2ReqType = X_DRI2QueryVersion; 233 req->majorVersion = DRI2_MAJOR; 234 req->minorVersion = DRI2_MINOR; 235 if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) { 236 UnlockDisplay(dpy); 237 SyncHandle(); 238 return False; 239 } 240 *major = rep.majorVersion; 241 *minor = rep.minorVersion; 242 UnlockDisplay(dpy); 243 SyncHandle(); 244 245 switch (rep.minorVersion) { 246 case 1: 247 nevents = 0; 248 break; 249 case 2: 250 nevents = 1; 251 break; 252 case 3: 253 default: 254 nevents = 2; 255 break; 256 } 257 258 for (i = 0; i < nevents; i++) { 259 XESetWireToEvent (dpy, info->codes->first_event + i, DRI2WireToEvent); 260 XESetEventToWire (dpy, info->codes->first_event + i, DRI2EventToWire); 261 } 262 263 return True; 264} 265 266Bool 267DRI2Connect(Display * dpy, XID window, char **driverName, char **deviceName) 268{ 269 XExtDisplayInfo *info = DRI2FindDisplay(dpy); 270 xDRI2ConnectReply rep; 271 xDRI2ConnectReq *req; 272 273 XextCheckExtension(dpy, info, dri2ExtensionName, False); 274 275 LockDisplay(dpy); 276 GetReq(DRI2Connect, req); 277 req->reqType = info->codes->major_opcode; 278 req->dri2ReqType = X_DRI2Connect; 279 req->window = window; 280 req->driverType = DRI2DriverDRI; 281 if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) { 282 UnlockDisplay(dpy); 283 SyncHandle(); 284 return False; 285 } 286 287 if (rep.driverNameLength == 0 && rep.deviceNameLength == 0) { 288 UnlockDisplay(dpy); 289 SyncHandle(); 290 return False; 291 } 292 293 *driverName = Xmalloc(rep.driverNameLength + 1); 294 if (*driverName == NULL) { 295 _XEatData(dpy, 296 ((rep.driverNameLength + 3) & ~3) + 297 ((rep.deviceNameLength + 3) & ~3)); 298 UnlockDisplay(dpy); 299 SyncHandle(); 300 return False; 301 } 302 _XReadPad(dpy, *driverName, rep.driverNameLength); 303 (*driverName)[rep.driverNameLength] = '\0'; 304 305 *deviceName = Xmalloc(rep.deviceNameLength + 1); 306 if (*deviceName == NULL) { 307 Xfree(*driverName); 308 _XEatData(dpy, ((rep.deviceNameLength + 3) & ~3)); 309 UnlockDisplay(dpy); 310 SyncHandle(); 311 return False; 312 } 313 _XReadPad(dpy, *deviceName, rep.deviceNameLength); 314 (*deviceName)[rep.deviceNameLength] = '\0'; 315 316 UnlockDisplay(dpy); 317 SyncHandle(); 318 319 return True; 320} 321 322Bool 323DRI2Authenticate(Display * dpy, XID window, drm_magic_t magic) 324{ 325 XExtDisplayInfo *info = DRI2FindDisplay(dpy); 326 xDRI2AuthenticateReq *req; 327 xDRI2AuthenticateReply rep; 328 329 XextCheckExtension(dpy, info, dri2ExtensionName, False); 330 331 LockDisplay(dpy); 332 GetReq(DRI2Authenticate, req); 333 req->reqType = info->codes->major_opcode; 334 req->dri2ReqType = X_DRI2Authenticate; 335 req->window = window; 336 req->magic = magic; 337 338 if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) { 339 UnlockDisplay(dpy); 340 SyncHandle(); 341 return False; 342 } 343 344 UnlockDisplay(dpy); 345 SyncHandle(); 346 347 return rep.authenticated; 348} 349 350void 351DRI2CreateDrawable(Display * dpy, XID drawable) 352{ 353 XExtDisplayInfo *info = DRI2FindDisplay(dpy); 354 xDRI2CreateDrawableReq *req; 355 356 XextSimpleCheckExtension(dpy, info, dri2ExtensionName); 357 358 LockDisplay(dpy); 359 GetReq(DRI2CreateDrawable, req); 360 req->reqType = info->codes->major_opcode; 361 req->dri2ReqType = X_DRI2CreateDrawable; 362 req->drawable = drawable; 363 UnlockDisplay(dpy); 364 SyncHandle(); 365} 366 367void 368DRI2DestroyDrawable(Display * dpy, XID drawable) 369{ 370 XExtDisplayInfo *info = DRI2FindDisplay(dpy); 371 xDRI2DestroyDrawableReq *req; 372 373 XextSimpleCheckExtension(dpy, info, dri2ExtensionName); 374 375 XSync(dpy, False); 376 377 LockDisplay(dpy); 378 GetReq(DRI2DestroyDrawable, req); 379 req->reqType = info->codes->major_opcode; 380 req->dri2ReqType = X_DRI2DestroyDrawable; 381 req->drawable = drawable; 382 UnlockDisplay(dpy); 383 SyncHandle(); 384} 385 386DRI2Buffer * 387DRI2GetBuffers(Display * dpy, XID drawable, 388 int *width, int *height, 389 unsigned int *attachments, int count, int *outCount) 390{ 391 XExtDisplayInfo *info = DRI2FindDisplay(dpy); 392 xDRI2GetBuffersReply rep; 393 xDRI2GetBuffersReq *req; 394 DRI2Buffer *buffers; 395 xDRI2Buffer repBuffer; 396 CARD32 *p; 397 int i; 398 399 XextCheckExtension(dpy, info, dri2ExtensionName, False); 400 401 LockDisplay(dpy); 402 GetReqExtra(DRI2GetBuffers, count * 4, req); 403 req->reqType = info->codes->major_opcode; 404 req->dri2ReqType = X_DRI2GetBuffers; 405 req->drawable = drawable; 406 req->count = count; 407 p = (CARD32 *) & req[1]; 408 for (i = 0; i < count; i++) 409 p[i] = attachments[i]; 410 411 if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) { 412 UnlockDisplay(dpy); 413 SyncHandle(); 414 return NULL; 415 } 416 417 *width = rep.width; 418 *height = rep.height; 419 *outCount = rep.count; 420 421 buffers = Xmalloc(rep.count * sizeof buffers[0]); 422 if (buffers == NULL) { 423 _XEatData(dpy, rep.count * sizeof repBuffer); 424 UnlockDisplay(dpy); 425 SyncHandle(); 426 return NULL; 427 } 428 429 for (i = 0; i < rep.count; i++) { 430 _XReadPad(dpy, (char *) &repBuffer, sizeof repBuffer); 431 buffers[i].attachment = repBuffer.attachment; 432 buffers[i].name = repBuffer.name; 433 buffers[i].pitch = repBuffer.pitch; 434 buffers[i].cpp = repBuffer.cpp; 435 buffers[i].flags = repBuffer.flags; 436 } 437 438 UnlockDisplay(dpy); 439 SyncHandle(); 440 441 return buffers; 442} 443 444 445DRI2Buffer * 446DRI2GetBuffersWithFormat(Display * dpy, XID drawable, 447 int *width, int *height, 448 unsigned int *attachments, int count, int *outCount) 449{ 450 XExtDisplayInfo *info = DRI2FindDisplay(dpy); 451 xDRI2GetBuffersReply rep; 452 xDRI2GetBuffersReq *req; 453 DRI2Buffer *buffers; 454 xDRI2Buffer repBuffer; 455 CARD32 *p; 456 int i; 457 458 XextCheckExtension(dpy, info, dri2ExtensionName, False); 459 460 LockDisplay(dpy); 461 GetReqExtra(DRI2GetBuffers, count * (4 * 2), req); 462 req->reqType = info->codes->major_opcode; 463 req->dri2ReqType = X_DRI2GetBuffersWithFormat; 464 req->drawable = drawable; 465 req->count = count; 466 p = (CARD32 *) & req[1]; 467 for (i = 0; i < (count * 2); i++) 468 p[i] = attachments[i]; 469 470 if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) { 471 UnlockDisplay(dpy); 472 SyncHandle(); 473 return NULL; 474 } 475 476 *width = rep.width; 477 *height = rep.height; 478 *outCount = rep.count; 479 480 buffers = Xmalloc(rep.count * sizeof buffers[0]); 481 if (buffers == NULL) { 482 _XEatData(dpy, rep.count * sizeof repBuffer); 483 UnlockDisplay(dpy); 484 SyncHandle(); 485 return NULL; 486 } 487 488 for (i = 0; i < rep.count; i++) { 489 _XReadPad(dpy, (char *) &repBuffer, sizeof repBuffer); 490 buffers[i].attachment = repBuffer.attachment; 491 buffers[i].name = repBuffer.name; 492 buffers[i].pitch = repBuffer.pitch; 493 buffers[i].cpp = repBuffer.cpp; 494 buffers[i].flags = repBuffer.flags; 495 } 496 497 UnlockDisplay(dpy); 498 SyncHandle(); 499 500 return buffers; 501} 502 503 504void 505DRI2CopyRegion(Display * dpy, XID drawable, XserverRegion region, 506 CARD32 dest, CARD32 src) 507{ 508 XExtDisplayInfo *info = DRI2FindDisplay(dpy); 509 xDRI2CopyRegionReq *req; 510 xDRI2CopyRegionReply rep; 511 512 XextSimpleCheckExtension(dpy, info, dri2ExtensionName); 513 514 LockDisplay(dpy); 515 GetReq(DRI2CopyRegion, req); 516 req->reqType = info->codes->major_opcode; 517 req->dri2ReqType = X_DRI2CopyRegion; 518 req->drawable = drawable; 519 req->region = region; 520 req->dest = dest; 521 req->src = src; 522 523 _XReply(dpy, (xReply *) & rep, 0, xFalse); 524 525 UnlockDisplay(dpy); 526 SyncHandle(); 527} 528 529#ifdef X_DRI2SwapBuffers 530static void 531load_swap_req(xDRI2SwapBuffersReq *req, CARD64 target, CARD64 divisor, 532 CARD64 remainder) 533{ 534 req->target_msc_hi = target >> 32; 535 req->target_msc_lo = target & 0xffffffff; 536 req->divisor_hi = divisor >> 32; 537 req->divisor_lo = divisor & 0xffffffff; 538 req->remainder_hi = remainder >> 32; 539 req->remainder_lo = remainder & 0xffffffff; 540} 541 542static CARD64 543vals_to_card64(CARD32 lo, CARD32 hi) 544{ 545 return (CARD64)hi << 32 | lo; 546} 547 548void DRI2SwapBuffers(Display *dpy, XID drawable, CARD64 target_msc, 549 CARD64 divisor, CARD64 remainder, CARD64 *count) 550{ 551 XExtDisplayInfo *info = DRI2FindDisplay(dpy); 552 xDRI2SwapBuffersReq *req; 553 xDRI2SwapBuffersReply rep; 554 555 XextSimpleCheckExtension (dpy, info, dri2ExtensionName); 556 557 LockDisplay(dpy); 558 GetReq(DRI2SwapBuffers, req); 559 req->reqType = info->codes->major_opcode; 560 req->dri2ReqType = X_DRI2SwapBuffers; 561 req->drawable = drawable; 562 load_swap_req(req, target_msc, divisor, remainder); 563 564 _XReply(dpy, (xReply *)&rep, 0, xFalse); 565 566 *count = vals_to_card64(rep.swap_lo, rep.swap_hi); 567 568 UnlockDisplay(dpy); 569 SyncHandle(); 570} 571#endif 572 573#ifdef X_DRI2GetMSC 574Bool DRI2GetMSC(Display *dpy, XID drawable, CARD64 *ust, CARD64 *msc, 575 CARD64 *sbc) 576{ 577 XExtDisplayInfo *info = DRI2FindDisplay(dpy); 578 xDRI2GetMSCReq *req; 579 xDRI2MSCReply rep; 580 581 XextCheckExtension (dpy, info, dri2ExtensionName, False); 582 583 LockDisplay(dpy); 584 GetReq(DRI2GetMSC, req); 585 req->reqType = info->codes->major_opcode; 586 req->dri2ReqType = X_DRI2GetMSC; 587 req->drawable = drawable; 588 589 if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) { 590 UnlockDisplay(dpy); 591 SyncHandle(); 592 return False; 593 } 594 595 *ust = vals_to_card64(rep.ust_lo, rep.ust_hi); 596 *msc = vals_to_card64(rep.msc_lo, rep.msc_hi); 597 *sbc = vals_to_card64(rep.sbc_lo, rep.sbc_hi); 598 599 UnlockDisplay(dpy); 600 SyncHandle(); 601 602 return True; 603} 604#endif 605 606#ifdef X_DRI2WaitMSC 607static void 608load_msc_req(xDRI2WaitMSCReq *req, CARD64 target, CARD64 divisor, 609 CARD64 remainder) 610{ 611 req->target_msc_hi = target >> 32; 612 req->target_msc_lo = target & 0xffffffff; 613 req->divisor_hi = divisor >> 32; 614 req->divisor_lo = divisor & 0xffffffff; 615 req->remainder_hi = remainder >> 32; 616 req->remainder_lo = remainder & 0xffffffff; 617} 618 619Bool DRI2WaitMSC(Display *dpy, XID drawable, CARD64 target_msc, CARD64 divisor, 620 CARD64 remainder, CARD64 *ust, CARD64 *msc, CARD64 *sbc) 621{ 622 XExtDisplayInfo *info = DRI2FindDisplay(dpy); 623 xDRI2WaitMSCReq *req; 624 xDRI2MSCReply rep; 625 626 XextCheckExtension (dpy, info, dri2ExtensionName, False); 627 628 LockDisplay(dpy); 629 GetReq(DRI2WaitMSC, req); 630 req->reqType = info->codes->major_opcode; 631 req->dri2ReqType = X_DRI2WaitMSC; 632 req->drawable = drawable; 633 load_msc_req(req, target_msc, divisor, remainder); 634 635 if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) { 636 UnlockDisplay(dpy); 637 SyncHandle(); 638 return False; 639 } 640 641 *ust = ((CARD64)rep.ust_hi << 32) | (CARD64)rep.ust_lo; 642 *msc = ((CARD64)rep.msc_hi << 32) | (CARD64)rep.msc_lo; 643 *sbc = ((CARD64)rep.sbc_hi << 32) | (CARD64)rep.sbc_lo; 644 645 UnlockDisplay(dpy); 646 SyncHandle(); 647 648 return True; 649} 650#endif 651 652#ifdef X_DRI2WaitSBC 653static void 654load_sbc_req(xDRI2WaitSBCReq *req, CARD64 target) 655{ 656 req->target_sbc_hi = target >> 32; 657 req->target_sbc_lo = target & 0xffffffff; 658} 659 660Bool DRI2WaitSBC(Display *dpy, XID drawable, CARD64 target_sbc, CARD64 *ust, 661 CARD64 *msc, CARD64 *sbc) 662{ 663 XExtDisplayInfo *info = DRI2FindDisplay(dpy); 664 xDRI2WaitSBCReq *req; 665 xDRI2MSCReply rep; 666 667 XextCheckExtension (dpy, info, dri2ExtensionName, False); 668 669 LockDisplay(dpy); 670 GetReq(DRI2WaitSBC, req); 671 req->reqType = info->codes->major_opcode; 672 req->dri2ReqType = X_DRI2WaitSBC; 673 req->drawable = drawable; 674 load_sbc_req(req, target_sbc); 675 676 if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) { 677 UnlockDisplay(dpy); 678 SyncHandle(); 679 return False; 680 } 681 682 *ust = ((CARD64)rep.ust_hi << 32) | rep.ust_lo; 683 *msc = ((CARD64)rep.msc_hi << 32) | rep.msc_lo; 684 *sbc = ((CARD64)rep.sbc_hi << 32) | rep.sbc_lo; 685 686 UnlockDisplay(dpy); 687 SyncHandle(); 688 689 return True; 690} 691#endif 692 693#ifdef X_DRI2SwapInterval 694void DRI2SwapInterval(Display *dpy, XID drawable, int interval) 695{ 696 XExtDisplayInfo *info = DRI2FindDisplay(dpy); 697 xDRI2SwapIntervalReq *req; 698 699 XextSimpleCheckExtension (dpy, info, dri2ExtensionName); 700 701 LockDisplay(dpy); 702 GetReq(DRI2SwapInterval, req); 703 req->reqType = info->codes->major_opcode; 704 req->dri2ReqType = X_DRI2SwapInterval; 705 req->drawable = drawable; 706 req->interval = interval; 707 UnlockDisplay(dpy); 708 SyncHandle(); 709} 710#endif 711 712#endif /* GLX_DIRECT_RENDERING */ 713