1 /* $XFree86: xc/lib/GL/dri/dri_util.c,v 1.7 2003/04/28 17:01:25 dawes Exp $ */
4 * DRI utility functions.
6 * This module acts as glue between GLX and the actual hardware driver. A DRI
7 * driver doesn't really \e have to use any of this - it's optional. But, some
8 * useful stuff is done here that otherwise would have to be duplicated in most
11 * Basically, these utility functions take care of some of the dirty details of
12 * screen initialization, context creation, context binding, DRM setup, etc.
14 * These functions are compiled into each DRI driver so libGL.so knows nothing
18 * When \c DRI_NEW_INTERFACE_ONLY is defined, code is built / not built so
19 * that only the "new" libGL-to-driver interfaces are supported. This breaks
20 * backwards compatability. However, this may be necessary when DRI drivers
21 * are built to be used in non-XFree86 environments.
23 * \todo There are still some places in the code that need to be wrapped with
24 * \c DRI_NEW_INTERFACE_ONLY.
28 #ifdef GLX_DIRECT_RENDERING
37 #define MAP_FAILED ((void *)-1)
40 #ifndef DRI_NEW_INTERFACE_ONLY
41 # include <X11/Xlibint.h>
45 # define _mesa_malloc(b) Xmalloc(b)
46 # define _mesa_free(m) Xfree(m)
50 #endif /* DRI_NEW_INTERFACE_ONLY */
53 #include "drm_sarea.h"
54 #include "glcontextmodes.h"
56 #ifndef PFNGLXGETMSCRATEOMLPROC
57 typedef GLboolean ( * PFNGLXGETMSCRATEOMLPROC
) (__DRInativeDisplay
*dpy
, __DRIid drawable
, int32_t *numerator
, int32_t *denominator
);
61 * Weak thread-safety dispatch pointer. Older versions of libGL will not have
62 * this symbol, so a "weak" version is included here so that the driver will
63 * dynamically link properly. The value is set to \c NULL. This forces the
64 * driver to fall back to the old dispatch interface.
66 struct _glapi_table
*_glapi_DispatchTSD
__attribute__((weak
)) = NULL
;
69 * This is used in a couple of places that call \c driCreateNewDrawable.
71 static const int empty_attribute_list
[1] = { None
};
74 * Function used to determine if a drawable (window) still exists. Ideally
75 * this function comes from libGL. With older versions of libGL from XFree86
76 * we can fall-back to an internal version.
78 * \sa __driWindowExists __glXWindowExists
80 static PFNGLXWINDOWEXISTSPROC window_exists
;
82 typedef GLboolean (*PFNGLXCREATECONTEXTWITHCONFIGPROC
)( __DRInativeDisplay
*, int, int, void *,
85 static PFNGLXCREATECONTEXTWITHCONFIGPROC create_context_with_config
;
88 * Cached copy of the internal API version used by libGL and the client-side
91 static int api_ver
= 0;
93 /* forward declarations */
94 static int driQueryFrameTracking( __DRInativeDisplay
* dpy
, void * priv
,
95 int64_t * sbc
, int64_t * missedFrames
, float * lastMissedUsage
,
98 static void *driCreateNewDrawable(__DRInativeDisplay
*dpy
, const __GLcontextModes
*modes
,
99 __DRIid draw
, __DRIdrawable
*pdraw
, int renderType
, const int *attrs
);
101 static void driDestroyDrawable(__DRInativeDisplay
*dpy
, void *drawablePrivate
);
107 static GLboolean
driFeatureOn(const char *name
)
109 char *env
= getenv(name
);
111 if (!env
) return GL_FALSE
;
112 if (!strcasecmp(env
, "enable")) return GL_TRUE
;
113 if (!strcasecmp(env
, "1")) return GL_TRUE
;
114 if (!strcasecmp(env
, "on")) return GL_TRUE
;
115 if (!strcasecmp(env
, "true")) return GL_TRUE
;
116 if (!strcasecmp(env
, "t")) return GL_TRUE
;
117 if (!strcasecmp(env
, "yes")) return GL_TRUE
;
118 if (!strcasecmp(env
, "y")) return GL_TRUE
;
122 #endif /* not_defined */
126 * Print message to \c stderr if the \c LIBGL_DEBUG environment variable
129 * Is called from the drivers.
131 * \param f \c printf like format string.
134 __driUtilMessage(const char *f
, ...)
138 if (getenv("LIBGL_DEBUG")) {
139 fprintf(stderr
, "libGL error: \n");
141 vfprintf(stderr
, f
, args
);
143 fprintf(stderr
, "\n");
148 * fd.o bug #1713: Some rare libGL's have __glXFindDRIScreen defined but do not
149 * export it via glXGetProcAddress. These are not supported anymore, so print
150 * an error message to that effect. - ajax 2004-10-26
152 typedef __DRIscreen
*(*PFNGLXFINDDRISCREEN
)(__DRInativeDisplay
*, int);
154 static __DRIscreen
*glx_find_dri_screen(__DRInativeDisplay
*d
, int i
)
156 PFNGLXFINDDRISCREEN findscreen
=
157 (PFNGLXFINDDRISCREEN
)glXGetProcAddress("__glXFindDRIScreen");
161 __driUtilMessage("glXGetProcAddress(\"__glXFindDRIScreen\") failed!");
162 __driUtilMessage("Your libGL is too old, please upgrade.");
165 else return findscreen(d
, i
);
168 /*****************************************************************/
169 /** \name Visual utility functions */
170 /*****************************************************************/
173 #ifndef DRI_NEW_INTERFACE_ONLY
175 * Find a \c __GLcontextModes structure matching the given visual ID.
177 * \param dpy Display to search for a matching configuration.
178 * \param scrn Screen number on \c dpy to be searched.
179 * \param vid Desired \c VisualID to find.
181 * \returns A pointer to a \c __GLcontextModes structure that matches \c vid,
182 * if found, or \c NULL if no match is found.
184 static const __GLcontextModes
*
185 findConfigMode(__DRInativeDisplay
*dpy
, int scrn
, VisualID vid
,
186 const __DRIscreen
* pDRIScreen
)
188 if ( (pDRIScreen
!= NULL
) && (pDRIScreen
->private != NULL
) ) {
189 const __DRIscreenPrivate
* const psp
=
190 (const __DRIscreenPrivate
*) pDRIScreen
->private;
192 return _gl_context_modes_find_visual( psp
->modes
, vid
);
200 * This function is a hack to work-around old versions of libGL.so that
201 * do not export \c XF86DRICreateContextWithConfig. I would modify the
202 * code to just use this function, but the stand-alone driver (i.e., DRI
203 * drivers that are built to work without XFree86) shouldn't have to know
204 * about X structures like a \c Visual.
207 fake_XF86DRICreateContextWithConfig( __DRInativeDisplay
* dpy
, int screen
, int configID
,
208 XID
* context
, drm_context_t
* hHWContext
)
212 vis
.visualid
= configID
;
213 return XF86DRICreateContext( dpy
, screen
, & vis
, context
, hHWContext
);
215 #endif /* DRI_NEW_INTERFACE_ONLY */
220 /*****************************************************************/
221 /** \name Drawable list management */
222 /*****************************************************************/
225 static GLboolean
__driAddDrawable(void *drawHash
, __DRIdrawable
*pdraw
)
227 __DRIdrawablePrivate
*pdp
= (__DRIdrawablePrivate
*)pdraw
->private;
229 if (drmHashInsert(drawHash
, pdp
->draw
, pdraw
))
235 static __DRIdrawable
*__driFindDrawable(void *drawHash
, __DRIid draw
)
240 __DRIdrawable
*pdraw
;
244 retcode
= drmHashLookup(drawHash
, draw
, &p
.ptr
);
251 static void __driRemoveDrawable(void *drawHash
, __DRIdrawable
*pdraw
)
256 __DRIdrawablePrivate
*pdp
;
260 p
.pdp
= (__DRIdrawablePrivate
*)pdraw
->private;
262 retcode
= drmHashLookup(drawHash
, p
.pdp
->draw
, &p
.ptr
);
263 if (!retcode
) { /* Found */
264 drmHashDelete(drawHash
, p
.pdp
->draw
);
268 #ifndef DRI_NEW_INTERFACE_ONLY
269 static GLboolean __driWindowExistsFlag
;
271 static int __driWindowExistsErrorHandler(Display
*dpy
, XErrorEvent
*xerr
)
273 if (xerr
->error_code
== BadWindow
) {
274 __driWindowExistsFlag
= GL_FALSE
;
280 * Determine if a window associated with a \c GLXDrawable exists on the
283 * \param dpy Display associated with the drawable to be queried.
284 * \param draw \c GLXDrawable to test.
286 * \returns \c GL_TRUE if a window exists that is associated with \c draw,
287 * otherwise \c GL_FALSE is returned.
289 * \warning This function is not currently thread-safe.
292 * \c __glXWindowExists (from libGL) is prefered over this function. Starting
293 * with the next major release of XFree86, this function will be removed.
294 * Even now this function is no longer directly called. Instead it is called
295 * via a function pointer if and only if \c __glXWindowExists does not exist.
297 * \sa __glXWindowExists glXGetProcAddress window_exists
299 static GLboolean
__driWindowExists(Display
*dpy
, GLXDrawable draw
)
301 XWindowAttributes xwa
;
302 int (*oldXErrorHandler
)(Display
*, XErrorEvent
*);
304 XSync(dpy
, GL_FALSE
);
305 __driWindowExistsFlag
= GL_TRUE
;
306 oldXErrorHandler
= XSetErrorHandler(__driWindowExistsErrorHandler
);
307 XGetWindowAttributes(dpy
, draw
, &xwa
); /* dummy request */
308 XSetErrorHandler(oldXErrorHandler
);
309 return __driWindowExistsFlag
;
311 #endif /* DRI_NEW_INTERFACE_ONLY */
314 * Find drawables in the local hash that have been destroyed on the
317 * \param drawHash Hash-table containing all know drawables.
319 static void __driGarbageCollectDrawables(void *drawHash
)
322 __DRInativeDisplay
*dpy
;
325 __DRIdrawable
*pdraw
;
329 if (drmHashFirst(drawHash
, &draw
, &p
.ptr
)) {
331 __DRIdrawablePrivate
*pdp
= (__DRIdrawablePrivate
*)p
.pdraw
->private;
332 dpy
= pdp
->driScreenPriv
->display
;
333 if (! (*window_exists
)(dpy
, draw
)) {
334 /* Destroy the local drawable data in the hash table, if the
335 drawable no longer exists in the Xserver */
336 __driRemoveDrawable(drawHash
, p
.pdraw
);
337 (*p
.pdraw
->destroyDrawable
)(dpy
, p
.pdraw
->private);
340 } while (drmHashNext(drawHash
, &draw
, &p
.ptr
));
347 /*****************************************************************/
348 /** \name Context (un)binding functions */
349 /*****************************************************************/
355 * \param dpy the display handle.
356 * \param scrn the screen number.
357 * \param draw drawable.
358 * \param read Current reading drawable.
361 * \return \c GL_TRUE on success, or \c GL_FALSE on failure.
364 * This function calls __DriverAPIRec::UnbindContext, and then decrements
365 * __DRIdrawablePrivateRec::refcount which must be non-zero for a successful
368 * While casting the opaque private pointers associated with the parameters
369 * into their respective real types it also assures they are not \c NULL.
371 static GLboolean
driUnbindContext3(__DRInativeDisplay
*dpy
, int scrn
,
372 __DRIid draw
, __DRIid read
,
375 __DRIscreen
*pDRIScreen
;
376 __DRIdrawable
*pdraw
;
377 __DRIdrawable
*pread
;
378 __DRIcontextPrivate
*pcp
;
379 __DRIscreenPrivate
*psp
;
380 __DRIdrawablePrivate
*pdp
;
381 __DRIdrawablePrivate
*prp
;
384 ** Assume error checking is done properly in glXMakeCurrent before
385 ** calling driUnbindContext3.
388 if (ctx
== NULL
|| draw
== None
|| read
== None
) {
393 pDRIScreen
= glx_find_dri_screen(dpy
, scrn
);
394 if ( (pDRIScreen
== NULL
) || (pDRIScreen
->private == NULL
) ) {
399 psp
= (__DRIscreenPrivate
*)pDRIScreen
->private;
400 pcp
= (__DRIcontextPrivate
*)ctx
->private;
402 pdraw
= __driFindDrawable(psp
->drawHash
, draw
);
407 pdp
= (__DRIdrawablePrivate
*)pdraw
->private;
409 pread
= __driFindDrawable(psp
->drawHash
, read
);
414 prp
= (__DRIdrawablePrivate
*)pread
->private;
417 /* Let driver unbind drawable from context */
418 (*psp
->DriverAPI
.UnbindContext
)(pcp
);
421 if (pdp
->refcount
== 0) {
429 if (prp
->refcount
== 0) {
438 /* XXX this is disabled so that if we call SwapBuffers on an unbound
439 * window we can determine the last context bound to the window and
440 * use that context's lock. (BrianP, 2-Dec-2000)
443 /* Unbind the drawable */
444 pcp
->driDrawablePriv
= NULL
;
445 pdp
->driContextPriv
= &psp
->dummyContextPriv
;
453 * This function takes both a read buffer and a draw buffer. This is needed
454 * for \c glXMakeCurrentReadSGI or GLX 1.3's \c glXMakeContextCurrent
457 * \bug This function calls \c driCreateNewDrawable in two places with the
458 * \c renderType hard-coded to \c GLX_WINDOW_BIT. Some checking might
459 * be needed in those places when support for pbuffers and / or pixmaps
460 * is added. Is it safe to assume that the drawable is a window?
462 static GLboolean
DoBindContext(__DRInativeDisplay
*dpy
,
463 __DRIid draw
, __DRIid read
,
464 __DRIcontext
*ctx
, const __GLcontextModes
* modes
,
465 __DRIscreenPrivate
*psp
)
467 __DRIdrawable
*pdraw
;
468 __DRIdrawablePrivate
*pdp
;
469 __DRIdrawable
*pread
;
470 __DRIdrawablePrivate
*prp
;
471 __DRIcontextPrivate
* const pcp
= ctx
->private;
474 /* Find the _DRIdrawable which corresponds to the writing drawable. */
475 pdraw
= __driFindDrawable(psp
->drawHash
, draw
);
477 /* Allocate a new drawable */
478 pdraw
= (__DRIdrawable
*)_mesa_malloc(sizeof(__DRIdrawable
));
484 /* Create a new drawable */
485 driCreateNewDrawable(dpy
, modes
, draw
, pdraw
, GLX_WINDOW_BIT
,
486 empty_attribute_list
);
487 if (!pdraw
->private) {
494 pdp
= (__DRIdrawablePrivate
*) pdraw
->private;
496 /* Find the _DRIdrawable which corresponds to the reading drawable. */
498 /* read buffer == draw buffer */
502 pread
= __driFindDrawable(psp
->drawHash
, read
);
504 /* Allocate a new drawable */
505 pread
= (__DRIdrawable
*)_mesa_malloc(sizeof(__DRIdrawable
));
511 /* Create a new drawable */
512 driCreateNewDrawable(dpy
, modes
, read
, pread
, GLX_WINDOW_BIT
,
513 empty_attribute_list
);
514 if (!pread
->private) {
520 prp
= (__DRIdrawablePrivate
*) pread
->private;
523 /* Bind the drawable to the context */
524 pcp
->driDrawablePriv
= pdp
;
525 pdp
->driContextPriv
= pcp
;
532 ** Now that we have a context associated with this drawable, we can
533 ** initialize the drawable information if has not been done before.
535 if (!pdp
->pStamp
|| *pdp
->pStamp
!= pdp
->lastStamp
) {
536 DRM_SPINLOCK(&psp
->pSAREA
->drawable_lock
, psp
->drawLockID
);
537 __driUtilUpdateDrawableInfo(pdp
);
538 DRM_SPINUNLOCK(&psp
->pSAREA
->drawable_lock
, psp
->drawLockID
);
541 /* Call device-specific MakeCurrent */
542 (*psp
->DriverAPI
.MakeCurrent
)(pcp
, pdp
, prp
);
549 * This function takes both a read buffer and a draw buffer. This is needed
550 * for \c glXMakeCurrentReadSGI or GLX 1.3's \c glXMakeContextCurrent
553 static GLboolean
driBindContext3(__DRInativeDisplay
*dpy
, int scrn
,
554 __DRIid draw
, __DRIid read
,
557 __DRIscreen
*pDRIScreen
;
560 ** Assume error checking is done properly in glXMakeCurrent before
561 ** calling driBindContext.
564 if (ctx
== NULL
|| draw
== None
|| read
== None
) {
569 pDRIScreen
= glx_find_dri_screen(dpy
, scrn
);
570 if ( (pDRIScreen
== NULL
) || (pDRIScreen
->private == NULL
) ) {
575 return DoBindContext( dpy
, draw
, read
, ctx
, ctx
->mode
,
576 (__DRIscreenPrivate
*)pDRIScreen
->private );
580 #ifndef DRI_NEW_INTERFACE_ONLY
582 * This function takes both a read buffer and a draw buffer. This is needed
583 * for \c glXMakeCurrentReadSGI or GLX 1.3's \c glXMakeContextCurrent
586 static GLboolean
driBindContext2(Display
*dpy
, int scrn
,
587 GLXDrawable draw
, GLXDrawable read
,
590 __DRIscreen
*pDRIScreen
;
591 const __GLcontextModes
*modes
;
594 ** Assume error checking is done properly in glXMakeCurrent before
595 ** calling driBindContext.
598 if (gc
== NULL
|| draw
== None
|| read
== None
) {
603 pDRIScreen
= glx_find_dri_screen(dpy
, scrn
);
604 modes
= (driCompareGLXAPIVersion( 20040317 ) >= 0)
605 ? gc
->driContext
.mode
606 : findConfigMode( dpy
, scrn
, gc
->vid
, pDRIScreen
);
608 if ( modes
== NULL
) {
613 /* findConfigMode will return NULL if the DRI screen or screen private
616 assert( (pDRIScreen
!= NULL
) && (pDRIScreen
->private != NULL
) );
618 return DoBindContext( dpy
, draw
, read
, & gc
->driContext
, modes
,
619 (__DRIscreenPrivate
*)pDRIScreen
->private );
622 static GLboolean
driUnbindContext2(Display
*dpy
, int scrn
,
623 GLXDrawable draw
, GLXDrawable read
,
626 return driUnbindContext3(dpy
, scrn
, draw
, read
, & gc
->driContext
);
630 * Simply call bind with the same GLXDrawable for the read and draw buffers.
632 static GLboolean
driBindContext(Display
*dpy
, int scrn
,
633 GLXDrawable draw
, GLXContext gc
)
635 return driBindContext2(dpy
, scrn
, draw
, draw
, gc
);
640 * Simply call bind with the same GLXDrawable for the read and draw buffers.
642 static GLboolean
driUnbindContext(Display
*dpy
, int scrn
,
643 GLXDrawable draw
, GLXContext gc
,
647 return driUnbindContext2( dpy
, scrn
, draw
, draw
, gc
);
649 #endif /* DRI_NEW_INTERFACE_ONLY */
654 /*****************************************************************/
655 /** \name Drawable handling functions */
656 /*****************************************************************/
660 * Update private drawable information.
662 * \param pdp pointer to the private drawable information to update.
664 * This function basically updates the __DRIdrawablePrivate struct's
665 * cliprect information by calling \c __DRIDrawablePrivate::getInfo. This is
666 * usually called by the DRI_VALIDATE_DRAWABLE_INFO macro which
667 * compares the __DRIdrwablePrivate pStamp and lastStamp values. If
668 * the values are different that means we have to update the clipping
672 __driUtilUpdateDrawableInfo(__DRIdrawablePrivate
*pdp
)
674 __DRIscreenPrivate
*psp
;
675 __DRIcontextPrivate
*pcp
= pdp
->driContextPriv
;
677 if (!pcp
|| (pdp
!= pcp
->driDrawablePriv
)) {
682 psp
= pdp
->driScreenPriv
;
688 if (pdp
->pClipRects
) {
689 _mesa_free(pdp
->pClipRects
);
692 if (pdp
->pBackClipRects
) {
693 _mesa_free(pdp
->pBackClipRects
);
696 DRM_SPINUNLOCK(&psp
->pSAREA
->drawable_lock
, psp
->drawLockID
);
698 if (!__driFindDrawable(psp
->drawHash
, pdp
->draw
) ||
699 ! (*pdp
->getInfo
)(pdp
->display
, pdp
->screen
, pdp
->draw
,
700 &pdp
->index
, &pdp
->lastStamp
,
701 &pdp
->x
, &pdp
->y
, &pdp
->w
, &pdp
->h
,
702 &pdp
->numClipRects
, &pdp
->pClipRects
,
705 &pdp
->numBackClipRects
,
706 &pdp
->pBackClipRects
)) {
707 /* Error -- eg the window may have been destroyed. Keep going
710 pdp
->pStamp
= &pdp
->lastStamp
; /* prevent endless loop */
711 pdp
->numClipRects
= 0;
712 pdp
->pClipRects
= NULL
;
713 pdp
->numBackClipRects
= 0;
714 pdp
->pBackClipRects
= NULL
;
717 pdp
->pStamp
= &(psp
->pSAREA
->drawableTable
[pdp
->index
].stamp
);
719 DRM_SPINLOCK(&psp
->pSAREA
->drawable_lock
, psp
->drawLockID
);
725 /*****************************************************************/
726 /** \name GLX callbacks */
727 /*****************************************************************/
733 * \param dpy the display handle.
734 * \param drawablePrivate opaque pointer to the per-drawable private info.
737 * This function calls __DRIdrawablePrivate::swapBuffers.
739 * Is called directly from glXSwapBuffers().
741 static void driSwapBuffers( __DRInativeDisplay
*dpy
, void *drawablePrivate
)
743 __DRIdrawablePrivate
*dPriv
= (__DRIdrawablePrivate
*) drawablePrivate
;
744 dPriv
->swapBuffers(dPriv
);
749 * Called directly from a number of higher-level GLX functions.
751 static int driGetMSC( void *screenPrivate
, int64_t *msc
)
753 __DRIscreenPrivate
*sPriv
= (__DRIscreenPrivate
*) screenPrivate
;
755 return sPriv
->DriverAPI
.GetMSC( sPriv
, msc
);
759 * Called directly from a number of higher-level GLX functions.
761 static int driGetSBC( __DRInativeDisplay
*dpy
, void *drawablePrivate
, int64_t *sbc
)
763 __DRIdrawablePrivate
*dPriv
= (__DRIdrawablePrivate
*) drawablePrivate
;
768 status
= dPriv
->driScreenPriv
->DriverAPI
.GetSwapInfo( dPriv
, & sInfo
);
769 *sbc
= sInfo
.swap_count
;
774 static int driWaitForSBC( __DRInativeDisplay
* dpy
, void *drawablePriv
,
776 int64_t * msc
, int64_t * sbc
)
778 __DRIdrawablePrivate
*dPriv
= (__DRIdrawablePrivate
*) drawablePriv
;
780 return dPriv
->driScreenPriv
->DriverAPI
.WaitForSBC( dPriv
, target_sbc
,
784 static int driWaitForMSC( __DRInativeDisplay
* dpy
, void *drawablePriv
,
786 int64_t divisor
, int64_t remainder
,
787 int64_t * msc
, int64_t * sbc
)
789 __DRIdrawablePrivate
*dPriv
= (__DRIdrawablePrivate
*) drawablePriv
;
794 status
= dPriv
->driScreenPriv
->DriverAPI
.WaitForMSC( dPriv
, target_msc
,
798 /* GetSwapInfo() may not be provided by the driver if GLX_SGI_video_sync
799 * is supported but GLX_OML_sync_control is not. Therefore, don't return
800 * an error value if GetSwapInfo() is not implemented.
803 && dPriv
->driScreenPriv
->DriverAPI
.GetSwapInfo
) {
804 status
= dPriv
->driScreenPriv
->DriverAPI
.GetSwapInfo( dPriv
, & sInfo
);
805 *sbc
= sInfo
.swap_count
;
811 static int64_t driSwapBuffersMSC( __DRInativeDisplay
* dpy
, void *drawablePriv
,
813 int64_t divisor
, int64_t remainder
)
815 __DRIdrawablePrivate
*dPriv
= (__DRIdrawablePrivate
*) drawablePriv
;
817 return dPriv
->driScreenPriv
->DriverAPI
.SwapBuffersMSC( dPriv
, target_msc
,
824 * This is called via __DRIscreenRec's createNewDrawable pointer.
826 static void *driCreateNewDrawable(__DRInativeDisplay
*dpy
,
827 const __GLcontextModes
*modes
,
829 __DRIdrawable
*pdraw
,
833 __DRIscreen
* const pDRIScreen
= glx_find_dri_screen(dpy
, modes
->screen
);
834 __DRIscreenPrivate
*psp
;
835 __DRIdrawablePrivate
*pdp
;
838 pdraw
->private = NULL
;
840 /* Since pbuffers are not yet supported, no drawable attributes are
845 if ( (pDRIScreen
== NULL
) || (pDRIScreen
->private == NULL
) ) {
849 pdp
= (__DRIdrawablePrivate
*)_mesa_malloc(sizeof(__DRIdrawablePrivate
));
854 if (!XF86DRICreateDrawable(dpy
, modes
->screen
, draw
, &pdp
->hHWDrawable
)) {
869 pdp
->numClipRects
= 0;
870 pdp
->numBackClipRects
= 0;
871 pdp
->pClipRects
= NULL
;
872 pdp
->pBackClipRects
= NULL
;
874 pdp
->screen
= modes
->screen
;
876 psp
= (__DRIscreenPrivate
*)pDRIScreen
->private;
877 pdp
->driScreenPriv
= psp
;
878 pdp
->driContextPriv
= &psp
->dummyContextPriv
;
880 pdp
->getInfo
= (PFNGLXGETDRAWABLEINFOPROC
)
881 glXGetProcAddress( (const GLubyte
*) "__glXGetDrawableInfo" );
882 if ( pdp
->getInfo
== NULL
) {
883 #ifdef DRI_NEW_INTERFACE_ONLY
884 (void)XF86DRIDestroyDrawable(dpy
, modes
->screen
, pdp
->draw
);
888 pdp
->getInfo
= (PFNGLXGETDRAWABLEINFOPROC
) XF86DRIGetDrawableInfo
;
889 #endif /* DRI_NEW_INTERFACE_ONLY */
892 if (!(*psp
->DriverAPI
.CreateBuffer
)(psp
, pdp
, modes
,
893 renderType
== GLX_PIXMAP_BIT
)) {
894 (void)XF86DRIDestroyDrawable(dpy
, modes
->screen
, pdp
->draw
);
899 pdraw
->private = pdp
;
900 pdraw
->destroyDrawable
= driDestroyDrawable
;
901 pdraw
->swapBuffers
= driSwapBuffers
; /* called by glXSwapBuffers() */
903 if ( driCompareGLXAPIVersion( 20030317 ) >= 0 ) {
904 pdraw
->getSBC
= driGetSBC
;
905 pdraw
->waitForSBC
= driWaitForSBC
;
906 pdraw
->waitForMSC
= driWaitForMSC
;
907 pdraw
->swapBuffersMSC
= driSwapBuffersMSC
;
908 pdraw
->frameTracking
= NULL
;
909 pdraw
->queryFrameTracking
= driQueryFrameTracking
;
911 /* This special default value is replaced with the configured
912 * default value when the drawable is first bound to a direct
913 * rendering context. */
914 pdraw
->swap_interval
= (unsigned)-1;
917 pdp
->swapBuffers
= psp
->DriverAPI
.SwapBuffers
;
919 /* Add pdraw to drawable list */
920 if (!__driAddDrawable(psp
->drawHash
, pdraw
)) {
922 (*pdraw
->destroyDrawable
)(dpy
, pdp
);
925 pdraw
->private = NULL
;
931 static __DRIdrawable
*driGetDrawable(__DRInativeDisplay
*dpy
, __DRIid draw
,
934 __DRIscreenPrivate
*psp
= (__DRIscreenPrivate
*) screenPrivate
;
937 ** Make sure this routine returns NULL if the drawable is not bound
938 ** to a direct rendering context!
940 return __driFindDrawable(psp
->drawHash
, draw
);
943 static void driDestroyDrawable(__DRInativeDisplay
*dpy
, void *drawablePrivate
)
945 __DRIdrawablePrivate
*pdp
= (__DRIdrawablePrivate
*) drawablePrivate
;
946 __DRIscreenPrivate
*psp
= pdp
->driScreenPriv
;
947 int scrn
= psp
->myNum
;
950 (*psp
->DriverAPI
.DestroyBuffer
)(pdp
);
951 if ((*window_exists
)(dpy
, pdp
->draw
))
952 (void)XF86DRIDestroyDrawable(dpy
, scrn
, pdp
->draw
);
953 if (pdp
->pClipRects
) {
954 _mesa_free(pdp
->pClipRects
);
955 pdp
->pClipRects
= NULL
;
957 if (pdp
->pBackClipRects
) {
958 _mesa_free(pdp
->pBackClipRects
);
959 pdp
->pBackClipRects
= NULL
;
968 /*****************************************************************/
969 /** \name Context handling functions */
970 /*****************************************************************/
974 * Destroy the per-context private information.
976 * \param dpy the display handle.
977 * \param scrn the screen number.
978 * \param contextPrivate opaque pointer to the per-drawable private info.
981 * This function calls __DriverAPIRec::DestroyContext on \p contextPrivate, calls
982 * drmDestroyContext(), and finally frees \p contextPrivate.
984 static void driDestroyContext(__DRInativeDisplay
*dpy
, int scrn
, void *contextPrivate
)
986 __DRIcontextPrivate
*pcp
= (__DRIcontextPrivate
*) contextPrivate
;
989 (*pcp
->driScreenPriv
->DriverAPI
.DestroyContext
)(pcp
);
990 __driGarbageCollectDrawables(pcp
->driScreenPriv
->drawHash
);
991 (void)XF86DRIDestroyContext(dpy
, scrn
, pcp
->contextID
);
998 * Create the per-drawable private driver information.
1000 * \param dpy The display handle.
1001 * \param modes Mode used to create the new context.
1002 * \param render_type Type of rendering target. \c GLX_RGBA is the only
1003 * type likely to ever be supported for direct-rendering.
1004 * \param sharedPrivate The shared context dependent methods or \c NULL if
1006 * \param pctx DRI context to receive the context dependent methods.
1008 * \returns An opaque pointer to the per-context private information on
1009 * success, or \c NULL on failure.
1012 * This function allocates and fills a __DRIcontextPrivateRec structure. It
1013 * performs some device independent initialization and passes all the
1014 * relevent information to __DriverAPIRec::CreateContext to create the
1019 driCreateNewContext(__DRInativeDisplay
*dpy
, const __GLcontextModes
*modes
,
1020 int render_type
, void *sharedPrivate
, __DRIcontext
*pctx
)
1022 __DRIscreen
*pDRIScreen
;
1023 __DRIcontextPrivate
*pcp
;
1024 __DRIcontextPrivate
*pshare
= (__DRIcontextPrivate
*) sharedPrivate
;
1025 __DRIscreenPrivate
*psp
;
1026 void * const shareCtx
= (pshare
!= NULL
) ? pshare
->driverPrivate
: NULL
;
1028 pDRIScreen
= glx_find_dri_screen(dpy
, modes
->screen
);
1029 if ( (pDRIScreen
== NULL
) || (pDRIScreen
->private == NULL
) ) {
1034 psp
= (__DRIscreenPrivate
*)pDRIScreen
->private;
1036 pcp
= (__DRIcontextPrivate
*)_mesa_malloc(sizeof(__DRIcontextPrivate
));
1041 if (! (*create_context_with_config
)(dpy
, modes
->screen
, modes
->fbconfigID
,
1042 &pcp
->contextID
, &pcp
->hHWContext
)) {
1048 pcp
->driScreenPriv
= psp
;
1049 pcp
->driDrawablePriv
= NULL
;
1051 /* When the first context is created for a screen, initialize a "dummy"
1055 if (!psp
->dummyContextPriv
.driScreenPriv
) {
1056 psp
->dummyContextPriv
.contextID
= 0;
1057 psp
->dummyContextPriv
.hHWContext
= psp
->pSAREA
->dummy_context
;
1058 psp
->dummyContextPriv
.driScreenPriv
= psp
;
1059 psp
->dummyContextPriv
.driDrawablePriv
= NULL
;
1060 psp
->dummyContextPriv
.driverPrivate
= NULL
;
1061 /* No other fields should be used! */
1064 pctx
->destroyContext
= driDestroyContext
;
1065 #ifdef DRI_NEW_INTERFACE_ONLY
1066 pctx
->bindContext
= NULL
;
1067 pctx
->unbindContext
= NULL
;
1068 pctx
->bindContext2
= NULL
;
1069 pctx
->unbindContext2
= NULL
;
1070 pctx
->bindContext3
= driBindContext3
;
1071 pctx
->unbindContext3
= driUnbindContext3
;
1073 pctx
->bindContext
= (void *)driBindContext
;
1074 pctx
->unbindContext
= (void *)driUnbindContext
;
1075 if ( driCompareGLXAPIVersion( 20030606 ) >= 0 ) {
1076 pctx
->bindContext2
= (void *)driBindContext2
;
1077 pctx
->unbindContext2
= (void *)driUnbindContext2
;
1080 if ( driCompareGLXAPIVersion( 20040415 ) >= 0 ) {
1081 pctx
->bindContext3
= (void *)driBindContext3
;
1082 pctx
->unbindContext3
= (void *)driUnbindContext3
;
1086 if ( !(*psp
->DriverAPI
.CreateContext
)(modes
, pcp
, shareCtx
) ) {
1087 (void)XF86DRIDestroyContext(dpy
, modes
->screen
, pcp
->contextID
);
1092 __driGarbageCollectDrawables(pcp
->driScreenPriv
->drawHash
);
1098 #ifndef DRI_NEW_INTERFACE_ONLY
1100 * Create the per-drawable private driver information.
1102 * \param dpy the display handle.
1103 * \param vis the visual information.
1104 * \param sharedPrivate the shared context dependent methods or \c NULL if
1106 * \param pctx will receive the context dependent methods.
1108 * \returns a opaque pointer to the per-context private information on success, or \c NULL
1112 * This function has been replaced by \c driCreateNewContext. In drivers
1113 * built to work with XFree86, this function will continue to exist to support
1114 * older versions of libGL. Starting with the next major relelase of XFree86,
1115 * this function will be removed.
1118 * This function allocates and fills a __DRIcontextPrivateRec structure. It
1119 * gets the visual, converts it into a __GLcontextModesRec and passes it
1120 * to __DriverAPIRec::CreateContext to create the context.
1122 static void *driCreateContext(Display
*dpy
, XVisualInfo
*vis
,
1123 void *sharedPrivate
, __DRIcontext
*pctx
)
1125 __DRIscreen
*pDRIScreen
;
1126 const __GLcontextModes
*modes
;
1128 pDRIScreen
= glx_find_dri_screen(dpy
, vis
->screen
);
1129 if ( (pDRIScreen
== NULL
) || (pDRIScreen
->private == NULL
) ) {
1135 /* Setup a __GLcontextModes struct corresponding to vis->visualid
1136 * and create the rendering context.
1139 modes
= findConfigMode(dpy
, vis
->screen
, vis
->visualid
, pDRIScreen
);
1140 return (modes
== NULL
)
1142 : driCreateNewContext( dpy
, modes
, GLX_RGBA_TYPE
,
1143 sharedPrivate
, pctx
);
1145 #endif /* DRI_NEW_INTERFACE_ONLY */
1150 /*****************************************************************/
1151 /** \name Screen handling functions */
1152 /*****************************************************************/
1156 * Destroy the per-screen private information.
1158 * \param dpy the display handle.
1159 * \param scrn the screen number.
1160 * \param screenPrivate opaque pointer to the per-screen private information.
1163 * This function calls __DriverAPIRec::DestroyScreen on \p screenPrivate, calls
1164 * drmClose(), and finally frees \p screenPrivate.
1166 static void driDestroyScreen(__DRInativeDisplay
*dpy
, int scrn
, void *screenPrivate
)
1168 __DRIscreenPrivate
*psp
= (__DRIscreenPrivate
*) screenPrivate
;
1171 /* No interaction with the X-server is possible at this point. This
1172 * routine is called after XCloseDisplay, so there is no protocol
1173 * stream open to the X-server anymore.
1176 if (psp
->DriverAPI
.DestroyScreen
)
1177 (*psp
->DriverAPI
.DestroyScreen
)(psp
);
1179 (void)drmUnmap((drmAddress
)psp
->pSAREA
, SAREA_MAX
);
1180 (void)drmUnmap((drmAddress
)psp
->pFB
, psp
->fbSize
);
1181 _mesa_free(psp
->pDevPriv
);
1182 (void)drmClose(psp
->fd
);
1183 if ( psp
->modes
!= NULL
) {
1184 _gl_context_modes_destroy( psp
->modes
);
1192 * Utility function used to create a new driver-private screen structure.
1194 * \param dpy Display pointer
1195 * \param scrn Index of the screen
1196 * \param psc DRI screen data (not driver private)
1197 * \param modes Linked list of known display modes. This list is, at a
1198 * minimum, a list of modes based on the current display mode.
1199 * These roughly match the set of available X11 visuals, but it
1200 * need not be limited to X11! The calling libGL should create
1201 * a list that will inform the driver of the current display
1202 * mode (i.e., color buffer depth, depth buffer depth, etc.).
1203 * \param ddx_version Version of the 2D DDX. This may not be meaningful for
1205 * \param dri_version Version of the "server-side" DRI.
1206 * \param drm_version Version of the kernel DRM.
1207 * \param frame_buffer Data describing the location and layout of the
1209 * \param pSAREA Pointer the the SAREA.
1210 * \param fd Device handle for the DRM.
1211 * \param internal_api_version Version of the internal interface between the
1213 * \param driverAPI Driver API functions used by other routines in dri_util.c.
1215 __DRIscreenPrivate
*
1216 __driUtilCreateNewScreen(__DRInativeDisplay
*dpy
, int scrn
, __DRIscreen
*psc
,
1217 __GLcontextModes
* modes
,
1218 const __DRIversion
* ddx_version
,
1219 const __DRIversion
* dri_version
,
1220 const __DRIversion
* drm_version
,
1221 const __DRIframebuffer
* frame_buffer
,
1222 drm_sarea_t
*pSAREA
,
1224 int internal_api_version
,
1225 const struct __DriverAPIRec
*driverAPI
)
1227 __DRIscreenPrivate
*psp
;
1230 #ifdef DRI_NEW_INTERFACE_ONLY
1231 if ( internal_api_version
< 20040602 ) {
1232 fprintf( stderr
, "libGL error: libGL.so version (%08u) is too old. "
1233 "20040602 or later is required.\n", internal_api_version
);
1237 if ( internal_api_version
== 20031201 ) {
1238 fprintf( stderr
, "libGL error: libGL version 20031201 has critical "
1239 "binary compatilibity bugs.\nlibGL error: You must upgrade "
1240 "to use direct-rendering!\n" );
1243 #endif /* DRI_NEW_INTERFACE_ONLY */
1246 window_exists
= (PFNGLXWINDOWEXISTSPROC
)
1247 glXGetProcAddress( (const GLubyte
*) "__glXWindowExists" );
1249 if ( window_exists
== NULL
) {
1250 #ifdef DRI_NEW_INTERFACE_ONLY
1251 fprintf( stderr
, "libGL error: libGL.so version (%08u) is too old. "
1252 "20021128 or later is required.\n", internal_api_version
);
1255 window_exists
= (PFNGLXWINDOWEXISTSPROC
) __driWindowExists
;
1256 #endif /* DRI_NEW_INTERFACE_ONLY */
1259 create_context_with_config
= (PFNGLXCREATECONTEXTWITHCONFIGPROC
)
1260 glXGetProcAddress( (const GLubyte
*) "__glXCreateContextWithConfig" );
1261 if ( create_context_with_config
== NULL
) {
1262 #ifdef DRI_NEW_INTERFACE_ONLY
1263 fprintf( stderr
, "libGL error: libGL.so version (%08u) is too old. "
1264 "20031201 or later is required.\n", internal_api_version
);
1267 create_context_with_config
= (PFNGLXCREATECONTEXTWITHCONFIGPROC
)
1268 fake_XF86DRICreateContextWithConfig
;
1269 #endif /* DRI_NEW_INTERFACE_ONLY */
1272 api_ver
= internal_api_version
;
1274 psp
= (__DRIscreenPrivate
*)_mesa_malloc(sizeof(__DRIscreenPrivate
));
1279 /* Create the hash table */
1280 psp
->drawHash
= drmHashCreate();
1281 if ( psp
->drawHash
== NULL
) {
1292 ** NOT_DONE: This is used by the X server to detect when the client
1293 ** has died while holding the drawable lock. The client sets the
1294 ** drawable lock to this value.
1296 psp
->drawLockID
= 1;
1298 psp
->drmMajor
= drm_version
->major
;
1299 psp
->drmMinor
= drm_version
->minor
;
1300 psp
->drmPatch
= drm_version
->patch
;
1301 psp
->ddxMajor
= ddx_version
->major
;
1302 psp
->ddxMinor
= ddx_version
->minor
;
1303 psp
->ddxPatch
= ddx_version
->patch
;
1304 psp
->driMajor
= dri_version
->major
;
1305 psp
->driMinor
= dri_version
->minor
;
1306 psp
->driPatch
= dri_version
->patch
;
1308 /* install driver's callback functions */
1309 memcpy( &psp
->DriverAPI
, driverAPI
, sizeof(struct __DriverAPIRec
) );
1311 psp
->pSAREA
= pSAREA
;
1313 psp
->pFB
= frame_buffer
->base
;
1314 psp
->fbSize
= frame_buffer
->size
;
1315 psp
->fbStride
= frame_buffer
->stride
;
1316 psp
->fbWidth
= frame_buffer
->width
;
1317 psp
->fbHeight
= frame_buffer
->height
;
1318 psp
->devPrivSize
= frame_buffer
->dev_priv_size
;
1319 psp
->pDevPriv
= frame_buffer
->dev_priv
;
1324 ** Do not init dummy context here; actual initialization will be
1325 ** done when the first DRI context is created. Init screen priv ptr
1326 ** to NULL to let CreateContext routine that it needs to be inited.
1328 psp
->dummyContextPriv
.driScreenPriv
= NULL
;
1330 psc
->destroyScreen
= driDestroyScreen
;
1331 #ifndef DRI_NEW_INTERFACE_ONLY
1332 psc
->createContext
= driCreateContext
;
1334 psc
->createContext
= NULL
;
1336 psc
->createNewDrawable
= driCreateNewDrawable
;
1337 psc
->getDrawable
= driGetDrawable
;
1338 #ifdef DRI_NEW_INTERFACE_ONLY
1339 psc
->getMSC
= driGetMSC
;
1340 psc
->createNewContext
= driCreateNewContext
;
1342 if ( driCompareGLXAPIVersion( 20030317 ) >= 0 ) {
1343 psc
->getMSC
= driGetMSC
;
1345 if ( driCompareGLXAPIVersion( 20030824 ) >= 0 ) {
1346 psc
->createNewContext
= driCreateNewContext
;
1351 if ( (psp
->DriverAPI
.InitDriver
!= NULL
)
1352 && !(*psp
->DriverAPI
.InitDriver
)(psp
) ) {
1362 #ifndef DRI_NEW_INTERFACE_ONLY
1364 * Utility function used to create a new driver-private screen structure.
1366 * \param dpy Display pointer.
1367 * \param scrn Index of the screen.
1368 * \param psc DRI screen data (not driver private)
1369 * \param numConfigs Number of visual configs pointed to by \c configs.
1370 * \param configs Array of GLXvisualConfigs exported by the 2D driver.
1371 * \param driverAPI Driver API functions used by other routines in dri_util.c.
1374 * This function has been replaced by \c __driUtilCreateNewScreen. In drivers
1375 * built to work with XFree86, this function will continue to exist to support
1376 * older versions of libGL. Starting with the next major relelase of XFree86,
1377 * this function will be removed.
1379 __DRIscreenPrivate
*
1380 __driUtilCreateScreen(Display
*dpy
, int scrn
, __DRIscreen
*psc
,
1381 int numConfigs
, __GLXvisualConfig
*configs
,
1382 const struct __DriverAPIRec
*driverAPI
)
1385 __DRIscreenPrivate
*psp
= NULL
;
1386 drm_handle_t hSAREA
;
1389 __GLcontextModes
*modes
;
1390 __GLcontextModes
*temp
;
1392 __DRIversion ddx_version
;
1393 __DRIversion dri_version
;
1394 __DRIversion drm_version
;
1395 __DRIframebuffer framebuffer
;
1398 const char * err_msg
;
1399 const char * err_extra
;
1402 if (!XF86DRIQueryDirectRenderingCapable(dpy
, scrn
, &directCapable
)
1403 || !directCapable
) {
1408 /* Create the linked list of context modes, and populate it with the
1409 * GLX visual information passed in by libGL.
1412 modes
= _gl_context_modes_create( numConfigs
, sizeof(__GLcontextModes
) );
1413 if ( modes
== NULL
) {
1418 for ( i
= 0 ; i
< numConfigs
; i
++ ) {
1419 assert( temp
!= NULL
);
1420 _gl_copy_visual_to_context_mode( temp
, & configs
[i
] );
1421 temp
->screen
= scrn
;
1426 err_msg
= "XF86DRIOpenConnection";
1429 if (XF86DRIOpenConnection(dpy
, scrn
, &hSAREA
, &BusID
)) {
1430 fd
= drmOpen(NULL
,BusID
);
1431 _mesa_free(BusID
); /* No longer needed */
1433 err_msg
= "open DRM";
1434 err_extra
= strerror( -fd
);
1439 err_msg
= "drmGetMagic";
1442 if (!drmGetMagic(fd
, &magic
)) {
1443 drmVersionPtr version
= drmGetVersion(fd
);
1445 drm_version
.major
= version
->version_major
;
1446 drm_version
.minor
= version
->version_minor
;
1447 drm_version
.patch
= version
->version_patchlevel
;
1448 drmFreeVersion(version
);
1451 drm_version
.major
= -1;
1452 drm_version
.minor
= -1;
1453 drm_version
.patch
= -1;
1456 err_msg
= "XF86DRIAuthConnection";
1457 if (XF86DRIAuthConnection(dpy
, scrn
, magic
)) {
1461 * Get device name (like "tdfx") and the ddx version numbers.
1462 * We'll check the version in each DRI driver's "createScreen"
1465 err_msg
= "XF86DRIGetClientDriverName";
1466 if (XF86DRIGetClientDriverName(dpy
, scrn
,
1472 /* No longer needed. */
1473 _mesa_free( driverName
);
1476 * Get the DRI X extension version.
1478 err_msg
= "XF86DRIQueryVersion";
1479 if (XF86DRIQueryVersion(dpy
,
1482 &dri_version
.patch
)) {
1487 * Get device-specific info. pDevPriv will point to a struct
1488 * (such as DRIRADEONRec in xfree86/driver/ati/radeon_dri.h)
1489 * that has information about the screen size, depth, pitch,
1490 * ancilliary buffers, DRM mmap handles, etc.
1492 err_msg
= "XF86DRIGetDeviceInfo";
1493 if (XF86DRIGetDeviceInfo(dpy
, scrn
,
1497 &framebuffer
.stride
,
1498 &framebuffer
.dev_priv_size
,
1499 &framebuffer
.dev_priv
)) {
1500 framebuffer
.width
= DisplayWidth(dpy
, scrn
);
1501 framebuffer
.height
= DisplayHeight(dpy
, scrn
);
1504 * Map the framebuffer region.
1506 status
= drmMap(fd
, hFB
, framebuffer
.size
,
1507 (drmAddressPtr
)&framebuffer
.base
);
1509 err_msg
= "drmMap of framebuffer";
1510 err_extra
= strerror( -status
);
1512 if ( status
== 0 ) {
1514 * Map the SAREA region. Further mmap regions may be setup in
1515 * each DRI driver's "createScreen" function.
1517 status
= drmMap(fd
, hSAREA
, SAREA_MAX
,
1520 err_msg
= "drmMap of sarea";
1521 err_extra
= strerror( -status
);
1523 if ( status
== 0 ) {
1524 PFNGLXGETINTERNALVERSIONPROC get_ver
;
1526 get_ver
= (PFNGLXGETINTERNALVERSIONPROC
)
1527 glXGetProcAddress( (const GLubyte
*) "__glXGetInternalVersion" );
1529 err_msg
= "InitDriver";
1531 psp
= __driUtilCreateNewScreen( dpy
, scrn
, psc
, modes
,
1538 (get_ver
!= NULL
) ? (*get_ver
)() : 1,
1550 if ( psp
== NULL
) {
1551 if ( pSAREA
!= MAP_FAILED
) {
1552 (void)drmUnmap(pSAREA
, SAREA_MAX
);
1555 if ( framebuffer
.base
!= MAP_FAILED
) {
1556 (void)drmUnmap((drmAddress
)framebuffer
.base
, framebuffer
.size
);
1559 if ( framebuffer
.dev_priv
!= NULL
) {
1560 _mesa_free(framebuffer
.dev_priv
);
1567 if ( modes
!= NULL
) {
1568 _gl_context_modes_destroy( modes
);
1571 (void)XF86DRICloseConnection(dpy
, scrn
);
1573 if ( err_extra
!= NULL
) {
1574 fprintf(stderr
, "libGL error: %s failed (%s)\n", err_msg
,
1578 fprintf(stderr
, "libGL error: %s failed\n", err_msg
);
1581 fprintf(stderr
, "libGL error: reverting to (slow) indirect rendering\n");
1586 #endif /* DRI_NEW_INTERFACE_ONLY */
1590 * Compare the current GLX API version with a driver supplied required version.
1592 * The minimum required version is compared with the API version exported by
1593 * the \c __glXGetInternalVersion function (in libGL.so).
1595 * \param required_version Minimum required internal GLX API version.
1596 * \return A tri-value return, as from strcmp is returned. A value less
1597 * than, equal to, or greater than zero will be returned if the
1598 * internal GLX API version is less than, equal to, or greater
1599 * than \c required_version.
1601 * \sa __glXGetInternalVersion().
1603 int driCompareGLXAPIVersion( GLuint required_version
)
1605 if ( api_ver
> required_version
) {
1608 else if ( api_ver
== required_version
) {
1617 driQueryFrameTracking( __DRInativeDisplay
* dpy
, void * priv
,
1618 int64_t * sbc
, int64_t * missedFrames
,
1619 float * lastMissedUsage
, float * usage
)
1621 static PFNGLXGETUSTPROC get_ust
;
1622 __DRIswapInfo sInfo
;
1625 __DRIdrawablePrivate
* dpriv
= (__DRIdrawablePrivate
*) priv
;
1627 if ( get_ust
== NULL
) {
1628 get_ust
= (PFNGLXGETUSTPROC
) glXGetProcAddress( (const GLubyte
*) "__glXGetUST" );
1631 status
= dpriv
->driScreenPriv
->DriverAPI
.GetSwapInfo( dpriv
, & sInfo
);
1632 if ( status
== 0 ) {
1633 *sbc
= sInfo
.swap_count
;
1634 *missedFrames
= sInfo
.swap_missed_count
;
1635 *lastMissedUsage
= sInfo
.swap_missed_usage
;
1637 (*get_ust
)( & ust
);
1638 *usage
= driCalculateSwapUsage( dpriv
, sInfo
.swap_ust
, ust
);
1646 * Calculate amount of swap interval used between GLX buffer swaps.
1648 * The usage value, on the range [0,max], is the fraction of total swap
1649 * interval time used between GLX buffer swaps is calculated.
1651 * \f$p = t_d / (i * t_r)\f$
1653 * Where \f$t_d\f$ is the time since the last GLX buffer swap, \f$i\f$ is the
1654 * swap interval (as set by \c glXSwapIntervalSGI), and \f$t_r\f$ time
1655 * required for a single vertical refresh period (as returned by \c
1656 * glXGetMscRateOML).
1658 * See the documentation for the GLX_MESA_swap_frame_usage extension for more
1661 * \param dPriv Pointer to the private drawable structure.
1662 * \return If less than a single swap interval time period was required
1663 * between GLX buffer swaps, a number greater than 0 and less than
1664 * 1.0 is returned. If exactly one swap interval time period is
1665 * required, 1.0 is returned, and if more than one is required then
1666 * a number greater than 1.0 will be returned.
1668 * \sa glXSwapIntervalSGI glXGetMscRateOML
1670 * \todo Instead of caching the \c glXGetMscRateOML function pointer, would it
1671 * be possible to cache the sync rate?
1674 driCalculateSwapUsage( __DRIdrawablePrivate
*dPriv
, int64_t last_swap_ust
,
1675 int64_t current_ust
)
1677 static PFNGLXGETMSCRATEOMLPROC get_msc_rate
= NULL
;
1684 if ( get_msc_rate
== NULL
) {
1685 get_msc_rate
= (PFNGLXGETMSCRATEOMLPROC
)
1686 glXGetProcAddress( (const GLubyte
*) "glXGetMscRateOML" );
1689 if ( (get_msc_rate
!= NULL
)
1690 && get_msc_rate( dPriv
->display
, dPriv
->draw
, &n
, &d
) ) {
1691 interval
= (dPriv
->pdraw
->swap_interval
!= 0)
1692 ? dPriv
->pdraw
->swap_interval
: 1;
1695 /* We want to calculate
1696 * (current_UST - last_swap_UST) / (interval * us_per_refresh). We get
1697 * current_UST by calling __glXGetUST. last_swap_UST is stored in
1698 * dPriv->swap_ust. interval has already been calculated.
1700 * The only tricky part is us_per_refresh. us_per_refresh is
1701 * 1000000 / MSC_rate. We know the MSC_rate is n / d. We can flip it
1702 * around and say us_per_refresh = 1000000 * d / n. Since this goes in
1703 * the denominator of the final calculation, we calculate
1704 * (interval * 1000000 * d) and move n into the numerator.
1707 usage
= (current_ust
- last_swap_ust
);
1709 usage
/= (interval
* d
);
1718 #endif /* GLX_DIRECT_RENDERING */