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) {
268 for (i = 0; i < nevents; i++) {
269 XESetWireToEvent (dpy, info->codes->first_event + i, DRI2WireToEvent);
270 XESetEventToWire (dpy, info->codes->first_event + i, DRI2EventToWire);
277 DRI2Connect(Display * dpy, XID window, char **driverName, char **deviceName)
279 XExtDisplayInfo *info = DRI2FindDisplay(dpy);
280 xDRI2ConnectReply rep;
281 xDRI2ConnectReq *req;
283 XextCheckExtension(dpy, info, dri2ExtensionName, False);
286 GetReq(DRI2Connect, req);
287 req->reqType = info->codes->major_opcode;
288 req->dri2ReqType = X_DRI2Connect;
289 req->window = window;
290 req->driverType = DRI2DriverDRI;
291 if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
297 if (rep.driverNameLength == 0 && rep.deviceNameLength == 0) {
303 *driverName = Xmalloc(rep.driverNameLength + 1);
304 if (*driverName == NULL) {
306 ((rep.driverNameLength + 3) & ~3) +
307 ((rep.deviceNameLength + 3) & ~3));
312 _XReadPad(dpy, *driverName, rep.driverNameLength);
313 (*driverName)[rep.driverNameLength] = '\0';
315 *deviceName = Xmalloc(rep.deviceNameLength + 1);
316 if (*deviceName == NULL) {
318 _XEatData(dpy, ((rep.deviceNameLength + 3) & ~3));
323 _XReadPad(dpy, *deviceName, rep.deviceNameLength);
324 (*deviceName)[rep.deviceNameLength] = '\0';
333 DRI2Authenticate(Display * dpy, XID window, unsigned int magic)
335 XExtDisplayInfo *info = DRI2FindDisplay(dpy);
336 xDRI2AuthenticateReq *req;
337 xDRI2AuthenticateReply rep;
339 XextCheckExtension(dpy, info, dri2ExtensionName, False);
342 GetReq(DRI2Authenticate, req);
343 req->reqType = info->codes->major_opcode;
344 req->dri2ReqType = X_DRI2Authenticate;
345 req->window = window;
348 if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
357 return rep.authenticated;
361 DRI2CreateDrawable(Display * dpy, XID drawable)
363 XExtDisplayInfo *info = DRI2FindDisplay(dpy);
364 xDRI2CreateDrawableReq *req;
366 XextSimpleCheckExtension(dpy, info, dri2ExtensionName);
369 LOG("CREATE drawable:0x%x\n", (unsigned int)drawable);
371 GetReq(DRI2CreateDrawable, req);
372 req->reqType = info->codes->major_opcode;
373 req->dri2ReqType = X_DRI2CreateDrawable;
374 req->drawable = drawable;
380 DRI2DestroyDrawable(Display * dpy, XID drawable)
382 XExtDisplayInfo *info = DRI2FindDisplay(dpy);
383 xDRI2DestroyDrawableReq *req;
385 XextSimpleCheckExtension(dpy, info, dri2ExtensionName);
389 LOG("DESTROY drawable:0x%x\n", (unsigned int)drawable);
391 GetReq(DRI2DestroyDrawable, req);
392 req->reqType = info->codes->major_opcode;
393 req->dri2ReqType = X_DRI2DestroyDrawable;
394 req->drawable = drawable;
400 DRI2GetBuffers(Display * dpy, XID drawable,
401 int *width, int *height,
402 unsigned int *attachments, int count, int *outCount)
404 XExtDisplayInfo *info = DRI2FindDisplay(dpy);
405 xDRI2GetBuffersReply rep;
406 xDRI2GetBuffersReq *req;
408 xDRI2Buffer repBuffer;
412 XextCheckExtension(dpy, info, dri2ExtensionName, False);
419 LOG("GET-BUF drawable:0x%x, count:%d, attach:%d \n"
420 , (unsigned int)drawable, count, *attachments);
422 GetReqExtra(DRI2GetBuffers, count * 4, req);
423 req->reqType = info->codes->major_opcode;
424 req->dri2ReqType = X_DRI2GetBuffers;
425 req->drawable = drawable;
427 p = (CARD32 *) & req[1];
428 for (i = 0; i < count; i++)
429 p[i] = attachments[i];
431 if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
438 *height = rep.height;
439 *outCount = rep.count;
441 buffers = Xmalloc(rep.count * sizeof buffers[0]);
442 if (buffers == NULL) {
443 _XEatData(dpy, rep.count * sizeof repBuffer);
449 for (i = 0; i < rep.count; i++) {
450 _XReadPad(dpy, (char *) &repBuffer, sizeof repBuffer);
451 buffers[i].attachment = repBuffer.attachment;
452 buffers[i].name = repBuffer.name;
453 buffers[i].pitch = repBuffer.pitch;
454 buffers[i].cpp = repBuffer.cpp;
455 buffers[i].flags = repBuffer.flags;
457 LOG("\t\t New attach:%d name:%d flags:0x%x width:%d, height:%d\n"
458 , buffers[i].attachment, buffers[i].name, buffers[i].flags, *width, *height);
463 GFX_PERF_INT("G", buffers[0].name);
474 DRI2GetBuffersWithFormat(Display * dpy, XID drawable,
475 int *width, int *height,
476 unsigned int *attachments, int count, int *outCount)
478 XExtDisplayInfo *info = DRI2FindDisplay(dpy);
479 xDRI2GetBuffersReply rep;
480 xDRI2GetBuffersReq *req;
482 xDRI2Buffer repBuffer;
486 XextCheckExtension(dpy, info, dri2ExtensionName, False);
489 GetReqExtra(DRI2GetBuffers, count * (4 * 2), req);
490 req->reqType = info->codes->major_opcode;
491 req->dri2ReqType = X_DRI2GetBuffersWithFormat;
492 req->drawable = drawable;
494 p = (CARD32 *) & req[1];
495 for (i = 0; i < (count * 2); i++)
496 p[i] = attachments[i];
498 if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
505 *height = rep.height;
506 *outCount = rep.count;
508 buffers = Xmalloc(rep.count * sizeof buffers[0]);
509 if (buffers == NULL) {
510 _XEatData(dpy, rep.count * sizeof repBuffer);
516 for (i = 0; i < rep.count; i++) {
517 _XReadPad(dpy, (char *) &repBuffer, sizeof repBuffer);
518 buffers[i].attachment = repBuffer.attachment;
519 buffers[i].name = repBuffer.name;
520 buffers[i].pitch = repBuffer.pitch;
521 buffers[i].cpp = repBuffer.cpp;
522 buffers[i].flags = repBuffer.flags;
533 DRI2CopyRegion(Display * dpy, XID drawable, XserverRegion region,
534 CARD32 dest, CARD32 src)
536 XExtDisplayInfo *info = DRI2FindDisplay(dpy);
537 xDRI2CopyRegionReq *req;
538 xDRI2CopyRegionReply rep;
540 XextSimpleCheckExtension(dpy, info, dri2ExtensionName);
542 LOG("COPY-REGION drawable:0x%x, src:%d, dest:%d\n", (unsigned int)drawable, (int)src, (int)dest);
545 GetReq(DRI2CopyRegion, req);
546 req->reqType = info->codes->major_opcode;
547 req->dri2ReqType = X_DRI2CopyRegion;
548 req->drawable = drawable;
549 req->region = region;
553 _XReply(dpy, (xReply *) & rep, 0, xFalse);
559 #ifdef X_DRI2SwapBuffers
561 load_swap_req(xDRI2SwapBuffersReq *req, CARD64 target, CARD64 divisor,
564 req->target_msc_hi = target >> 32;
565 req->target_msc_lo = target & 0xffffffff;
566 req->divisor_hi = divisor >> 32;
567 req->divisor_lo = divisor & 0xffffffff;
568 req->remainder_hi = remainder >> 32;
569 req->remainder_lo = remainder & 0xffffffff;
573 vals_to_card64(CARD32 lo, CARD32 hi)
575 return (CARD64)hi << 32 | lo;
578 void DRI2SwapBuffers(Display *dpy, XID drawable, CARD64 target_msc,
579 CARD64 divisor, CARD64 remainder, CARD64 *count)
581 XExtDisplayInfo *info = DRI2FindDisplay(dpy);
582 xDRI2SwapBuffersReq *req;
583 xDRI2SwapBuffersReply rep;
585 XextSimpleCheckExtension (dpy, info, dri2ExtensionName);
588 LOG("SWAP drawable:0x%x\n", (unsigned int)drawable);
590 GetReq(DRI2SwapBuffers, req);
591 req->reqType = info->codes->major_opcode;
592 req->dri2ReqType = X_DRI2SwapBuffers;
593 req->drawable = drawable;
594 load_swap_req(req, target_msc, divisor, remainder);
596 _XReply(dpy, (xReply *)&rep, 0, xFalse);
598 *count = vals_to_card64(rep.swap_lo, rep.swap_hi);
610 Bool DRI2GetMSC(Display *dpy, XID drawable, CARD64 *ust, CARD64 *msc,
613 XExtDisplayInfo *info = DRI2FindDisplay(dpy);
617 XextCheckExtension (dpy, info, dri2ExtensionName, False);
620 GetReq(DRI2GetMSC, req);
621 req->reqType = info->codes->major_opcode;
622 req->dri2ReqType = X_DRI2GetMSC;
623 req->drawable = drawable;
625 if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
631 *ust = vals_to_card64(rep.ust_lo, rep.ust_hi);
632 *msc = vals_to_card64(rep.msc_lo, rep.msc_hi);
633 *sbc = vals_to_card64(rep.sbc_lo, rep.sbc_hi);
644 load_msc_req(xDRI2WaitMSCReq *req, CARD64 target, CARD64 divisor,
647 req->target_msc_hi = target >> 32;
648 req->target_msc_lo = target & 0xffffffff;
649 req->divisor_hi = divisor >> 32;
650 req->divisor_lo = divisor & 0xffffffff;
651 req->remainder_hi = remainder >> 32;
652 req->remainder_lo = remainder & 0xffffffff;
655 Bool DRI2WaitMSC(Display *dpy, XID drawable, CARD64 target_msc, CARD64 divisor,
656 CARD64 remainder, CARD64 *ust, CARD64 *msc, CARD64 *sbc)
658 XExtDisplayInfo *info = DRI2FindDisplay(dpy);
659 xDRI2WaitMSCReq *req;
662 XextCheckExtension (dpy, info, dri2ExtensionName, False);
665 GetReq(DRI2WaitMSC, req);
666 req->reqType = info->codes->major_opcode;
667 req->dri2ReqType = X_DRI2WaitMSC;
668 req->drawable = drawable;
669 load_msc_req(req, target_msc, divisor, remainder);
671 if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
677 *ust = ((CARD64)rep.ust_hi << 32) | (CARD64)rep.ust_lo;
678 *msc = ((CARD64)rep.msc_hi << 32) | (CARD64)rep.msc_lo;
679 *sbc = ((CARD64)rep.sbc_hi << 32) | (CARD64)rep.sbc_lo;
690 load_sbc_req(xDRI2WaitSBCReq *req, CARD64 target)
692 req->target_sbc_hi = target >> 32;
693 req->target_sbc_lo = target & 0xffffffff;
696 Bool DRI2WaitSBC(Display *dpy, XID drawable, CARD64 target_sbc, CARD64 *ust,
697 CARD64 *msc, CARD64 *sbc)
699 XExtDisplayInfo *info = DRI2FindDisplay(dpy);
700 xDRI2WaitSBCReq *req;
703 XextCheckExtension (dpy, info, dri2ExtensionName, False);
706 GetReq(DRI2WaitSBC, req);
707 req->reqType = info->codes->major_opcode;
708 req->dri2ReqType = X_DRI2WaitSBC;
709 req->drawable = drawable;
710 load_sbc_req(req, target_sbc);
712 if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
718 *ust = ((CARD64)rep.ust_hi << 32) | rep.ust_lo;
719 *msc = ((CARD64)rep.msc_hi << 32) | rep.msc_lo;
720 *sbc = ((CARD64)rep.sbc_hi << 32) | rep.sbc_lo;
729 #ifdef X_DRI2SwapInterval
730 void DRI2SwapInterval(Display *dpy, XID drawable, int interval)
732 XExtDisplayInfo *info = DRI2FindDisplay(dpy);
733 xDRI2SwapIntervalReq *req;
735 XextSimpleCheckExtension (dpy, info, dri2ExtensionName);
738 GetReq(DRI2SwapInterval, req);
739 req->reqType = info->codes->major_opcode;
740 req->dri2ReqType = X_DRI2SwapInterval;
741 req->drawable = drawable;
742 req->interval = interval;
748 #ifdef X_DRI2SwapBuffersWithRegion
749 void DRI2SwapBuffersWithRegion(Display *dpy, XID drawable, XserverRegion region,
752 XExtDisplayInfo *info = DRI2FindDisplay(dpy);
753 xDRI2SwapBuffersWithRegionReq *req;
754 xDRI2SwapBuffersReply rep;
756 XextSimpleCheckExtension (dpy, info, dri2ExtensionName);
759 LOG("SWAP drawable:0x%x\n", (unsigned int)drawable);
761 GetReq(DRI2SwapBuffersWithRegion, req);
762 req->reqType = info->codes->major_opcode;
763 req->dri2ReqType = X_DRI2SwapBuffersWithRegion;
764 req->drawable = drawable;
765 req->region = region;
767 _XReply(dpy, (xReply *)&rep, 0, xFalse);
769 *count = vals_to_card64(rep.swap_lo, rep.swap_hi);