dri2.c revision 16887d042a917fa4773e4d853f50051b54e9948c
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 92 XextCheckExtension(dpy, info, dri2ExtensionName, False); 93 94 switch ((wire->u.u.type & 0x7f) - info->codes->first_event) { 95 96#ifdef X_DRI2SwapBuffers 97 case DRI2_BufferSwapComplete: 98 { 99 GLXBufferSwapComplete *aevent = (GLXBufferSwapComplete *)event; 100 xDRI2BufferSwapComplete *awire = (xDRI2BufferSwapComplete *)wire; 101 __GLXDRIdrawable *pdraw; 102 struct glx_display *glx_dpy = __glXInitialize(dpy); 103 104 /* Ignore swap events if we're not looking for them */ 105 pdraw = dri2GetGlxDrawableFromXDrawableId(dpy, awire->drawable); 106 if (!(pdraw->eventMask & GLX_BUFFER_SWAP_COMPLETE_INTEL_MASK)) 107 return False; 108 109 aevent->serial = _XSetLastRequestRead(dpy, (xGenericReply *) wire); 110 aevent->type = glx_dpy->codes->first_event + GLX_BufferSwapComplete; 111 aevent->send_event = (awire->type & 0x80) != 0; 112 aevent->display = dpy; 113 aevent->drawable = awire->drawable; 114 switch (awire->event_type) { 115 case DRI2_EXCHANGE_COMPLETE: 116 aevent->event_type = GLX_EXCHANGE_COMPLETE_INTEL; 117 break; 118 case DRI2_BLIT_COMPLETE: 119 aevent->event_type = GLX_COPY_COMPLETE_INTEL; 120 break; 121 case DRI2_FLIP_COMPLETE: 122 aevent->event_type = GLX_FLIP_COMPLETE_INTEL; 123 break; 124 default: 125 /* unknown swap completion type */ 126 return False; 127 } 128 aevent->ust = ((CARD64)awire->ust_hi << 32) | awire->ust_lo; 129 aevent->msc = ((CARD64)awire->msc_hi << 32) | awire->msc_lo; 130 aevent->sbc = ((CARD64)awire->sbc_hi << 32) | awire->sbc_lo; 131 return True; 132 } 133#endif 134#ifdef DRI2_InvalidateBuffers 135 case DRI2_InvalidateBuffers: 136 { 137 xDRI2InvalidateBuffers *awire = (xDRI2InvalidateBuffers *)wire; 138 139 dri2InvalidateBuffers(dpy, awire->drawable); 140 return False; 141 } 142#endif 143 default: 144 /* client doesn't support server event */ 145 break; 146 } 147 148 return False; 149} 150 151/* We don't actually support this. It doesn't make sense for clients to 152 * send each other DRI2 events. 153 */ 154static Status 155DRI2EventToWire(Display *dpy, XEvent *event, xEvent *wire) 156{ 157 XExtDisplayInfo *info = DRI2FindDisplay(dpy); 158 159 XextCheckExtension(dpy, info, dri2ExtensionName, False); 160 161 switch (event->type) { 162 default: 163 /* client doesn't support server event */ 164 break; 165 } 166 167 return Success; 168} 169 170static int 171DRI2Error(Display *display, xError *err, XExtCodes *codes, int *ret_code) 172{ 173 if (err->majorCode == codes->major_opcode && 174 err->errorCode == BadDrawable && 175 err->minorCode == X_DRI2CopyRegion) 176 return True; 177 178 /* If the X drawable was destroyed before the GLX drawable, the 179 * DRI2 drawble will be gone by the time we call 180 * DRI2DestroyDrawable. So just ignore BadDrawable here. */ 181 if (err->majorCode == codes->major_opcode && 182 err->errorCode == BadDrawable && 183 err->minorCode == X_DRI2DestroyDrawable) 184 return True; 185 186 return False; 187} 188 189Bool 190DRI2QueryExtension(Display * dpy, int *eventBase, int *errorBase) 191{ 192 XExtDisplayInfo *info = DRI2FindDisplay(dpy); 193 194 if (XextHasExtension(info)) { 195 *eventBase = info->codes->first_event; 196 *errorBase = info->codes->first_error; 197 return True; 198 } 199 200 return False; 201} 202 203Bool 204DRI2QueryVersion(Display * dpy, int *major, int *minor) 205{ 206 XExtDisplayInfo *info = DRI2FindDisplay(dpy); 207 xDRI2QueryVersionReply rep; 208 xDRI2QueryVersionReq *req; 209 int i, nevents; 210 211 XextCheckExtension(dpy, info, dri2ExtensionName, False); 212 213 LockDisplay(dpy); 214 GetReq(DRI2QueryVersion, req); 215 req->reqType = info->codes->major_opcode; 216 req->dri2ReqType = X_DRI2QueryVersion; 217 req->majorVersion = DRI2_MAJOR; 218 req->minorVersion = DRI2_MINOR; 219 if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) { 220 UnlockDisplay(dpy); 221 SyncHandle(); 222 return False; 223 } 224 *major = rep.majorVersion; 225 *minor = rep.minorVersion; 226 UnlockDisplay(dpy); 227 SyncHandle(); 228 229 switch (rep.minorVersion) { 230 case 1: 231 nevents = 0; 232 break; 233 case 2: 234 nevents = 1; 235 break; 236 case 3: 237 default: 238 nevents = 2; 239 break; 240 } 241 242 for (i = 0; i < nevents; i++) { 243 XESetWireToEvent (dpy, info->codes->first_event + i, DRI2WireToEvent); 244 XESetEventToWire (dpy, info->codes->first_event + i, DRI2EventToWire); 245 } 246 247 return True; 248} 249 250Bool 251DRI2Connect(Display * dpy, XID window, char **driverName, char **deviceName) 252{ 253 XExtDisplayInfo *info = DRI2FindDisplay(dpy); 254 xDRI2ConnectReply rep; 255 xDRI2ConnectReq *req; 256 257 XextCheckExtension(dpy, info, dri2ExtensionName, False); 258 259 LockDisplay(dpy); 260 GetReq(DRI2Connect, req); 261 req->reqType = info->codes->major_opcode; 262 req->dri2ReqType = X_DRI2Connect; 263 req->window = window; 264 req->driverType = DRI2DriverDRI; 265 if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) { 266 UnlockDisplay(dpy); 267 SyncHandle(); 268 return False; 269 } 270 271 if (rep.driverNameLength == 0 && rep.deviceNameLength == 0) { 272 UnlockDisplay(dpy); 273 SyncHandle(); 274 return False; 275 } 276 277 *driverName = Xmalloc(rep.driverNameLength + 1); 278 if (*driverName == NULL) { 279 _XEatData(dpy, 280 ((rep.driverNameLength + 3) & ~3) + 281 ((rep.deviceNameLength + 3) & ~3)); 282 UnlockDisplay(dpy); 283 SyncHandle(); 284 return False; 285 } 286 _XReadPad(dpy, *driverName, rep.driverNameLength); 287 (*driverName)[rep.driverNameLength] = '\0'; 288 289 *deviceName = Xmalloc(rep.deviceNameLength + 1); 290 if (*deviceName == NULL) { 291 Xfree(*driverName); 292 _XEatData(dpy, ((rep.deviceNameLength + 3) & ~3)); 293 UnlockDisplay(dpy); 294 SyncHandle(); 295 return False; 296 } 297 _XReadPad(dpy, *deviceName, rep.deviceNameLength); 298 (*deviceName)[rep.deviceNameLength] = '\0'; 299 300 UnlockDisplay(dpy); 301 SyncHandle(); 302 303 return True; 304} 305 306Bool 307DRI2Authenticate(Display * dpy, XID window, drm_magic_t magic) 308{ 309 XExtDisplayInfo *info = DRI2FindDisplay(dpy); 310 xDRI2AuthenticateReq *req; 311 xDRI2AuthenticateReply rep; 312 313 XextCheckExtension(dpy, info, dri2ExtensionName, False); 314 315 LockDisplay(dpy); 316 GetReq(DRI2Authenticate, req); 317 req->reqType = info->codes->major_opcode; 318 req->dri2ReqType = X_DRI2Authenticate; 319 req->window = window; 320 req->magic = magic; 321 322 if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) { 323 UnlockDisplay(dpy); 324 SyncHandle(); 325 return False; 326 } 327 328 UnlockDisplay(dpy); 329 SyncHandle(); 330 331 return rep.authenticated; 332} 333 334void 335DRI2CreateDrawable(Display * dpy, XID drawable) 336{ 337 XExtDisplayInfo *info = DRI2FindDisplay(dpy); 338 xDRI2CreateDrawableReq *req; 339 340 XextSimpleCheckExtension(dpy, info, dri2ExtensionName); 341 342 LockDisplay(dpy); 343 GetReq(DRI2CreateDrawable, req); 344 req->reqType = info->codes->major_opcode; 345 req->dri2ReqType = X_DRI2CreateDrawable; 346 req->drawable = drawable; 347 UnlockDisplay(dpy); 348 SyncHandle(); 349} 350 351void 352DRI2DestroyDrawable(Display * dpy, XID drawable) 353{ 354 XExtDisplayInfo *info = DRI2FindDisplay(dpy); 355 xDRI2DestroyDrawableReq *req; 356 357 XextSimpleCheckExtension(dpy, info, dri2ExtensionName); 358 359 XSync(dpy, False); 360 361 LockDisplay(dpy); 362 GetReq(DRI2DestroyDrawable, req); 363 req->reqType = info->codes->major_opcode; 364 req->dri2ReqType = X_DRI2DestroyDrawable; 365 req->drawable = drawable; 366 UnlockDisplay(dpy); 367 SyncHandle(); 368} 369 370DRI2Buffer * 371DRI2GetBuffers(Display * dpy, XID drawable, 372 int *width, int *height, 373 unsigned int *attachments, int count, int *outCount) 374{ 375 XExtDisplayInfo *info = DRI2FindDisplay(dpy); 376 xDRI2GetBuffersReply rep; 377 xDRI2GetBuffersReq *req; 378 DRI2Buffer *buffers; 379 xDRI2Buffer repBuffer; 380 CARD32 *p; 381 int i; 382 383 XextCheckExtension(dpy, info, dri2ExtensionName, False); 384 385 LockDisplay(dpy); 386 GetReqExtra(DRI2GetBuffers, count * 4, req); 387 req->reqType = info->codes->major_opcode; 388 req->dri2ReqType = X_DRI2GetBuffers; 389 req->drawable = drawable; 390 req->count = count; 391 p = (CARD32 *) & req[1]; 392 for (i = 0; i < count; i++) 393 p[i] = attachments[i]; 394 395 if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) { 396 UnlockDisplay(dpy); 397 SyncHandle(); 398 return NULL; 399 } 400 401 *width = rep.width; 402 *height = rep.height; 403 *outCount = rep.count; 404 405 buffers = Xmalloc(rep.count * sizeof buffers[0]); 406 if (buffers == NULL) { 407 _XEatData(dpy, rep.count * sizeof repBuffer); 408 UnlockDisplay(dpy); 409 SyncHandle(); 410 return NULL; 411 } 412 413 for (i = 0; i < rep.count; i++) { 414 _XReadPad(dpy, (char *) &repBuffer, sizeof repBuffer); 415 buffers[i].attachment = repBuffer.attachment; 416 buffers[i].name = repBuffer.name; 417 buffers[i].pitch = repBuffer.pitch; 418 buffers[i].cpp = repBuffer.cpp; 419 buffers[i].flags = repBuffer.flags; 420 } 421 422 UnlockDisplay(dpy); 423 SyncHandle(); 424 425 return buffers; 426} 427 428 429DRI2Buffer * 430DRI2GetBuffersWithFormat(Display * dpy, XID drawable, 431 int *width, int *height, 432 unsigned int *attachments, int count, int *outCount) 433{ 434 XExtDisplayInfo *info = DRI2FindDisplay(dpy); 435 xDRI2GetBuffersReply rep; 436 xDRI2GetBuffersReq *req; 437 DRI2Buffer *buffers; 438 xDRI2Buffer repBuffer; 439 CARD32 *p; 440 int i; 441 442 XextCheckExtension(dpy, info, dri2ExtensionName, False); 443 444 LockDisplay(dpy); 445 GetReqExtra(DRI2GetBuffers, count * (4 * 2), req); 446 req->reqType = info->codes->major_opcode; 447 req->dri2ReqType = X_DRI2GetBuffersWithFormat; 448 req->drawable = drawable; 449 req->count = count; 450 p = (CARD32 *) & req[1]; 451 for (i = 0; i < (count * 2); i++) 452 p[i] = attachments[i]; 453 454 if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) { 455 UnlockDisplay(dpy); 456 SyncHandle(); 457 return NULL; 458 } 459 460 *width = rep.width; 461 *height = rep.height; 462 *outCount = rep.count; 463 464 buffers = Xmalloc(rep.count * sizeof buffers[0]); 465 if (buffers == NULL) { 466 _XEatData(dpy, rep.count * sizeof repBuffer); 467 UnlockDisplay(dpy); 468 SyncHandle(); 469 return NULL; 470 } 471 472 for (i = 0; i < rep.count; i++) { 473 _XReadPad(dpy, (char *) &repBuffer, sizeof repBuffer); 474 buffers[i].attachment = repBuffer.attachment; 475 buffers[i].name = repBuffer.name; 476 buffers[i].pitch = repBuffer.pitch; 477 buffers[i].cpp = repBuffer.cpp; 478 buffers[i].flags = repBuffer.flags; 479 } 480 481 UnlockDisplay(dpy); 482 SyncHandle(); 483 484 return buffers; 485} 486 487 488void 489DRI2CopyRegion(Display * dpy, XID drawable, XserverRegion region, 490 CARD32 dest, CARD32 src) 491{ 492 XExtDisplayInfo *info = DRI2FindDisplay(dpy); 493 xDRI2CopyRegionReq *req; 494 xDRI2CopyRegionReply rep; 495 496 XextSimpleCheckExtension(dpy, info, dri2ExtensionName); 497 498 LockDisplay(dpy); 499 GetReq(DRI2CopyRegion, req); 500 req->reqType = info->codes->major_opcode; 501 req->dri2ReqType = X_DRI2CopyRegion; 502 req->drawable = drawable; 503 req->region = region; 504 req->dest = dest; 505 req->src = src; 506 507 _XReply(dpy, (xReply *) & rep, 0, xFalse); 508 509 UnlockDisplay(dpy); 510 SyncHandle(); 511} 512 513#ifdef X_DRI2SwapBuffers 514static void 515load_swap_req(xDRI2SwapBuffersReq *req, CARD64 target, CARD64 divisor, 516 CARD64 remainder) 517{ 518 req->target_msc_hi = target >> 32; 519 req->target_msc_lo = target & 0xffffffff; 520 req->divisor_hi = divisor >> 32; 521 req->divisor_lo = divisor & 0xffffffff; 522 req->remainder_hi = remainder >> 32; 523 req->remainder_lo = remainder & 0xffffffff; 524} 525 526static CARD64 527vals_to_card64(CARD32 lo, CARD32 hi) 528{ 529 return (CARD64)hi << 32 | lo; 530} 531 532void DRI2SwapBuffers(Display *dpy, XID drawable, CARD64 target_msc, 533 CARD64 divisor, CARD64 remainder, CARD64 *count) 534{ 535 XExtDisplayInfo *info = DRI2FindDisplay(dpy); 536 xDRI2SwapBuffersReq *req; 537 xDRI2SwapBuffersReply rep; 538 539 XextSimpleCheckExtension (dpy, info, dri2ExtensionName); 540 541 LockDisplay(dpy); 542 GetReq(DRI2SwapBuffers, req); 543 req->reqType = info->codes->major_opcode; 544 req->dri2ReqType = X_DRI2SwapBuffers; 545 req->drawable = drawable; 546 load_swap_req(req, target_msc, divisor, remainder); 547 548 _XReply(dpy, (xReply *)&rep, 0, xFalse); 549 550 *count = vals_to_card64(rep.swap_lo, rep.swap_hi); 551 552 UnlockDisplay(dpy); 553 SyncHandle(); 554} 555#endif 556 557#ifdef X_DRI2GetMSC 558Bool DRI2GetMSC(Display *dpy, XID drawable, CARD64 *ust, CARD64 *msc, 559 CARD64 *sbc) 560{ 561 XExtDisplayInfo *info = DRI2FindDisplay(dpy); 562 xDRI2GetMSCReq *req; 563 xDRI2MSCReply rep; 564 565 XextCheckExtension (dpy, info, dri2ExtensionName, False); 566 567 LockDisplay(dpy); 568 GetReq(DRI2GetMSC, req); 569 req->reqType = info->codes->major_opcode; 570 req->dri2ReqType = X_DRI2GetMSC; 571 req->drawable = drawable; 572 573 if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) { 574 UnlockDisplay(dpy); 575 SyncHandle(); 576 return False; 577 } 578 579 *ust = vals_to_card64(rep.ust_lo, rep.ust_hi); 580 *msc = vals_to_card64(rep.msc_lo, rep.msc_hi); 581 *sbc = vals_to_card64(rep.sbc_lo, rep.sbc_hi); 582 583 UnlockDisplay(dpy); 584 SyncHandle(); 585 586 return True; 587} 588#endif 589 590#ifdef X_DRI2WaitMSC 591static void 592load_msc_req(xDRI2WaitMSCReq *req, CARD64 target, CARD64 divisor, 593 CARD64 remainder) 594{ 595 req->target_msc_hi = target >> 32; 596 req->target_msc_lo = target & 0xffffffff; 597 req->divisor_hi = divisor >> 32; 598 req->divisor_lo = divisor & 0xffffffff; 599 req->remainder_hi = remainder >> 32; 600 req->remainder_lo = remainder & 0xffffffff; 601} 602 603Bool DRI2WaitMSC(Display *dpy, XID drawable, CARD64 target_msc, CARD64 divisor, 604 CARD64 remainder, CARD64 *ust, CARD64 *msc, CARD64 *sbc) 605{ 606 XExtDisplayInfo *info = DRI2FindDisplay(dpy); 607 xDRI2WaitMSCReq *req; 608 xDRI2MSCReply rep; 609 610 XextCheckExtension (dpy, info, dri2ExtensionName, False); 611 612 LockDisplay(dpy); 613 GetReq(DRI2WaitMSC, req); 614 req->reqType = info->codes->major_opcode; 615 req->dri2ReqType = X_DRI2WaitMSC; 616 req->drawable = drawable; 617 load_msc_req(req, target_msc, divisor, remainder); 618 619 if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) { 620 UnlockDisplay(dpy); 621 SyncHandle(); 622 return False; 623 } 624 625 *ust = ((CARD64)rep.ust_hi << 32) | (CARD64)rep.ust_lo; 626 *msc = ((CARD64)rep.msc_hi << 32) | (CARD64)rep.msc_lo; 627 *sbc = ((CARD64)rep.sbc_hi << 32) | (CARD64)rep.sbc_lo; 628 629 UnlockDisplay(dpy); 630 SyncHandle(); 631 632 return True; 633} 634#endif 635 636#ifdef X_DRI2WaitSBC 637static void 638load_sbc_req(xDRI2WaitSBCReq *req, CARD64 target) 639{ 640 req->target_sbc_hi = target >> 32; 641 req->target_sbc_lo = target & 0xffffffff; 642} 643 644Bool DRI2WaitSBC(Display *dpy, XID drawable, CARD64 target_sbc, CARD64 *ust, 645 CARD64 *msc, CARD64 *sbc) 646{ 647 XExtDisplayInfo *info = DRI2FindDisplay(dpy); 648 xDRI2WaitSBCReq *req; 649 xDRI2MSCReply rep; 650 651 XextCheckExtension (dpy, info, dri2ExtensionName, False); 652 653 LockDisplay(dpy); 654 GetReq(DRI2WaitSBC, req); 655 req->reqType = info->codes->major_opcode; 656 req->dri2ReqType = X_DRI2WaitSBC; 657 req->drawable = drawable; 658 load_sbc_req(req, target_sbc); 659 660 if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) { 661 UnlockDisplay(dpy); 662 SyncHandle(); 663 return False; 664 } 665 666 *ust = ((CARD64)rep.ust_hi << 32) | rep.ust_lo; 667 *msc = ((CARD64)rep.msc_hi << 32) | rep.msc_lo; 668 *sbc = ((CARD64)rep.sbc_hi << 32) | rep.sbc_lo; 669 670 UnlockDisplay(dpy); 671 SyncHandle(); 672 673 return True; 674} 675#endif 676 677#ifdef X_DRI2SwapInterval 678void DRI2SwapInterval(Display *dpy, XID drawable, int interval) 679{ 680 XExtDisplayInfo *info = DRI2FindDisplay(dpy); 681 xDRI2SwapIntervalReq *req; 682 683 XextSimpleCheckExtension (dpy, info, dri2ExtensionName); 684 685 LockDisplay(dpy); 686 GetReq(DRI2SwapInterval, req); 687 req->reqType = info->codes->major_opcode; 688 req->dri2ReqType = X_DRI2SwapInterval; 689 req->drawable = drawable; 690 req->interval = interval; 691 UnlockDisplay(dpy); 692 SyncHandle(); 693} 694#endif 695 696#endif /* GLX_DIRECT_RENDERING */ 697