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;
111 }
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)
142 {
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;
153 }
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);
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;
171 }
173 static int
174 DRI2Error(Display *dpy, xError *err, XExtCodes *codes, int *ret_code)
175 {
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;
183 }
185 Bool
186 DRI2QueryExtension(Display * dpy, int *eventBase, int *errorBase)
187 {
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;
197 }
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;
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 }
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;
252 }
254 Bool
255 DRI2Connect(Display * dpy, XID window,
256 int driverType, char **driverName, char **deviceName)
257 {
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;
309 }
311 Bool
312 DRI2Authenticate(Display * dpy, XID window, drm_magic_t magic)
313 {
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;
337 }
339 void
340 DRI2CreateDrawable(Display * dpy, XID drawable)
341 {
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();
354 }
356 void
357 DRI2DestroyDrawable(Display * dpy, XID drawable)
358 {
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();
373 }
375 static DRI2Buffer *
376 getbuffers(Display *dpy, XID drawable, int *width, int *height,
377 unsigned int *attachments, int count, int *outCount, int dri2ReqType)
378 {
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;
434 }
436 DRI2Buffer *
437 DRI2GetBuffers(Display * dpy, XID drawable,
438 int *width, int *height,
439 unsigned int *attachments, int count, int *outCount)
440 {
441 return getbuffers(dpy, drawable, width, height, attachments,
442 count, outCount, X_DRI2GetBuffers);
443 }
445 DRI2Buffer *
446 DRI2GetBuffersWithFormat(Display * dpy, XID drawable,
447 int *width, int *height,
448 unsigned int *attachments, int count, int *outCount)
449 {
450 return getbuffers(dpy, drawable, width, height, attachments,
451 count, outCount, X_DRI2GetBuffersWithFormat);
452 }
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)
459 {
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;
522 }
523 #endif
525 void
526 DRI2CopyRegion(Display * dpy, XID drawable, XserverRegion region,
527 CARD32 dest, CARD32 src)
528 {
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();
548 }
550 #ifdef X_DRI2SwapBuffers
551 static void
552 load_swap_req(xDRI2SwapBuffersReq *req, CARD64 target, CARD64 divisor,
553 CARD64 remainder)
554 {
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;
561 }
563 static CARD64
564 vals_to_card64(CARD32 lo, CARD32 hi)
565 {
566 return (CARD64)hi << 32 | lo;
567 }
569 void DRI2SwapBuffers(Display *dpy, XID drawable, CARD64 target_msc,
570 CARD64 divisor, CARD64 remainder, CARD64 *count)
571 {
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();
591 }
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)
598 {
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();
630 }
631 #endif
633 #ifdef X_DRI2GetMSC
634 Bool DRI2GetMSC(Display *dpy, XID drawable, CARD64 *ust, CARD64 *msc,
635 CARD64 *sbc)
636 {
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;
663 }
664 #endif
666 #ifdef X_DRI2WaitMSC
667 static void
668 load_msc_req(xDRI2WaitMSCReq *req, CARD64 target, CARD64 divisor,
669 CARD64 remainder)
670 {
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;
677 }
679 Bool DRI2WaitMSC(Display *dpy, XID drawable, CARD64 target_msc, CARD64 divisor,
680 CARD64 remainder, CARD64 *ust, CARD64 *msc, CARD64 *sbc)
681 {
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;
709 }
710 #endif
712 #ifdef X_DRI2WaitSBC
713 static void
714 load_sbc_req(xDRI2WaitSBCReq *req, CARD64 target)
715 {
716 req->target_sbc_hi = target >> 32;
717 req->target_sbc_lo = target & 0xffffffff;
718 }
720 Bool DRI2WaitSBC(Display *dpy, XID drawable, CARD64 target_sbc, CARD64 *ust,
721 CARD64 *msc, CARD64 *sbc)
722 {
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;
750 }
751 #endif
753 #ifdef X_DRI2SwapInterval
754 void DRI2SwapInterval(Display *dpy, XID drawable, int interval)
755 {
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();
769 }
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)
777 {
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();
796 }
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)
806 {
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;
839 }
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)
847 {
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;
886 }
887 #endif