1 /* -*- mode: c; tab-width: 3; indent-tabs-mode: nil; c-basic-offset: 3; coding: utf-8-unix -*- */
2 /**************************************************************************
4 Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
5 Copyright 2000 VA Linux Systems, Inc.
8 Permission is hereby granted, free of charge, to any person obtaining a
9 copy of this software and associated documentation files (the
10 "Software"), to deal in the Software without restriction, including
11 without limitation the rights to use, copy, modify, merge, publish,
12 distribute, sub license, and/or sell copies of the Software, and to
13 permit persons to whom the Software is furnished to do so, subject to
14 the following conditions:
16 The above copyright notice and this permission notice (including the
17 next paragraph) shall be included in all copies or substantial portions
20 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
23 IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
24 ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
25 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
26 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 **************************************************************************/
32 * Kevin E. Martin <martin@valinux.com>
33 * Jens Owen <jens@tungstengraphics.com>
34 * Rickard E. (Rik) Faith <faith@valinux.com>
38 /* THIS IS NOT AN X CONSORTIUM STANDARD */
40 #ifdef GLX_DIRECT_RENDERING
43 #include <X11/Xlibint.h>
44 #include <X11/extensions/Xext.h>
45 #include <X11/extensions/extutil.h>
46 #include "xf86dristr.h"
49 #if defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__) >= 303
50 # define PUBLIC __attribute__((visibility("default")))
51 # define USED __attribute__((used))
59 static XExtensionInfo _xf86dri_info_data
;
60 static XExtensionInfo
*xf86dri_info
= &_xf86dri_info_data
;
61 static char xf86dri_extension_name
[] = XF86DRINAME
;
63 #define XF86DRICheckExtension(dpy,i,val) \
64 XextCheckExtension (dpy, i, xf86dri_extension_name, val)
66 /*****************************************************************************
68 * private utility routines *
70 *****************************************************************************/
72 static int close_display(Display
*dpy
, XExtCodes
*extCodes
);
73 static /* const */ XExtensionHooks xf86dri_extension_hooks
= {
78 NULL
, /* create_font */
80 close_display
, /* close_display */
81 NULL
, /* wire_to_event */
82 NULL
, /* event_to_wire */
84 NULL
, /* error_string */
87 static XEXT_GENERATE_FIND_DISPLAY (find_display
, xf86dri_info
,
88 xf86dri_extension_name
,
89 &xf86dri_extension_hooks
,
92 static XEXT_GENERATE_CLOSE_DISPLAY (close_display
, xf86dri_info
)
95 /*****************************************************************************
97 * public XFree86-DRI Extension routines *
99 *****************************************************************************/
103 #define TRACE(msg) fprintf(stderr,"XF86DRI%s\n", msg);
109 PUBLIC Bool
XF86DRIQueryExtension (Display
* dpy
, int* event_basep
, int* error_basep
)
111 XExtDisplayInfo
*info
= find_display (dpy
);
113 TRACE("QueryExtension...");
114 if (XextHasExtension(info
)) {
115 *event_basep
= info
->codes
->first_event
;
116 *error_basep
= info
->codes
->first_error
;
117 TRACE("QueryExtension... return True");
120 TRACE("QueryExtension... return False");
125 PUBLIC Bool
XF86DRIQueryVersion(Display
* dpy
, int* majorVersion
, int* minorVersion
, int* patchVersion
)
127 XExtDisplayInfo
*info
= find_display (dpy
);
128 xXF86DRIQueryVersionReply rep
;
129 xXF86DRIQueryVersionReq
*req
;
131 TRACE("QueryVersion...");
132 XF86DRICheckExtension (dpy
, info
, False
);
135 GetReq(XF86DRIQueryVersion
, req
);
136 req
->reqType
= info
->codes
->major_opcode
;
137 req
->driReqType
= X_XF86DRIQueryVersion
;
138 if (!_XReply(dpy
, (xReply
*)&rep
, 0, xFalse
)) {
141 TRACE("QueryVersion... return False");
144 *majorVersion
= rep
.majorVersion
;
145 *minorVersion
= rep
.minorVersion
;
146 *patchVersion
= rep
.patchVersion
;
149 TRACE("QueryVersion... return True");
153 PUBLIC Bool
XF86DRIQueryDirectRenderingCapable(Display
* dpy
, int screen
, Bool
* isCapable
)
155 XExtDisplayInfo
*info
= find_display (dpy
);
156 xXF86DRIQueryDirectRenderingCapableReply rep
;
157 xXF86DRIQueryDirectRenderingCapableReq
*req
;
159 TRACE("QueryDirectRenderingCapable...");
160 XF86DRICheckExtension (dpy
, info
, False
);
163 GetReq(XF86DRIQueryDirectRenderingCapable
, req
);
164 req
->reqType
= info
->codes
->major_opcode
;
165 req
->driReqType
= X_XF86DRIQueryDirectRenderingCapable
;
166 req
->screen
= screen
;
167 if (!_XReply(dpy
, (xReply
*)&rep
, 0, xFalse
)) {
170 TRACE("QueryDirectRenderingCapable... return False");
173 *isCapable
= rep
.isCapable
;
176 TRACE("QueryDirectRenderingCapable... return True");
180 PUBLIC Bool
XF86DRIOpenConnection(Display
* dpy
, int screen
, drm_handle_t
* hSAREA
, char** busIdString
)
182 XExtDisplayInfo
*info
= find_display (dpy
);
183 xXF86DRIOpenConnectionReply rep
;
184 xXF86DRIOpenConnectionReq
*req
;
186 TRACE("OpenConnection...");
187 XF86DRICheckExtension (dpy
, info
, False
);
190 GetReq(XF86DRIOpenConnection
, req
);
191 req
->reqType
= info
->codes
->major_opcode
;
192 req
->driReqType
= X_XF86DRIOpenConnection
;
193 req
->screen
= screen
;
194 if (!_XReply(dpy
, (xReply
*)&rep
, 0, xFalse
)) {
197 TRACE("OpenConnection... return False");
201 *hSAREA
= rep
.hSAREALow
;
202 if (sizeof(drm_handle_t
) == 8) {
203 int shift
= 32; /* var to prevent warning on next line */
204 *hSAREA
|= ((drm_handle_t
) rep
.hSAREAHigh
) << shift
;
208 if (!(*busIdString
= (char *)Xcalloc(rep
.busIdStringLength
+ 1, 1))) {
209 _XEatData(dpy
, ((rep
.busIdStringLength
+3) & ~3));
212 TRACE("OpenConnection... return False");
215 _XReadPad(dpy
, *busIdString
, rep
.busIdStringLength
);
221 TRACE("OpenConnection... return True");
225 PUBLIC Bool
XF86DRIAuthConnection(Display
* dpy
, int screen
, drm_magic_t magic
)
227 XExtDisplayInfo
*info
= find_display (dpy
);
228 xXF86DRIAuthConnectionReq
*req
;
229 xXF86DRIAuthConnectionReply rep
;
231 TRACE("AuthConnection...");
232 XF86DRICheckExtension (dpy
, info
, False
);
235 GetReq(XF86DRIAuthConnection
, req
);
236 req
->reqType
= info
->codes
->major_opcode
;
237 req
->driReqType
= X_XF86DRIAuthConnection
;
238 req
->screen
= screen
;
240 rep
.authenticated
= 0;
241 if (!_XReply(dpy
, (xReply
*)&rep
, 0, xFalse
) || !rep
.authenticated
) {
244 TRACE("AuthConnection... return False");
249 TRACE("AuthConnection... return True");
253 PUBLIC Bool
XF86DRICloseConnection(Display
* dpy
, int screen
)
255 XExtDisplayInfo
*info
= find_display (dpy
);
256 xXF86DRICloseConnectionReq
*req
;
258 TRACE("CloseConnection...");
260 XF86DRICheckExtension (dpy
, info
, False
);
263 GetReq(XF86DRICloseConnection
, req
);
264 req
->reqType
= info
->codes
->major_opcode
;
265 req
->driReqType
= X_XF86DRICloseConnection
;
266 req
->screen
= screen
;
269 TRACE("CloseConnection... return True");
273 PUBLIC Bool
XF86DRIGetClientDriverName(Display
* dpy
, int screen
, int* ddxDriverMajorVersion
,
274 int* ddxDriverMinorVersion
, int* ddxDriverPatchVersion
, char** clientDriverName
)
276 XExtDisplayInfo
*info
= find_display (dpy
);
277 xXF86DRIGetClientDriverNameReply rep
;
278 xXF86DRIGetClientDriverNameReq
*req
;
280 TRACE("GetClientDriverName...");
281 XF86DRICheckExtension (dpy
, info
, False
);
284 GetReq(XF86DRIGetClientDriverName
, req
);
285 req
->reqType
= info
->codes
->major_opcode
;
286 req
->driReqType
= X_XF86DRIGetClientDriverName
;
287 req
->screen
= screen
;
288 if (!_XReply(dpy
, (xReply
*)&rep
, 0, xFalse
)) {
291 TRACE("GetClientDriverName... return False");
295 *ddxDriverMajorVersion
= rep
.ddxDriverMajorVersion
;
296 *ddxDriverMinorVersion
= rep
.ddxDriverMinorVersion
;
297 *ddxDriverPatchVersion
= rep
.ddxDriverPatchVersion
;
300 if (!(*clientDriverName
= (char *)Xcalloc(rep
.clientDriverNameLength
+ 1, 1))) {
301 _XEatData(dpy
, ((rep
.clientDriverNameLength
+3) & ~3));
304 TRACE("GetClientDriverName... return False");
307 _XReadPad(dpy
, *clientDriverName
, rep
.clientDriverNameLength
);
309 *clientDriverName
= NULL
;
313 TRACE("GetClientDriverName... return True");
317 PUBLIC Bool
XF86DRICreateContextWithConfig(Display
* dpy
, int screen
, int configID
, XID
* context
,
318 drm_context_t
* hHWContext
)
320 XExtDisplayInfo
*info
= find_display (dpy
);
321 xXF86DRICreateContextReply rep
;
322 xXF86DRICreateContextReq
*req
;
324 TRACE("CreateContext...");
325 XF86DRICheckExtension (dpy
, info
, False
);
328 GetReq(XF86DRICreateContext
, req
);
329 req
->reqType
= info
->codes
->major_opcode
;
330 req
->driReqType
= X_XF86DRICreateContext
;
331 req
->visual
= configID
;
332 req
->screen
= screen
;
333 *context
= XAllocID(dpy
);
334 req
->context
= *context
;
335 if (!_XReply(dpy
, (xReply
*)&rep
, 0, xFalse
)) {
338 TRACE("CreateContext... return False");
341 *hHWContext
= rep
.hHWContext
;
344 TRACE("CreateContext... return True");
348 PUBLIC Bool
XF86DRICreateContext(Display
* dpy
, int screen
, Visual
* visual
, XID
* context
, drm_context_t
* hHWContext
)
350 return XF86DRICreateContextWithConfig( dpy
, screen
, visual
->visualid
,
351 context
, hHWContext
);
354 PUBLIC Bool
XF86DRIDestroyContext(Display
*dpy
, int screen
,
357 XExtDisplayInfo
*info
= find_display (dpy
);
358 xXF86DRIDestroyContextReq
*req
;
360 TRACE("DestroyContext...");
361 XF86DRICheckExtension (dpy
, info
, False
);
364 GetReq(XF86DRIDestroyContext
, req
);
365 req
->reqType
= info
->codes
->major_opcode
;
366 req
->driReqType
= X_XF86DRIDestroyContext
;
367 req
->screen
= screen
;
368 req
->context
= context
;
371 TRACE("DestroyContext... return True");
375 PUBLIC Bool
XF86DRICreateDrawable(Display
*dpy
, int screen
,
376 XID drawable
, drm_drawable_t
* hHWDrawable
)
378 XExtDisplayInfo
*info
= find_display (dpy
);
379 xXF86DRICreateDrawableReply rep
;
380 xXF86DRICreateDrawableReq
*req
;
382 TRACE("CreateDrawable...");
383 XF86DRICheckExtension (dpy
, info
, False
);
386 GetReq(XF86DRICreateDrawable
, req
);
387 req
->reqType
= info
->codes
->major_opcode
;
388 req
->driReqType
= X_XF86DRICreateDrawable
;
389 req
->screen
= screen
;
390 req
->drawable
= drawable
;
391 if (!_XReply(dpy
, (xReply
*)&rep
, 0, xFalse
)) {
394 TRACE("CreateDrawable... return False");
397 *hHWDrawable
= rep
.hHWDrawable
;
400 TRACE("CreateDrawable... return True");
404 static int noopErrorHandler(Display
*dpy
, XErrorEvent
*xerr
)
409 PUBLIC Bool
XF86DRIDestroyDrawable(Display
*dpy
, int screen
,
412 XExtDisplayInfo
*info
= find_display (dpy
);
413 xXF86DRIDestroyDrawableReq
*req
;
414 int (*oldXErrorHandler
)(Display
*, XErrorEvent
*);
416 TRACE("DestroyDrawable...");
417 XF86DRICheckExtension (dpy
, info
, False
);
419 /* This is called from the DRI driver, which used call it like this
421 * if (windowExists(drawable))
422 * destroyDrawable(drawable);
424 * which is a textbook race condition - the window may disappear
425 * from the server between checking for its existance and
426 * destroying it. Instead we change the semantics of
427 * __DRIinterfaceMethodsRec::destroyDrawable() to succeed even if
428 * the windows is gone, by wrapping the destroy call in an error
432 oldXErrorHandler
= XSetErrorHandler(noopErrorHandler
);
435 GetReq(XF86DRIDestroyDrawable
, req
);
436 req
->reqType
= info
->codes
->major_opcode
;
437 req
->driReqType
= X_XF86DRIDestroyDrawable
;
438 req
->screen
= screen
;
439 req
->drawable
= drawable
;
443 XSetErrorHandler(oldXErrorHandler
);
445 TRACE("DestroyDrawable... return True");
449 PUBLIC Bool
XF86DRIGetDrawableInfo(Display
* dpy
, int screen
, Drawable drawable
,
450 unsigned int* index
, unsigned int* stamp
,
451 int* X
, int* Y
, int* W
, int* H
,
452 int* numClipRects
, drm_clip_rect_t
** pClipRects
,
453 int* backX
, int* backY
,
454 int* numBackClipRects
, drm_clip_rect_t
** pBackClipRects
)
456 XExtDisplayInfo
*info
= find_display (dpy
);
457 xXF86DRIGetDrawableInfoReply rep
;
458 xXF86DRIGetDrawableInfoReq
*req
;
461 TRACE("GetDrawableInfo...");
462 XF86DRICheckExtension (dpy
, info
, False
);
465 GetReq(XF86DRIGetDrawableInfo
, req
);
466 req
->reqType
= info
->codes
->major_opcode
;
467 req
->driReqType
= X_XF86DRIGetDrawableInfo
;
468 req
->screen
= screen
;
469 req
->drawable
= drawable
;
471 if (!_XReply(dpy
, (xReply
*)&rep
, 1, xFalse
))
475 TRACE("GetDrawableInfo... return False");
478 *index
= rep
.drawableTableIndex
;
479 *stamp
= rep
.drawableTableStamp
;
480 *X
= (int)rep
.drawableX
;
481 *Y
= (int)rep
.drawableY
;
482 *W
= (int)rep
.drawableWidth
;
483 *H
= (int)rep
.drawableHeight
;
484 *numClipRects
= rep
.numClipRects
;
485 total_rects
= *numClipRects
;
489 *numBackClipRects
= rep
.numBackClipRects
;
490 total_rects
+= *numBackClipRects
;
493 /* Because of the fix in Xserver/GL/dri/xf86dri.c, this check breaks
494 * backwards compatibility (Because of the >> 2 shift) but the fix
495 * enables multi-threaded apps to work.
497 if (rep
.length
!= ((((SIZEOF(xXF86DRIGetDrawableInfoReply
) -
498 SIZEOF(xGenericReply
) +
499 total_rects
* sizeof(drm_clip_rect_t
)) + 3) & ~3) >> 2)) {
500 _XEatData(dpy
, rep
.length
);
503 TRACE("GetDrawableInfo... return False");
509 int len
= sizeof(drm_clip_rect_t
) * (*numClipRects
);
511 *pClipRects
= (drm_clip_rect_t
*)Xcalloc(len
, 1);
513 _XRead(dpy
, (char*)*pClipRects
, len
);
518 if (*numBackClipRects
) {
519 int len
= sizeof(drm_clip_rect_t
) * (*numBackClipRects
);
521 *pBackClipRects
= (drm_clip_rect_t
*)Xcalloc(len
, 1);
523 _XRead(dpy
, (char*)*pBackClipRects
, len
);
525 *pBackClipRects
= NULL
;
530 TRACE("GetDrawableInfo... return True");
534 PUBLIC Bool
XF86DRIGetDeviceInfo(Display
* dpy
, int screen
, drm_handle_t
* hFrameBuffer
,
535 int* fbOrigin
, int* fbSize
, int* fbStride
, int* devPrivateSize
, void** pDevPrivate
)
537 XExtDisplayInfo
*info
= find_display (dpy
);
538 xXF86DRIGetDeviceInfoReply rep
;
539 xXF86DRIGetDeviceInfoReq
*req
;
541 TRACE("GetDeviceInfo...");
542 XF86DRICheckExtension (dpy
, info
, False
);
545 GetReq(XF86DRIGetDeviceInfo
, req
);
546 req
->reqType
= info
->codes
->major_opcode
;
547 req
->driReqType
= X_XF86DRIGetDeviceInfo
;
548 req
->screen
= screen
;
549 if (!_XReply(dpy
, (xReply
*)&rep
, 0, xFalse
)) {
552 TRACE("GetDeviceInfo... return False");
556 *hFrameBuffer
= rep
.hFrameBufferLow
;
557 if (sizeof(drm_handle_t
) == 8) {
558 int shift
= 32; /* var to prevent warning on next line */
559 *hFrameBuffer
|= ((drm_handle_t
) rep
.hFrameBufferHigh
) << shift
;
562 *fbOrigin
= rep
.framebufferOrigin
;
563 *fbSize
= rep
.framebufferSize
;
564 *fbStride
= rep
.framebufferStride
;
565 *devPrivateSize
= rep
.devPrivateSize
;
568 if (!(*pDevPrivate
= (void *)Xcalloc(rep
.devPrivateSize
, 1))) {
569 _XEatData(dpy
, ((rep
.devPrivateSize
+3) & ~3));
572 TRACE("GetDeviceInfo... return False");
575 _XRead(dpy
, (char*)*pDevPrivate
, rep
.devPrivateSize
);
582 TRACE("GetDeviceInfo... return True");
586 PUBLIC Bool
XF86DRIOpenFullScreen(Display
* dpy
, int screen
, Drawable drawable
)
588 /* This function and the underlying X protocol are deprecated.
596 PUBLIC Bool
XF86DRICloseFullScreen(Display
* dpy
, int screen
, Drawable drawable
)
598 /* This function and the underlying X protocol are deprecated.
606 #endif /* GLX_DIRECT_RENDERING */