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