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
26 #define MAP_FAILED ((void *)-1)
33 #include "drm_sarea.h"
35 #ifndef GLX_OML_sync_control
36 typedef GLboolean ( * PFNGLXGETMSCRATEOMLPROC
) (__DRInativeDisplay
*dpy
, __DRIid drawable
, int32_t *numerator
, int32_t *denominator
);
39 /* This pointer *must* be set by the driver's __driCreateNewScreen funciton!
41 const __DRIinterfaceMethods
* dri_interface
= NULL
;
44 * This is used in a couple of places that call \c driCreateNewDrawable.
46 static const int empty_attribute_list
[1] = { None
};
50 * Cached copy of the internal API version used by libGL and the client-side
53 static int api_ver
= 0;
55 /* forward declarations */
56 static int driQueryFrameTracking( __DRInativeDisplay
*dpy
, void *priv
,
57 int64_t *sbc
, int64_t *missedFrames
,
58 float *lastMissedUsage
, float *usage
);
60 static void *driCreateNewDrawable(__DRInativeDisplay
*dpy
,
61 const __GLcontextModes
*modes
,
62 __DRIid draw
, __DRIdrawable
*pdraw
,
63 int renderType
, const int *attrs
);
65 static void driDestroyDrawable(__DRInativeDisplay
*dpy
, void *drawablePrivate
);
69 * Print message to \c stderr if the \c LIBGL_DEBUG environment variable
72 * Is called from the drivers.
74 * \param f \c printf like format string.
77 __driUtilMessage(const char *f
, ...)
81 if (getenv("LIBGL_DEBUG")) {
82 fprintf(stderr
, "libGL error: \n");
84 vfprintf(stderr
, f
, args
);
86 fprintf(stderr
, "\n");
91 /*****************************************************************/
92 /** \name Drawable list management */
93 /*****************************************************************/
96 static GLboolean
__driAddDrawable(void *drawHash
, __DRIdrawable
*pdraw
)
98 __DRIdrawablePrivate
*pdp
= (__DRIdrawablePrivate
*)pdraw
->private;
100 if (drmHashInsert(drawHash
, pdp
->draw
, pdraw
))
106 static __DRIdrawable
*__driFindDrawable(void *drawHash
, __DRIid draw
)
109 __DRIdrawable
*pdraw
;
111 retcode
= drmHashLookup(drawHash
, draw
, (void *)&pdraw
);
120 * Find drawables in the local hash that have been destroyed on the
123 * \param drawHash Hash-table containing all known drawables.
125 static void __driGarbageCollectDrawables(void *drawHash
)
128 __DRInativeDisplay
*dpy
;
129 __DRIdrawable
*pdraw
;
131 if (drmHashFirst(drawHash
, &draw
, (void *)&pdraw
) == 1) {
133 __DRIdrawablePrivate
*pdp
= (__DRIdrawablePrivate
*)pdraw
->private;
134 dpy
= pdp
->driScreenPriv
->display
;
135 if (! (*dri_interface
->windowExists
)(dpy
, draw
)) {
136 /* Destroy the local drawable data, if the drawable no
137 longer exists in the Xserver */
138 (*pdraw
->destroyDrawable
)(dpy
, pdraw
->private);
141 } while (drmHashNext(drawHash
, &draw
, (void *)&pdraw
) == 1);
148 /*****************************************************************/
149 /** \name Context (un)binding functions */
150 /*****************************************************************/
156 * \param dpy the display handle.
157 * \param scrn the screen number.
158 * \param draw drawable.
159 * \param read Current reading drawable.
162 * \return \c GL_TRUE on success, or \c GL_FALSE on failure.
165 * This function calls __DriverAPIRec::UnbindContext, and then decrements
166 * __DRIdrawablePrivateRec::refcount which must be non-zero for a successful
169 * While casting the opaque private pointers associated with the parameters
170 * into their respective real types it also assures they are not \c NULL.
172 static GLboolean
driUnbindContext(__DRInativeDisplay
*dpy
, int scrn
,
173 __DRIid draw
, __DRIid read
,
176 __DRIscreen
*pDRIScreen
;
177 __DRIdrawable
*pdraw
;
178 __DRIdrawable
*pread
;
179 __DRIcontextPrivate
*pcp
;
180 __DRIscreenPrivate
*psp
;
181 __DRIdrawablePrivate
*pdp
;
182 __DRIdrawablePrivate
*prp
;
185 ** Assume error checking is done properly in glXMakeCurrent before
186 ** calling driUnbindContext.
189 if (ctx
== NULL
|| draw
== None
|| read
== None
) {
194 pDRIScreen
= (*dri_interface
->getScreen
)(dpy
, scrn
);
195 if ( (pDRIScreen
== NULL
) || (pDRIScreen
->private == NULL
) ) {
200 psp
= (__DRIscreenPrivate
*)pDRIScreen
->private;
201 pcp
= (__DRIcontextPrivate
*)ctx
->private;
203 pdraw
= __driFindDrawable(psp
->drawHash
, draw
);
208 pdp
= (__DRIdrawablePrivate
*)pdraw
->private;
210 pread
= __driFindDrawable(psp
->drawHash
, read
);
215 prp
= (__DRIdrawablePrivate
*)pread
->private;
218 /* Let driver unbind drawable from context */
219 (*psp
->DriverAPI
.UnbindContext
)(pcp
);
222 if (pdp
->refcount
== 0) {
230 if (prp
->refcount
== 0) {
238 /* destroy the drawables if they no longer exist on the server */
239 if ((pdp
->refcount
== 0) || (prp
->refcount
== 0)) {
240 /* probably shouldn't need the collector here,
241 as we know the affected drawables (or could there be others?) */
242 __driGarbageCollectDrawables(pdp
->driScreenPriv
->drawHash
);
245 /* XXX this is disabled so that if we call SwapBuffers on an unbound
246 * window we can determine the last context bound to the window and
247 * use that context's lock. (BrianP, 2-Dec-2000)
250 /* Unbind the drawable */
251 pcp
->driDrawablePriv
= NULL
;
252 pdp
->driContextPriv
= &psp
->dummyContextPriv
;
260 * This function takes both a read buffer and a draw buffer. This is needed
261 * for \c glXMakeCurrentReadSGI or GLX 1.3's \c glXMakeContextCurrent
264 * \bug This function calls \c driCreateNewDrawable in two places with the
265 * \c renderType hard-coded to \c GLX_WINDOW_BIT. Some checking might
266 * be needed in those places when support for pbuffers and / or pixmaps
267 * is added. Is it safe to assume that the drawable is a window?
269 static GLboolean
DoBindContext(__DRInativeDisplay
*dpy
,
270 __DRIid draw
, __DRIid read
,
271 __DRIcontext
*ctx
, const __GLcontextModes
* modes
,
272 __DRIscreenPrivate
*psp
)
274 __DRIdrawable
*pdraw
;
275 __DRIdrawablePrivate
*pdp
;
276 __DRIdrawable
*pread
;
277 __DRIdrawablePrivate
*prp
;
278 __DRIcontextPrivate
* const pcp
= ctx
->private;
281 /* Find the _DRIdrawable which corresponds to the writing drawable. */
282 pdraw
= __driFindDrawable(psp
->drawHash
, draw
);
284 /* Allocate a new drawable */
285 pdraw
= (__DRIdrawable
*)_mesa_malloc(sizeof(__DRIdrawable
));
291 /* Create a new drawable */
292 driCreateNewDrawable(dpy
, modes
, draw
, pdraw
, GLX_WINDOW_BIT
,
293 empty_attribute_list
);
294 if (!pdraw
->private) {
301 pdp
= (__DRIdrawablePrivate
*) pdraw
->private;
303 /* Find the _DRIdrawable which corresponds to the reading drawable. */
305 /* read buffer == draw buffer */
309 pread
= __driFindDrawable(psp
->drawHash
, read
);
311 /* Allocate a new drawable */
312 pread
= (__DRIdrawable
*)_mesa_malloc(sizeof(__DRIdrawable
));
318 /* Create a new drawable */
319 driCreateNewDrawable(dpy
, modes
, read
, pread
, GLX_WINDOW_BIT
,
320 empty_attribute_list
);
321 if (!pread
->private) {
327 prp
= (__DRIdrawablePrivate
*) pread
->private;
330 /* Bind the drawable to the context */
331 pcp
->driDrawablePriv
= pdp
;
332 pcp
->driReadablePriv
= prp
;
333 pdp
->driContextPriv
= pcp
;
340 ** Now that we have a context associated with this drawable, we can
341 ** initialize the drawable information if has not been done before.
343 if (!pdp
->pStamp
|| *pdp
->pStamp
!= pdp
->lastStamp
) {
344 DRM_SPINLOCK(&psp
->pSAREA
->drawable_lock
, psp
->drawLockID
);
345 __driUtilUpdateDrawableInfo(pdp
);
346 DRM_SPINUNLOCK(&psp
->pSAREA
->drawable_lock
, psp
->drawLockID
);
349 if ((pdp
!= prp
) && (!prp
->pStamp
|| *prp
->pStamp
!= prp
->lastStamp
)) {
350 DRM_SPINLOCK(&psp
->pSAREA
->drawable_lock
, psp
->drawLockID
);
351 __driUtilUpdateDrawableInfo(prp
);
352 DRM_SPINUNLOCK(&psp
->pSAREA
->drawable_lock
, psp
->drawLockID
);
355 /* Call device-specific MakeCurrent */
356 (*psp
->DriverAPI
.MakeCurrent
)(pcp
, pdp
, prp
);
363 * This function takes both a read buffer and a draw buffer. This is needed
364 * for \c glXMakeCurrentReadSGI or GLX 1.3's \c glXMakeContextCurrent
367 static GLboolean
driBindContext(__DRInativeDisplay
*dpy
, int scrn
,
368 __DRIid draw
, __DRIid read
,
371 __DRIscreen
*pDRIScreen
;
374 ** Assume error checking is done properly in glXMakeCurrent before
375 ** calling driBindContext.
378 if (ctx
== NULL
|| draw
== None
|| read
== None
) {
383 pDRIScreen
= (*dri_interface
->getScreen
)(dpy
, scrn
);
384 if ( (pDRIScreen
== NULL
) || (pDRIScreen
->private == NULL
) ) {
389 return DoBindContext( dpy
, draw
, read
, ctx
, ctx
->mode
,
390 (__DRIscreenPrivate
*)pDRIScreen
->private );
395 /*****************************************************************/
396 /** \name Drawable handling functions */
397 /*****************************************************************/
401 * Update private drawable information.
403 * \param pdp pointer to the private drawable information to update.
405 * This function basically updates the __DRIdrawablePrivate struct's
406 * cliprect information by calling \c __DRIinterfaceMethods::getDrawableInfo.
407 * This is usually called by the DRI_VALIDATE_DRAWABLE_INFO macro which
408 * compares the __DRIdrwablePrivate pStamp and lastStamp values. If
409 * the values are different that means we have to update the clipping
413 __driUtilUpdateDrawableInfo(__DRIdrawablePrivate
*pdp
)
415 __DRIscreenPrivate
*psp
;
416 __DRIcontextPrivate
*pcp
= pdp
->driContextPriv
;
419 || ((pdp
!= pcp
->driDrawablePriv
) && (pdp
!= pcp
->driReadablePriv
))) {
421 * ...but we must ignore it. There can be many contexts bound to a
426 psp
= pdp
->driScreenPriv
;
429 _mesa_problem(NULL
, "Warning! Possible infinite loop due to bug "
430 "in file %s, line %d\n",
435 if (pdp
->pClipRects
) {
436 _mesa_free(pdp
->pClipRects
);
437 pdp
->pClipRects
= NULL
;
440 if (pdp
->pBackClipRects
) {
441 _mesa_free(pdp
->pBackClipRects
);
442 pdp
->pBackClipRects
= NULL
;
445 DRM_SPINUNLOCK(&psp
->pSAREA
->drawable_lock
, psp
->drawLockID
);
447 if (!__driFindDrawable(psp
->drawHash
, pdp
->draw
) ||
448 ! (*dri_interface
->getDrawableInfo
)(pdp
->display
, pdp
->screen
, pdp
->draw
,
449 &pdp
->index
, &pdp
->lastStamp
,
450 &pdp
->x
, &pdp
->y
, &pdp
->w
, &pdp
->h
,
451 &pdp
->numClipRects
, &pdp
->pClipRects
,
454 &pdp
->numBackClipRects
,
455 &pdp
->pBackClipRects
)) {
456 /* Error -- eg the window may have been destroyed. Keep going
459 pdp
->pStamp
= &pdp
->lastStamp
; /* prevent endless loop */
460 pdp
->numClipRects
= 0;
461 pdp
->pClipRects
= NULL
;
462 pdp
->numBackClipRects
= 0;
463 pdp
->pBackClipRects
= NULL
;
466 pdp
->pStamp
= &(psp
->pSAREA
->drawableTable
[pdp
->index
].stamp
);
468 DRM_SPINLOCK(&psp
->pSAREA
->drawable_lock
, psp
->drawLockID
);
474 /*****************************************************************/
475 /** \name GLX callbacks */
476 /*****************************************************************/
482 * \param dpy the display handle.
483 * \param drawablePrivate opaque pointer to the per-drawable private info.
486 * This function calls __DRIdrawablePrivate::swapBuffers.
488 * Is called directly from glXSwapBuffers().
490 static void driSwapBuffers( __DRInativeDisplay
*dpy
, void *drawablePrivate
)
492 __DRIdrawablePrivate
*dPriv
= (__DRIdrawablePrivate
*) drawablePrivate
;
493 drm_clip_rect_t rect
;
495 dPriv
->swapBuffers(dPriv
);
497 /* Check that we actually have the new damage report method */
498 if (api_ver
< 20070105 || dri_interface
->reportDamage
== NULL
)
501 /* Assume it's affecting the whole drawable for now */
504 rect
.x2
= rect
.x1
+ dPriv
->w
;
505 rect
.y2
= rect
.y1
+ dPriv
->h
;
507 /* Report the damage. Currently, all our drivers draw directly to the
508 * front buffer, so we report the damage there rather than to the backing
511 (*dri_interface
->reportDamage
)(dpy
, dPriv
->screen
, dPriv
->draw
,
517 * Called directly from a number of higher-level GLX functions.
519 static int driGetMSC( void *screenPrivate
, int64_t *msc
)
521 __DRIscreenPrivate
*sPriv
= (__DRIscreenPrivate
*) screenPrivate
;
523 return sPriv
->DriverAPI
.GetMSC( sPriv
, msc
);
527 * Called directly from a number of higher-level GLX functions.
529 static int driGetSBC( __DRInativeDisplay
*dpy
, void *drawablePrivate
, int64_t *sbc
)
531 __DRIdrawablePrivate
*dPriv
= (__DRIdrawablePrivate
*) drawablePrivate
;
536 status
= dPriv
->driScreenPriv
->DriverAPI
.GetSwapInfo( dPriv
, & sInfo
);
537 *sbc
= sInfo
.swap_count
;
542 static int driWaitForSBC( __DRInativeDisplay
* dpy
, void *drawablePriv
,
544 int64_t * msc
, int64_t * sbc
)
546 __DRIdrawablePrivate
*dPriv
= (__DRIdrawablePrivate
*) drawablePriv
;
548 return dPriv
->driScreenPriv
->DriverAPI
.WaitForSBC( dPriv
, target_sbc
,
552 static int driWaitForMSC( __DRInativeDisplay
* dpy
, void *drawablePriv
,
554 int64_t divisor
, int64_t remainder
,
555 int64_t * msc
, int64_t * sbc
)
557 __DRIdrawablePrivate
*dPriv
= (__DRIdrawablePrivate
*) drawablePriv
;
562 status
= dPriv
->driScreenPriv
->DriverAPI
.WaitForMSC( dPriv
, target_msc
,
566 /* GetSwapInfo() may not be provided by the driver if GLX_SGI_video_sync
567 * is supported but GLX_OML_sync_control is not. Therefore, don't return
568 * an error value if GetSwapInfo() is not implemented.
571 && dPriv
->driScreenPriv
->DriverAPI
.GetSwapInfo
) {
572 status
= dPriv
->driScreenPriv
->DriverAPI
.GetSwapInfo( dPriv
, & sInfo
);
573 *sbc
= sInfo
.swap_count
;
579 static int64_t driSwapBuffersMSC( __DRInativeDisplay
* dpy
, void *drawablePriv
,
581 int64_t divisor
, int64_t remainder
)
583 __DRIdrawablePrivate
*dPriv
= (__DRIdrawablePrivate
*) drawablePriv
;
585 return dPriv
->driScreenPriv
->DriverAPI
.SwapBuffersMSC( dPriv
, target_msc
,
590 static void driCopySubBuffer( __DRInativeDisplay
*dpy
, void *drawablePrivate
,
591 int x
, int y
, int w
, int h
)
593 __DRIdrawablePrivate
*dPriv
= (__DRIdrawablePrivate
*) drawablePrivate
;
594 dPriv
->driScreenPriv
->DriverAPI
.CopySubBuffer(dPriv
, x
, y
, w
, h
);
599 * This is called via __DRIscreenRec's createNewDrawable pointer.
601 static void *driCreateNewDrawable(__DRInativeDisplay
*dpy
,
602 const __GLcontextModes
*modes
,
604 __DRIdrawable
*pdraw
,
608 __DRIscreen
* const pDRIScreen
= (*dri_interface
->getScreen
)(dpy
, modes
->screen
);
609 __DRIscreenPrivate
*psp
;
610 __DRIdrawablePrivate
*pdp
;
613 pdraw
->private = NULL
;
615 /* Since pbuffers are not yet supported, no drawable attributes are
620 if ( (pDRIScreen
== NULL
) || (pDRIScreen
->private == NULL
) ) {
624 pdp
= (__DRIdrawablePrivate
*)_mesa_malloc(sizeof(__DRIdrawablePrivate
));
629 if (!(*dri_interface
->createDrawable
)(dpy
, modes
->screen
, draw
, &pdp
->hHWDrawable
)) {
644 pdp
->numClipRects
= 0;
645 pdp
->numBackClipRects
= 0;
646 pdp
->pClipRects
= NULL
;
647 pdp
->pBackClipRects
= NULL
;
649 pdp
->screen
= modes
->screen
;
651 psp
= (__DRIscreenPrivate
*)pDRIScreen
->private;
652 pdp
->driScreenPriv
= psp
;
653 pdp
->driContextPriv
= &psp
->dummyContextPriv
;
655 if (!(*psp
->DriverAPI
.CreateBuffer
)(psp
, pdp
, modes
,
656 renderType
== GLX_PIXMAP_BIT
)) {
657 (void)(*dri_interface
->destroyDrawable
)(dpy
, modes
->screen
, pdp
->draw
);
662 pdraw
->private = pdp
;
663 pdraw
->destroyDrawable
= driDestroyDrawable
;
664 pdraw
->swapBuffers
= driSwapBuffers
; /* called by glXSwapBuffers() */
666 pdraw
->getSBC
= driGetSBC
;
667 pdraw
->waitForSBC
= driWaitForSBC
;
668 pdraw
->waitForMSC
= driWaitForMSC
;
669 pdraw
->swapBuffersMSC
= driSwapBuffersMSC
;
670 pdraw
->frameTracking
= NULL
;
671 pdraw
->queryFrameTracking
= driQueryFrameTracking
;
673 if (driCompareGLXAPIVersion (20060314) >= 0)
674 pdraw
->copySubBuffer
= driCopySubBuffer
;
676 /* This special default value is replaced with the configured
677 * default value when the drawable is first bound to a direct
680 pdraw
->swap_interval
= (unsigned)-1;
682 pdp
->swapBuffers
= psp
->DriverAPI
.SwapBuffers
;
684 /* Add pdraw to drawable list */
685 if (!__driAddDrawable(psp
->drawHash
, pdraw
)) {
687 (*pdraw
->destroyDrawable
)(dpy
, pdp
);
690 pdraw
->private = NULL
;
696 static __DRIdrawable
*
697 driGetDrawable(__DRInativeDisplay
*dpy
, __DRIid draw
, void *screenPrivate
)
699 __DRIscreenPrivate
*psp
= (__DRIscreenPrivate
*) screenPrivate
;
702 ** Make sure this routine returns NULL if the drawable is not bound
703 ** to a direct rendering context!
705 return __driFindDrawable(psp
->drawHash
, draw
);
709 driDestroyDrawable(__DRInativeDisplay
*dpy
, void *drawablePrivate
)
711 __DRIdrawablePrivate
*pdp
= (__DRIdrawablePrivate
*) drawablePrivate
;
712 __DRIscreenPrivate
*psp
;
716 psp
= pdp
->driScreenPriv
;
718 (*psp
->DriverAPI
.DestroyBuffer
)(pdp
);
719 if ((*dri_interface
->windowExists
)(dpy
, pdp
->draw
))
720 (void)(*dri_interface
->destroyDrawable
)(dpy
, scrn
, pdp
->draw
);
721 drmHashDelete(psp
->drawHash
, pdp
->draw
);
722 if (pdp
->pClipRects
) {
723 _mesa_free(pdp
->pClipRects
);
724 pdp
->pClipRects
= NULL
;
726 if (pdp
->pBackClipRects
) {
727 _mesa_free(pdp
->pBackClipRects
);
728 pdp
->pBackClipRects
= NULL
;
737 /*****************************************************************/
738 /** \name Context handling functions */
739 /*****************************************************************/
743 * Destroy the per-context private information.
745 * \param dpy the display handle.
746 * \param scrn the screen number.
747 * \param contextPrivate opaque pointer to the per-drawable private info.
750 * This function calls __DriverAPIRec::DestroyContext on \p contextPrivate, calls
751 * drmDestroyContext(), and finally frees \p contextPrivate.
754 driDestroyContext(__DRInativeDisplay
*dpy
, int scrn
, void *contextPrivate
)
756 __DRIcontextPrivate
*pcp
= (__DRIcontextPrivate
*) contextPrivate
;
759 (*pcp
->driScreenPriv
->DriverAPI
.DestroyContext
)(pcp
);
760 __driGarbageCollectDrawables(pcp
->driScreenPriv
->drawHash
);
761 (void) (*dri_interface
->destroyContext
)(dpy
, scrn
, pcp
->contextID
);
768 * Create the per-drawable private driver information.
770 * \param dpy The display handle.
771 * \param modes Mode used to create the new context.
772 * \param render_type Type of rendering target. \c GLX_RGBA is the only
773 * type likely to ever be supported for direct-rendering.
774 * \param sharedPrivate The shared context dependent methods or \c NULL if
776 * \param pctx DRI context to receive the context dependent methods.
778 * \returns An opaque pointer to the per-context private information on
779 * success, or \c NULL on failure.
782 * This function allocates and fills a __DRIcontextPrivateRec structure. It
783 * performs some device independent initialization and passes all the
784 * relevent information to __DriverAPIRec::CreateContext to create the
789 driCreateNewContext(__DRInativeDisplay
*dpy
, const __GLcontextModes
*modes
,
790 int render_type
, void *sharedPrivate
, __DRIcontext
*pctx
)
792 __DRIscreen
*pDRIScreen
;
793 __DRIcontextPrivate
*pcp
;
794 __DRIcontextPrivate
*pshare
= (__DRIcontextPrivate
*) sharedPrivate
;
795 __DRIscreenPrivate
*psp
;
796 void * const shareCtx
= (pshare
!= NULL
) ? pshare
->driverPrivate
: NULL
;
798 pDRIScreen
= (*dri_interface
->getScreen
)(dpy
, modes
->screen
);
799 if ( (pDRIScreen
== NULL
) || (pDRIScreen
->private == NULL
) ) {
804 psp
= (__DRIscreenPrivate
*)pDRIScreen
->private;
806 pcp
= (__DRIcontextPrivate
*)_mesa_malloc(sizeof(__DRIcontextPrivate
));
811 if (! (*dri_interface
->createContext
)(dpy
, modes
->screen
, modes
->fbconfigID
,
812 &pcp
->contextID
, &pcp
->hHWContext
)) {
818 pcp
->driScreenPriv
= psp
;
819 pcp
->driDrawablePriv
= NULL
;
821 /* When the first context is created for a screen, initialize a "dummy"
825 if (!psp
->dummyContextPriv
.driScreenPriv
) {
826 psp
->dummyContextPriv
.contextID
= 0;
827 psp
->dummyContextPriv
.hHWContext
= psp
->pSAREA
->dummy_context
;
828 psp
->dummyContextPriv
.driScreenPriv
= psp
;
829 psp
->dummyContextPriv
.driDrawablePriv
= NULL
;
830 psp
->dummyContextPriv
.driverPrivate
= NULL
;
831 /* No other fields should be used! */
834 pctx
->destroyContext
= driDestroyContext
;
835 pctx
->bindContext
= driBindContext
;
836 pctx
->unbindContext
= driUnbindContext
;
838 if ( !(*psp
->DriverAPI
.CreateContext
)(modes
, pcp
, shareCtx
) ) {
839 (void) (*dri_interface
->destroyContext
)(dpy
, modes
->screen
,
845 __driGarbageCollectDrawables(pcp
->driScreenPriv
->drawHash
);
852 /*****************************************************************/
853 /** \name Screen handling functions */
854 /*****************************************************************/
858 * Destroy the per-screen private information.
860 * \param dpy the display handle.
861 * \param scrn the screen number.
862 * \param screenPrivate opaque pointer to the per-screen private information.
865 * This function calls __DriverAPIRec::DestroyScreen on \p screenPrivate, calls
866 * drmClose(), and finally frees \p screenPrivate.
868 static void driDestroyScreen(__DRInativeDisplay
*dpy
, int scrn
, void *screenPrivate
)
870 __DRIscreenPrivate
*psp
= (__DRIscreenPrivate
*) screenPrivate
;
873 /* No interaction with the X-server is possible at this point. This
874 * routine is called after XCloseDisplay, so there is no protocol
875 * stream open to the X-server anymore.
878 if (psp
->DriverAPI
.DestroyScreen
)
879 (*psp
->DriverAPI
.DestroyScreen
)(psp
);
881 (void)drmUnmap((drmAddress
)psp
->pSAREA
, SAREA_MAX
);
882 (void)drmUnmap((drmAddress
)psp
->pFB
, psp
->fbSize
);
883 _mesa_free(psp
->pDevPriv
);
884 (void)drmCloseOnce(psp
->fd
);
885 if ( psp
->modes
!= NULL
) {
886 (*dri_interface
->destroyContextModes
)( psp
->modes
);
889 assert(psp
->drawHash
);
890 drmHashDestroy(psp
->drawHash
);
898 * Utility function used to create a new driver-private screen structure.
900 * \param dpy Display pointer
901 * \param scrn Index of the screen
902 * \param psc DRI screen data (not driver private)
903 * \param modes Linked list of known display modes. This list is, at a
904 * minimum, a list of modes based on the current display mode.
905 * These roughly match the set of available X11 visuals, but it
906 * need not be limited to X11! The calling libGL should create
907 * a list that will inform the driver of the current display
908 * mode (i.e., color buffer depth, depth buffer depth, etc.).
909 * \param ddx_version Version of the 2D DDX. This may not be meaningful for
911 * \param dri_version Version of the "server-side" DRI.
912 * \param drm_version Version of the kernel DRM.
913 * \param frame_buffer Data describing the location and layout of the
915 * \param pSAREA Pointer the the SAREA.
916 * \param fd Device handle for the DRM.
917 * \param internal_api_version Version of the internal interface between the
919 * \param driverAPI Driver API functions used by other routines in dri_util.c.
922 * There is no need to check the minimum API version in this function. Since
923 * the \c __driCreateNewScreen function is versioned, it is impossible for a
924 * loader that is too old to even load this driver.
927 __driUtilCreateNewScreen(__DRInativeDisplay
*dpy
, int scrn
, __DRIscreen
*psc
,
928 __GLcontextModes
* modes
,
929 const __DRIversion
* ddx_version
,
930 const __DRIversion
* dri_version
,
931 const __DRIversion
* drm_version
,
932 const __DRIframebuffer
* frame_buffer
,
935 int internal_api_version
,
936 const struct __DriverAPIRec
*driverAPI
)
938 __DRIscreenPrivate
*psp
;
941 api_ver
= internal_api_version
;
943 psp
= (__DRIscreenPrivate
*)_mesa_malloc(sizeof(__DRIscreenPrivate
));
948 /* Create the hash table */
949 psp
->drawHash
= drmHashCreate();
950 if ( psp
->drawHash
== NULL
) {
961 ** NOT_DONE: This is used by the X server to detect when the client
962 ** has died while holding the drawable lock. The client sets the
963 ** drawable lock to this value.
967 psp
->drmMajor
= drm_version
->major
;
968 psp
->drmMinor
= drm_version
->minor
;
969 psp
->drmPatch
= drm_version
->patch
;
970 psp
->ddxMajor
= ddx_version
->major
;
971 psp
->ddxMinor
= ddx_version
->minor
;
972 psp
->ddxPatch
= ddx_version
->patch
;
973 psp
->driMajor
= dri_version
->major
;
974 psp
->driMinor
= dri_version
->minor
;
975 psp
->driPatch
= dri_version
->patch
;
977 /* install driver's callback functions */
978 memcpy( &psp
->DriverAPI
, driverAPI
, sizeof(struct __DriverAPIRec
) );
980 psp
->pSAREA
= pSAREA
;
982 psp
->pFB
= frame_buffer
->base
;
983 psp
->fbSize
= frame_buffer
->size
;
984 psp
->fbStride
= frame_buffer
->stride
;
985 psp
->fbWidth
= frame_buffer
->width
;
986 psp
->fbHeight
= frame_buffer
->height
;
987 psp
->devPrivSize
= frame_buffer
->dev_priv_size
;
988 psp
->pDevPriv
= frame_buffer
->dev_priv
;
989 psp
->fbBPP
= psp
->fbStride
* 8 / frame_buffer
->width
;
994 ** Do not init dummy context here; actual initialization will be
995 ** done when the first DRI context is created. Init screen priv ptr
996 ** to NULL to let CreateContext routine that it needs to be inited.
998 psp
->dummyContextPriv
.driScreenPriv
= NULL
;
1000 psc
->destroyScreen
= driDestroyScreen
;
1001 psc
->createNewDrawable
= driCreateNewDrawable
;
1002 psc
->getDrawable
= driGetDrawable
;
1003 psc
->getMSC
= driGetMSC
;
1004 psc
->createNewContext
= driCreateNewContext
;
1006 if (internal_api_version
>= 20070121)
1007 psc
->setTexOffset
= psp
->DriverAPI
.setTexOffset
;
1009 if ( (psp
->DriverAPI
.InitDriver
!= NULL
)
1010 && !(*psp
->DriverAPI
.InitDriver
)(psp
) ) {
1021 * Compare the current GLX API version with a driver supplied required version.
1023 * The minimum required version is compared with the API version exported by
1024 * the \c __glXGetInternalVersion function (in libGL.so).
1026 * \param required_version Minimum required internal GLX API version.
1027 * \return A tri-value return, as from strcmp is returned. A value less
1028 * than, equal to, or greater than zero will be returned if the
1029 * internal GLX API version is less than, equal to, or greater
1030 * than \c required_version.
1032 * \sa __glXGetInternalVersion().
1034 int driCompareGLXAPIVersion( GLint required_version
)
1036 if ( api_ver
> required_version
) {
1039 else if ( api_ver
== required_version
) {
1048 driQueryFrameTracking( __DRInativeDisplay
* dpy
, void * priv
,
1049 int64_t * sbc
, int64_t * missedFrames
,
1050 float * lastMissedUsage
, float * usage
)
1052 __DRIswapInfo sInfo
;
1055 __DRIdrawablePrivate
* dpriv
= (__DRIdrawablePrivate
*) priv
;
1058 status
= dpriv
->driScreenPriv
->DriverAPI
.GetSwapInfo( dpriv
, & sInfo
);
1059 if ( status
== 0 ) {
1060 *sbc
= sInfo
.swap_count
;
1061 *missedFrames
= sInfo
.swap_missed_count
;
1062 *lastMissedUsage
= sInfo
.swap_missed_usage
;
1064 (*dri_interface
->getUST
)( & ust
);
1065 *usage
= driCalculateSwapUsage( dpriv
, sInfo
.swap_ust
, ust
);
1073 * Calculate amount of swap interval used between GLX buffer swaps.
1075 * The usage value, on the range [0,max], is the fraction of total swap
1076 * interval time used between GLX buffer swaps is calculated.
1078 * \f$p = t_d / (i * t_r)\f$
1080 * Where \f$t_d\f$ is the time since the last GLX buffer swap, \f$i\f$ is the
1081 * swap interval (as set by \c glXSwapIntervalSGI), and \f$t_r\f$ time
1082 * required for a single vertical refresh period (as returned by \c
1083 * glXGetMscRateOML).
1085 * See the documentation for the GLX_MESA_swap_frame_usage extension for more
1088 * \param dPriv Pointer to the private drawable structure.
1089 * \return If less than a single swap interval time period was required
1090 * between GLX buffer swaps, a number greater than 0 and less than
1091 * 1.0 is returned. If exactly one swap interval time period is
1092 * required, 1.0 is returned, and if more than one is required then
1093 * a number greater than 1.0 will be returned.
1095 * \sa glXSwapIntervalSGI glXGetMscRateOML
1097 * \todo Instead of caching the \c glXGetMscRateOML function pointer, would it
1098 * be possible to cache the sync rate?
1101 driCalculateSwapUsage( __DRIdrawablePrivate
*dPriv
, int64_t last_swap_ust
,
1102 int64_t current_ust
)
1110 if ( (*dri_interface
->getMSCRate
)( dPriv
->display
, dPriv
->draw
, &n
, &d
) ) {
1111 interval
= (dPriv
->pdraw
->swap_interval
!= 0)
1112 ? dPriv
->pdraw
->swap_interval
: 1;
1115 /* We want to calculate
1116 * (current_UST - last_swap_UST) / (interval * us_per_refresh). We get
1117 * current_UST by calling __glXGetUST. last_swap_UST is stored in
1118 * dPriv->swap_ust. interval has already been calculated.
1120 * The only tricky part is us_per_refresh. us_per_refresh is
1121 * 1000000 / MSC_rate. We know the MSC_rate is n / d. We can flip it
1122 * around and say us_per_refresh = 1000000 * d / n. Since this goes in
1123 * the denominator of the final calculation, we calculate
1124 * (interval * 1000000 * d) and move n into the numerator.
1127 usage
= (current_ust
- last_swap_ust
);
1129 usage
/= (interval
* d
);