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 DRI2Connect(Display * dpy, XID window, char **driverName, char **deviceName)
281 XExtDisplayInfo *info = DRI2FindDisplay(dpy);
282 xDRI2ConnectReply rep;
283 xDRI2ConnectReq *req;
285 XextCheckExtension(dpy, info, dri2ExtensionName, False);
288 GetReq(DRI2Connect, req);
289 req->reqType = info->codes->major_opcode;
290 req->dri2ReqType = X_DRI2Connect;
291 req->window = window;
292 req->driverType = DRI2DriverDRI;
293 if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
299 if (rep.driverNameLength == 0 && rep.deviceNameLength == 0) {
305 *driverName = Xmalloc(rep.driverNameLength + 1);
306 if (*driverName == NULL) {
308 ((rep.driverNameLength + 3) & ~3) +
309 ((rep.deviceNameLength + 3) & ~3));
314 _XReadPad(dpy, *driverName, rep.driverNameLength);
315 (*driverName)[rep.driverNameLength] = '\0';
317 *deviceName = Xmalloc(rep.deviceNameLength + 1);
318 if (*deviceName == NULL) {
320 _XEatData(dpy, ((rep.deviceNameLength + 3) & ~3));
325 _XReadPad(dpy, *deviceName, rep.deviceNameLength);
326 (*deviceName)[rep.deviceNameLength] = '\0';
335 DRI2Authenticate(Display * dpy, XID window, unsigned int magic)
337 XExtDisplayInfo *info = DRI2FindDisplay(dpy);
338 xDRI2AuthenticateReq *req;
339 xDRI2AuthenticateReply rep;
341 XextCheckExtension(dpy, info, dri2ExtensionName, False);
344 GetReq(DRI2Authenticate, req);
345 req->reqType = info->codes->major_opcode;
346 req->dri2ReqType = X_DRI2Authenticate;
347 req->window = window;
350 if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
359 return rep.authenticated;
363 DRI2CreateDrawable(Display * dpy, XID drawable)
365 XExtDisplayInfo *info = DRI2FindDisplay(dpy);
366 xDRI2CreateDrawableReq *req;
368 XextSimpleCheckExtension(dpy, info, dri2ExtensionName);
371 LOG("CREATE drawable:0x%x\n", (unsigned int)drawable);
373 GetReq(DRI2CreateDrawable, req);
374 req->reqType = info->codes->major_opcode;
375 req->dri2ReqType = X_DRI2CreateDrawable;
376 req->drawable = drawable;
382 DRI2DestroyDrawable(Display * dpy, XID drawable)
384 XExtDisplayInfo *info = DRI2FindDisplay(dpy);
385 xDRI2DestroyDrawableReq *req;
387 XextSimpleCheckExtension(dpy, info, dri2ExtensionName);
391 LOG("DESTROY drawable:0x%x\n", (unsigned int)drawable);
393 GetReq(DRI2DestroyDrawable, req);
394 req->reqType = info->codes->major_opcode;
395 req->dri2ReqType = X_DRI2DestroyDrawable;
396 req->drawable = drawable;
402 DRI2GetBuffers(Display * dpy, XID drawable,
403 int *width, int *height,
404 unsigned int *attachments, int count, int *outCount)
406 XExtDisplayInfo *info = DRI2FindDisplay(dpy);
407 xDRI2GetBuffersReply rep;
408 xDRI2GetBuffersReq *req;
410 xDRI2Buffer repBuffer;
414 XextCheckExtension(dpy, info, dri2ExtensionName, False);
421 LOG("GET-BUF drawable:0x%x, count:%d, attach:%d \n"
422 , (unsigned int)drawable, count, *attachments);
424 GetReqExtra(DRI2GetBuffers, count * 4, req);
425 req->reqType = info->codes->major_opcode;
426 req->dri2ReqType = X_DRI2GetBuffers;
427 req->drawable = drawable;
429 p = (CARD32 *) & req[1];
430 for (i = 0; i < count; i++)
431 p[i] = attachments[i];
433 if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
440 *height = rep.height;
441 *outCount = rep.count;
443 buffers = Xmalloc(rep.count * sizeof buffers[0]);
444 if (buffers == NULL) {
445 _XEatData(dpy, rep.count * sizeof repBuffer);
451 for (i = 0; i < rep.count; i++) {
452 _XReadPad(dpy, (char *) &repBuffer, sizeof repBuffer);
453 buffers[i].attachment = repBuffer.attachment;
454 buffers[i].name = repBuffer.name;
455 buffers[i].pitch = repBuffer.pitch;
456 buffers[i].cpp = repBuffer.cpp;
457 buffers[i].flags = repBuffer.flags;
459 LOG("\t\t New attach:%d name:%d flags:0x%x width:%d, height:%d\n"
460 , buffers[i].attachment, buffers[i].name, buffers[i].flags, *width, *height);
465 GFX_PERF_INT("G", buffers[0].name);
476 DRI2GetBuffersWithFormat(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);
491 GetReqExtra(DRI2GetBuffers, count * (4 * 2), req);
492 req->reqType = info->codes->major_opcode;
493 req->dri2ReqType = X_DRI2GetBuffersWithFormat;
494 req->drawable = drawable;
496 p = (CARD32 *) & req[1];
497 for (i = 0; i < (count * 2); i++)
498 p[i] = attachments[i];
500 if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
507 *height = rep.height;
508 *outCount = rep.count;
510 buffers = Xmalloc(rep.count * sizeof buffers[0]);
511 if (buffers == NULL) {
512 _XEatData(dpy, rep.count * sizeof repBuffer);
518 for (i = 0; i < rep.count; i++) {
519 _XReadPad(dpy, (char *) &repBuffer, sizeof repBuffer);
520 buffers[i].attachment = repBuffer.attachment;
521 buffers[i].name = repBuffer.name;
522 buffers[i].pitch = repBuffer.pitch;
523 buffers[i].cpp = repBuffer.cpp;
524 buffers[i].flags = repBuffer.flags;
535 DRI2CopyRegion(Display * dpy, XID drawable, XserverRegion region,
536 CARD32 dest, CARD32 src)
538 XExtDisplayInfo *info = DRI2FindDisplay(dpy);
539 xDRI2CopyRegionReq *req;
540 xDRI2CopyRegionReply rep;
542 XextSimpleCheckExtension(dpy, info, dri2ExtensionName);
544 LOG("COPY-REGION drawable:0x%x, src:%d, dest:%d\n", (unsigned int)drawable, (int)src, (int)dest);
547 GetReq(DRI2CopyRegion, req);
548 req->reqType = info->codes->major_opcode;
549 req->dri2ReqType = X_DRI2CopyRegion;
550 req->drawable = drawable;
551 req->region = region;
555 _XReply(dpy, (xReply *) & rep, 0, xFalse);
561 #ifdef X_DRI2SwapBuffers
563 load_swap_req(xDRI2SwapBuffersReq *req, CARD64 target, CARD64 divisor,
566 req->target_msc_hi = target >> 32;
567 req->target_msc_lo = target & 0xffffffff;
568 req->divisor_hi = divisor >> 32;
569 req->divisor_lo = divisor & 0xffffffff;
570 req->remainder_hi = remainder >> 32;
571 req->remainder_lo = remainder & 0xffffffff;
575 vals_to_card64(CARD32 lo, CARD32 hi)
577 return (CARD64)hi << 32 | lo;
580 void DRI2SwapBuffers(Display *dpy, XID drawable, CARD64 target_msc,
581 CARD64 divisor, CARD64 remainder, CARD64 *count)
583 XExtDisplayInfo *info = DRI2FindDisplay(dpy);
584 xDRI2SwapBuffersReq *req;
585 xDRI2SwapBuffersReply rep;
587 XextSimpleCheckExtension (dpy, info, dri2ExtensionName);
590 LOG("SWAP drawable:0x%x\n", (unsigned int)drawable);
592 GetReq(DRI2SwapBuffers, req);
593 req->reqType = info->codes->major_opcode;
594 req->dri2ReqType = X_DRI2SwapBuffers;
595 req->drawable = drawable;
596 load_swap_req(req, target_msc, divisor, remainder);
598 _XReply(dpy, (xReply *)&rep, 0, xFalse);
600 *count = vals_to_card64(rep.swap_lo, rep.swap_hi);
612 Bool DRI2GetMSC(Display *dpy, XID drawable, CARD64 *ust, CARD64 *msc,
615 XExtDisplayInfo *info = DRI2FindDisplay(dpy);
619 XextCheckExtension (dpy, info, dri2ExtensionName, False);
622 GetReq(DRI2GetMSC, req);
623 req->reqType = info->codes->major_opcode;
624 req->dri2ReqType = X_DRI2GetMSC;
625 req->drawable = drawable;
627 if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
633 *ust = vals_to_card64(rep.ust_lo, rep.ust_hi);
634 *msc = vals_to_card64(rep.msc_lo, rep.msc_hi);
635 *sbc = vals_to_card64(rep.sbc_lo, rep.sbc_hi);
646 load_msc_req(xDRI2WaitMSCReq *req, CARD64 target, CARD64 divisor,
649 req->target_msc_hi = target >> 32;
650 req->target_msc_lo = target & 0xffffffff;
651 req->divisor_hi = divisor >> 32;
652 req->divisor_lo = divisor & 0xffffffff;
653 req->remainder_hi = remainder >> 32;
654 req->remainder_lo = remainder & 0xffffffff;
657 Bool DRI2WaitMSC(Display *dpy, XID drawable, CARD64 target_msc, CARD64 divisor,
658 CARD64 remainder, CARD64 *ust, CARD64 *msc, CARD64 *sbc)
660 XExtDisplayInfo *info = DRI2FindDisplay(dpy);
661 xDRI2WaitMSCReq *req;
664 XextCheckExtension (dpy, info, dri2ExtensionName, False);
667 GetReq(DRI2WaitMSC, req);
668 req->reqType = info->codes->major_opcode;
669 req->dri2ReqType = X_DRI2WaitMSC;
670 req->drawable = drawable;
671 load_msc_req(req, target_msc, divisor, remainder);
673 if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
679 *ust = ((CARD64)rep.ust_hi << 32) | (CARD64)rep.ust_lo;
680 *msc = ((CARD64)rep.msc_hi << 32) | (CARD64)rep.msc_lo;
681 *sbc = ((CARD64)rep.sbc_hi << 32) | (CARD64)rep.sbc_lo;
692 load_sbc_req(xDRI2WaitSBCReq *req, CARD64 target)
694 req->target_sbc_hi = target >> 32;
695 req->target_sbc_lo = target & 0xffffffff;
698 Bool DRI2WaitSBC(Display *dpy, XID drawable, CARD64 target_sbc, CARD64 *ust,
699 CARD64 *msc, CARD64 *sbc)
701 XExtDisplayInfo *info = DRI2FindDisplay(dpy);
702 xDRI2WaitSBCReq *req;
705 XextCheckExtension (dpy, info, dri2ExtensionName, False);
708 GetReq(DRI2WaitSBC, req);
709 req->reqType = info->codes->major_opcode;
710 req->dri2ReqType = X_DRI2WaitSBC;
711 req->drawable = drawable;
712 load_sbc_req(req, target_sbc);
714 if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
720 *ust = ((CARD64)rep.ust_hi << 32) | rep.ust_lo;
721 *msc = ((CARD64)rep.msc_hi << 32) | rep.msc_lo;
722 *sbc = ((CARD64)rep.sbc_hi << 32) | rep.sbc_lo;
731 #ifdef X_DRI2SwapInterval
732 void DRI2SwapInterval(Display *dpy, XID drawable, int interval)
734 XExtDisplayInfo *info = DRI2FindDisplay(dpy);
735 xDRI2SwapIntervalReq *req;
737 XextSimpleCheckExtension (dpy, info, dri2ExtensionName);
740 GetReq(DRI2SwapInterval, req);
741 req->reqType = info->codes->major_opcode;
742 req->dri2ReqType = X_DRI2SwapInterval;
743 req->drawable = drawable;
744 req->interval = interval;
750 #ifdef X_DRI2SwapBuffersWithRegion
751 void DRI2SwapBuffersWithRegion(Display *dpy, XID drawable, XserverRegion region,
754 XExtDisplayInfo *info = DRI2FindDisplay(dpy);
755 xDRI2SwapBuffersWithRegionReq *req;
756 xDRI2SwapBuffersReply rep;
758 XextSimpleCheckExtension (dpy, info, dri2ExtensionName);
761 LOG("SWAP drawable:0x%x\n", (unsigned int)drawable);
763 GetReq(DRI2SwapBuffersWithRegion, req);
764 req->reqType = info->codes->major_opcode;
765 req->dri2ReqType = X_DRI2SwapBuffersWithRegion;
766 req->drawable = drawable;
767 req->region = region;
769 _XReply(dpy, (xReply *)&rep, 0, xFalse);
771 *count = vals_to_card64(rep.swap_lo, rep.swap_hi);