1 /**************************************************************************
3 Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
4 Copyright 2000 VA Linux Systems, Inc.
7 Permission is hereby granted, free of charge, to any person obtaining a
8 copy of this software and associated documentation files (the
9 "Software"), to deal in the Software without restriction, including
10 without limitation the rights to use, copy, modify, merge, publish,
11 distribute, sub license, and/or sell copies of the Software, and to
12 permit persons to whom the Software is furnished to do so, subject to
13 the following conditions:
15 The above copyright notice and this permission notice (including the
16 next paragraph) shall be included in all copies or substantial portions
19 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
22 IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
23 ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
24 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
25 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 **************************************************************************/
31 * Kevin E. Martin <martin@valinux.com>
32 * Jens Owen <jens@tungstengraphics.com>
33 * Rickard E. (Rik) Faith <faith@valinux.com>
37 /* THIS IS NOT AN X CONSORTIUM STANDARD */
39 #ifdef GLX_DIRECT_RENDERING
42 #include <X11/Xlibint.h>
43 #include <X11/extensions/Xext.h>
44 #include <X11/extensions/extutil.h>
45 #include "xf86dristr.h"
48 #if defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__) >= 303
49 # define PUBLIC __attribute__((visibility("default")))
50 # define USED __attribute__((used))
58 static XExtensionInfo _xf86dri_info_data
;
59 static XExtensionInfo
*xf86dri_info
= &_xf86dri_info_data
;
60 static char xf86dri_extension_name
[] = XF86DRINAME
;
62 #define XF86DRICheckExtension(dpy,i,val) \
63 XextCheckExtension (dpy, i, xf86dri_extension_name, val)
65 /*****************************************************************************
67 * private utility routines *
69 *****************************************************************************/
71 static int close_display(Display
*dpy
, XExtCodes
*extCodes
);
72 static /* const */ XExtensionHooks xf86dri_extension_hooks
= {
77 NULL
, /* create_font */
79 close_display
, /* close_display */
80 NULL
, /* wire_to_event */
81 NULL
, /* event_to_wire */
83 NULL
, /* error_string */
86 static XEXT_GENERATE_FIND_DISPLAY (find_display
, xf86dri_info
,
87 xf86dri_extension_name
,
88 &xf86dri_extension_hooks
,
91 static XEXT_GENERATE_CLOSE_DISPLAY (close_display
, xf86dri_info
)
94 /*****************************************************************************
96 * public XFree86-DRI Extension routines *
98 *****************************************************************************/
102 #define TRACE(msg) fprintf(stderr,"XF86DRI%s\n", msg);
108 PUBLIC Bool
XF86DRIQueryExtension (dpy
, event_basep
, error_basep
)
110 int *event_basep
, *error_basep
;
112 XExtDisplayInfo
*info
= find_display (dpy
);
114 TRACE("QueryExtension...");
115 if (XextHasExtension(info
)) {
116 *event_basep
= info
->codes
->first_event
;
117 *error_basep
= info
->codes
->first_error
;
118 TRACE("QueryExtension... return True");
121 TRACE("QueryExtension... return False");
126 PUBLIC Bool
XF86DRIQueryVersion(dpy
, majorVersion
, minorVersion
, patchVersion
)
132 XExtDisplayInfo
*info
= find_display (dpy
);
133 xXF86DRIQueryVersionReply rep
;
134 xXF86DRIQueryVersionReq
*req
;
136 TRACE("QueryVersion...");
137 XF86DRICheckExtension (dpy
, info
, False
);
140 GetReq(XF86DRIQueryVersion
, req
);
141 req
->reqType
= info
->codes
->major_opcode
;
142 req
->driReqType
= X_XF86DRIQueryVersion
;
143 if (!_XReply(dpy
, (xReply
*)&rep
, 0, xFalse
)) {
146 TRACE("QueryVersion... return False");
149 *majorVersion
= rep
.majorVersion
;
150 *minorVersion
= rep
.minorVersion
;
151 *patchVersion
= rep
.patchVersion
;
154 TRACE("QueryVersion... return True");
158 PUBLIC Bool
XF86DRIQueryDirectRenderingCapable(dpy
, screen
, isCapable
)
163 XExtDisplayInfo
*info
= find_display (dpy
);
164 xXF86DRIQueryDirectRenderingCapableReply rep
;
165 xXF86DRIQueryDirectRenderingCapableReq
*req
;
167 TRACE("QueryDirectRenderingCapable...");
168 XF86DRICheckExtension (dpy
, info
, False
);
171 GetReq(XF86DRIQueryDirectRenderingCapable
, req
);
172 req
->reqType
= info
->codes
->major_opcode
;
173 req
->driReqType
= X_XF86DRIQueryDirectRenderingCapable
;
174 req
->screen
= screen
;
175 if (!_XReply(dpy
, (xReply
*)&rep
, 0, xFalse
)) {
178 TRACE("QueryDirectRenderingCapable... return False");
181 *isCapable
= rep
.isCapable
;
184 TRACE("QueryDirectRenderingCapable... return True");
188 PUBLIC Bool
XF86DRIOpenConnection(dpy
, screen
, hSAREA
, busIdString
)
191 drm_handle_t
* hSAREA
;
194 XExtDisplayInfo
*info
= find_display (dpy
);
195 xXF86DRIOpenConnectionReply rep
;
196 xXF86DRIOpenConnectionReq
*req
;
198 TRACE("OpenConnection...");
199 XF86DRICheckExtension (dpy
, info
, False
);
202 GetReq(XF86DRIOpenConnection
, req
);
203 req
->reqType
= info
->codes
->major_opcode
;
204 req
->driReqType
= X_XF86DRIOpenConnection
;
205 req
->screen
= screen
;
206 if (!_XReply(dpy
, (xReply
*)&rep
, 0, xFalse
)) {
209 TRACE("OpenConnection... return False");
213 *hSAREA
= rep
.hSAREALow
;
214 if (sizeof(drm_handle_t
) == 8) {
215 int shift
= 32; /* var to prevent warning on next line */
216 *hSAREA
|= ((drm_handle_t
) rep
.hSAREAHigh
) << shift
;
220 if (!(*busIdString
= (char *)Xcalloc(rep
.busIdStringLength
+ 1, 1))) {
221 _XEatData(dpy
, ((rep
.busIdStringLength
+3) & ~3));
224 TRACE("OpenConnection... return False");
227 _XReadPad(dpy
, *busIdString
, rep
.busIdStringLength
);
233 TRACE("OpenConnection... return True");
237 PUBLIC Bool
XF86DRIAuthConnection(dpy
, screen
, magic
)
242 XExtDisplayInfo
*info
= find_display (dpy
);
243 xXF86DRIAuthConnectionReq
*req
;
244 xXF86DRIAuthConnectionReply rep
;
246 TRACE("AuthConnection...");
247 XF86DRICheckExtension (dpy
, info
, False
);
250 GetReq(XF86DRIAuthConnection
, req
);
251 req
->reqType
= info
->codes
->major_opcode
;
252 req
->driReqType
= X_XF86DRIAuthConnection
;
253 req
->screen
= screen
;
255 rep
.authenticated
= 0;
256 if (!_XReply(dpy
, (xReply
*)&rep
, 0, xFalse
) || !rep
.authenticated
) {
259 TRACE("AuthConnection... return False");
264 TRACE("AuthConnection... return True");
268 PUBLIC Bool
XF86DRICloseConnection(dpy
, screen
)
272 XExtDisplayInfo
*info
= find_display (dpy
);
273 xXF86DRICloseConnectionReq
*req
;
275 TRACE("CloseConnection...");
277 XF86DRICheckExtension (dpy
, info
, False
);
280 GetReq(XF86DRICloseConnection
, req
);
281 req
->reqType
= info
->codes
->major_opcode
;
282 req
->driReqType
= X_XF86DRICloseConnection
;
283 req
->screen
= screen
;
286 TRACE("CloseConnection... return True");
290 PUBLIC Bool
XF86DRIGetClientDriverName(dpy
, screen
, ddxDriverMajorVersion
,
291 ddxDriverMinorVersion
, ddxDriverPatchVersion
, clientDriverName
)
294 int* ddxDriverMajorVersion
;
295 int* ddxDriverMinorVersion
;
296 int* ddxDriverPatchVersion
;
297 char** clientDriverName
;
299 XExtDisplayInfo
*info
= find_display (dpy
);
300 xXF86DRIGetClientDriverNameReply rep
;
301 xXF86DRIGetClientDriverNameReq
*req
;
303 TRACE("GetClientDriverName...");
304 XF86DRICheckExtension (dpy
, info
, False
);
307 GetReq(XF86DRIGetClientDriverName
, req
);
308 req
->reqType
= info
->codes
->major_opcode
;
309 req
->driReqType
= X_XF86DRIGetClientDriverName
;
310 req
->screen
= screen
;
311 if (!_XReply(dpy
, (xReply
*)&rep
, 0, xFalse
)) {
314 TRACE("GetClientDriverName... return False");
318 *ddxDriverMajorVersion
= rep
.ddxDriverMajorVersion
;
319 *ddxDriverMinorVersion
= rep
.ddxDriverMinorVersion
;
320 *ddxDriverPatchVersion
= rep
.ddxDriverPatchVersion
;
323 if (!(*clientDriverName
= (char *)Xcalloc(rep
.clientDriverNameLength
+ 1, 1))) {
324 _XEatData(dpy
, ((rep
.clientDriverNameLength
+3) & ~3));
327 TRACE("GetClientDriverName... return False");
330 _XReadPad(dpy
, *clientDriverName
, rep
.clientDriverNameLength
);
332 *clientDriverName
= NULL
;
336 TRACE("GetClientDriverName... return True");
340 PUBLIC Bool
XF86DRICreateContextWithConfig(dpy
, screen
, configID
, context
,
346 drm_context_t
* hHWContext
;
348 XExtDisplayInfo
*info
= find_display (dpy
);
349 xXF86DRICreateContextReply rep
;
350 xXF86DRICreateContextReq
*req
;
352 TRACE("CreateContext...");
353 XF86DRICheckExtension (dpy
, info
, False
);
356 GetReq(XF86DRICreateContext
, req
);
357 req
->reqType
= info
->codes
->major_opcode
;
358 req
->driReqType
= X_XF86DRICreateContext
;
359 req
->visual
= configID
;
360 req
->screen
= screen
;
361 *context
= XAllocID(dpy
);
362 req
->context
= *context
;
363 if (!_XReply(dpy
, (xReply
*)&rep
, 0, xFalse
)) {
366 TRACE("CreateContext... return False");
369 *hHWContext
= rep
.hHWContext
;
372 TRACE("CreateContext... return True");
376 PUBLIC Bool
XF86DRICreateContext(dpy
, screen
, visual
, context
, hHWContext
)
381 drm_context_t
* hHWContext
;
383 return XF86DRICreateContextWithConfig( dpy
, screen
, visual
->visualid
,
384 context
, hHWContext
);
387 PUBLIC Bool
XF86DRIDestroyContext(Display
*dpy
, int screen
,
390 XExtDisplayInfo
*info
= find_display (dpy
);
391 xXF86DRIDestroyContextReq
*req
;
393 TRACE("DestroyContext...");
394 XF86DRICheckExtension (dpy
, info
, False
);
397 GetReq(XF86DRIDestroyContext
, req
);
398 req
->reqType
= info
->codes
->major_opcode
;
399 req
->driReqType
= X_XF86DRIDestroyContext
;
400 req
->screen
= screen
;
401 req
->context
= context
;
404 TRACE("DestroyContext... return True");
408 PUBLIC Bool
XF86DRICreateDrawable(Display
*dpy
, int screen
,
409 XID drawable
, drm_drawable_t
* hHWDrawable
)
411 XExtDisplayInfo
*info
= find_display (dpy
);
412 xXF86DRICreateDrawableReply rep
;
413 xXF86DRICreateDrawableReq
*req
;
415 TRACE("CreateDrawable...");
416 XF86DRICheckExtension (dpy
, info
, False
);
419 GetReq(XF86DRICreateDrawable
, req
);
420 req
->reqType
= info
->codes
->major_opcode
;
421 req
->driReqType
= X_XF86DRICreateDrawable
;
422 req
->screen
= screen
;
423 req
->drawable
= drawable
;
424 if (!_XReply(dpy
, (xReply
*)&rep
, 0, xFalse
)) {
427 TRACE("CreateDrawable... return False");
430 *hHWDrawable
= rep
.hHWDrawable
;
433 TRACE("CreateDrawable... return True");
437 static int noopErrorHandler(Display
*dpy
, XErrorEvent
*xerr
)
442 PUBLIC Bool
XF86DRIDestroyDrawable(Display
*dpy
, int screen
,
445 XExtDisplayInfo
*info
= find_display (dpy
);
446 xXF86DRIDestroyDrawableReq
*req
;
447 int (*oldXErrorHandler
)(Display
*, XErrorEvent
*);
449 TRACE("DestroyDrawable...");
450 XF86DRICheckExtension (dpy
, info
, False
);
452 /* This is called from the DRI driver, which used call it like this
454 * if (windowExists(drawable))
455 * destroyDrawable(drawable);
457 * which is a textbook race condition - the window may disappear
458 * from the server between checking for its existance and
459 * destroying it. Instead we change the semantics of
460 * __DRIinterfaceMethodsRec::destroyDrawable() to succeed even if
461 * the windows is gone, by wrapping the destroy call in an error
465 oldXErrorHandler
= XSetErrorHandler(noopErrorHandler
);
468 GetReq(XF86DRIDestroyDrawable
, req
);
469 req
->reqType
= info
->codes
->major_opcode
;
470 req
->driReqType
= X_XF86DRIDestroyDrawable
;
471 req
->screen
= screen
;
472 req
->drawable
= drawable
;
476 XSetErrorHandler(oldXErrorHandler
);
478 TRACE("DestroyDrawable... return True");
482 PUBLIC Bool
XF86DRIGetDrawableInfo(Display
* dpy
, int screen
, Drawable drawable
,
483 unsigned int* index
, unsigned int* stamp
,
484 int* X
, int* Y
, int* W
, int* H
,
485 int* numClipRects
, drm_clip_rect_t
** pClipRects
,
486 int* backX
, int* backY
,
487 int* numBackClipRects
, drm_clip_rect_t
** pBackClipRects
)
489 XExtDisplayInfo
*info
= find_display (dpy
);
490 xXF86DRIGetDrawableInfoReply rep
;
491 xXF86DRIGetDrawableInfoReq
*req
;
494 TRACE("GetDrawableInfo...");
495 XF86DRICheckExtension (dpy
, info
, False
);
498 GetReq(XF86DRIGetDrawableInfo
, req
);
499 req
->reqType
= info
->codes
->major_opcode
;
500 req
->driReqType
= X_XF86DRIGetDrawableInfo
;
501 req
->screen
= screen
;
502 req
->drawable
= drawable
;
504 if (!_XReply(dpy
, (xReply
*)&rep
, 1, xFalse
))
508 TRACE("GetDrawableInfo... return False");
511 *index
= rep
.drawableTableIndex
;
512 *stamp
= rep
.drawableTableStamp
;
513 *X
= (int)rep
.drawableX
;
514 *Y
= (int)rep
.drawableY
;
515 *W
= (int)rep
.drawableWidth
;
516 *H
= (int)rep
.drawableHeight
;
517 *numClipRects
= rep
.numClipRects
;
518 total_rects
= *numClipRects
;
522 *numBackClipRects
= rep
.numBackClipRects
;
523 total_rects
+= *numBackClipRects
;
526 /* Because of the fix in Xserver/GL/dri/xf86dri.c, this check breaks
527 * backwards compatibility (Because of the >> 2 shift) but the fix
528 * enables multi-threaded apps to work.
530 if (rep
.length
!= ((((SIZEOF(xXF86DRIGetDrawableInfoReply
) -
531 SIZEOF(xGenericReply
) +
532 total_rects
* sizeof(drm_clip_rect_t
)) + 3) & ~3) >> 2)) {
533 _XEatData(dpy
, rep
.length
);
536 TRACE("GetDrawableInfo... return False");
542 int len
= sizeof(drm_clip_rect_t
) * (*numClipRects
);
544 *pClipRects
= (drm_clip_rect_t
*)Xcalloc(len
, 1);
546 _XRead(dpy
, (char*)*pClipRects
, len
);
551 if (*numBackClipRects
) {
552 int len
= sizeof(drm_clip_rect_t
) * (*numBackClipRects
);
554 *pBackClipRects
= (drm_clip_rect_t
*)Xcalloc(len
, 1);
556 _XRead(dpy
, (char*)*pBackClipRects
, len
);
558 *pBackClipRects
= NULL
;
563 TRACE("GetDrawableInfo... return True");
567 PUBLIC Bool
XF86DRIGetDeviceInfo(dpy
, screen
, hFrameBuffer
,
568 fbOrigin
, fbSize
, fbStride
, devPrivateSize
, pDevPrivate
)
571 drm_handle_t
* hFrameBuffer
;
578 XExtDisplayInfo
*info
= find_display (dpy
);
579 xXF86DRIGetDeviceInfoReply rep
;
580 xXF86DRIGetDeviceInfoReq
*req
;
582 TRACE("GetDeviceInfo...");
583 XF86DRICheckExtension (dpy
, info
, False
);
586 GetReq(XF86DRIGetDeviceInfo
, req
);
587 req
->reqType
= info
->codes
->major_opcode
;
588 req
->driReqType
= X_XF86DRIGetDeviceInfo
;
589 req
->screen
= screen
;
590 if (!_XReply(dpy
, (xReply
*)&rep
, 0, xFalse
)) {
593 TRACE("GetDeviceInfo... return False");
597 *hFrameBuffer
= rep
.hFrameBufferLow
;
598 if (sizeof(drm_handle_t
) == 8) {
599 int shift
= 32; /* var to prevent warning on next line */
600 *hFrameBuffer
|= ((drm_handle_t
) rep
.hFrameBufferHigh
) << shift
;
603 *fbOrigin
= rep
.framebufferOrigin
;
604 *fbSize
= rep
.framebufferSize
;
605 *fbStride
= rep
.framebufferStride
;
606 *devPrivateSize
= rep
.devPrivateSize
;
609 if (!(*pDevPrivate
= (void *)Xcalloc(rep
.devPrivateSize
, 1))) {
610 _XEatData(dpy
, ((rep
.devPrivateSize
+3) & ~3));
613 TRACE("GetDeviceInfo... return False");
616 _XRead(dpy
, (char*)*pDevPrivate
, rep
.devPrivateSize
);
623 TRACE("GetDeviceInfo... return True");
627 PUBLIC Bool
XF86DRIOpenFullScreen(dpy
, screen
, drawable
)
632 /* This function and the underlying X protocol are deprecated.
640 PUBLIC Bool
XF86DRICloseFullScreen(dpy
, screen
, drawable
)
645 /* This function and the underlying X protocol are deprecated.
653 #endif /* GLX_DIRECT_RENDERING */