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 (dpy
, event_basep
, error_basep
)
111 int *event_basep
, *error_basep
;
113 XExtDisplayInfo
*info
= find_display (dpy
);
115 TRACE("QueryExtension...");
116 if (XextHasExtension(info
)) {
117 *event_basep
= info
->codes
->first_event
;
118 *error_basep
= info
->codes
->first_error
;
119 TRACE("QueryExtension... return True");
122 TRACE("QueryExtension... return False");
127 PUBLIC Bool
XF86DRIQueryVersion(dpy
, majorVersion
, minorVersion
, patchVersion
)
133 XExtDisplayInfo
*info
= find_display (dpy
);
134 xXF86DRIQueryVersionReply rep
;
135 xXF86DRIQueryVersionReq
*req
;
137 TRACE("QueryVersion...");
138 XF86DRICheckExtension (dpy
, info
, False
);
141 GetReq(XF86DRIQueryVersion
, req
);
142 req
->reqType
= info
->codes
->major_opcode
;
143 req
->driReqType
= X_XF86DRIQueryVersion
;
144 if (!_XReply(dpy
, (xReply
*)&rep
, 0, xFalse
)) {
147 TRACE("QueryVersion... return False");
150 *majorVersion
= rep
.majorVersion
;
151 *minorVersion
= rep
.minorVersion
;
152 *patchVersion
= rep
.patchVersion
;
155 TRACE("QueryVersion... return True");
159 PUBLIC Bool
XF86DRIQueryDirectRenderingCapable(dpy
, screen
, isCapable
)
164 XExtDisplayInfo
*info
= find_display (dpy
);
165 xXF86DRIQueryDirectRenderingCapableReply rep
;
166 xXF86DRIQueryDirectRenderingCapableReq
*req
;
168 TRACE("QueryDirectRenderingCapable...");
169 XF86DRICheckExtension (dpy
, info
, False
);
172 GetReq(XF86DRIQueryDirectRenderingCapable
, req
);
173 req
->reqType
= info
->codes
->major_opcode
;
174 req
->driReqType
= X_XF86DRIQueryDirectRenderingCapable
;
175 req
->screen
= screen
;
176 if (!_XReply(dpy
, (xReply
*)&rep
, 0, xFalse
)) {
179 TRACE("QueryDirectRenderingCapable... return False");
182 *isCapable
= rep
.isCapable
;
185 TRACE("QueryDirectRenderingCapable... return True");
189 PUBLIC Bool
XF86DRIOpenConnection(dpy
, screen
, hSAREA
, busIdString
)
192 drm_handle_t
* hSAREA
;
195 XExtDisplayInfo
*info
= find_display (dpy
);
196 xXF86DRIOpenConnectionReply rep
;
197 xXF86DRIOpenConnectionReq
*req
;
199 TRACE("OpenConnection...");
200 XF86DRICheckExtension (dpy
, info
, False
);
203 GetReq(XF86DRIOpenConnection
, req
);
204 req
->reqType
= info
->codes
->major_opcode
;
205 req
->driReqType
= X_XF86DRIOpenConnection
;
206 req
->screen
= screen
;
207 if (!_XReply(dpy
, (xReply
*)&rep
, 0, xFalse
)) {
210 TRACE("OpenConnection... return False");
214 *hSAREA
= rep
.hSAREALow
;
215 if (sizeof(drm_handle_t
) == 8) {
216 int shift
= 32; /* var to prevent warning on next line */
217 *hSAREA
|= ((drm_handle_t
) rep
.hSAREAHigh
) << shift
;
221 if (!(*busIdString
= (char *)Xcalloc(rep
.busIdStringLength
+ 1, 1))) {
222 _XEatData(dpy
, ((rep
.busIdStringLength
+3) & ~3));
225 TRACE("OpenConnection... return False");
228 _XReadPad(dpy
, *busIdString
, rep
.busIdStringLength
);
234 TRACE("OpenConnection... return True");
238 PUBLIC Bool
XF86DRIAuthConnection(dpy
, screen
, magic
)
243 XExtDisplayInfo
*info
= find_display (dpy
);
244 xXF86DRIAuthConnectionReq
*req
;
245 xXF86DRIAuthConnectionReply rep
;
247 TRACE("AuthConnection...");
248 XF86DRICheckExtension (dpy
, info
, False
);
251 GetReq(XF86DRIAuthConnection
, req
);
252 req
->reqType
= info
->codes
->major_opcode
;
253 req
->driReqType
= X_XF86DRIAuthConnection
;
254 req
->screen
= screen
;
256 rep
.authenticated
= 0;
257 if (!_XReply(dpy
, (xReply
*)&rep
, 0, xFalse
) || !rep
.authenticated
) {
260 TRACE("AuthConnection... return False");
265 TRACE("AuthConnection... return True");
269 PUBLIC Bool
XF86DRICloseConnection(dpy
, screen
)
273 XExtDisplayInfo
*info
= find_display (dpy
);
274 xXF86DRICloseConnectionReq
*req
;
276 TRACE("CloseConnection...");
278 XF86DRICheckExtension (dpy
, info
, False
);
281 GetReq(XF86DRICloseConnection
, req
);
282 req
->reqType
= info
->codes
->major_opcode
;
283 req
->driReqType
= X_XF86DRICloseConnection
;
284 req
->screen
= screen
;
287 TRACE("CloseConnection... return True");
291 PUBLIC Bool
XF86DRIGetClientDriverName(dpy
, screen
, ddxDriverMajorVersion
,
292 ddxDriverMinorVersion
, ddxDriverPatchVersion
, clientDriverName
)
295 int* ddxDriverMajorVersion
;
296 int* ddxDriverMinorVersion
;
297 int* ddxDriverPatchVersion
;
298 char** clientDriverName
;
300 XExtDisplayInfo
*info
= find_display (dpy
);
301 xXF86DRIGetClientDriverNameReply rep
;
302 xXF86DRIGetClientDriverNameReq
*req
;
304 TRACE("GetClientDriverName...");
305 XF86DRICheckExtension (dpy
, info
, False
);
308 GetReq(XF86DRIGetClientDriverName
, req
);
309 req
->reqType
= info
->codes
->major_opcode
;
310 req
->driReqType
= X_XF86DRIGetClientDriverName
;
311 req
->screen
= screen
;
312 if (!_XReply(dpy
, (xReply
*)&rep
, 0, xFalse
)) {
315 TRACE("GetClientDriverName... return False");
319 *ddxDriverMajorVersion
= rep
.ddxDriverMajorVersion
;
320 *ddxDriverMinorVersion
= rep
.ddxDriverMinorVersion
;
321 *ddxDriverPatchVersion
= rep
.ddxDriverPatchVersion
;
324 if (!(*clientDriverName
= (char *)Xcalloc(rep
.clientDriverNameLength
+ 1, 1))) {
325 _XEatData(dpy
, ((rep
.clientDriverNameLength
+3) & ~3));
328 TRACE("GetClientDriverName... return False");
331 _XReadPad(dpy
, *clientDriverName
, rep
.clientDriverNameLength
);
333 *clientDriverName
= NULL
;
337 TRACE("GetClientDriverName... return True");
341 PUBLIC Bool
XF86DRICreateContextWithConfig(dpy
, screen
, configID
, context
,
347 drm_context_t
* hHWContext
;
349 XExtDisplayInfo
*info
= find_display (dpy
);
350 xXF86DRICreateContextReply rep
;
351 xXF86DRICreateContextReq
*req
;
353 TRACE("CreateContext...");
354 XF86DRICheckExtension (dpy
, info
, False
);
357 GetReq(XF86DRICreateContext
, req
);
358 req
->reqType
= info
->codes
->major_opcode
;
359 req
->driReqType
= X_XF86DRICreateContext
;
360 req
->visual
= configID
;
361 req
->screen
= screen
;
362 *context
= XAllocID(dpy
);
363 req
->context
= *context
;
364 if (!_XReply(dpy
, (xReply
*)&rep
, 0, xFalse
)) {
367 TRACE("CreateContext... return False");
370 *hHWContext
= rep
.hHWContext
;
373 TRACE("CreateContext... return True");
377 PUBLIC Bool
XF86DRICreateContext(dpy
, screen
, visual
, context
, hHWContext
)
382 drm_context_t
* hHWContext
;
384 return XF86DRICreateContextWithConfig( dpy
, screen
, visual
->visualid
,
385 context
, hHWContext
);
388 PUBLIC Bool
XF86DRIDestroyContext(Display
*dpy
, int screen
,
391 XExtDisplayInfo
*info
= find_display (dpy
);
392 xXF86DRIDestroyContextReq
*req
;
394 TRACE("DestroyContext...");
395 XF86DRICheckExtension (dpy
, info
, False
);
398 GetReq(XF86DRIDestroyContext
, req
);
399 req
->reqType
= info
->codes
->major_opcode
;
400 req
->driReqType
= X_XF86DRIDestroyContext
;
401 req
->screen
= screen
;
402 req
->context
= context
;
405 TRACE("DestroyContext... return True");
409 PUBLIC Bool
XF86DRICreateDrawable(Display
*dpy
, int screen
,
410 XID drawable
, drm_drawable_t
* hHWDrawable
)
412 XExtDisplayInfo
*info
= find_display (dpy
);
413 xXF86DRICreateDrawableReply rep
;
414 xXF86DRICreateDrawableReq
*req
;
416 TRACE("CreateDrawable...");
417 XF86DRICheckExtension (dpy
, info
, False
);
420 GetReq(XF86DRICreateDrawable
, req
);
421 req
->reqType
= info
->codes
->major_opcode
;
422 req
->driReqType
= X_XF86DRICreateDrawable
;
423 req
->screen
= screen
;
424 req
->drawable
= drawable
;
425 if (!_XReply(dpy
, (xReply
*)&rep
, 0, xFalse
)) {
428 TRACE("CreateDrawable... return False");
431 *hHWDrawable
= rep
.hHWDrawable
;
434 TRACE("CreateDrawable... return True");
438 static int noopErrorHandler(Display
*dpy
, XErrorEvent
*xerr
)
443 PUBLIC Bool
XF86DRIDestroyDrawable(Display
*dpy
, int screen
,
446 XExtDisplayInfo
*info
= find_display (dpy
);
447 xXF86DRIDestroyDrawableReq
*req
;
448 int (*oldXErrorHandler
)(Display
*, XErrorEvent
*);
450 TRACE("DestroyDrawable...");
451 XF86DRICheckExtension (dpy
, info
, False
);
453 /* This is called from the DRI driver, which used call it like this
455 * if (windowExists(drawable))
456 * destroyDrawable(drawable);
458 * which is a textbook race condition - the window may disappear
459 * from the server between checking for its existance and
460 * destroying it. Instead we change the semantics of
461 * __DRIinterfaceMethodsRec::destroyDrawable() to succeed even if
462 * the windows is gone, by wrapping the destroy call in an error
466 oldXErrorHandler
= XSetErrorHandler(noopErrorHandler
);
469 GetReq(XF86DRIDestroyDrawable
, req
);
470 req
->reqType
= info
->codes
->major_opcode
;
471 req
->driReqType
= X_XF86DRIDestroyDrawable
;
472 req
->screen
= screen
;
473 req
->drawable
= drawable
;
477 XSetErrorHandler(oldXErrorHandler
);
479 TRACE("DestroyDrawable... return True");
483 PUBLIC Bool
XF86DRIGetDrawableInfo(Display
* dpy
, int screen
, Drawable drawable
,
484 unsigned int* index
, unsigned int* stamp
,
485 int* X
, int* Y
, int* W
, int* H
,
486 int* numClipRects
, drm_clip_rect_t
** pClipRects
,
487 int* backX
, int* backY
,
488 int* numBackClipRects
, drm_clip_rect_t
** pBackClipRects
)
490 XExtDisplayInfo
*info
= find_display (dpy
);
491 xXF86DRIGetDrawableInfoReply rep
;
492 xXF86DRIGetDrawableInfoReq
*req
;
495 TRACE("GetDrawableInfo...");
496 XF86DRICheckExtension (dpy
, info
, False
);
499 GetReq(XF86DRIGetDrawableInfo
, req
);
500 req
->reqType
= info
->codes
->major_opcode
;
501 req
->driReqType
= X_XF86DRIGetDrawableInfo
;
502 req
->screen
= screen
;
503 req
->drawable
= drawable
;
505 if (!_XReply(dpy
, (xReply
*)&rep
, 1, xFalse
))
509 TRACE("GetDrawableInfo... return False");
512 *index
= rep
.drawableTableIndex
;
513 *stamp
= rep
.drawableTableStamp
;
514 *X
= (int)rep
.drawableX
;
515 *Y
= (int)rep
.drawableY
;
516 *W
= (int)rep
.drawableWidth
;
517 *H
= (int)rep
.drawableHeight
;
518 *numClipRects
= rep
.numClipRects
;
519 total_rects
= *numClipRects
;
523 *numBackClipRects
= rep
.numBackClipRects
;
524 total_rects
+= *numBackClipRects
;
527 /* Because of the fix in Xserver/GL/dri/xf86dri.c, this check breaks
528 * backwards compatibility (Because of the >> 2 shift) but the fix
529 * enables multi-threaded apps to work.
531 if (rep
.length
!= ((((SIZEOF(xXF86DRIGetDrawableInfoReply
) -
532 SIZEOF(xGenericReply
) +
533 total_rects
* sizeof(drm_clip_rect_t
)) + 3) & ~3) >> 2)) {
534 _XEatData(dpy
, rep
.length
);
537 TRACE("GetDrawableInfo... return False");
543 int len
= sizeof(drm_clip_rect_t
) * (*numClipRects
);
545 *pClipRects
= (drm_clip_rect_t
*)Xcalloc(len
, 1);
547 _XRead(dpy
, (char*)*pClipRects
, len
);
552 if (*numBackClipRects
) {
553 int len
= sizeof(drm_clip_rect_t
) * (*numBackClipRects
);
555 *pBackClipRects
= (drm_clip_rect_t
*)Xcalloc(len
, 1);
557 _XRead(dpy
, (char*)*pBackClipRects
, len
);
559 *pBackClipRects
= NULL
;
564 TRACE("GetDrawableInfo... return True");
568 PUBLIC Bool
XF86DRIGetDeviceInfo(dpy
, screen
, hFrameBuffer
,
569 fbOrigin
, fbSize
, fbStride
, devPrivateSize
, pDevPrivate
)
572 drm_handle_t
* hFrameBuffer
;
579 XExtDisplayInfo
*info
= find_display (dpy
);
580 xXF86DRIGetDeviceInfoReply rep
;
581 xXF86DRIGetDeviceInfoReq
*req
;
583 TRACE("GetDeviceInfo...");
584 XF86DRICheckExtension (dpy
, info
, False
);
587 GetReq(XF86DRIGetDeviceInfo
, req
);
588 req
->reqType
= info
->codes
->major_opcode
;
589 req
->driReqType
= X_XF86DRIGetDeviceInfo
;
590 req
->screen
= screen
;
591 if (!_XReply(dpy
, (xReply
*)&rep
, 0, xFalse
)) {
594 TRACE("GetDeviceInfo... return False");
598 *hFrameBuffer
= rep
.hFrameBufferLow
;
599 if (sizeof(drm_handle_t
) == 8) {
600 int shift
= 32; /* var to prevent warning on next line */
601 *hFrameBuffer
|= ((drm_handle_t
) rep
.hFrameBufferHigh
) << shift
;
604 *fbOrigin
= rep
.framebufferOrigin
;
605 *fbSize
= rep
.framebufferSize
;
606 *fbStride
= rep
.framebufferStride
;
607 *devPrivateSize
= rep
.devPrivateSize
;
610 if (!(*pDevPrivate
= (void *)Xcalloc(rep
.devPrivateSize
, 1))) {
611 _XEatData(dpy
, ((rep
.devPrivateSize
+3) & ~3));
614 TRACE("GetDeviceInfo... return False");
617 _XRead(dpy
, (char*)*pDevPrivate
, rep
.devPrivateSize
);
624 TRACE("GetDeviceInfo... return True");
628 PUBLIC Bool
XF86DRIOpenFullScreen(dpy
, screen
, drawable
)
633 /* This function and the underlying X protocol are deprecated.
641 PUBLIC Bool
XF86DRICloseFullScreen(dpy
, screen
, drawable
)
646 /* This function and the underlying X protocol are deprecated.
654 #endif /* GLX_DIRECT_RENDERING */