3 * DRI utility functions.
5 * This module acts as glue between GLX and the actual hardware driver. A DRI
6 * driver doesn't really \e have to use any of this - it's optional. But, some
7 * useful stuff is done here that otherwise would have to be duplicated in most
10 * Basically, these utility functions take care of some of the dirty details of
11 * screen initialization, context creation, context binding, DRM setup, etc.
13 * These functions are compiled into each DRI driver so libGL.so knows nothing
25 #define MAP_FAILED ((void *)-1)
28 #include "main/imports.h"
32 #include "drm_sarea.h"
35 #include "../glsl/glsl_parser_extras.h"
37 PUBLIC
const char __dri2ConfigOptions
[] =
39 DRI_CONF_SECTION_PERFORMANCE
40 DRI_CONF_VBLANK_MODE(DRI_CONF_VBLANK_DEF_INTERVAL_1
)
44 static const uint __dri2NConfigOptions
= 1;
46 #ifndef GLX_OML_sync_control
47 typedef GLboolean ( * PFNGLXGETMSCRATEOMLPROC
) (__DRIdrawable
*drawable
, int32_t *numerator
, int32_t *denominator
);
50 static void dri_get_drawable(__DRIdrawable
*pdp
);
51 static void dri_put_drawable(__DRIdrawable
*pdp
);
54 driIntersectArea( drm_clip_rect_t rect1
, drm_clip_rect_t rect2
)
56 if (rect2
.x1
> rect1
.x1
) rect1
.x1
= rect2
.x1
;
57 if (rect2
.x2
< rect1
.x2
) rect1
.x2
= rect2
.x2
;
58 if (rect2
.y1
> rect1
.y1
) rect1
.y1
= rect2
.y1
;
59 if (rect2
.y2
< rect1
.y2
) rect1
.y2
= rect2
.y2
;
61 if (rect1
.x1
> rect1
.x2
|| rect1
.y1
> rect1
.y2
) return 0;
63 return (rect1
.x2
- rect1
.x1
) * (rect1
.y2
- rect1
.y1
);
66 /*****************************************************************/
67 /** \name Context (un)binding functions */
68 /*****************************************************************/
74 * \param scrn the screen.
77 * \return \c GL_TRUE on success, or \c GL_FALSE on failure.
80 * This function calls __DriverAPIRec::UnbindContext, and then decrements
81 * __DRIdrawableRec::refcount which must be non-zero for a successful
84 * While casting the opaque private pointers associated with the parameters
85 * into their respective real types it also assures they are not \c NULL.
87 static int driUnbindContext(__DRIcontext
*pcp
)
94 ** Assume error checking is done properly in glXMakeCurrent before
95 ** calling driUnbindContext.
101 psp
= pcp
->driScreenPriv
;
102 pdp
= pcp
->driDrawablePriv
;
103 prp
= pcp
->driReadablePriv
;
105 /* already unbound */
108 /* Let driver unbind drawable from context */
109 (*psp
->DriverAPI
.UnbindContext
)(pcp
);
112 if (pdp
->refcount
== 0) {
117 dri_put_drawable(pdp
);
120 if (prp
->refcount
== 0) {
125 dri_put_drawable(prp
);
129 /* XXX this is disabled so that if we call SwapBuffers on an unbound
130 * window we can determine the last context bound to the window and
131 * use that context's lock. (BrianP, 2-Dec-2000)
133 pcp
->driDrawablePriv
= pcp
->driReadablePriv
= NULL
;
139 * This function takes both a read buffer and a draw buffer. This is needed
140 * for \c glXMakeCurrentReadSGI or GLX 1.3's \c glXMakeContextCurrent
143 static int driBindContext(__DRIcontext
*pcp
,
147 __DRIscreen
*psp
= NULL
;
150 ** Assume error checking is done properly in glXMakeCurrent before
151 ** calling driUnbindContext.
157 /* Bind the drawable to the context */
158 psp
= pcp
->driScreenPriv
;
159 pcp
->driDrawablePriv
= pdp
;
160 pcp
->driReadablePriv
= prp
;
162 pdp
->driContextPriv
= pcp
;
163 dri_get_drawable(pdp
);
165 if (prp
&& pdp
!= prp
) {
166 dri_get_drawable(prp
);
170 ** Now that we have a context associated with this drawable, we can
171 ** initialize the drawable information if has not been done before.
174 if (!psp
->dri2
.enabled
) {
175 if (pdp
&& !pdp
->pStamp
) {
176 DRM_SPINLOCK(&psp
->pSAREA
->drawable_lock
, psp
->drawLockID
);
177 __driUtilUpdateDrawableInfo(pdp
);
178 DRM_SPINUNLOCK(&psp
->pSAREA
->drawable_lock
, psp
->drawLockID
);
180 if (prp
&& pdp
!= prp
&& !prp
->pStamp
) {
181 DRM_SPINLOCK(&psp
->pSAREA
->drawable_lock
, psp
->drawLockID
);
182 __driUtilUpdateDrawableInfo(prp
);
183 DRM_SPINUNLOCK(&psp
->pSAREA
->drawable_lock
, psp
->drawLockID
);
187 /* Call device-specific MakeCurrent */
188 return (*psp
->DriverAPI
.MakeCurrent
)(pcp
, pdp
, prp
);
194 /*****************************************************************/
195 /** \name Drawable handling functions */
196 /*****************************************************************/
200 * Update private drawable information.
202 * \param pdp pointer to the private drawable information to update.
204 * This function basically updates the __DRIdrawable struct's
205 * cliprect information by calling \c __DRIinterfaceMethods::getDrawableInfo.
206 * This is usually called by the DRI_VALIDATE_DRAWABLE_INFO macro which
207 * compares the __DRIdrwablePrivate pStamp and lastStamp values. If
208 * the values are different that means we have to update the clipping
212 __driUtilUpdateDrawableInfo(__DRIdrawable
*pdp
)
214 __DRIscreen
*psp
= pdp
->driScreenPriv
;
215 __DRIcontext
*pcp
= pdp
->driContextPriv
;
218 || ((pdp
!= pcp
->driDrawablePriv
) && (pdp
!= pcp
->driReadablePriv
))) {
220 * ...but we must ignore it. There can be many contexts bound to a
225 if (pdp
->pClipRects
) {
226 free(pdp
->pClipRects
);
227 pdp
->pClipRects
= NULL
;
230 if (pdp
->pBackClipRects
) {
231 free(pdp
->pBackClipRects
);
232 pdp
->pBackClipRects
= NULL
;
235 DRM_SPINUNLOCK(&psp
->pSAREA
->drawable_lock
, psp
->drawLockID
);
237 if (! (*psp
->getDrawableInfo
->getDrawableInfo
)(pdp
,
238 &pdp
->index
, &pdp
->lastStamp
,
239 &pdp
->x
, &pdp
->y
, &pdp
->w
, &pdp
->h
,
240 &pdp
->numClipRects
, &pdp
->pClipRects
,
243 &pdp
->numBackClipRects
,
244 &pdp
->pBackClipRects
,
245 pdp
->loaderPrivate
)) {
246 /* Error -- eg the window may have been destroyed. Keep going
249 pdp
->pStamp
= &pdp
->lastStamp
; /* prevent endless loop */
250 pdp
->numClipRects
= 0;
251 pdp
->pClipRects
= NULL
;
252 pdp
->numBackClipRects
= 0;
253 pdp
->pBackClipRects
= NULL
;
256 pdp
->pStamp
= &(psp
->pSAREA
->drawableTable
[pdp
->index
].stamp
);
258 DRM_SPINLOCK(&psp
->pSAREA
->drawable_lock
, psp
->drawLockID
);
263 /*****************************************************************/
264 /** \name GLX callbacks */
265 /*****************************************************************/
268 static void driReportDamage(__DRIdrawable
*pdp
,
269 struct drm_clip_rect
*pClipRects
, int numClipRects
)
271 __DRIscreen
*psp
= pdp
->driScreenPriv
;
273 /* Check that we actually have the new damage report method */
275 /* Report the damage. Currently, all our drivers draw
276 * directly to the front buffer, so we report the damage there
277 * rather than to the backing storein (if any).
279 (*psp
->damage
->reportDamage
)(pdp
,
281 pClipRects
, numClipRects
,
282 GL_TRUE
, pdp
->loaderPrivate
);
290 * \param drawablePrivate opaque pointer to the per-drawable private info.
293 * This function calls __DRIdrawable::swapBuffers.
295 * Is called directly from glXSwapBuffers().
297 static void driSwapBuffers(__DRIdrawable
*dPriv
)
299 __DRIscreen
*psp
= dPriv
->driScreenPriv
;
300 drm_clip_rect_t
*rects
;
303 psp
->DriverAPI
.SwapBuffers(dPriv
);
305 if (!dPriv
->numClipRects
)
308 rects
= malloc(sizeof(*rects
) * dPriv
->numClipRects
);
313 for (i
= 0; i
< dPriv
->numClipRects
; i
++) {
314 rects
[i
].x1
= dPriv
->pClipRects
[i
].x1
- dPriv
->x
;
315 rects
[i
].y1
= dPriv
->pClipRects
[i
].y1
- dPriv
->y
;
316 rects
[i
].x2
= dPriv
->pClipRects
[i
].x2
- dPriv
->x
;
317 rects
[i
].y2
= dPriv
->pClipRects
[i
].y2
- dPriv
->y
;
320 driReportDamage(dPriv
, rects
, dPriv
->numClipRects
);
325 * This is called via __DRIscreenRec's createNewDrawable pointer.
327 static __DRIdrawable
*
328 driCreateNewDrawable(__DRIscreen
*psp
, const __DRIconfig
*config
,
329 drm_drawable_t hwDrawable
, int renderType
,
330 const int *attrs
, void *data
)
334 /* Since pbuffers are not yet supported, no drawable attributes are
340 pdp
= malloc(sizeof *pdp
);
345 pdp
->driContextPriv
= NULL
;
346 pdp
->loaderPrivate
= data
;
347 pdp
->hHWDrawable
= hwDrawable
;
356 pdp
->numClipRects
= 0;
357 pdp
->numBackClipRects
= 0;
358 pdp
->pClipRects
= NULL
;
359 pdp
->pBackClipRects
= NULL
;
363 pdp
->driScreenPriv
= psp
;
365 if (!(*psp
->DriverAPI
.CreateBuffer
)(psp
, pdp
, &config
->modes
, 0)) {
372 /* This special default value is replaced with the configured
373 * default value when the drawable is first bound to a direct
376 pdp
->swap_interval
= (unsigned)-1;
382 static __DRIdrawable
*
383 dri2CreateNewDrawable(__DRIscreen
*screen
,
384 const __DRIconfig
*config
,
387 __DRIdrawable
*pdraw
;
389 pdraw
= driCreateNewDrawable(screen
, config
, 0, 0, NULL
, loaderPrivate
);
393 pdraw
->pClipRects
= &pdraw
->dri2
.clipRect
;
394 pdraw
->pBackClipRects
= &pdraw
->dri2
.clipRect
;
396 pdraw
->pStamp
= &pdraw
->dri2
.stamp
;
397 *pdraw
->pStamp
= pdraw
->lastStamp
+ 1;
403 dri2AllocateBuffer(__DRIscreen
*screen
,
404 unsigned int attachment
, unsigned int format
,
405 int width
, int height
)
407 return (*screen
->DriverAPI
.AllocateBuffer
)(screen
, attachment
, format
,
412 dri2ReleaseBuffer(__DRIscreen
*screen
, __DRIbuffer
*buffer
)
414 (*screen
->DriverAPI
.ReleaseBuffer
)(screen
, buffer
);
419 dri2ConfigQueryb(__DRIscreen
*screen
, const char *var
, GLboolean
*val
)
421 if (!driCheckOption(&screen
->optionCache
, var
, DRI_BOOL
))
424 *val
= driQueryOptionb(&screen
->optionCache
, var
);
430 dri2ConfigQueryi(__DRIscreen
*screen
, const char *var
, GLint
*val
)
432 if (!driCheckOption(&screen
->optionCache
, var
, DRI_INT
) &&
433 !driCheckOption(&screen
->optionCache
, var
, DRI_ENUM
))
436 *val
= driQueryOptioni(&screen
->optionCache
, var
);
442 dri2ConfigQueryf(__DRIscreen
*screen
, const char *var
, GLfloat
*val
)
444 if (!driCheckOption(&screen
->optionCache
, var
, DRI_FLOAT
))
447 *val
= driQueryOptionf(&screen
->optionCache
, var
);
453 static void dri_get_drawable(__DRIdrawable
*pdp
)
458 static void dri_put_drawable(__DRIdrawable
*pdp
)
467 psp
= pdp
->driScreenPriv
;
468 (*psp
->DriverAPI
.DestroyBuffer
)(pdp
);
469 if (pdp
->pClipRects
&& pdp
->pClipRects
!= &pdp
->dri2
.clipRect
) {
470 free(pdp
->pClipRects
);
471 pdp
->pClipRects
= NULL
;
473 if (pdp
->pBackClipRects
&& pdp
->pClipRects
!= &pdp
->dri2
.clipRect
) {
474 free(pdp
->pBackClipRects
);
475 pdp
->pBackClipRects
= NULL
;
482 driDestroyDrawable(__DRIdrawable
*pdp
)
484 dri_put_drawable(pdp
);
490 /*****************************************************************/
491 /** \name Context handling functions */
492 /*****************************************************************/
496 * Destroy the per-context private information.
499 * This function calls __DriverAPIRec::DestroyContext on \p contextPrivate, calls
500 * drmDestroyContext(), and finally frees \p contextPrivate.
503 driDestroyContext(__DRIcontext
*pcp
)
506 (*pcp
->driScreenPriv
->DriverAPI
.DestroyContext
)(pcp
);
513 * Create the per-drawable private driver information.
515 * \param render_type Type of rendering target. \c GLX_RGBA_TYPE is the only
516 * type likely to ever be supported for direct-rendering.
517 * However, \c GLX_RGBA_FLOAT_TYPE_ARB may eventually be
518 * supported by some drivers.
519 * \param shared Context with which to share textures, etc. or NULL
521 * \returns An opaque pointer to the per-context private information on
522 * success, or \c NULL on failure.
525 * This function allocates and fills a __DRIcontextRec structure. It
526 * performs some device independent initialization and passes all the
527 * relevent information to __DriverAPIRec::CreateContext to create the
531 static __DRIcontext
*
532 driCreateNewContext(__DRIscreen
*psp
, const __DRIconfig
*config
,
533 int render_type
, __DRIcontext
*shared
,
534 drm_context_t hwContext
, void *data
)
537 void * const shareCtx
= (shared
!= NULL
) ? shared
->driverPrivate
: NULL
;
541 pcp
= malloc(sizeof *pcp
);
545 pcp
->driScreenPriv
= psp
;
546 pcp
->driDrawablePriv
= NULL
;
547 pcp
->loaderPrivate
= data
;
549 pcp
->dri2
.draw_stamp
= 0;
550 pcp
->dri2
.read_stamp
= 0;
552 pcp
->hHWContext
= hwContext
;
554 if ( !(*psp
->DriverAPI
.CreateContext
)(API_OPENGL
,
555 &config
->modes
, pcp
, shareCtx
) ) {
564 dri2GetAPIMask(__DRIscreen
*screen
)
566 return screen
->api_mask
;
569 static __DRIcontext
*
570 dri2CreateNewContextForAPI(__DRIscreen
*screen
, int api
,
571 const __DRIconfig
*config
,
572 __DRIcontext
*shared
, void *data
)
574 __DRIcontext
*context
;
575 const struct gl_config
*modes
= (config
!= NULL
) ? &config
->modes
: NULL
;
576 void *shareCtx
= (shared
!= NULL
) ? shared
->driverPrivate
: NULL
;
579 if (!(screen
->api_mask
& (1 << api
)))
583 case __DRI_API_OPENGL
:
584 mesa_api
= API_OPENGL
;
587 mesa_api
= API_OPENGLES
;
589 case __DRI_API_GLES2
:
590 mesa_api
= API_OPENGLES2
;
596 context
= malloc(sizeof *context
);
600 context
->driScreenPriv
= screen
;
601 context
->driDrawablePriv
= NULL
;
602 context
->loaderPrivate
= data
;
604 if (!(*screen
->DriverAPI
.CreateContext
)(mesa_api
, modes
,
605 context
, shareCtx
) ) {
614 static __DRIcontext
*
615 dri2CreateNewContext(__DRIscreen
*screen
, const __DRIconfig
*config
,
616 __DRIcontext
*shared
, void *data
)
618 return dri2CreateNewContextForAPI(screen
, __DRI_API_OPENGL
,
619 config
, shared
, data
);
623 driCopyContext(__DRIcontext
*dest
, __DRIcontext
*src
, unsigned long mask
)
634 /*****************************************************************/
635 /** \name Screen handling functions */
636 /*****************************************************************/
640 * Destroy the per-screen private information.
643 * This function calls __DriverAPIRec::DestroyScreen on \p screenPrivate, calls
644 * drmClose(), and finally frees \p screenPrivate.
646 static void driDestroyScreen(__DRIscreen
*psp
)
649 /* No interaction with the X-server is possible at this point. This
650 * routine is called after XCloseDisplay, so there is no protocol
651 * stream open to the X-server anymore.
654 _mesa_destroy_shader_compiler();
656 if (psp
->DriverAPI
.DestroyScreen
)
657 (*psp
->DriverAPI
.DestroyScreen
)(psp
);
659 if (!psp
->dri2
.enabled
) {
660 (void)drmUnmap((drmAddress
)psp
->pSAREA
, SAREA_MAX
);
661 (void)drmUnmap((drmAddress
)psp
->pFB
, psp
->fbSize
);
662 (void)drmCloseOnce(psp
->fd
);
664 driDestroyOptionCache(&psp
->optionCache
);
665 driDestroyOptionInfo(&psp
->optionInfo
);
673 setupLoaderExtensions(__DRIscreen
*psp
,
674 const __DRIextension
**extensions
)
678 for (i
= 0; extensions
[i
]; i
++) {
679 if (strcmp(extensions
[i
]->name
, __DRI_GET_DRAWABLE_INFO
) == 0)
680 psp
->getDrawableInfo
= (__DRIgetDrawableInfoExtension
*) extensions
[i
];
681 if (strcmp(extensions
[i
]->name
, __DRI_DAMAGE
) == 0)
682 psp
->damage
= (__DRIdamageExtension
*) extensions
[i
];
683 if (strcmp(extensions
[i
]->name
, __DRI_SYSTEM_TIME
) == 0)
684 psp
->systemTime
= (__DRIsystemTimeExtension
*) extensions
[i
];
685 if (strcmp(extensions
[i
]->name
, __DRI_DRI2_LOADER
) == 0)
686 psp
->dri2
.loader
= (__DRIdri2LoaderExtension
*) extensions
[i
];
687 if (strcmp(extensions
[i
]->name
, __DRI_IMAGE_LOOKUP
) == 0)
688 psp
->dri2
.image
= (__DRIimageLookupExtension
*) extensions
[i
];
689 if (strcmp(extensions
[i
]->name
, __DRI_USE_INVALIDATE
) == 0)
690 psp
->dri2
.useInvalidate
= (__DRIuseInvalidateExtension
*) extensions
[i
];
698 dri2CreateNewScreen(int scrn
, int fd
,
699 const __DRIextension
**extensions
,
700 const __DRIconfig
***driver_configs
, void *data
)
702 static const __DRIextension
*emptyExtensionList
[] = { NULL
};
704 drmVersionPtr version
;
706 if (driDriverAPI
.InitScreen2
== NULL
)
709 psp
= calloc(1, sizeof(*psp
));
713 setupLoaderExtensions(psp
, extensions
);
715 version
= drmGetVersion(fd
);
717 psp
->drm_version
.major
= version
->version_major
;
718 psp
->drm_version
.minor
= version
->version_minor
;
719 psp
->drm_version
.patch
= version
->version_patchlevel
;
720 drmFreeVersion(version
);
723 psp
->extensions
= emptyExtensionList
;
726 psp
->dri2
.enabled
= GL_TRUE
;
728 psp
->DriverAPI
= driDriverAPI
;
729 psp
->api_mask
= (1 << __DRI_API_OPENGL
);
730 *driver_configs
= driDriverAPI
.InitScreen2(psp
);
731 if (*driver_configs
== NULL
) {
736 psp
->DriverAPI
= driDriverAPI
;
737 psp
->loaderPrivate
= data
;
739 driParseOptionInfo(&psp
->optionInfo
, __dri2ConfigOptions
,
740 __dri2NConfigOptions
);
741 driParseConfigFiles(&psp
->optionCache
, &psp
->optionInfo
, psp
->myNum
,
747 static const __DRIextension
**driGetExtensions(__DRIscreen
*psp
)
749 return psp
->extensions
;
752 /** Core interface */
753 const __DRIcoreExtension driCoreExtension
= {
754 { __DRI_CORE
, __DRI_CORE_VERSION
},
759 driIndexConfigAttrib
,
770 /** DRI2 interface */
771 const __DRIdri2Extension driDRI2Extension
= {
772 { __DRI_DRI2
, __DRI_DRI2_VERSION
},
774 dri2CreateNewDrawable
,
775 dri2CreateNewContext
,
777 dri2CreateNewContextForAPI
,
782 const __DRI2configQueryExtension dri2ConfigQueryExtension
= {
783 { __DRI2_CONFIG_QUERY
, __DRI2_CONFIG_QUERY_VERSION
},
790 * Calculate amount of swap interval used between GLX buffer swaps.
792 * The usage value, on the range [0,max], is the fraction of total swap
793 * interval time used between GLX buffer swaps is calculated.
795 * \f$p = t_d / (i * t_r)\f$
797 * Where \f$t_d\f$ is the time since the last GLX buffer swap, \f$i\f$ is the
798 * swap interval (as set by \c glXSwapIntervalSGI), and \f$t_r\f$ time
799 * required for a single vertical refresh period (as returned by \c
802 * See the documentation for the GLX_MESA_swap_frame_usage extension for more
805 * \param dPriv Pointer to the private drawable structure.
806 * \return If less than a single swap interval time period was required
807 * between GLX buffer swaps, a number greater than 0 and less than
808 * 1.0 is returned. If exactly one swap interval time period is
809 * required, 1.0 is returned, and if more than one is required then
810 * a number greater than 1.0 will be returned.
812 * \sa glXSwapIntervalSGI glXGetMscRateOML
814 * \todo Instead of caching the \c glXGetMscRateOML function pointer, would it
815 * be possible to cache the sync rate?
818 driCalculateSwapUsage( __DRIdrawable
*dPriv
, int64_t last_swap_ust
,
819 int64_t current_ust
)
825 __DRIscreen
*psp
= dPriv
->driScreenPriv
;
827 if ( (*psp
->systemTime
->getMSCRate
)(dPriv
, &n
, &d
, dPriv
->loaderPrivate
) ) {
828 interval
= (dPriv
->swap_interval
!= 0) ? dPriv
->swap_interval
: 1;
831 /* We want to calculate
832 * (current_UST - last_swap_UST) / (interval * us_per_refresh). We get
833 * current_UST by calling __glXGetUST. last_swap_UST is stored in
834 * dPriv->swap_ust. interval has already been calculated.
836 * The only tricky part is us_per_refresh. us_per_refresh is
837 * 1000000 / MSC_rate. We know the MSC_rate is n / d. We can flip it
838 * around and say us_per_refresh = 1000000 * d / n. Since this goes in
839 * the denominator of the final calculation, we calculate
840 * (interval * 1000000 * d) and move n into the numerator.
843 usage
= (current_ust
- last_swap_ust
);
845 usage
/= (interval
* d
);
853 dri2InvalidateDrawable(__DRIdrawable
*drawable
)
855 drawable
->dri2
.stamp
++;