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