Don't handle DRI2 events on emulator
[platform/core/uifw/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 #ifndef _EMUL_
269    for (i = 0; i < nevents; i++) {
270        XESetWireToEvent (dpy, info->codes->first_event + i, DRI2WireToEvent);
271        XESetEventToWire (dpy, info->codes->first_event + i, DRI2EventToWire);
272    }
273 #endif
274
275    return True;
276 }
277
278 Bool
279 DRI2Connect(Display * dpy, XID window, char **driverName, char **deviceName)
280 {
281    XExtDisplayInfo *info = DRI2FindDisplay(dpy);
282    xDRI2ConnectReply rep;
283    xDRI2ConnectReq *req;
284
285    XextCheckExtension(dpy, info, dri2ExtensionName, False);
286
287    LockDisplay(dpy);
288    GetReq(DRI2Connect, req);
289    req->reqType = info->codes->major_opcode;
290    req->dri2ReqType = X_DRI2Connect;
291    req->window = window;
292    req->driverType = DRI2DriverDRI;
293    if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
294       UnlockDisplay(dpy);
295       SyncHandle();
296       return False;
297    }
298
299    if (rep.driverNameLength == 0 && rep.deviceNameLength == 0) {
300       UnlockDisplay(dpy);
301       SyncHandle();
302       return False;
303    }
304
305    *driverName = Xmalloc(rep.driverNameLength + 1);
306    if (*driverName == NULL) {
307       _XEatData(dpy,
308                 ((rep.driverNameLength + 3) & ~3) +
309                 ((rep.deviceNameLength + 3) & ~3));
310       UnlockDisplay(dpy);
311       SyncHandle();
312       return False;
313    }
314    _XReadPad(dpy, *driverName, rep.driverNameLength);
315    (*driverName)[rep.driverNameLength] = '\0';
316
317    *deviceName = Xmalloc(rep.deviceNameLength + 1);
318    if (*deviceName == NULL) {
319       Xfree(*driverName);
320       _XEatData(dpy, ((rep.deviceNameLength + 3) & ~3));
321       UnlockDisplay(dpy);
322       SyncHandle();
323       return False;
324    }
325    _XReadPad(dpy, *deviceName, rep.deviceNameLength);
326    (*deviceName)[rep.deviceNameLength] = '\0';
327
328    UnlockDisplay(dpy);
329    SyncHandle();
330
331    return True;
332 }
333
334 Bool
335 DRI2Authenticate(Display * dpy, XID window, unsigned int magic)
336 {
337    XExtDisplayInfo *info = DRI2FindDisplay(dpy);
338    xDRI2AuthenticateReq *req;
339    xDRI2AuthenticateReply rep;
340
341    XextCheckExtension(dpy, info, dri2ExtensionName, False);
342
343    LockDisplay(dpy);
344    GetReq(DRI2Authenticate, req);
345    req->reqType = info->codes->major_opcode;
346    req->dri2ReqType = X_DRI2Authenticate;
347    req->window = window;
348    req->magic = magic;
349
350    if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
351       UnlockDisplay(dpy);
352       SyncHandle();
353       return False;
354    }
355
356    UnlockDisplay(dpy);
357    SyncHandle();
358
359    return rep.authenticated;
360 }
361
362 void
363 DRI2CreateDrawable(Display * dpy, XID drawable)
364 {
365     XExtDisplayInfo *info = DRI2FindDisplay(dpy);
366     xDRI2CreateDrawableReq *req;
367
368     XextSimpleCheckExtension(dpy, info, dri2ExtensionName);
369     LockDisplay(dpy);
370
371     LOG("CREATE drawable:0x%x\n", (unsigned int)drawable);
372
373     GetReq(DRI2CreateDrawable, req);
374     req->reqType = info->codes->major_opcode;
375     req->dri2ReqType = X_DRI2CreateDrawable;
376     req->drawable = drawable;
377     UnlockDisplay(dpy);
378     SyncHandle();
379 }
380
381 void
382 DRI2DestroyDrawable(Display * dpy, XID drawable)
383 {
384     XExtDisplayInfo *info = DRI2FindDisplay(dpy);
385     xDRI2DestroyDrawableReq *req;
386
387     XextSimpleCheckExtension(dpy, info, dri2ExtensionName);
388     XSync(dpy, False);
389     LockDisplay(dpy);
390
391     LOG("DESTROY drawable:0x%x\n", (unsigned int)drawable);
392
393     GetReq(DRI2DestroyDrawable, req);
394     req->reqType = info->codes->major_opcode;
395     req->dri2ReqType = X_DRI2DestroyDrawable;
396     req->drawable = drawable;
397     UnlockDisplay(dpy);
398     SyncHandle();
399 }
400
401 DRI2Buffer *
402 DRI2GetBuffers(Display * dpy, XID drawable,
403                int *width, int *height,
404                unsigned int *attachments, int count, int *outCount)
405 {
406     XExtDisplayInfo *info = DRI2FindDisplay(dpy);
407     xDRI2GetBuffersReply rep;
408     xDRI2GetBuffersReq *req;
409     DRI2Buffer *buffers;
410     xDRI2Buffer repBuffer;
411     CARD32 *p;
412     int i;
413
414     XextCheckExtension(dpy, info, dri2ExtensionName, False);
415     LockDisplay(dpy);
416
417 #if GFXLOG
418     GFX_PERF("DRAW_S");
419 #endif
420
421     LOG("GET-BUF drawable:0x%x, count:%d, attach:%d \n"
422                 , (unsigned int)drawable, count, *attachments);
423
424     GetReqExtra(DRI2GetBuffers, count * 4, req);
425     req->reqType = info->codes->major_opcode;
426     req->dri2ReqType = X_DRI2GetBuffers;
427     req->drawable = drawable;
428     req->count = count;
429     p = (CARD32 *) & req[1];
430     for (i = 0; i < count; i++)
431         p[i] = attachments[i];
432
433     if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
434         UnlockDisplay(dpy);
435         SyncHandle();
436         return NULL;
437     }
438
439     *width = rep.width;
440     *height = rep.height;
441     *outCount = rep.count;
442
443     buffers = Xmalloc(rep.count * sizeof buffers[0]);
444     if (buffers == NULL) {
445         _XEatData(dpy, rep.count * sizeof repBuffer);
446         UnlockDisplay(dpy);
447         SyncHandle();
448         return NULL;
449     }
450
451     for (i = 0; i < rep.count; i++) {
452         _XReadPad(dpy, (char *) &repBuffer, sizeof repBuffer);
453         buffers[i].attachment = repBuffer.attachment;
454         buffers[i].name = repBuffer.name;
455         buffers[i].pitch = repBuffer.pitch;
456         buffers[i].cpp = repBuffer.cpp;
457         buffers[i].flags = repBuffer.flags;
458
459         LOG("\t\t New attach:%d name:%d flags:0x%x width:%d, height:%d\n"
460                 , buffers[i].attachment, buffers[i].name, buffers[i].flags, *width, *height);
461     }
462
463 #if GFXLOG
464     if(buffers)
465         GFX_PERF_INT("G", buffers[0].name);
466 #endif
467
468     UnlockDisplay(dpy);
469     SyncHandle();
470
471     return buffers;
472 }
473
474
475 DRI2Buffer *
476 DRI2GetBuffersWithFormat(Display * dpy, XID drawable,
477                          int *width, int *height,
478                          unsigned int *attachments, int count, int *outCount)
479 {
480     XExtDisplayInfo *info = DRI2FindDisplay(dpy);
481     xDRI2GetBuffersReply rep;
482     xDRI2GetBuffersReq *req;
483     DRI2Buffer *buffers;
484     xDRI2Buffer repBuffer;
485     CARD32 *p;
486     int i;
487
488     XextCheckExtension(dpy, info, dri2ExtensionName, False);
489     LockDisplay(dpy);
490
491     GetReqExtra(DRI2GetBuffers, count * (4 * 2), req);
492     req->reqType = info->codes->major_opcode;
493     req->dri2ReqType = X_DRI2GetBuffersWithFormat;
494     req->drawable = drawable;
495     req->count = count;
496     p = (CARD32 *) & req[1];
497     for (i = 0; i < (count * 2); i++)
498         p[i] = attachments[i];
499
500     if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
501         UnlockDisplay(dpy);
502         SyncHandle();
503         return NULL;
504     }
505
506     *width = rep.width;
507     *height = rep.height;
508     *outCount = rep.count;
509
510     buffers = Xmalloc(rep.count * sizeof buffers[0]);
511     if (buffers == NULL) {
512         _XEatData(dpy, rep.count * sizeof repBuffer);
513         UnlockDisplay(dpy);
514         SyncHandle();
515         return NULL;
516     }
517
518     for (i = 0; i < rep.count; i++) {
519         _XReadPad(dpy, (char *) &repBuffer, sizeof repBuffer);
520         buffers[i].attachment = repBuffer.attachment;
521         buffers[i].name = repBuffer.name;
522         buffers[i].pitch = repBuffer.pitch;
523         buffers[i].cpp = repBuffer.cpp;
524         buffers[i].flags = repBuffer.flags;
525     }
526
527     UnlockDisplay(dpy);
528     SyncHandle();
529
530     return buffers;
531 }
532
533
534 void
535 DRI2CopyRegion(Display * dpy, XID drawable, XserverRegion region,
536                CARD32 dest, CARD32 src)
537 {
538     XExtDisplayInfo *info = DRI2FindDisplay(dpy);
539     xDRI2CopyRegionReq *req;
540     xDRI2CopyRegionReply rep;
541
542     XextSimpleCheckExtension(dpy, info, dri2ExtensionName);
543
544     LOG("COPY-REGION drawable:0x%x, src:%d, dest:%d\n", (unsigned int)drawable, (int)src, (int)dest);
545
546     LockDisplay(dpy);
547     GetReq(DRI2CopyRegion, req);
548     req->reqType = info->codes->major_opcode;
549     req->dri2ReqType = X_DRI2CopyRegion;
550     req->drawable = drawable;
551     req->region = region;
552     req->dest = dest;
553     req->src = src;
554
555     _XReply(dpy, (xReply *) & rep, 0, xFalse);
556
557     UnlockDisplay(dpy);
558     SyncHandle();
559 }
560
561 #ifdef X_DRI2SwapBuffers
562 static void
563 load_swap_req(xDRI2SwapBuffersReq *req, CARD64 target, CARD64 divisor,
564              CARD64 remainder)
565 {
566     req->target_msc_hi = target >> 32;
567     req->target_msc_lo = target & 0xffffffff;
568     req->divisor_hi = divisor >> 32;
569     req->divisor_lo = divisor & 0xffffffff;
570     req->remainder_hi = remainder >> 32;
571     req->remainder_lo = remainder & 0xffffffff;
572 }
573
574 static CARD64
575 vals_to_card64(CARD32 lo, CARD32 hi)
576 {
577     return (CARD64)hi << 32 | lo;
578 }
579
580 void DRI2SwapBuffers(Display *dpy, XID drawable, CARD64 target_msc,
581                      CARD64 divisor, CARD64 remainder, CARD64 *count)
582 {
583     XExtDisplayInfo *info = DRI2FindDisplay(dpy);
584     xDRI2SwapBuffersReq *req;
585     xDRI2SwapBuffersReply rep;
586
587     XextSimpleCheckExtension (dpy, info, dri2ExtensionName);
588     LockDisplay(dpy);
589
590     LOG("SWAP drawable:0x%x\n", (unsigned int)drawable);
591
592     GetReq(DRI2SwapBuffers, req);
593     req->reqType = info->codes->major_opcode;
594     req->dri2ReqType = X_DRI2SwapBuffers;
595     req->drawable = drawable;
596     load_swap_req(req, target_msc, divisor, remainder);
597
598     _XReply(dpy, (xReply *)&rep, 0, xFalse);
599
600     *count = vals_to_card64(rep.swap_lo, rep.swap_hi);
601
602 #if GFXLOG
603     GFX_PERF("DRAW_E");
604 #endif
605
606     UnlockDisplay(dpy);
607     SyncHandle();
608 }
609 #endif
610
611 #ifdef X_DRI2GetMSC
612 Bool DRI2GetMSC(Display *dpy, XID drawable, CARD64 *ust, CARD64 *msc,
613                 CARD64 *sbc)
614 {
615     XExtDisplayInfo *info = DRI2FindDisplay(dpy);
616     xDRI2GetMSCReq *req;
617     xDRI2MSCReply rep;
618
619     XextCheckExtension (dpy, info, dri2ExtensionName, False);
620
621     LockDisplay(dpy);
622     GetReq(DRI2GetMSC, req);
623     req->reqType = info->codes->major_opcode;
624     req->dri2ReqType = X_DRI2GetMSC;
625     req->drawable = drawable;
626
627     if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
628         UnlockDisplay(dpy);
629         SyncHandle();
630         return False;
631     }
632
633     *ust = vals_to_card64(rep.ust_lo, rep.ust_hi);
634     *msc = vals_to_card64(rep.msc_lo, rep.msc_hi);
635     *sbc = vals_to_card64(rep.sbc_lo, rep.sbc_hi);
636
637     UnlockDisplay(dpy);
638     SyncHandle();
639
640     return True;
641 }
642 #endif
643
644 #ifdef X_DRI2WaitMSC
645 static void
646 load_msc_req(xDRI2WaitMSCReq *req, CARD64 target, CARD64 divisor,
647              CARD64 remainder)
648 {
649     req->target_msc_hi = target >> 32;
650     req->target_msc_lo = target & 0xffffffff;
651     req->divisor_hi = divisor >> 32;
652     req->divisor_lo = divisor & 0xffffffff;
653     req->remainder_hi = remainder >> 32;
654     req->remainder_lo = remainder & 0xffffffff;
655 }
656
657 Bool DRI2WaitMSC(Display *dpy, XID drawable, CARD64 target_msc, CARD64 divisor,
658                  CARD64 remainder, CARD64 *ust, CARD64 *msc, CARD64 *sbc)
659 {
660     XExtDisplayInfo *info = DRI2FindDisplay(dpy);
661     xDRI2WaitMSCReq *req;
662     xDRI2MSCReply rep;
663
664     XextCheckExtension (dpy, info, dri2ExtensionName, False);
665
666     LockDisplay(dpy);
667     GetReq(DRI2WaitMSC, req);
668     req->reqType = info->codes->major_opcode;
669     req->dri2ReqType = X_DRI2WaitMSC;
670     req->drawable = drawable;
671     load_msc_req(req, target_msc, divisor, remainder);
672
673     if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
674         UnlockDisplay(dpy);
675         SyncHandle();
676         return False;
677     }
678
679     *ust = ((CARD64)rep.ust_hi << 32) | (CARD64)rep.ust_lo;
680     *msc = ((CARD64)rep.msc_hi << 32) | (CARD64)rep.msc_lo;
681     *sbc = ((CARD64)rep.sbc_hi << 32) | (CARD64)rep.sbc_lo;
682
683     UnlockDisplay(dpy);
684     SyncHandle();
685
686     return True;
687 }
688 #endif
689
690 #ifdef X_DRI2WaitSBC
691 static void
692 load_sbc_req(xDRI2WaitSBCReq *req, CARD64 target)
693 {
694     req->target_sbc_hi = target >> 32;
695     req->target_sbc_lo = target & 0xffffffff;
696 }
697
698 Bool DRI2WaitSBC(Display *dpy, XID drawable, CARD64 target_sbc, CARD64 *ust,
699                  CARD64 *msc, CARD64 *sbc)
700 {
701     XExtDisplayInfo *info = DRI2FindDisplay(dpy);
702     xDRI2WaitSBCReq *req;
703     xDRI2MSCReply rep;
704
705     XextCheckExtension (dpy, info, dri2ExtensionName, False);
706
707     LockDisplay(dpy);
708     GetReq(DRI2WaitSBC, req);
709     req->reqType = info->codes->major_opcode;
710     req->dri2ReqType = X_DRI2WaitSBC;
711     req->drawable = drawable;
712     load_sbc_req(req, target_sbc);
713
714     if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
715         UnlockDisplay(dpy);
716         SyncHandle();
717         return False;
718     }
719
720     *ust = ((CARD64)rep.ust_hi << 32) | rep.ust_lo;
721     *msc = ((CARD64)rep.msc_hi << 32) | rep.msc_lo;
722     *sbc = ((CARD64)rep.sbc_hi << 32) | rep.sbc_lo;
723
724     UnlockDisplay(dpy);
725     SyncHandle();
726
727     return True;
728 }
729 #endif
730
731 #ifdef X_DRI2SwapInterval
732 void DRI2SwapInterval(Display *dpy, XID drawable, int interval)
733 {
734     XExtDisplayInfo *info = DRI2FindDisplay(dpy);
735     xDRI2SwapIntervalReq *req;
736
737     XextSimpleCheckExtension (dpy, info, dri2ExtensionName);
738
739     LockDisplay(dpy);
740     GetReq(DRI2SwapInterval, req);
741     req->reqType = info->codes->major_opcode;
742     req->dri2ReqType = X_DRI2SwapInterval;
743     req->drawable = drawable;
744     req->interval = interval;
745     UnlockDisplay(dpy);
746     SyncHandle();
747 }
748 #endif
749
750 #ifdef X_DRI2SwapBuffersWithRegion
751 void DRI2SwapBuffersWithRegion(Display *dpy, XID drawable, XserverRegion region,
752                 CARD64 *count)
753 {
754     XExtDisplayInfo *info = DRI2FindDisplay(dpy);
755     xDRI2SwapBuffersWithRegionReq *req;
756     xDRI2SwapBuffersReply rep;
757
758     XextSimpleCheckExtension (dpy, info, dri2ExtensionName);
759     LockDisplay(dpy);
760
761     LOG("SWAP drawable:0x%x\n", (unsigned int)drawable);
762
763     GetReq(DRI2SwapBuffersWithRegion, req);
764     req->reqType = info->codes->major_opcode;
765     req->dri2ReqType = X_DRI2SwapBuffersWithRegion;
766     req->drawable = drawable;
767     req->region = region;
768
769     _XReply(dpy, (xReply *)&rep, 0, xFalse);
770
771     *count = vals_to_card64(rep.swap_lo, rep.swap_hi);
772
773 #if GFXLOG
774     GFX_PERF("DRAW_E");
775 #endif
776
777     UnlockDisplay(dpy);
778     SyncHandle();
779 }
780 #endif