dri2video support
[gstreamer-omap:libdri2.git] / src / 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 #ifdef HAVE_CONFIG_H
34 #  include "config.h"
35 #endif
36
37 #define NEED_REPLIES
38 #include <stdio.h>
39 #include <stdint.h>
40 #include <X11/Xlibint.h>
41 #include <X11/extensions/Xext.h>
42 #include <X11/extensions/extutil.h>
43 #include <X11/extensions/dri2proto.h>
44 #include <drm.h>
45 #include <xf86drm.h>
46 #include "list.h"
47 #include "X11/extensions/dri2.h"
48
49 /* Allow the build to work with an older versions of dri2proto.h and
50  * dri2tokens.h.
51  */
52 #if DRI2_MINOR < 1
53 #undef DRI2_MINOR
54 #define DRI2_MINOR 1
55 #define X_DRI2GetBuffersWithFormat 7
56 #endif
57
58
59 static char dri2ExtensionName[] = DRI2_NAME;
60 static XExtensionInfo *dri2Info;
61 static XEXT_GENERATE_CLOSE_DISPLAY (DRI2CloseDisplay2, dri2Info)
62
63 /**
64  * List of per-Display privates..
65  */
66 static struct list dpy_list = { &dpy_list, &dpy_list };
67
68 typedef struct {
69         struct list list;
70         Display *dpy;
71         const DRI2EventOps *ops;
72         int major, minor;
73 } DRI2Display;
74
75 static DRI2Display * dpy2dri(Display *dpy)
76 {
77         DRI2Display *dri2dpy;
78         list_for_each_entry(dri2dpy, &dpy_list, list) {
79                 if (dri2dpy->dpy == dpy) {
80                         return dri2dpy;
81                 }
82         }
83         return NULL;
84 }
85
86 static int
87 DRI2CloseDisplay(Display *dpy, XExtCodes *codes)
88 {
89         DRI2Display *dri2dpy = dpy2dri(dpy);
90         if (dri2dpy) {
91                 list_del(&dri2dpy->list);
92                 free(dri2dpy);
93         }
94         return DRI2CloseDisplay2(dpy, codes);
95 }
96
97 Bool
98 DRI2InitDisplay(Display *dpy, const DRI2EventOps *ops)
99 {
100         DRI2Display *dri2dpy = dpy2dri(dpy);
101         if (!dri2dpy) {
102                 dri2dpy = malloc(sizeof(*dri2dpy));
103                 if (!dri2dpy) {
104                         return False;
105                 }
106                 dri2dpy->dpy = dpy;
107                 dri2dpy->ops = ops;
108                 list_add(&dri2dpy->list, &dpy_list);
109         }
110         return True;
111 }
112
113 static Bool
114 DRI2WireToEvent(Display *dpy, XEvent *event, xEvent *wire);
115 static Status
116 DRI2EventToWire(Display *dpy, XEvent *event, xEvent *wire);
117 static int
118 DRI2Error(Display *display, xError *err, XExtCodes *codes, int *ret_code);
119
120 static /* const */ XExtensionHooks dri2ExtensionHooks = {
121   NULL,                   /* create_gc */
122   NULL,                   /* copy_gc */
123   NULL,                   /* flush_gc */
124   NULL,                   /* free_gc */
125   NULL,                   /* create_font */
126   NULL,                   /* free_font */
127   DRI2CloseDisplay,       /* close_display */
128   DRI2WireToEvent,        /* wire_to_event */
129   DRI2EventToWire,        /* event_to_wire */
130   DRI2Error,              /* error */
131   NULL,                   /* error_string */
132 };
133
134 static XEXT_GENERATE_FIND_DISPLAY (DRI2FindDisplay,
135                                    dri2Info,
136                                    dri2ExtensionName,
137                                    &dri2ExtensionHooks,
138                                    0, NULL)
139
140 static Bool
141 DRI2WireToEvent(Display *dpy, XEvent *event, xEvent *wire)
142 {
143    XExtDisplayInfo *info = DRI2FindDisplay(dpy);
144    DRI2Display *dri2dpy = dpy2dri(dpy);
145
146    XextCheckExtension(dpy, info, dri2ExtensionName, False);
147
148    if (dri2dpy && dri2dpy->ops && dri2dpy->ops->WireToEvent) {
149            return dri2dpy->ops->WireToEvent(dpy, info, event, wire);
150    }
151
152    return False;
153 }
154
155 /* We don't actually support this.  It doesn't make sense for clients to
156  * send each other DRI2 events.
157  */
158 static Status
159 DRI2EventToWire(Display *dpy, XEvent *event, xEvent *wire)
160 {
161    XExtDisplayInfo *info = DRI2FindDisplay(dpy);
162    DRI2Display *dri2dpy = dpy2dri(dpy);
163
164    XextCheckExtension(dpy, info, dri2ExtensionName, False);
165
166    if (dri2dpy && dri2dpy->ops && dri2dpy->ops->EventToWire) {
167            return dri2dpy->ops->EventToWire(dpy, info, event, wire);
168    }
169
170    return Success;
171 }
172
173 static int
174 DRI2Error(Display *dpy, xError *err, XExtCodes *codes, int *ret_code)
175 {
176         DRI2Display *dri2dpy = dpy2dri(dpy);
177
178         if (dri2dpy && dri2dpy->ops && dri2dpy->ops->Error) {
179                 return dri2dpy->ops->Error(dpy, err, codes, ret_code);
180         }
181
182     return False;
183 }
184
185 Bool
186 DRI2QueryExtension(Display * dpy, int *eventBase, int *errorBase)
187 {
188    XExtDisplayInfo *info = DRI2FindDisplay(dpy);
189
190    if (XextHasExtension(info)) {
191       *eventBase = info->codes->first_event;
192       *errorBase = info->codes->first_error;
193       return True;
194    }
195
196    return False;
197 }
198
199 Bool
200 DRI2QueryVersion(Display * dpy, int *major, int *minor)
201 {
202    XExtDisplayInfo *info = DRI2FindDisplay(dpy);
203    DRI2Display *dri2dpy = dpy2dri(dpy);
204    xDRI2QueryVersionReply rep;
205    xDRI2QueryVersionReq *req;
206    int i, nevents;
207
208    XextCheckExtension(dpy, info, dri2ExtensionName, False);
209
210    LockDisplay(dpy);
211    GetReq(DRI2QueryVersion, req);
212    req->reqType = info->codes->major_opcode;
213    req->dri2ReqType = X_DRI2QueryVersion;
214    req->majorVersion = DRI2_MAJOR;
215    req->minorVersion = DRI2_MINOR;
216    if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
217       UnlockDisplay(dpy);
218       SyncHandle();
219       return False;
220    }
221    dri2dpy->major = *major = rep.majorVersion;
222    dri2dpy->minor = *minor = rep.minorVersion;
223    UnlockDisplay(dpy);
224    SyncHandle();
225
226    switch (rep.minorVersion) {
227    case 1:
228            nevents = 0;
229            break;
230    case 2:
231            nevents = 1;
232            break;
233    case 3:
234    default:
235            nevents = 2;
236            break;
237    }
238         
239    for (i = 0; i < nevents; i++) {
240        XESetWireToEvent (dpy, info->codes->first_event + i, DRI2WireToEvent);
241        XESetEventToWire (dpy, info->codes->first_event + i, DRI2EventToWire);
242    }
243
244    return True;
245 }
246
247 Bool
248 DRI2Connect(Display * dpy, XID window,
249                 int driverType, char **driverName, char **deviceName)
250 {
251    XExtDisplayInfo *info = DRI2FindDisplay(dpy);
252    xDRI2ConnectReply rep;
253    xDRI2ConnectReq *req;
254
255    XextCheckExtension(dpy, info, dri2ExtensionName, False);
256
257    LockDisplay(dpy);
258    GetReq(DRI2Connect, req);
259    req->reqType = info->codes->major_opcode;
260    req->dri2ReqType = X_DRI2Connect;
261    req->window = window;
262    req->driverType = driverType;
263    if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
264       UnlockDisplay(dpy);
265       SyncHandle();
266       return False;
267    }
268
269    if (rep.driverNameLength == 0 && rep.deviceNameLength == 0) {
270       UnlockDisplay(dpy);
271       SyncHandle();
272       return False;
273    }
274
275    *driverName = Xmalloc(rep.driverNameLength + 1);
276    if (*driverName == NULL) {
277       _XEatData(dpy,
278                 ((rep.driverNameLength + 3) & ~3) +
279                 ((rep.deviceNameLength + 3) & ~3));
280       UnlockDisplay(dpy);
281       SyncHandle();
282       return False;
283    }
284    _XReadPad(dpy, *driverName, rep.driverNameLength);
285    (*driverName)[rep.driverNameLength] = '\0';
286
287    *deviceName = Xmalloc(rep.deviceNameLength + 1);
288    if (*deviceName == NULL) {
289       Xfree(*driverName);
290       _XEatData(dpy, ((rep.deviceNameLength + 3) & ~3));
291       UnlockDisplay(dpy);
292       SyncHandle();
293       return False;
294    }
295    _XReadPad(dpy, *deviceName, rep.deviceNameLength);
296    (*deviceName)[rep.deviceNameLength] = '\0';
297
298    UnlockDisplay(dpy);
299    SyncHandle();
300
301    return True;
302 }
303
304 Bool
305 DRI2Authenticate(Display * dpy, XID window, drm_magic_t magic)
306 {
307    XExtDisplayInfo *info = DRI2FindDisplay(dpy);
308    xDRI2AuthenticateReq *req;
309    xDRI2AuthenticateReply rep;
310
311    XextCheckExtension(dpy, info, dri2ExtensionName, False);
312
313    LockDisplay(dpy);
314    GetReq(DRI2Authenticate, req);
315    req->reqType = info->codes->major_opcode;
316    req->dri2ReqType = X_DRI2Authenticate;
317    req->window = window;
318    req->magic = magic;
319
320    if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
321       UnlockDisplay(dpy);
322       SyncHandle();
323       return False;
324    }
325
326    UnlockDisplay(dpy);
327    SyncHandle();
328
329    return rep.authenticated;
330 }
331
332 void
333 DRI2CreateDrawable(Display * dpy, XID drawable)
334 {
335    XExtDisplayInfo *info = DRI2FindDisplay(dpy);
336    xDRI2CreateDrawableReq *req;
337
338    XextSimpleCheckExtension(dpy, info, dri2ExtensionName);
339
340    LockDisplay(dpy);
341    GetReq(DRI2CreateDrawable, req);
342    req->reqType = info->codes->major_opcode;
343    req->dri2ReqType = X_DRI2CreateDrawable;
344    req->drawable = drawable;
345    UnlockDisplay(dpy);
346    SyncHandle();
347 }
348
349 void
350 DRI2DestroyDrawable(Display * dpy, XID drawable)
351 {
352    XExtDisplayInfo *info = DRI2FindDisplay(dpy);
353    xDRI2DestroyDrawableReq *req;
354
355    XextSimpleCheckExtension(dpy, info, dri2ExtensionName);
356
357    XSync(dpy, False);
358
359    LockDisplay(dpy);
360    GetReq(DRI2DestroyDrawable, req);
361    req->reqType = info->codes->major_opcode;
362    req->dri2ReqType = X_DRI2DestroyDrawable;
363    req->drawable = drawable;
364    UnlockDisplay(dpy);
365    SyncHandle();
366 }
367
368 static DRI2Buffer *
369 getbuffers(Display *dpy, XID drawable, int *width, int *height,
370                 unsigned int *attachments, int count, int *outCount, int dri2ReqType)
371 {
372    XExtDisplayInfo *info = DRI2FindDisplay(dpy);
373    xDRI2GetBuffersReply rep;
374    xDRI2GetBuffersReq *req;
375    DRI2Buffer *buffers;
376    xDRI2Buffer repBuffer;
377    CARD32 *p;
378    int i, nattachments;
379
380    /* DRI2GetBuffersWithFormat has interleaved attachment+format in
381     * attachments[] array, so length of array is 2x as long..
382     */
383    if (dri2ReqType == X_DRI2GetBuffersWithFormat) {
384           nattachments = 2 * count;
385    } else {
386           nattachments = count;
387    }
388
389    XextCheckExtension(dpy, info, dri2ExtensionName, False);
390
391    LockDisplay(dpy);
392    GetReqExtra(DRI2GetBuffers, nattachments * 4, req);
393    req->reqType = info->codes->major_opcode;
394    req->dri2ReqType = dri2ReqType;
395    req->drawable = drawable;
396    req->count = count;
397    p = (CARD32 *) & req[1];
398    for (i = 0; i < nattachments; 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 = calloc(rep.count, sizeof buffers[0]);
412    for (i = 0; i < rep.count; i++) {
413       _XReadPad(dpy, (char *) &repBuffer, sizeof repBuffer);
414       if (buffers) {
415          buffers[i].attachment = repBuffer.attachment;
416          buffers[i].names[0] = repBuffer.name;
417          buffers[i].pitch[0] = repBuffer.pitch;
418          buffers[i].cpp = repBuffer.cpp;
419          buffers[i].flags = repBuffer.flags;
420       }
421    }
422
423    UnlockDisplay(dpy);
424    SyncHandle();
425
426    return buffers;
427 }
428
429 DRI2Buffer *
430 DRI2GetBuffers(Display * dpy, XID drawable,
431                int *width, int *height,
432                unsigned int *attachments, int count, int *outCount)
433 {
434         return getbuffers(dpy, drawable, width, height, attachments,
435                         count, outCount, X_DRI2GetBuffers);
436 }
437
438 DRI2Buffer *
439 DRI2GetBuffersWithFormat(Display * dpy, XID drawable,
440                          int *width, int *height,
441                          unsigned int *attachments, int count, int *outCount)
442 {
443         return getbuffers(dpy, drawable, width, height, attachments,
444                         count, outCount, X_DRI2GetBuffersWithFormat);
445 }
446
447 #ifdef X_DRI2GetBuffersVid
448 DRI2Buffer *
449 DRI2GetBuffersVid(Display * dpy, XID drawable,
450                int width, int height,
451                unsigned int *attachments, int count, int *outCount)
452 {
453         XExtDisplayInfo *info = DRI2FindDisplay(dpy);
454         DRI2Display *dri2dpy = dpy2dri(dpy);
455         xDRI2GetBuffersReply rep;
456         xDRI2GetBuffersVidReq *req;
457         DRI2Buffer *buffers;
458         xDRI2Buffer repBuffer;
459         CARD32 *p;
460         int i, nattachments = 2 * count;
461
462         XextCheckExtension(dpy, info, dri2ExtensionName, False);
463
464     if (dri2dpy->minor < 4)
465         return False;
466
467         LockDisplay(dpy);
468         GetReqExtra(DRI2GetBuffersVid, nattachments * 4, req);
469         req->reqType = info->codes->major_opcode;
470         req->dri2ReqType = X_DRI2GetBuffersVid;
471         req->drawable = drawable;
472         req->width = width;
473         req->height = height;
474         req->count = count;
475         p = (CARD32 *) & req[1];
476         for (i = 0; i < nattachments; i++)
477                 p[i] = attachments[i];
478
479         if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
480                 UnlockDisplay(dpy);
481                 SyncHandle();
482                 return NULL;
483         }
484
485         *outCount = rep.count;
486
487         buffers = calloc(rep.count, sizeof buffers[0]);
488         for (i = 0; i < rep.count; i++) {
489                 CARD32 n, j;
490                 _XReadPad(dpy, (char *) &repBuffer, sizeof repBuffer);
491                 if (buffers) {
492                         buffers[i].attachment = repBuffer.attachment;
493                         buffers[i].names[0] = repBuffer.name;
494                         buffers[i].pitch[0] = repBuffer.pitch;
495                         buffers[i].cpp = repBuffer.cpp;
496                         buffers[i].flags = repBuffer.flags;
497                 }
498
499                 _XReadPad(dpy, (char *) &n, sizeof n);
500                 for (j = 0; j < n; j++) {
501                         CARD32 name, pitch;
502                         _XReadPad(dpy, (char *) &name, 4);
503                         _XReadPad(dpy, (char *) &pitch, 4);
504                         if (buffers) {
505                                 buffers[i].names[j+1] = name;
506                                 buffers[i].pitch[j+1] = pitch;
507                         }
508                 }
509         }
510
511         UnlockDisplay(dpy);
512         SyncHandle();
513
514         return buffers;
515 }
516 #endif
517
518 void
519 DRI2CopyRegion(Display * dpy, XID drawable, XserverRegion region,
520                CARD32 dest, CARD32 src)
521 {
522    XExtDisplayInfo *info = DRI2FindDisplay(dpy);
523    xDRI2CopyRegionReq *req;
524    xDRI2CopyRegionReply rep;
525
526    XextSimpleCheckExtension(dpy, info, dri2ExtensionName);
527
528    LockDisplay(dpy);
529    GetReq(DRI2CopyRegion, req);
530    req->reqType = info->codes->major_opcode;
531    req->dri2ReqType = X_DRI2CopyRegion;
532    req->drawable = drawable;
533    req->region = region;
534    req->dest = dest;
535    req->src = src;
536
537    _XReply(dpy, (xReply *) & rep, 0, xFalse);
538
539    UnlockDisplay(dpy);
540    SyncHandle();
541 }
542
543 #ifdef X_DRI2SwapBuffers
544 static void
545 load_swap_req(xDRI2SwapBuffersReq *req, CARD64 target, CARD64 divisor,
546              CARD64 remainder)
547 {
548     req->target_msc_hi = target >> 32;
549     req->target_msc_lo = target & 0xffffffff;
550     req->divisor_hi = divisor >> 32;
551     req->divisor_lo = divisor & 0xffffffff;
552     req->remainder_hi = remainder >> 32;
553     req->remainder_lo = remainder & 0xffffffff;
554 }
555
556 static CARD64
557 vals_to_card64(CARD32 lo, CARD32 hi)
558 {
559     return (CARD64)hi << 32 | lo;
560 }
561
562 void DRI2SwapBuffers(Display *dpy, XID drawable, CARD64 target_msc,
563                      CARD64 divisor, CARD64 remainder, CARD64 *count)
564 {
565     XExtDisplayInfo *info = DRI2FindDisplay(dpy);
566     xDRI2SwapBuffersReq *req;
567     xDRI2SwapBuffersReply rep;
568
569     XextSimpleCheckExtension (dpy, info, dri2ExtensionName);
570
571     LockDisplay(dpy);
572     GetReq(DRI2SwapBuffers, req);
573     req->reqType = info->codes->major_opcode;
574     req->dri2ReqType = X_DRI2SwapBuffers;
575     req->drawable = drawable;
576     load_swap_req(req, target_msc, divisor, remainder);
577
578     _XReply(dpy, (xReply *)&rep, 0, xFalse);
579
580     *count = vals_to_card64(rep.swap_lo, rep.swap_hi);
581
582     UnlockDisplay(dpy);
583     SyncHandle();
584 }
585 #endif
586
587 #ifdef X_DRI2SwapBuffersVid
588 void DRI2SwapBuffersVid(Display *dpy, XID drawable, CARD64 target_msc,
589                      CARD64 divisor, CARD64 remainder, CARD64 *count,
590                      unsigned int source, BoxPtr b)
591 {
592     XExtDisplayInfo *info = DRI2FindDisplay(dpy);
593     DRI2Display *dri2dpy = dpy2dri(dpy);
594     xDRI2SwapBuffersVidReq *req;
595     xDRI2SwapBuffersReply rep;
596
597     XextSimpleCheckExtension (dpy, info, dri2ExtensionName);
598
599     if (dri2dpy->minor < 4)
600         return;
601
602     LockDisplay(dpy);
603     GetReq(DRI2SwapBuffersVid, req);
604     req->reqType = info->codes->major_opcode;
605     req->dri2ReqType = X_DRI2SwapBuffersVid;
606     req->drawable = drawable;
607
608     /* first part of message is same as original DRI2SwapBuffers.. */
609     load_swap_req((xDRI2SwapBuffersReq *)req, target_msc, divisor, remainder);
610
611     req->source = source;
612     req->x1 = b->x1;
613     req->y1 = b->y1;
614     req->x2 = b->x2;
615     req->y2 = b->y2;
616
617     _XReply(dpy, (xReply *)&rep, 0, xFalse);
618
619     *count = vals_to_card64(rep.swap_lo, rep.swap_hi);
620
621     UnlockDisplay(dpy);
622     SyncHandle();
623 }
624 #endif
625
626 #ifdef X_DRI2GetMSC
627 Bool DRI2GetMSC(Display *dpy, XID drawable, CARD64 *ust, CARD64 *msc,
628                 CARD64 *sbc)
629 {
630     XExtDisplayInfo *info = DRI2FindDisplay(dpy);
631     xDRI2GetMSCReq *req;
632     xDRI2MSCReply rep;
633
634     XextCheckExtension (dpy, info, dri2ExtensionName, False);
635
636     LockDisplay(dpy);
637     GetReq(DRI2GetMSC, req);
638     req->reqType = info->codes->major_opcode;
639     req->dri2ReqType = X_DRI2GetMSC;
640     req->drawable = drawable;
641
642     if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
643         UnlockDisplay(dpy);
644         SyncHandle();
645         return False;
646     }
647
648     *ust = vals_to_card64(rep.ust_lo, rep.ust_hi);
649     *msc = vals_to_card64(rep.msc_lo, rep.msc_hi);
650     *sbc = vals_to_card64(rep.sbc_lo, rep.sbc_hi);
651
652     UnlockDisplay(dpy);
653     SyncHandle();
654
655     return True;
656 }
657 #endif
658
659 #ifdef X_DRI2WaitMSC
660 static void
661 load_msc_req(xDRI2WaitMSCReq *req, CARD64 target, CARD64 divisor,
662              CARD64 remainder)
663 {
664     req->target_msc_hi = target >> 32;
665     req->target_msc_lo = target & 0xffffffff;
666     req->divisor_hi = divisor >> 32;
667     req->divisor_lo = divisor & 0xffffffff;
668     req->remainder_hi = remainder >> 32;
669     req->remainder_lo = remainder & 0xffffffff;
670 }
671
672 Bool DRI2WaitMSC(Display *dpy, XID drawable, CARD64 target_msc, CARD64 divisor,
673                  CARD64 remainder, CARD64 *ust, CARD64 *msc, CARD64 *sbc)
674 {
675     XExtDisplayInfo *info = DRI2FindDisplay(dpy);
676     xDRI2WaitMSCReq *req;
677     xDRI2MSCReply rep;
678
679     XextCheckExtension (dpy, info, dri2ExtensionName, False);
680
681     LockDisplay(dpy);
682     GetReq(DRI2WaitMSC, req);
683     req->reqType = info->codes->major_opcode;
684     req->dri2ReqType = X_DRI2WaitMSC;
685     req->drawable = drawable;
686     load_msc_req(req, target_msc, divisor, remainder);
687
688     if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
689         UnlockDisplay(dpy);
690         SyncHandle();
691         return False;
692     }
693
694     *ust = ((CARD64)rep.ust_hi << 32) | (CARD64)rep.ust_lo;
695     *msc = ((CARD64)rep.msc_hi << 32) | (CARD64)rep.msc_lo;
696     *sbc = ((CARD64)rep.sbc_hi << 32) | (CARD64)rep.sbc_lo;
697
698     UnlockDisplay(dpy);
699     SyncHandle();
700
701     return True;
702 }
703 #endif
704
705 #ifdef X_DRI2WaitSBC
706 static void
707 load_sbc_req(xDRI2WaitSBCReq *req, CARD64 target)
708 {
709     req->target_sbc_hi = target >> 32;
710     req->target_sbc_lo = target & 0xffffffff;
711 }
712
713 Bool DRI2WaitSBC(Display *dpy, XID drawable, CARD64 target_sbc, CARD64 *ust,
714                  CARD64 *msc, CARD64 *sbc)
715 {
716     XExtDisplayInfo *info = DRI2FindDisplay(dpy);
717     xDRI2WaitSBCReq *req;
718     xDRI2MSCReply rep;
719
720     XextCheckExtension (dpy, info, dri2ExtensionName, False);
721
722     LockDisplay(dpy);
723     GetReq(DRI2WaitSBC, req);
724     req->reqType = info->codes->major_opcode;
725     req->dri2ReqType = X_DRI2WaitSBC;
726     req->drawable = drawable;
727     load_sbc_req(req, target_sbc);
728
729     if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
730         UnlockDisplay(dpy);
731         SyncHandle();
732         return False;
733     }
734
735     *ust = ((CARD64)rep.ust_hi << 32) | rep.ust_lo;
736     *msc = ((CARD64)rep.msc_hi << 32) | rep.msc_lo;
737     *sbc = ((CARD64)rep.sbc_hi << 32) | rep.sbc_lo;
738
739     UnlockDisplay(dpy);
740     SyncHandle();
741
742     return True;
743 }
744 #endif
745
746 #ifdef X_DRI2SwapInterval
747 void DRI2SwapInterval(Display *dpy, XID drawable, int interval)
748 {
749     XExtDisplayInfo *info = DRI2FindDisplay(dpy);
750     xDRI2SwapIntervalReq *req;
751
752     XextSimpleCheckExtension (dpy, info, dri2ExtensionName);
753
754     LockDisplay(dpy);
755     GetReq(DRI2SwapInterval, req);
756     req->reqType = info->codes->major_opcode;
757     req->dri2ReqType = X_DRI2SwapInterval;
758     req->drawable = drawable;
759     req->interval = interval;
760     UnlockDisplay(dpy);
761     SyncHandle();
762 }
763 #endif
764
765 #ifdef X_DRI2SetAttribute
766 /* length in multiple of CARD32's */
767 void
768 DRI2SetAttribute(Display * dpy, XID drawable, Atom attribute,
769                 int len, const CARD32 *val)
770 {
771     XExtDisplayInfo *info = DRI2FindDisplay(dpy);
772     DRI2Display *dri2dpy = dpy2dri(dpy);
773     xDRI2SetAttributeReq *req;
774
775     XextSimpleCheckExtension (dpy, info, dri2ExtensionName);
776
777     if (dri2dpy->minor < 4)
778         return;
779
780     LockDisplay(dpy);
781     GetReqExtra(DRI2SetAttribute, len * 4, req);
782     req->reqType = info->codes->major_opcode;
783     req->dri2ReqType = X_DRI2SetAttribute;
784     req->drawable = drawable;
785     req->attribute = attribute;
786     memcpy(&req[1], val, len * 4);
787     UnlockDisplay(dpy);
788     SyncHandle();
789 }
790 #endif
791
792 #ifdef X_DRI2GetAttribute
793 /* returned attribute should be free'd by caller.. length in multiple of
794  * CARD32's
795  */
796 Bool
797 DRI2GetAttribute(Display * dpy, XID drawable, Atom attribute,
798                 int *len, CARD32 **val)
799 {
800     XExtDisplayInfo *info = DRI2FindDisplay(dpy);
801     DRI2Display *dri2dpy = dpy2dri(dpy);
802     xDRI2GetAttributeReq *req;
803     xDRI2GetAttributeReply rep;
804
805     XextCheckExtension (dpy, info, dri2ExtensionName, False);
806
807     if (dri2dpy->minor < 4)
808         return False;
809
810     LockDisplay(dpy);
811     GetReq(DRI2GetAttribute, req);
812     req->reqType = info->codes->major_opcode;
813     req->dri2ReqType = X_DRI2GetAttribute;
814     req->drawable = drawable;
815     req->attribute = attribute;
816
817     if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
818         UnlockDisplay(dpy);
819         SyncHandle();
820         return False;
821     }
822
823     *len = rep.length;
824     *val = malloc(rep.length * 4);
825
826     _XReadPad(dpy, (char *) *val, rep.length * 4);
827
828     UnlockDisplay(dpy);
829     SyncHandle();
830
831     return True;
832 }
833 #endif
834
835 #ifdef X_DRI2GetFormats
836 /* returned formats should be freed by caller */
837 Bool
838 DRI2GetFormats(Display * dpy, XID drawable, unsigned int *pnformats,
839                 unsigned int **pformats)
840 {
841     XExtDisplayInfo *info = DRI2FindDisplay(dpy);
842     DRI2Display *dri2dpy = dpy2dri(dpy);
843     xDRI2GetFormatsReq *req;
844     xDRI2GetFormatsReply rep;
845     unsigned int nformats, *formats;
846     int i;
847
848     XextCheckExtension (dpy, info, dri2ExtensionName, False);
849
850     if (dri2dpy->minor < 4)
851         return False;
852
853     LockDisplay(dpy);
854     GetReq(DRI2GetFormats, req);
855     req->reqType = info->codes->major_opcode;
856     req->dri2ReqType = X_DRI2GetFormats;
857     req->drawable = drawable;
858
859     if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
860         UnlockDisplay(dpy);
861         SyncHandle();
862         return False;
863     }
864
865     nformats = rep.length * 4 / sizeof(*formats);
866     formats = malloc(nformats * sizeof(*formats));
867
868     for (i = 0; i < nformats; i++) {
869         _XReadPad(dpy, (char *) &formats[i], sizeof(formats[i]));
870     }
871
872     UnlockDisplay(dpy);
873     SyncHandle();
874
875     *pnformats = nformats;
876     *pformats = formats;
877
878     return True;
879 }
880 #endif