Fix potential NPE if user doesn't register display
[glsdk/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  */
33 #ifdef HAVE_CONFIG_H
34 #  include "config.h"
35 #endif
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"
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
59 static char dri2ExtensionName[] = DRI2_NAME;
60 static XExtensionInfo *dri2Info;
61 static XEXT_GENERATE_CLOSE_DISPLAY (DRI2CloseDisplay2, dri2Info)
63 /**
64  * List of per-Display privates..
65  */
66 static struct list dpy_list = { &dpy_list, &dpy_list };
68 typedef struct {
69         struct list list;
70         Display *dpy;
71         const DRI2EventOps *ops;
72         int major, minor;
73 } DRI2Display;
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 }
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 }
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;
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);
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 };
134 static XEXT_GENERATE_FIND_DISPLAY (DRI2FindDisplay,
135                                    dri2Info,
136                                    dri2ExtensionName,
137                                    &dri2ExtensionHooks,
138                                    0, NULL)
140 static Bool
141 DRI2WireToEvent(Display *dpy, XEvent *event, xEvent *wire)
143    XExtDisplayInfo *info = DRI2FindDisplay(dpy);
144    DRI2Display *dri2dpy = dpy2dri(dpy);
146    XextCheckExtension(dpy, info, dri2ExtensionName, False);
148    if (dri2dpy && dri2dpy->ops && dri2dpy->ops->WireToEvent) {
149            return dri2dpy->ops->WireToEvent(dpy, info, event, wire);
150    }
152    return False;
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)
161    XExtDisplayInfo *info = DRI2FindDisplay(dpy);
162    DRI2Display *dri2dpy = dpy2dri(dpy);
164    XextCheckExtension(dpy, info, dri2ExtensionName, False);
166    if (dri2dpy && dri2dpy->ops && dri2dpy->ops->EventToWire) {
167            return dri2dpy->ops->EventToWire(dpy, info, event, wire);
168    }
170    return Success;
173 static int
174 DRI2Error(Display *dpy, xError *err, XExtCodes *codes, int *ret_code)
176         DRI2Display *dri2dpy = dpy2dri(dpy);
178         if (dri2dpy && dri2dpy->ops && dri2dpy->ops->Error) {
179                 return dri2dpy->ops->Error(dpy, err, codes, ret_code);
180         }
182     return False;
185 Bool
186 DRI2QueryExtension(Display * dpy, int *eventBase, int *errorBase)
188    XExtDisplayInfo *info = DRI2FindDisplay(dpy);
190    if (XextHasExtension(info)) {
191       *eventBase = info->codes->first_event;
192       *errorBase = info->codes->first_error;
193       return True;
194    }
196    return False;
199 Bool
200 DRI2QueryVersion(Display * dpy, int *major, int *minor)
202    XExtDisplayInfo *info = DRI2FindDisplay(dpy);
203    DRI2Display *dri2dpy = dpy2dri(dpy);
204    xDRI2QueryVersionReply rep;
205    xDRI2QueryVersionReq *req;
206    int i, nevents;
208    XextCheckExtension(dpy, info, dri2ExtensionName, False);
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    }
222    *major = rep.majorVersion;
223    *minor = rep.minorVersion;
225    if (dri2dpy) {
226            dri2dpy->major = rep.majorVersion;
227            dri2dpy->minor = rep.minorVersion;
228    }
230    UnlockDisplay(dpy);
231    SyncHandle();
233    switch (rep.minorVersion) {
234    case 1:
235            nevents = 0;
236            break;
237    case 2:
238            nevents = 1;
239            break;
240    case 3:
241    default:
242            nevents = 2;
243            break;
244    }
245         
246    for (i = 0; i < nevents; i++) {
247        XESetWireToEvent (dpy, info->codes->first_event + i, DRI2WireToEvent);
248        XESetEventToWire (dpy, info->codes->first_event + i, DRI2EventToWire);
249    }
251    return True;
254 Bool
255 DRI2Connect(Display * dpy, XID window,
256                 int driverType, char **driverName, char **deviceName)
258    XExtDisplayInfo *info = DRI2FindDisplay(dpy);
259    xDRI2ConnectReply rep;
260    xDRI2ConnectReq *req;
262    XextCheckExtension(dpy, info, dri2ExtensionName, False);
264    LockDisplay(dpy);
265    GetReq(DRI2Connect, req);
266    req->reqType = info->codes->major_opcode;
267    req->dri2ReqType = X_DRI2Connect;
268    req->window = window;
269    req->driverType = driverType;
270    if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
271       UnlockDisplay(dpy);
272       SyncHandle();
273       return False;
274    }
276    if (rep.driverNameLength == 0 && rep.deviceNameLength == 0) {
277       UnlockDisplay(dpy);
278       SyncHandle();
279       return False;
280    }
282    *driverName = Xmalloc(rep.driverNameLength + 1);
283    if (*driverName == NULL) {
284       _XEatData(dpy,
285                 ((rep.driverNameLength + 3) & ~3) +
286                 ((rep.deviceNameLength + 3) & ~3));
287       UnlockDisplay(dpy);
288       SyncHandle();
289       return False;
290    }
291    _XReadPad(dpy, *driverName, rep.driverNameLength);
292    (*driverName)[rep.driverNameLength] = '\0';
294    *deviceName = Xmalloc(rep.deviceNameLength + 1);
295    if (*deviceName == NULL) {
296       Xfree(*driverName);
297       _XEatData(dpy, ((rep.deviceNameLength + 3) & ~3));
298       UnlockDisplay(dpy);
299       SyncHandle();
300       return False;
301    }
302    _XReadPad(dpy, *deviceName, rep.deviceNameLength);
303    (*deviceName)[rep.deviceNameLength] = '\0';
305    UnlockDisplay(dpy);
306    SyncHandle();
308    return True;
311 Bool
312 DRI2Authenticate(Display * dpy, XID window, drm_magic_t magic)
314    XExtDisplayInfo *info = DRI2FindDisplay(dpy);
315    xDRI2AuthenticateReq *req;
316    xDRI2AuthenticateReply rep;
318    XextCheckExtension(dpy, info, dri2ExtensionName, False);
320    LockDisplay(dpy);
321    GetReq(DRI2Authenticate, req);
322    req->reqType = info->codes->major_opcode;
323    req->dri2ReqType = X_DRI2Authenticate;
324    req->window = window;
325    req->magic = magic;
327    if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
328       UnlockDisplay(dpy);
329       SyncHandle();
330       return False;
331    }
333    UnlockDisplay(dpy);
334    SyncHandle();
336    return rep.authenticated;
339 void
340 DRI2CreateDrawable(Display * dpy, XID drawable)
342    XExtDisplayInfo *info = DRI2FindDisplay(dpy);
343    xDRI2CreateDrawableReq *req;
345    XextSimpleCheckExtension(dpy, info, dri2ExtensionName);
347    LockDisplay(dpy);
348    GetReq(DRI2CreateDrawable, req);
349    req->reqType = info->codes->major_opcode;
350    req->dri2ReqType = X_DRI2CreateDrawable;
351    req->drawable = drawable;
352    UnlockDisplay(dpy);
353    SyncHandle();
356 void
357 DRI2DestroyDrawable(Display * dpy, XID drawable)
359    XExtDisplayInfo *info = DRI2FindDisplay(dpy);
360    xDRI2DestroyDrawableReq *req;
362    XextSimpleCheckExtension(dpy, info, dri2ExtensionName);
364    XSync(dpy, False);
366    LockDisplay(dpy);
367    GetReq(DRI2DestroyDrawable, req);
368    req->reqType = info->codes->major_opcode;
369    req->dri2ReqType = X_DRI2DestroyDrawable;
370    req->drawable = drawable;
371    UnlockDisplay(dpy);
372    SyncHandle();
375 static DRI2Buffer *
376 getbuffers(Display *dpy, XID drawable, int *width, int *height,
377                 unsigned int *attachments, int count, int *outCount, int dri2ReqType)
379    XExtDisplayInfo *info = DRI2FindDisplay(dpy);
380    xDRI2GetBuffersReply rep;
381    xDRI2GetBuffersReq *req;
382    DRI2Buffer *buffers;
383    xDRI2Buffer repBuffer;
384    CARD32 *p;
385    int i, nattachments;
387    /* DRI2GetBuffersWithFormat has interleaved attachment+format in
388     * attachments[] array, so length of array is 2x as long..
389     */
390    if (dri2ReqType == X_DRI2GetBuffersWithFormat) {
391           nattachments = 2 * count;
392    } else {
393           nattachments = count;
394    }
396    XextCheckExtension(dpy, info, dri2ExtensionName, False);
398    LockDisplay(dpy);
399    GetReqExtra(DRI2GetBuffers, nattachments * 4, req);
400    req->reqType = info->codes->major_opcode;
401    req->dri2ReqType = dri2ReqType;
402    req->drawable = drawable;
403    req->count = count;
404    p = (CARD32 *) & req[1];
405    for (i = 0; i < nattachments; i++)
406       p[i] = attachments[i];
408    if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
409       UnlockDisplay(dpy);
410       SyncHandle();
411       return NULL;
412    }
414    *width = rep.width;
415    *height = rep.height;
416    *outCount = rep.count;
418    buffers = calloc(rep.count, sizeof buffers[0]);
419    for (i = 0; i < rep.count; i++) {
420       _XReadPad(dpy, (char *) &repBuffer, sizeof repBuffer);
421       if (buffers) {
422          buffers[i].attachment = repBuffer.attachment;
423          buffers[i].names[0] = repBuffer.name;
424          buffers[i].pitch[0] = repBuffer.pitch;
425          buffers[i].cpp = repBuffer.cpp;
426          buffers[i].flags = repBuffer.flags;
427       }
428    }
430    UnlockDisplay(dpy);
431    SyncHandle();
433    return buffers;
436 DRI2Buffer *
437 DRI2GetBuffers(Display * dpy, XID drawable,
438                int *width, int *height,
439                unsigned int *attachments, int count, int *outCount)
441         return getbuffers(dpy, drawable, width, height, attachments,
442                         count, outCount, X_DRI2GetBuffers);
445 DRI2Buffer *
446 DRI2GetBuffersWithFormat(Display * dpy, XID drawable,
447                          int *width, int *height,
448                          unsigned int *attachments, int count, int *outCount)
450         return getbuffers(dpy, drawable, width, height, attachments,
451                         count, outCount, X_DRI2GetBuffersWithFormat);
454 #ifdef X_DRI2GetBuffersVid
455 DRI2Buffer *
456 DRI2GetBuffersVid(Display * dpy, XID drawable,
457                int width, int height,
458                unsigned int *attachments, int count, int *outCount)
460         XExtDisplayInfo *info = DRI2FindDisplay(dpy);
461         DRI2Display *dri2dpy = dpy2dri(dpy);
462         xDRI2GetBuffersReply rep;
463         xDRI2GetBuffersVidReq *req;
464         DRI2Buffer *buffers;
465         xDRI2Buffer repBuffer;
466         CARD32 *p;
467         int i, nattachments = 2 * count;
469         XextCheckExtension(dpy, info, dri2ExtensionName, False);
471     if (dri2dpy->minor < 4)
472         return False;
474         LockDisplay(dpy);
475         GetReqExtra(DRI2GetBuffersVid, nattachments * 4, req);
476         req->reqType = info->codes->major_opcode;
477         req->dri2ReqType = X_DRI2GetBuffersVid;
478         req->drawable = drawable;
479         req->width = width;
480         req->height = height;
481         req->count = count;
482         p = (CARD32 *) & req[1];
483         for (i = 0; i < nattachments; i++)
484                 p[i] = attachments[i];
486         if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
487                 UnlockDisplay(dpy);
488                 SyncHandle();
489                 return NULL;
490         }
492         *outCount = rep.count;
494         buffers = calloc(rep.count, sizeof buffers[0]);
495         for (i = 0; i < rep.count; i++) {
496                 CARD32 n, j;
497                 _XReadPad(dpy, (char *) &repBuffer, sizeof repBuffer);
498                 if (buffers) {
499                         buffers[i].attachment = repBuffer.attachment;
500                         buffers[i].names[0] = repBuffer.name;
501                         buffers[i].pitch[0] = repBuffer.pitch;
502                         buffers[i].cpp = repBuffer.cpp;
503                         buffers[i].flags = repBuffer.flags;
504                 }
506                 _XReadPad(dpy, (char *) &n, sizeof n);
507                 for (j = 0; j < n; j++) {
508                         CARD32 name, pitch;
509                         _XReadPad(dpy, (char *) &name, 4);
510                         _XReadPad(dpy, (char *) &pitch, 4);
511                         if (buffers) {
512                                 buffers[i].names[j+1] = name;
513                                 buffers[i].pitch[j+1] = pitch;
514                         }
515                 }
516         }
518         UnlockDisplay(dpy);
519         SyncHandle();
521         return buffers;
523 #endif
525 void
526 DRI2CopyRegion(Display * dpy, XID drawable, XserverRegion region,
527                CARD32 dest, CARD32 src)
529    XExtDisplayInfo *info = DRI2FindDisplay(dpy);
530    xDRI2CopyRegionReq *req;
531    xDRI2CopyRegionReply rep;
533    XextSimpleCheckExtension(dpy, info, dri2ExtensionName);
535    LockDisplay(dpy);
536    GetReq(DRI2CopyRegion, req);
537    req->reqType = info->codes->major_opcode;
538    req->dri2ReqType = X_DRI2CopyRegion;
539    req->drawable = drawable;
540    req->region = region;
541    req->dest = dest;
542    req->src = src;
544    _XReply(dpy, (xReply *) & rep, 0, xFalse);
546    UnlockDisplay(dpy);
547    SyncHandle();
550 #ifdef X_DRI2SwapBuffers
551 static void
552 load_swap_req(xDRI2SwapBuffersReq *req, CARD64 target, CARD64 divisor,
553              CARD64 remainder)
555     req->target_msc_hi = target >> 32;
556     req->target_msc_lo = target & 0xffffffff;
557     req->divisor_hi = divisor >> 32;
558     req->divisor_lo = divisor & 0xffffffff;
559     req->remainder_hi = remainder >> 32;
560     req->remainder_lo = remainder & 0xffffffff;
563 static CARD64
564 vals_to_card64(CARD32 lo, CARD32 hi)
566     return (CARD64)hi << 32 | lo;
569 void DRI2SwapBuffers(Display *dpy, XID drawable, CARD64 target_msc,
570                      CARD64 divisor, CARD64 remainder, CARD64 *count)
572     XExtDisplayInfo *info = DRI2FindDisplay(dpy);
573     xDRI2SwapBuffersReq *req;
574     xDRI2SwapBuffersReply rep;
576     XextSimpleCheckExtension (dpy, info, dri2ExtensionName);
578     LockDisplay(dpy);
579     GetReq(DRI2SwapBuffers, req);
580     req->reqType = info->codes->major_opcode;
581     req->dri2ReqType = X_DRI2SwapBuffers;
582     req->drawable = drawable;
583     load_swap_req(req, target_msc, divisor, remainder);
585     _XReply(dpy, (xReply *)&rep, 0, xFalse);
587     *count = vals_to_card64(rep.swap_lo, rep.swap_hi);
589     UnlockDisplay(dpy);
590     SyncHandle();
592 #endif
594 #ifdef X_DRI2SwapBuffersVid
595 void DRI2SwapBuffersVid(Display *dpy, XID drawable, CARD64 target_msc,
596                      CARD64 divisor, CARD64 remainder, CARD64 *count,
597                      unsigned int source, BoxPtr b)
599     XExtDisplayInfo *info = DRI2FindDisplay(dpy);
600     DRI2Display *dri2dpy = dpy2dri(dpy);
601     xDRI2SwapBuffersVidReq *req;
602     xDRI2SwapBuffersReply rep;
604     XextSimpleCheckExtension (dpy, info, dri2ExtensionName);
606     if (dri2dpy->minor < 4)
607         return;
609     LockDisplay(dpy);
610     GetReq(DRI2SwapBuffersVid, req);
611     req->reqType = info->codes->major_opcode;
612     req->dri2ReqType = X_DRI2SwapBuffersVid;
613     req->drawable = drawable;
615     /* first part of message is same as original DRI2SwapBuffers.. */
616     load_swap_req((xDRI2SwapBuffersReq *)req, target_msc, divisor, remainder);
618     req->source = source;
619     req->x1 = b->x1;
620     req->y1 = b->y1;
621     req->x2 = b->x2;
622     req->y2 = b->y2;
624     _XReply(dpy, (xReply *)&rep, 0, xFalse);
626     *count = vals_to_card64(rep.swap_lo, rep.swap_hi);
628     UnlockDisplay(dpy);
629     SyncHandle();
631 #endif
633 #ifdef X_DRI2GetMSC
634 Bool DRI2GetMSC(Display *dpy, XID drawable, CARD64 *ust, CARD64 *msc,
635                 CARD64 *sbc)
637     XExtDisplayInfo *info = DRI2FindDisplay(dpy);
638     xDRI2GetMSCReq *req;
639     xDRI2MSCReply rep;
641     XextCheckExtension (dpy, info, dri2ExtensionName, False);
643     LockDisplay(dpy);
644     GetReq(DRI2GetMSC, req);
645     req->reqType = info->codes->major_opcode;
646     req->dri2ReqType = X_DRI2GetMSC;
647     req->drawable = drawable;
649     if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
650         UnlockDisplay(dpy);
651         SyncHandle();
652         return False;
653     }
655     *ust = vals_to_card64(rep.ust_lo, rep.ust_hi);
656     *msc = vals_to_card64(rep.msc_lo, rep.msc_hi);
657     *sbc = vals_to_card64(rep.sbc_lo, rep.sbc_hi);
659     UnlockDisplay(dpy);
660     SyncHandle();
662     return True;
664 #endif
666 #ifdef X_DRI2WaitMSC
667 static void
668 load_msc_req(xDRI2WaitMSCReq *req, CARD64 target, CARD64 divisor,
669              CARD64 remainder)
671     req->target_msc_hi = target >> 32;
672     req->target_msc_lo = target & 0xffffffff;
673     req->divisor_hi = divisor >> 32;
674     req->divisor_lo = divisor & 0xffffffff;
675     req->remainder_hi = remainder >> 32;
676     req->remainder_lo = remainder & 0xffffffff;
679 Bool DRI2WaitMSC(Display *dpy, XID drawable, CARD64 target_msc, CARD64 divisor,
680                  CARD64 remainder, CARD64 *ust, CARD64 *msc, CARD64 *sbc)
682     XExtDisplayInfo *info = DRI2FindDisplay(dpy);
683     xDRI2WaitMSCReq *req;
684     xDRI2MSCReply rep;
686     XextCheckExtension (dpy, info, dri2ExtensionName, False);
688     LockDisplay(dpy);
689     GetReq(DRI2WaitMSC, req);
690     req->reqType = info->codes->major_opcode;
691     req->dri2ReqType = X_DRI2WaitMSC;
692     req->drawable = drawable;
693     load_msc_req(req, target_msc, divisor, remainder);
695     if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
696         UnlockDisplay(dpy);
697         SyncHandle();
698         return False;
699     }
701     *ust = ((CARD64)rep.ust_hi << 32) | (CARD64)rep.ust_lo;
702     *msc = ((CARD64)rep.msc_hi << 32) | (CARD64)rep.msc_lo;
703     *sbc = ((CARD64)rep.sbc_hi << 32) | (CARD64)rep.sbc_lo;
705     UnlockDisplay(dpy);
706     SyncHandle();
708     return True;
710 #endif
712 #ifdef X_DRI2WaitSBC
713 static void
714 load_sbc_req(xDRI2WaitSBCReq *req, CARD64 target)
716     req->target_sbc_hi = target >> 32;
717     req->target_sbc_lo = target & 0xffffffff;
720 Bool DRI2WaitSBC(Display *dpy, XID drawable, CARD64 target_sbc, CARD64 *ust,
721                  CARD64 *msc, CARD64 *sbc)
723     XExtDisplayInfo *info = DRI2FindDisplay(dpy);
724     xDRI2WaitSBCReq *req;
725     xDRI2MSCReply rep;
727     XextCheckExtension (dpy, info, dri2ExtensionName, False);
729     LockDisplay(dpy);
730     GetReq(DRI2WaitSBC, req);
731     req->reqType = info->codes->major_opcode;
732     req->dri2ReqType = X_DRI2WaitSBC;
733     req->drawable = drawable;
734     load_sbc_req(req, target_sbc);
736     if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
737         UnlockDisplay(dpy);
738         SyncHandle();
739         return False;
740     }
742     *ust = ((CARD64)rep.ust_hi << 32) | rep.ust_lo;
743     *msc = ((CARD64)rep.msc_hi << 32) | rep.msc_lo;
744     *sbc = ((CARD64)rep.sbc_hi << 32) | rep.sbc_lo;
746     UnlockDisplay(dpy);
747     SyncHandle();
749     return True;
751 #endif
753 #ifdef X_DRI2SwapInterval
754 void DRI2SwapInterval(Display *dpy, XID drawable, int interval)
756     XExtDisplayInfo *info = DRI2FindDisplay(dpy);
757     xDRI2SwapIntervalReq *req;
759     XextSimpleCheckExtension (dpy, info, dri2ExtensionName);
761     LockDisplay(dpy);
762     GetReq(DRI2SwapInterval, req);
763     req->reqType = info->codes->major_opcode;
764     req->dri2ReqType = X_DRI2SwapInterval;
765     req->drawable = drawable;
766     req->interval = interval;
767     UnlockDisplay(dpy);
768     SyncHandle();
770 #endif
772 #ifdef X_DRI2SetAttribute
773 /* length in multiple of CARD32's */
774 void
775 DRI2SetAttribute(Display * dpy, XID drawable, Atom attribute,
776                 int len, const CARD32 *val)
778     XExtDisplayInfo *info = DRI2FindDisplay(dpy);
779     DRI2Display *dri2dpy = dpy2dri(dpy);
780     xDRI2SetAttributeReq *req;
782     XextSimpleCheckExtension (dpy, info, dri2ExtensionName);
784     if (dri2dpy->minor < 4)
785         return;
787     LockDisplay(dpy);
788     GetReqExtra(DRI2SetAttribute, len * 4, req);
789     req->reqType = info->codes->major_opcode;
790     req->dri2ReqType = X_DRI2SetAttribute;
791     req->drawable = drawable;
792     req->attribute = attribute;
793     memcpy(&req[1], val, len * 4);
794     UnlockDisplay(dpy);
795     SyncHandle();
797 #endif
799 #ifdef X_DRI2GetAttribute
800 /* returned attribute should be free'd by caller.. length in multiple of
801  * CARD32's
802  */
803 Bool
804 DRI2GetAttribute(Display * dpy, XID drawable, Atom attribute,
805                 int *len, CARD32 **val)
807     XExtDisplayInfo *info = DRI2FindDisplay(dpy);
808     DRI2Display *dri2dpy = dpy2dri(dpy);
809     xDRI2GetAttributeReq *req;
810     xDRI2GetAttributeReply rep;
812     XextCheckExtension (dpy, info, dri2ExtensionName, False);
814     if (dri2dpy->minor < 4)
815         return False;
817     LockDisplay(dpy);
818     GetReq(DRI2GetAttribute, req);
819     req->reqType = info->codes->major_opcode;
820     req->dri2ReqType = X_DRI2GetAttribute;
821     req->drawable = drawable;
822     req->attribute = attribute;
824     if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
825         UnlockDisplay(dpy);
826         SyncHandle();
827         return False;
828     }
830     *len = rep.length;
831     *val = malloc(rep.length * 4);
833     _XReadPad(dpy, (char *) *val, rep.length * 4);
835     UnlockDisplay(dpy);
836     SyncHandle();
838     return True;
840 #endif
842 #ifdef X_DRI2GetFormats
843 /* returned formats should be freed by caller */
844 Bool
845 DRI2GetFormats(Display * dpy, XID drawable, unsigned int *pnformats,
846                 unsigned int **pformats)
848     XExtDisplayInfo *info = DRI2FindDisplay(dpy);
849     DRI2Display *dri2dpy = dpy2dri(dpy);
850     xDRI2GetFormatsReq *req;
851     xDRI2GetFormatsReply rep;
852     unsigned int nformats, *formats;
853     int i;
855     XextCheckExtension (dpy, info, dri2ExtensionName, False);
857     if (dri2dpy->minor < 4)
858         return False;
860     LockDisplay(dpy);
861     GetReq(DRI2GetFormats, req);
862     req->reqType = info->codes->major_opcode;
863     req->dri2ReqType = X_DRI2GetFormats;
864     req->drawable = drawable;
866     if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
867         UnlockDisplay(dpy);
868         SyncHandle();
869         return False;
870     }
872     nformats = rep.length * 4 / sizeof(*formats);
873     formats = malloc(nformats * sizeof(*formats));
875     for (i = 0; i < nformats; i++) {
876         _XReadPad(dpy, (char *) &formats[i], sizeof(formats[i]));
877     }
879     UnlockDisplay(dpy);
880     SyncHandle();
882     *pnformats = nformats;
883     *pformats = formats;
885     return True;
887 #endif