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