2 * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
3 * Copyright © 2008 Red Hat, Inc.
5 * Contact: Sangjin Lee <lsj119@samsung.com>, SooChan Lim <sc1.lim@samsung.com>
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.
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.
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.
33 * Kristian Høgsberg (krh@redhat.com)
37 #include <sys/types.h>
39 #include <X11/Xlibint.h>
40 #include <X11/extensions/Xext.h>
41 #include <X11/extensions/extutil.h>
42 #include <X11/extensions/dri2proto.h>
50 #define GFX_PERF_INT(...)
53 /* Allow the build to work with an older versions of dri2proto.h and
59 #define X_DRI2GetBuffersWithFormat 7
62 static Bool bEnableLog=False;
63 # define LOG( fmt, args... ) if( bEnableLog ) printf( " [libdri2|%d]"fmt, getpid(), ##args )
65 static char dri2ExtensionName[] = DRI2_NAME;
66 static XExtensionInfo *dri2Info;
69 DRI2CloseDisplay(Display *dpy, XExtCodes *codes);
71 DRI2WireToEvent(Display *dpy, XEvent *event, xEvent *wire);
73 DRI2EventToWire(Display *dpy, XEvent *event, xEvent *wire);
75 DRI2Error(Display *display, xError *err, XExtCodes *codes, int *ret_code);
77 static /* const */ XExtensionHooks dri2ExtensionHooks = {
82 NULL, /* create_font */
84 DRI2CloseDisplay, /* close_display */
85 DRI2WireToEvent, /* wire_to_event */
86 DRI2EventToWire, /* event_to_wire */
87 DRI2Error, /* error */
88 NULL, /* error_string */
91 static XEXT_GENERATE_FIND_DISPLAY (DRI2FindDisplay,
98 DRI2CloseDisplay(Display *dpy, XExtCodes *codes)
100 return XextRemoveDisplay (dri2Info, dpy);
104 DRI2WireToEvent(Display *dpy, XEvent *event, xEvent *wire)
106 XExtDisplayInfo *info = DRI2FindDisplay(dpy);
110 XextCheckExtension(dpy, info, dri2ExtensionName, False);
112 switch ((wire->u.u.type & 0x7f) - info->codes->first_event) {
114 #ifdef X_DRI2SwapBuffers
115 case DRI2_BufferSwapComplete:
117 DRI2BufferSwapComplete *aevent = (DRI2BufferSwapComplete *)event;
118 xDRI2BufferSwapComplete *awire = (xDRI2BufferSwapComplete *)wire;
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;
131 drawable = awire->drawable;
139 #ifdef DRI2_InvalidateBuffers
140 case DRI2_InvalidateBuffers:
142 DRI2BufferInvalidate *aevent = (DRI2BufferInvalidate *)event;
143 xDRI2InvalidateBuffers *awire = (xDRI2InvalidateBuffers *)wire;
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 */
152 drawable = awire->drawable;
161 /* client doesn't support server event */
162 LOG("EV_UNKNOWN type:%d, dri2type:%d\n"
164 , (wire->u.u.type & 0x7f) - info->codes->first_event);
171 /* We don't actually support this. It doesn't make sense for clients to
172 * send each other DRI2 events.
175 DRI2EventToWire(Display *dpy, XEvent *event, xEvent *wire)
177 XExtDisplayInfo *info = DRI2FindDisplay(dpy);
179 XextCheckExtension(dpy, info, dri2ExtensionName, False);
181 switch (event->type) {
183 /* client doesn't support server event */
191 DRI2Error(Display *display, xError *err, XExtCodes *codes, int *ret_code)
193 if (err->majorCode == codes->major_opcode &&
194 err->errorCode == BadDrawable &&
195 err->minorCode == X_DRI2CopyRegion)
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)
210 DRI2QueryExtension(Display * dpy, int *eventBase, int *errorBase)
212 XExtDisplayInfo *info = DRI2FindDisplay(dpy);
215 if((ptr=getenv("DRI2LOG")))
217 bEnableLog = atoi(ptr);
220 if (XextHasExtension(info)) {
221 *eventBase = info->codes->first_event;
222 *errorBase = info->codes->first_error;
230 DRI2QueryVersion(Display * dpy, int *major, int *minor)
232 XExtDisplayInfo *info = DRI2FindDisplay(dpy);
233 xDRI2QueryVersionReply rep;
234 xDRI2QueryVersionReq *req;
237 XextCheckExtension(dpy, info, dri2ExtensionName, False);
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)) {
250 *major = rep.majorVersion;
251 *minor = rep.minorVersion;
255 switch (rep.minorVersion) {
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);
279 DRI2QeuryExtensionAndCheckVersion(Display * dpy, int *eventBase, int *errorBase, int *major, int *minor, int check_major, int check_minor)
281 XExtDisplayInfo *info = DRI2FindDisplay(dpy);
282 xDRI2QueryVersionReply rep;
283 xDRI2QueryVersionReq *req;
287 XextCheckExtension(dpy, info, dri2ExtensionName, False);
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)) {
300 *major = rep.majorVersion;
301 *minor = rep.minorVersion;
305 if (rep.majorVersion < check_major)
308 if (rep.minorVersion < check_major)
311 if((ptr=getenv("DRI2LOG")))
313 bEnableLog = atoi(ptr);
316 if (XextHasExtension(info)) {
317 *eventBase = info->codes->first_event;
318 *errorBase = info->codes->first_error;
322 switch (rep.minorVersion) {
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);
346 XextRemoveDisplay (dri2Info, dpy);
353 DRI2Connect(Display * dpy, XID window, char **driverName, char **deviceName)
355 XExtDisplayInfo *info = DRI2FindDisplay(dpy);
356 xDRI2ConnectReply rep;
357 xDRI2ConnectReq *req;
359 XextCheckExtension(dpy, info, dri2ExtensionName, False);
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)) {
373 if (rep.driverNameLength == 0 && rep.deviceNameLength == 0) {
379 *driverName = Xmalloc(rep.driverNameLength + 1);
380 if (*driverName == NULL) {
382 ((rep.driverNameLength + 3) & ~3) +
383 ((rep.deviceNameLength + 3) & ~3));
388 _XReadPad(dpy, *driverName, rep.driverNameLength);
389 (*driverName)[rep.driverNameLength] = '\0';
391 *deviceName = Xmalloc(rep.deviceNameLength + 1);
392 if (*deviceName == NULL) {
394 _XEatData(dpy, ((rep.deviceNameLength + 3) & ~3));
399 _XReadPad(dpy, *deviceName, rep.deviceNameLength);
400 (*deviceName)[rep.deviceNameLength] = '\0';
409 DRI2Authenticate(Display * dpy, XID window, unsigned int magic)
411 XExtDisplayInfo *info = DRI2FindDisplay(dpy);
412 xDRI2AuthenticateReq *req;
413 xDRI2AuthenticateReply rep;
415 XextCheckExtension(dpy, info, dri2ExtensionName, False);
418 GetReq(DRI2Authenticate, req);
419 req->reqType = info->codes->major_opcode;
420 req->dri2ReqType = X_DRI2Authenticate;
421 req->window = window;
424 if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
433 return rep.authenticated;
437 DRI2CreateDrawable(Display * dpy, XID drawable)
439 XExtDisplayInfo *info = DRI2FindDisplay(dpy);
440 xDRI2CreateDrawableReq *req;
442 XextSimpleCheckExtension(dpy, info, dri2ExtensionName);
445 LOG("CREATE drawable:0x%x\n", (unsigned int)drawable);
447 GetReq(DRI2CreateDrawable, req);
448 req->reqType = info->codes->major_opcode;
449 req->dri2ReqType = X_DRI2CreateDrawable;
450 req->drawable = drawable;
456 DRI2DestroyDrawable(Display * dpy, XID drawable)
458 XExtDisplayInfo *info = DRI2FindDisplay(dpy);
459 xDRI2DestroyDrawableReq *req;
461 XextSimpleCheckExtension(dpy, info, dri2ExtensionName);
465 LOG("DESTROY drawable:0x%x\n", (unsigned int)drawable);
467 GetReq(DRI2DestroyDrawable, req);
468 req->reqType = info->codes->major_opcode;
469 req->dri2ReqType = X_DRI2DestroyDrawable;
470 req->drawable = drawable;
476 DRI2GetBuffers(Display * dpy, XID drawable,
477 int *width, int *height,
478 unsigned int *attachments, int count, int *outCount)
480 XExtDisplayInfo *info = DRI2FindDisplay(dpy);
481 xDRI2GetBuffersReply rep;
482 xDRI2GetBuffersReq *req;
484 xDRI2Buffer repBuffer;
488 XextCheckExtension(dpy, info, dri2ExtensionName, False);
495 LOG("GET-BUF drawable:0x%x, count:%d, attach:%d \n"
496 , (unsigned int)drawable, count, *attachments);
498 GetReqExtra(DRI2GetBuffers, count * 4, req);
499 req->reqType = info->codes->major_opcode;
500 req->dri2ReqType = X_DRI2GetBuffers;
501 req->drawable = drawable;
503 p = (CARD32 *) & req[1];
504 for (i = 0; i < count; i++)
505 p[i] = attachments[i];
507 if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
514 *height = rep.height;
515 *outCount = rep.count;
517 buffers = Xmalloc(rep.count * sizeof buffers[0]);
518 if (buffers == NULL) {
519 _XEatData(dpy, rep.count * sizeof repBuffer);
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;
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);
539 GFX_PERF_INT("G", buffers[0].name);
550 DRI2GetBuffersWithFormat(Display * dpy, XID drawable,
551 int *width, int *height,
552 unsigned int *attachments, int count, int *outCount)
554 XExtDisplayInfo *info = DRI2FindDisplay(dpy);
555 xDRI2GetBuffersReply rep;
556 xDRI2GetBuffersReq *req;
558 xDRI2Buffer repBuffer;
562 XextCheckExtension(dpy, info, dri2ExtensionName, False);
565 GetReqExtra(DRI2GetBuffers, count * (4 * 2), req);
566 req->reqType = info->codes->major_opcode;
567 req->dri2ReqType = X_DRI2GetBuffersWithFormat;
568 req->drawable = drawable;
570 p = (CARD32 *) & req[1];
571 for (i = 0; i < (count * 2); i++)
572 p[i] = attachments[i];
574 if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
581 *height = rep.height;
582 *outCount = rep.count;
584 buffers = Xmalloc(rep.count * sizeof buffers[0]);
585 if (buffers == NULL) {
586 _XEatData(dpy, rep.count * sizeof repBuffer);
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;
609 DRI2CopyRegion(Display * dpy, XID drawable, XserverRegion region,
610 CARD32 dest, CARD32 src)
612 XExtDisplayInfo *info = DRI2FindDisplay(dpy);
613 xDRI2CopyRegionReq *req;
614 xDRI2CopyRegionReply rep;
616 XextSimpleCheckExtension(dpy, info, dri2ExtensionName);
618 LOG("COPY-REGION drawable:0x%x, src:%d, dest:%d\n", (unsigned int)drawable, (int)src, (int)dest);
621 GetReq(DRI2CopyRegion, req);
622 req->reqType = info->codes->major_opcode;
623 req->dri2ReqType = X_DRI2CopyRegion;
624 req->drawable = drawable;
625 req->region = region;
629 _XReply(dpy, (xReply *) & rep, 0, xFalse);
635 #ifdef X_DRI2SwapBuffers
637 load_swap_req(xDRI2SwapBuffersReq *req, CARD64 target, CARD64 divisor,
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;
649 vals_to_card64(CARD32 lo, CARD32 hi)
651 return (CARD64)hi << 32 | lo;
654 void DRI2SwapBuffers(Display *dpy, XID drawable, CARD64 target_msc,
655 CARD64 divisor, CARD64 remainder, CARD64 *count)
657 XExtDisplayInfo *info = DRI2FindDisplay(dpy);
658 xDRI2SwapBuffersReq *req;
659 xDRI2SwapBuffersReply rep;
661 XextSimpleCheckExtension (dpy, info, dri2ExtensionName);
664 LOG("SWAP drawable:0x%x\n", (unsigned int)drawable);
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);
672 _XReply(dpy, (xReply *)&rep, 0, xFalse);
674 *count = vals_to_card64(rep.swap_lo, rep.swap_hi);
686 Bool DRI2GetMSC(Display *dpy, XID drawable, CARD64 *ust, CARD64 *msc,
689 XExtDisplayInfo *info = DRI2FindDisplay(dpy);
693 XextCheckExtension (dpy, info, dri2ExtensionName, False);
696 GetReq(DRI2GetMSC, req);
697 req->reqType = info->codes->major_opcode;
698 req->dri2ReqType = X_DRI2GetMSC;
699 req->drawable = drawable;
701 if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
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);
720 load_msc_req(xDRI2WaitMSCReq *req, CARD64 target, CARD64 divisor,
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;
731 Bool DRI2WaitMSC(Display *dpy, XID drawable, CARD64 target_msc, CARD64 divisor,
732 CARD64 remainder, CARD64 *ust, CARD64 *msc, CARD64 *sbc)
734 XExtDisplayInfo *info = DRI2FindDisplay(dpy);
735 xDRI2WaitMSCReq *req;
738 XextCheckExtension (dpy, info, dri2ExtensionName, False);
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);
747 if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
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;
766 load_sbc_req(xDRI2WaitSBCReq *req, CARD64 target)
768 req->target_sbc_hi = target >> 32;
769 req->target_sbc_lo = target & 0xffffffff;
772 Bool DRI2WaitSBC(Display *dpy, XID drawable, CARD64 target_sbc, CARD64 *ust,
773 CARD64 *msc, CARD64 *sbc)
775 XExtDisplayInfo *info = DRI2FindDisplay(dpy);
776 xDRI2WaitSBCReq *req;
779 XextCheckExtension (dpy, info, dri2ExtensionName, False);
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);
788 if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
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;
805 #ifdef X_DRI2SwapInterval
806 void DRI2SwapInterval(Display *dpy, XID drawable, int interval)
808 XExtDisplayInfo *info = DRI2FindDisplay(dpy);
809 xDRI2SwapIntervalReq *req;
811 XextSimpleCheckExtension (dpy, info, dri2ExtensionName);
814 GetReq(DRI2SwapInterval, req);
815 req->reqType = info->codes->major_opcode;
816 req->dri2ReqType = X_DRI2SwapInterval;
817 req->drawable = drawable;
818 req->interval = interval;
824 #ifdef X_DRI2SwapBuffersWithRegion
825 void DRI2SwapBuffersWithRegion(Display *dpy, XID drawable, XserverRegion region,
828 XExtDisplayInfo *info = DRI2FindDisplay(dpy);
829 xDRI2SwapBuffersWithRegionReq *req;
830 xDRI2SwapBuffersReply rep;
832 XextSimpleCheckExtension (dpy, info, dri2ExtensionName);
835 LOG("SWAP drawable:0x%x\n", (unsigned int)drawable);
837 GetReq(DRI2SwapBuffersWithRegion, req);
838 req->reqType = info->codes->major_opcode;
839 req->dri2ReqType = X_DRI2SwapBuffersWithRegion;
840 req->drawable = drawable;
841 req->region = region;
843 _XReply(dpy, (xReply *)&rep, 0, xFalse);
845 *count = vals_to_card64(rep.swap_lo, rep.swap_hi);