Home | History | Annotate | Download | only in glx
      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 Hgsberg (krh (at) 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 
     56 static char dri2ExtensionName[] = DRI2_NAME;
     57 static XExtensionInfo *dri2Info;
     58 static XEXT_GENERATE_CLOSE_DISPLAY (DRI2CloseDisplay, dri2Info)
     59 
     60 static Bool
     61 DRI2WireToEvent(Display *dpy, XEvent *event, xEvent *wire);
     62 static Status
     63 DRI2EventToWire(Display *dpy, XEvent *event, xEvent *wire);
     64 static int
     65 DRI2Error(Display *display, xError *err, XExtCodes *codes, int *ret_code);
     66 
     67 static /* 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 
     81 static XEXT_GENERATE_FIND_DISPLAY (DRI2FindDisplay,
     82                                    dri2Info,
     83                                    dri2ExtensionName,
     84                                    &dri2ExtensionHooks,
     85                                    0, NULL)
     86 
     87 static Bool
     88 DRI2WireToEvent(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  */
    161 static Status
    162 DRI2EventToWire(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 
    177 static int
    178 DRI2Error(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 
    205 Bool
    206 DRI2QueryExtension(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 
    219 Bool
    220 DRI2QueryVersion(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 
    266 Bool
    267 DRI2Connect(Display * dpy, XID window, char **driverName, char **deviceName)
    268 {
    269    XExtDisplayInfo *info = DRI2FindDisplay(dpy);
    270    xDRI2ConnectReply rep;
    271    xDRI2ConnectReq *req;
    272    char *prime;
    273 
    274    XextCheckExtension(dpy, info, dri2ExtensionName, False);
    275 
    276    LockDisplay(dpy);
    277    GetReq(DRI2Connect, req);
    278    req->reqType = info->codes->major_opcode;
    279    req->dri2ReqType = X_DRI2Connect;
    280    req->window = window;
    281 
    282    req->driverType = DRI2DriverDRI;
    283 #ifdef DRI2DriverPrimeShift
    284    prime = getenv("DRI_PRIME");
    285    if (prime) {
    286       uint32_t primeid;
    287       errno = 0;
    288       primeid = strtoul(prime, NULL, 0);
    289       if (errno == 0)
    290          req->driverType |= ((primeid & DRI2DriverPrimeMask) << DRI2DriverPrimeShift);
    291    }
    292 #endif
    293 
    294    if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
    295       UnlockDisplay(dpy);
    296       SyncHandle();
    297       return False;
    298    }
    299 
    300    if (rep.driverNameLength == 0 && rep.deviceNameLength == 0) {
    301       UnlockDisplay(dpy);
    302       SyncHandle();
    303       return False;
    304    }
    305 
    306    *driverName = Xmalloc(rep.driverNameLength + 1);
    307    if (*driverName == NULL) {
    308       _XEatData(dpy,
    309                 ((rep.driverNameLength + 3) & ~3) +
    310                 ((rep.deviceNameLength + 3) & ~3));
    311       UnlockDisplay(dpy);
    312       SyncHandle();
    313       return False;
    314    }
    315    _XReadPad(dpy, *driverName, rep.driverNameLength);
    316    (*driverName)[rep.driverNameLength] = '\0';
    317 
    318    *deviceName = Xmalloc(rep.deviceNameLength + 1);
    319    if (*deviceName == NULL) {
    320       Xfree(*driverName);
    321       _XEatData(dpy, ((rep.deviceNameLength + 3) & ~3));
    322       UnlockDisplay(dpy);
    323       SyncHandle();
    324       return False;
    325    }
    326    _XReadPad(dpy, *deviceName, rep.deviceNameLength);
    327    (*deviceName)[rep.deviceNameLength] = '\0';
    328 
    329    UnlockDisplay(dpy);
    330    SyncHandle();
    331 
    332    return True;
    333 }
    334 
    335 Bool
    336 DRI2Authenticate(Display * dpy, XID window, drm_magic_t magic)
    337 {
    338    XExtDisplayInfo *info = DRI2FindDisplay(dpy);
    339    xDRI2AuthenticateReq *req;
    340    xDRI2AuthenticateReply rep;
    341 
    342    XextCheckExtension(dpy, info, dri2ExtensionName, False);
    343 
    344    LockDisplay(dpy);
    345    GetReq(DRI2Authenticate, req);
    346    req->reqType = info->codes->major_opcode;
    347    req->dri2ReqType = X_DRI2Authenticate;
    348    req->window = window;
    349    req->magic = magic;
    350 
    351    if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
    352       UnlockDisplay(dpy);
    353       SyncHandle();
    354       return False;
    355    }
    356 
    357    UnlockDisplay(dpy);
    358    SyncHandle();
    359 
    360    return rep.authenticated;
    361 }
    362 
    363 void
    364 DRI2CreateDrawable(Display * dpy, XID drawable)
    365 {
    366    XExtDisplayInfo *info = DRI2FindDisplay(dpy);
    367    xDRI2CreateDrawableReq *req;
    368 
    369    XextSimpleCheckExtension(dpy, info, dri2ExtensionName);
    370 
    371    LockDisplay(dpy);
    372    GetReq(DRI2CreateDrawable, req);
    373    req->reqType = info->codes->major_opcode;
    374    req->dri2ReqType = X_DRI2CreateDrawable;
    375    req->drawable = drawable;
    376    UnlockDisplay(dpy);
    377    SyncHandle();
    378 }
    379 
    380 void
    381 DRI2DestroyDrawable(Display * dpy, XID drawable)
    382 {
    383    XExtDisplayInfo *info = DRI2FindDisplay(dpy);
    384    xDRI2DestroyDrawableReq *req;
    385 
    386    XextSimpleCheckExtension(dpy, info, dri2ExtensionName);
    387 
    388    XSync(dpy, False);
    389 
    390    LockDisplay(dpy);
    391    GetReq(DRI2DestroyDrawable, req);
    392    req->reqType = info->codes->major_opcode;
    393    req->dri2ReqType = X_DRI2DestroyDrawable;
    394    req->drawable = drawable;
    395    UnlockDisplay(dpy);
    396    SyncHandle();
    397 }
    398 
    399 DRI2Buffer *
    400 DRI2GetBuffers(Display * dpy, XID drawable,
    401                int *width, int *height,
    402                unsigned int *attachments, int count, int *outCount)
    403 {
    404    XExtDisplayInfo *info = DRI2FindDisplay(dpy);
    405    xDRI2GetBuffersReply rep;
    406    xDRI2GetBuffersReq *req;
    407    DRI2Buffer *buffers;
    408    xDRI2Buffer repBuffer;
    409    CARD32 *p;
    410    int i;
    411 
    412    XextCheckExtension(dpy, info, dri2ExtensionName, False);
    413 
    414    LockDisplay(dpy);
    415    GetReqExtra(DRI2GetBuffers, count * 4, req);
    416    req->reqType = info->codes->major_opcode;
    417    req->dri2ReqType = X_DRI2GetBuffers;
    418    req->drawable = drawable;
    419    req->count = count;
    420    p = (CARD32 *) & req[1];
    421    for (i = 0; i < count; i++)
    422       p[i] = attachments[i];
    423 
    424    if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
    425       UnlockDisplay(dpy);
    426       SyncHandle();
    427       return NULL;
    428    }
    429 
    430    *width = rep.width;
    431    *height = rep.height;
    432    *outCount = rep.count;
    433 
    434    buffers = Xmalloc(rep.count * sizeof buffers[0]);
    435    if (buffers == NULL) {
    436       _XEatData(dpy, rep.count * sizeof repBuffer);
    437       UnlockDisplay(dpy);
    438       SyncHandle();
    439       return NULL;
    440    }
    441 
    442    for (i = 0; i < rep.count; i++) {
    443       _XReadPad(dpy, (char *) &repBuffer, sizeof repBuffer);
    444       buffers[i].attachment = repBuffer.attachment;
    445       buffers[i].name = repBuffer.name;
    446       buffers[i].pitch = repBuffer.pitch;
    447       buffers[i].cpp = repBuffer.cpp;
    448       buffers[i].flags = repBuffer.flags;
    449    }
    450 
    451    UnlockDisplay(dpy);
    452    SyncHandle();
    453 
    454    return buffers;
    455 }
    456 
    457 
    458 DRI2Buffer *
    459 DRI2GetBuffersWithFormat(Display * dpy, XID drawable,
    460                          int *width, int *height,
    461                          unsigned int *attachments, int count, int *outCount)
    462 {
    463    XExtDisplayInfo *info = DRI2FindDisplay(dpy);
    464    xDRI2GetBuffersReply rep;
    465    xDRI2GetBuffersReq *req;
    466    DRI2Buffer *buffers;
    467    xDRI2Buffer repBuffer;
    468    CARD32 *p;
    469    int i;
    470 
    471    XextCheckExtension(dpy, info, dri2ExtensionName, False);
    472 
    473    LockDisplay(dpy);
    474    GetReqExtra(DRI2GetBuffers, count * (4 * 2), req);
    475    req->reqType = info->codes->major_opcode;
    476    req->dri2ReqType = X_DRI2GetBuffersWithFormat;
    477    req->drawable = drawable;
    478    req->count = count;
    479    p = (CARD32 *) & req[1];
    480    for (i = 0; i < (count * 2); i++)
    481       p[i] = attachments[i];
    482 
    483    if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
    484       UnlockDisplay(dpy);
    485       SyncHandle();
    486       return NULL;
    487    }
    488 
    489    *width = rep.width;
    490    *height = rep.height;
    491    *outCount = rep.count;
    492 
    493    buffers = Xmalloc(rep.count * sizeof buffers[0]);
    494    if (buffers == NULL) {
    495       _XEatData(dpy, rep.count * sizeof repBuffer);
    496       UnlockDisplay(dpy);
    497       SyncHandle();
    498       return NULL;
    499    }
    500 
    501    for (i = 0; i < rep.count; i++) {
    502       _XReadPad(dpy, (char *) &repBuffer, sizeof repBuffer);
    503       buffers[i].attachment = repBuffer.attachment;
    504       buffers[i].name = repBuffer.name;
    505       buffers[i].pitch = repBuffer.pitch;
    506       buffers[i].cpp = repBuffer.cpp;
    507       buffers[i].flags = repBuffer.flags;
    508    }
    509 
    510    UnlockDisplay(dpy);
    511    SyncHandle();
    512 
    513    return buffers;
    514 }
    515 
    516 
    517 void
    518 DRI2CopyRegion(Display * dpy, XID drawable, XserverRegion region,
    519                CARD32 dest, CARD32 src)
    520 {
    521    XExtDisplayInfo *info = DRI2FindDisplay(dpy);
    522    xDRI2CopyRegionReq *req;
    523    xDRI2CopyRegionReply rep;
    524 
    525    XextSimpleCheckExtension(dpy, info, dri2ExtensionName);
    526 
    527    LockDisplay(dpy);
    528    GetReq(DRI2CopyRegion, req);
    529    req->reqType = info->codes->major_opcode;
    530    req->dri2ReqType = X_DRI2CopyRegion;
    531    req->drawable = drawable;
    532    req->region = region;
    533    req->dest = dest;
    534    req->src = src;
    535 
    536    _XReply(dpy, (xReply *) & rep, 0, xFalse);
    537 
    538    UnlockDisplay(dpy);
    539    SyncHandle();
    540 }
    541 
    542 #ifdef X_DRI2SwapBuffers
    543 static void
    544 load_swap_req(xDRI2SwapBuffersReq *req, CARD64 target, CARD64 divisor,
    545 	     CARD64 remainder)
    546 {
    547     req->target_msc_hi = target >> 32;
    548     req->target_msc_lo = target & 0xffffffff;
    549     req->divisor_hi = divisor >> 32;
    550     req->divisor_lo = divisor & 0xffffffff;
    551     req->remainder_hi = remainder >> 32;
    552     req->remainder_lo = remainder & 0xffffffff;
    553 }
    554 
    555 static CARD64
    556 vals_to_card64(CARD32 lo, CARD32 hi)
    557 {
    558     return (CARD64)hi << 32 | lo;
    559 }
    560 
    561 void DRI2SwapBuffers(Display *dpy, XID drawable, CARD64 target_msc,
    562 		     CARD64 divisor, CARD64 remainder, CARD64 *count)
    563 {
    564     XExtDisplayInfo *info = DRI2FindDisplay(dpy);
    565     xDRI2SwapBuffersReq *req;
    566     xDRI2SwapBuffersReply rep;
    567 
    568     XextSimpleCheckExtension (dpy, info, dri2ExtensionName);
    569 
    570     LockDisplay(dpy);
    571     GetReq(DRI2SwapBuffers, req);
    572     req->reqType = info->codes->major_opcode;
    573     req->dri2ReqType = X_DRI2SwapBuffers;
    574     req->drawable = drawable;
    575     load_swap_req(req, target_msc, divisor, remainder);
    576 
    577     _XReply(dpy, (xReply *)&rep, 0, xFalse);
    578 
    579     *count = vals_to_card64(rep.swap_lo, rep.swap_hi);
    580 
    581     UnlockDisplay(dpy);
    582     SyncHandle();
    583 }
    584 #endif
    585 
    586 #ifdef X_DRI2GetMSC
    587 Bool DRI2GetMSC(Display *dpy, XID drawable, CARD64 *ust, CARD64 *msc,
    588 		CARD64 *sbc)
    589 {
    590     XExtDisplayInfo *info = DRI2FindDisplay(dpy);
    591     xDRI2GetMSCReq *req;
    592     xDRI2MSCReply rep;
    593 
    594     XextCheckExtension (dpy, info, dri2ExtensionName, False);
    595 
    596     LockDisplay(dpy);
    597     GetReq(DRI2GetMSC, req);
    598     req->reqType = info->codes->major_opcode;
    599     req->dri2ReqType = X_DRI2GetMSC;
    600     req->drawable = drawable;
    601 
    602     if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
    603 	UnlockDisplay(dpy);
    604 	SyncHandle();
    605 	return False;
    606     }
    607 
    608     *ust = vals_to_card64(rep.ust_lo, rep.ust_hi);
    609     *msc = vals_to_card64(rep.msc_lo, rep.msc_hi);
    610     *sbc = vals_to_card64(rep.sbc_lo, rep.sbc_hi);
    611 
    612     UnlockDisplay(dpy);
    613     SyncHandle();
    614 
    615     return True;
    616 }
    617 #endif
    618 
    619 #ifdef X_DRI2WaitMSC
    620 static void
    621 load_msc_req(xDRI2WaitMSCReq *req, CARD64 target, CARD64 divisor,
    622 	     CARD64 remainder)
    623 {
    624     req->target_msc_hi = target >> 32;
    625     req->target_msc_lo = target & 0xffffffff;
    626     req->divisor_hi = divisor >> 32;
    627     req->divisor_lo = divisor & 0xffffffff;
    628     req->remainder_hi = remainder >> 32;
    629     req->remainder_lo = remainder & 0xffffffff;
    630 }
    631 
    632 Bool DRI2WaitMSC(Display *dpy, XID drawable, CARD64 target_msc, CARD64 divisor,
    633 		 CARD64 remainder, CARD64 *ust, CARD64 *msc, CARD64 *sbc)
    634 {
    635     XExtDisplayInfo *info = DRI2FindDisplay(dpy);
    636     xDRI2WaitMSCReq *req;
    637     xDRI2MSCReply rep;
    638 
    639     XextCheckExtension (dpy, info, dri2ExtensionName, False);
    640 
    641     LockDisplay(dpy);
    642     GetReq(DRI2WaitMSC, req);
    643     req->reqType = info->codes->major_opcode;
    644     req->dri2ReqType = X_DRI2WaitMSC;
    645     req->drawable = drawable;
    646     load_msc_req(req, target_msc, divisor, remainder);
    647 
    648     if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
    649 	UnlockDisplay(dpy);
    650 	SyncHandle();
    651 	return False;
    652     }
    653 
    654     *ust = ((CARD64)rep.ust_hi << 32) | (CARD64)rep.ust_lo;
    655     *msc = ((CARD64)rep.msc_hi << 32) | (CARD64)rep.msc_lo;
    656     *sbc = ((CARD64)rep.sbc_hi << 32) | (CARD64)rep.sbc_lo;
    657 
    658     UnlockDisplay(dpy);
    659     SyncHandle();
    660 
    661     return True;
    662 }
    663 #endif
    664 
    665 #ifdef X_DRI2WaitSBC
    666 static void
    667 load_sbc_req(xDRI2WaitSBCReq *req, CARD64 target)
    668 {
    669     req->target_sbc_hi = target >> 32;
    670     req->target_sbc_lo = target & 0xffffffff;
    671 }
    672 
    673 Bool DRI2WaitSBC(Display *dpy, XID drawable, CARD64 target_sbc, CARD64 *ust,
    674 		 CARD64 *msc, CARD64 *sbc)
    675 {
    676     XExtDisplayInfo *info = DRI2FindDisplay(dpy);
    677     xDRI2WaitSBCReq *req;
    678     xDRI2MSCReply rep;
    679 
    680     XextCheckExtension (dpy, info, dri2ExtensionName, False);
    681 
    682     LockDisplay(dpy);
    683     GetReq(DRI2WaitSBC, req);
    684     req->reqType = info->codes->major_opcode;
    685     req->dri2ReqType = X_DRI2WaitSBC;
    686     req->drawable = drawable;
    687     load_sbc_req(req, target_sbc);
    688 
    689     if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
    690 	UnlockDisplay(dpy);
    691 	SyncHandle();
    692 	return False;
    693     }
    694 
    695     *ust = ((CARD64)rep.ust_hi << 32) | rep.ust_lo;
    696     *msc = ((CARD64)rep.msc_hi << 32) | rep.msc_lo;
    697     *sbc = ((CARD64)rep.sbc_hi << 32) | rep.sbc_lo;
    698 
    699     UnlockDisplay(dpy);
    700     SyncHandle();
    701 
    702     return True;
    703 }
    704 #endif
    705 
    706 #ifdef X_DRI2SwapInterval
    707 void DRI2SwapInterval(Display *dpy, XID drawable, int interval)
    708 {
    709     XExtDisplayInfo *info = DRI2FindDisplay(dpy);
    710     xDRI2SwapIntervalReq *req;
    711 
    712     XextSimpleCheckExtension (dpy, info, dri2ExtensionName);
    713 
    714     LockDisplay(dpy);
    715     GetReq(DRI2SwapInterval, req);
    716     req->reqType = info->codes->major_opcode;
    717     req->dri2ReqType = X_DRI2SwapInterval;
    718     req->drawable = drawable;
    719     req->interval = interval;
    720     UnlockDisplay(dpy);
    721     SyncHandle();
    722 }
    723 #endif
    724 
    725 #endif /* GLX_DIRECT_RENDERING */
    726