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 * This is just a token extension used to signal that the driver
55 * supports setting a read drawable.
57 const __DRIextension driReadDrawableExtension
= {
58 __DRI_READ_DRAWABLE
, __DRI_READ_DRAWABLE_VERSION
62 driIntersectArea( drm_clip_rect_t rect1
, drm_clip_rect_t rect2
)
64 if (rect2
.x1
> rect1
.x1
) rect1
.x1
= rect2
.x1
;
65 if (rect2
.x2
< rect1
.x2
) rect1
.x2
= rect2
.x2
;
66 if (rect2
.y1
> rect1
.y1
) rect1
.y1
= rect2
.y1
;
67 if (rect2
.y2
< rect1
.y2
) rect1
.y2
= rect2
.y2
;
69 if (rect1
.x1
> rect1
.x2
|| rect1
.y1
> rect1
.y2
) return 0;
71 return (rect1
.x2
- rect1
.x1
) * (rect1
.y2
- rect1
.y1
);
74 /*****************************************************************/
75 /** \name Context (un)binding functions */
76 /*****************************************************************/
82 * \param scrn the screen.
85 * \return \c GL_TRUE on success, or \c GL_FALSE on failure.
88 * This function calls __DriverAPIRec::UnbindContext, and then decrements
89 * __DRIdrawableRec::refcount which must be non-zero for a successful
92 * While casting the opaque private pointers associated with the parameters
93 * into their respective real types it also assures they are not \c NULL.
95 static int driUnbindContext(__DRIcontext
*pcp
)
102 ** Assume error checking is done properly in glXMakeCurrent before
103 ** calling driUnbindContext.
109 psp
= pcp
->driScreenPriv
;
110 pdp
= pcp
->driDrawablePriv
;
111 prp
= pcp
->driReadablePriv
;
113 /* already unbound */
116 /* Let driver unbind drawable from context */
117 (*psp
->DriverAPI
.UnbindContext
)(pcp
);
120 if (pdp
->refcount
== 0) {
125 dri_put_drawable(pdp
);
128 if (prp
->refcount
== 0) {
133 dri_put_drawable(prp
);
137 /* XXX this is disabled so that if we call SwapBuffers on an unbound
138 * window we can determine the last context bound to the window and
139 * use that context's lock. (BrianP, 2-Dec-2000)
141 pcp
->driDrawablePriv
= pcp
->driReadablePriv
= NULL
;
147 * This function takes both a read buffer and a draw buffer. This is needed
148 * for \c glXMakeCurrentReadSGI or GLX 1.3's \c glXMakeContextCurrent
151 static int driBindContext(__DRIcontext
*pcp
,
155 __DRIscreen
*psp
= NULL
;
158 ** Assume error checking is done properly in glXMakeCurrent before
159 ** calling driUnbindContext.
165 /* Bind the drawable to the context */
166 psp
= pcp
->driScreenPriv
;
167 pcp
->driDrawablePriv
= pdp
;
168 pcp
->driReadablePriv
= prp
;
170 pdp
->driContextPriv
= pcp
;
171 dri_get_drawable(pdp
);
173 if (prp
&& pdp
!= prp
) {
174 dri_get_drawable(prp
);
178 ** Now that we have a context associated with this drawable, we can
179 ** initialize the drawable information if has not been done before.
182 if (!psp
->dri2
.enabled
) {
183 if (pdp
&& !pdp
->pStamp
) {
184 DRM_SPINLOCK(&psp
->pSAREA
->drawable_lock
, psp
->drawLockID
);
185 __driUtilUpdateDrawableInfo(pdp
);
186 DRM_SPINUNLOCK(&psp
->pSAREA
->drawable_lock
, psp
->drawLockID
);
188 if (prp
&& pdp
!= prp
&& !prp
->pStamp
) {
189 DRM_SPINLOCK(&psp
->pSAREA
->drawable_lock
, psp
->drawLockID
);
190 __driUtilUpdateDrawableInfo(prp
);
191 DRM_SPINUNLOCK(&psp
->pSAREA
->drawable_lock
, psp
->drawLockID
);
195 /* Call device-specific MakeCurrent */
196 return (*psp
->DriverAPI
.MakeCurrent
)(pcp
, pdp
, prp
);
202 /*****************************************************************/
203 /** \name Drawable handling functions */
204 /*****************************************************************/
208 * Update private drawable information.
210 * \param pdp pointer to the private drawable information to update.
212 * This function basically updates the __DRIdrawable struct's
213 * cliprect information by calling \c __DRIinterfaceMethods::getDrawableInfo.
214 * This is usually called by the DRI_VALIDATE_DRAWABLE_INFO macro which
215 * compares the __DRIdrwablePrivate pStamp and lastStamp values. If
216 * the values are different that means we have to update the clipping
220 __driUtilUpdateDrawableInfo(__DRIdrawable
*pdp
)
222 __DRIscreen
*psp
= pdp
->driScreenPriv
;
223 __DRIcontext
*pcp
= pdp
->driContextPriv
;
226 || ((pdp
!= pcp
->driDrawablePriv
) && (pdp
!= pcp
->driReadablePriv
))) {
228 * ...but we must ignore it. There can be many contexts bound to a
233 if (pdp
->pClipRects
) {
234 free(pdp
->pClipRects
);
235 pdp
->pClipRects
= NULL
;
238 if (pdp
->pBackClipRects
) {
239 free(pdp
->pBackClipRects
);
240 pdp
->pBackClipRects
= NULL
;
243 DRM_SPINUNLOCK(&psp
->pSAREA
->drawable_lock
, psp
->drawLockID
);
245 if (! (*psp
->getDrawableInfo
->getDrawableInfo
)(pdp
,
246 &pdp
->index
, &pdp
->lastStamp
,
247 &pdp
->x
, &pdp
->y
, &pdp
->w
, &pdp
->h
,
248 &pdp
->numClipRects
, &pdp
->pClipRects
,
251 &pdp
->numBackClipRects
,
252 &pdp
->pBackClipRects
,
253 pdp
->loaderPrivate
)) {
254 /* Error -- eg the window may have been destroyed. Keep going
257 pdp
->pStamp
= &pdp
->lastStamp
; /* prevent endless loop */
258 pdp
->numClipRects
= 0;
259 pdp
->pClipRects
= NULL
;
260 pdp
->numBackClipRects
= 0;
261 pdp
->pBackClipRects
= NULL
;
264 pdp
->pStamp
= &(psp
->pSAREA
->drawableTable
[pdp
->index
].stamp
);
266 DRM_SPINLOCK(&psp
->pSAREA
->drawable_lock
, psp
->drawLockID
);
271 /*****************************************************************/
272 /** \name GLX callbacks */
273 /*****************************************************************/
276 static void driReportDamage(__DRIdrawable
*pdp
,
277 struct drm_clip_rect
*pClipRects
, int numClipRects
)
279 __DRIscreen
*psp
= pdp
->driScreenPriv
;
281 /* Check that we actually have the new damage report method */
283 /* Report the damage. Currently, all our drivers draw
284 * directly to the front buffer, so we report the damage there
285 * rather than to the backing storein (if any).
287 (*psp
->damage
->reportDamage
)(pdp
,
289 pClipRects
, numClipRects
,
290 GL_TRUE
, pdp
->loaderPrivate
);
298 * \param drawablePrivate opaque pointer to the per-drawable private info.
301 * This function calls __DRIdrawable::swapBuffers.
303 * Is called directly from glXSwapBuffers().
305 static void driSwapBuffers(__DRIdrawable
*dPriv
)
307 __DRIscreen
*psp
= dPriv
->driScreenPriv
;
308 drm_clip_rect_t
*rects
;
311 psp
->DriverAPI
.SwapBuffers(dPriv
);
313 if (!dPriv
->numClipRects
)
316 rects
= malloc(sizeof(*rects
) * dPriv
->numClipRects
);
321 for (i
= 0; i
< dPriv
->numClipRects
; i
++) {
322 rects
[i
].x1
= dPriv
->pClipRects
[i
].x1
- dPriv
->x
;
323 rects
[i
].y1
= dPriv
->pClipRects
[i
].y1
- dPriv
->y
;
324 rects
[i
].x2
= dPriv
->pClipRects
[i
].x2
- dPriv
->x
;
325 rects
[i
].y2
= dPriv
->pClipRects
[i
].y2
- dPriv
->y
;
328 driReportDamage(dPriv
, rects
, dPriv
->numClipRects
);
332 static int driDrawableGetMSC( __DRIscreen
*sPriv
, __DRIdrawable
*dPriv
,
335 return sPriv
->DriverAPI
.GetDrawableMSC(sPriv
, dPriv
, msc
);
339 static int driWaitForMSC(__DRIdrawable
*dPriv
, int64_t target_msc
,
340 int64_t divisor
, int64_t remainder
,
341 int64_t * msc
, int64_t * sbc
)
346 status
= dPriv
->driScreenPriv
->DriverAPI
.WaitForMSC( dPriv
, target_msc
,
350 /* GetSwapInfo() may not be provided by the driver if GLX_SGI_video_sync
351 * is supported but GLX_OML_sync_control is not. Therefore, don't return
352 * an error value if GetSwapInfo() is not implemented.
355 && dPriv
->driScreenPriv
->DriverAPI
.GetSwapInfo
) {
356 status
= dPriv
->driScreenPriv
->DriverAPI
.GetSwapInfo( dPriv
, & sInfo
);
357 *sbc
= sInfo
.swap_count
;
364 const __DRImediaStreamCounterExtension driMediaStreamCounterExtension
= {
365 { __DRI_MEDIA_STREAM_COUNTER
, __DRI_MEDIA_STREAM_COUNTER_VERSION
},
371 static void driCopySubBuffer(__DRIdrawable
*dPriv
,
372 int x
, int y
, int w
, int h
)
374 drm_clip_rect_t rect
;
377 rect
.y1
= dPriv
->h
- y
- h
;
379 rect
.y2
= rect
.y1
+ h
;
380 driReportDamage(dPriv
, &rect
, 1);
382 dPriv
->driScreenPriv
->DriverAPI
.CopySubBuffer(dPriv
, x
, y
, w
, h
);
385 const __DRIcopySubBufferExtension driCopySubBufferExtension
= {
386 { __DRI_COPY_SUB_BUFFER
, __DRI_COPY_SUB_BUFFER_VERSION
},
390 static void driSetSwapInterval(__DRIdrawable
*dPriv
, unsigned int interval
)
392 dPriv
->swap_interval
= interval
;
395 static unsigned int driGetSwapInterval(__DRIdrawable
*dPriv
)
397 return dPriv
->swap_interval
;
400 const __DRIswapControlExtension driSwapControlExtension
= {
401 { __DRI_SWAP_CONTROL
, __DRI_SWAP_CONTROL_VERSION
},
408 * This is called via __DRIscreenRec's createNewDrawable pointer.
410 static __DRIdrawable
*
411 driCreateNewDrawable(__DRIscreen
*psp
, const __DRIconfig
*config
,
412 drm_drawable_t hwDrawable
, int renderType
,
413 const int *attrs
, void *data
)
417 /* Since pbuffers are not yet supported, no drawable attributes are
422 pdp
= malloc(sizeof *pdp
);
427 pdp
->driContextPriv
= NULL
;
428 pdp
->loaderPrivate
= data
;
429 pdp
->hHWDrawable
= hwDrawable
;
438 pdp
->numClipRects
= 0;
439 pdp
->numBackClipRects
= 0;
440 pdp
->pClipRects
= NULL
;
441 pdp
->pBackClipRects
= NULL
;
445 pdp
->driScreenPriv
= psp
;
447 if (!(*psp
->DriverAPI
.CreateBuffer
)(psp
, pdp
, &config
->modes
, 0)) {
454 /* This special default value is replaced with the configured
455 * default value when the drawable is first bound to a direct
458 pdp
->swap_interval
= (unsigned)-1;
464 static __DRIdrawable
*
465 dri2CreateNewDrawable(__DRIscreen
*screen
,
466 const __DRIconfig
*config
,
469 __DRIdrawable
*pdraw
;
471 pdraw
= driCreateNewDrawable(screen
, config
, 0, 0, NULL
, loaderPrivate
);
475 pdraw
->pClipRects
= &pdraw
->dri2
.clipRect
;
476 pdraw
->pBackClipRects
= &pdraw
->dri2
.clipRect
;
478 pdraw
->pStamp
= &pdraw
->dri2
.stamp
;
479 *pdraw
->pStamp
= pdraw
->lastStamp
+ 1;
485 dri2AllocateBuffer(__DRIscreen
*screen
,
486 unsigned int attachment
, unsigned int format
,
487 int width
, int height
)
489 return (*screen
->DriverAPI
.AllocateBuffer
)(screen
, attachment
, format
,
494 dri2ReleaseBuffer(__DRIscreen
*screen
, __DRIbuffer
*buffer
)
496 (*screen
->DriverAPI
.ReleaseBuffer
)(screen
, buffer
);
501 dri2ConfigQueryb(__DRIscreen
*screen
, const char *var
, GLboolean
*val
)
503 if (!driCheckOption(&screen
->optionCache
, var
, DRI_BOOL
))
506 *val
= driQueryOptionb(&screen
->optionCache
, var
);
512 dri2ConfigQueryi(__DRIscreen
*screen
, const char *var
, GLint
*val
)
514 if (!driCheckOption(&screen
->optionCache
, var
, DRI_INT
) &&
515 !driCheckOption(&screen
->optionCache
, var
, DRI_ENUM
))
518 *val
= driQueryOptioni(&screen
->optionCache
, var
);
524 dri2ConfigQueryf(__DRIscreen
*screen
, const char *var
, GLfloat
*val
)
526 if (!driCheckOption(&screen
->optionCache
, var
, DRI_FLOAT
))
529 *val
= driQueryOptionf(&screen
->optionCache
, var
);
535 static void dri_get_drawable(__DRIdrawable
*pdp
)
540 static void dri_put_drawable(__DRIdrawable
*pdp
)
549 psp
= pdp
->driScreenPriv
;
550 (*psp
->DriverAPI
.DestroyBuffer
)(pdp
);
551 if (pdp
->pClipRects
&& pdp
->pClipRects
!= &pdp
->dri2
.clipRect
) {
552 free(pdp
->pClipRects
);
553 pdp
->pClipRects
= NULL
;
555 if (pdp
->pBackClipRects
&& pdp
->pClipRects
!= &pdp
->dri2
.clipRect
) {
556 free(pdp
->pBackClipRects
);
557 pdp
->pBackClipRects
= NULL
;
564 driDestroyDrawable(__DRIdrawable
*pdp
)
566 dri_put_drawable(pdp
);
572 /*****************************************************************/
573 /** \name Context handling functions */
574 /*****************************************************************/
578 * Destroy the per-context private information.
581 * This function calls __DriverAPIRec::DestroyContext on \p contextPrivate, calls
582 * drmDestroyContext(), and finally frees \p contextPrivate.
585 driDestroyContext(__DRIcontext
*pcp
)
588 (*pcp
->driScreenPriv
->DriverAPI
.DestroyContext
)(pcp
);
595 * Create the per-drawable private driver information.
597 * \param render_type Type of rendering target. \c GLX_RGBA is the only
598 * type likely to ever be supported for direct-rendering.
599 * \param shared Context with which to share textures, etc. or NULL
601 * \returns An opaque pointer to the per-context private information on
602 * success, or \c NULL on failure.
605 * This function allocates and fills a __DRIcontextRec structure. It
606 * performs some device independent initialization and passes all the
607 * relevent information to __DriverAPIRec::CreateContext to create the
611 static __DRIcontext
*
612 driCreateNewContext(__DRIscreen
*psp
, const __DRIconfig
*config
,
613 int render_type
, __DRIcontext
*shared
,
614 drm_context_t hwContext
, void *data
)
617 void * const shareCtx
= (shared
!= NULL
) ? shared
->driverPrivate
: NULL
;
619 pcp
= malloc(sizeof *pcp
);
623 pcp
->driScreenPriv
= psp
;
624 pcp
->driDrawablePriv
= NULL
;
625 pcp
->loaderPrivate
= data
;
627 pcp
->dri2
.draw_stamp
= 0;
628 pcp
->dri2
.read_stamp
= 0;
630 pcp
->hHWContext
= hwContext
;
632 if ( !(*psp
->DriverAPI
.CreateContext
)(API_OPENGL
,
633 &config
->modes
, pcp
, shareCtx
) ) {
642 dri2GetAPIMask(__DRIscreen
*screen
)
644 return screen
->api_mask
;
647 static __DRIcontext
*
648 dri2CreateNewContextForAPI(__DRIscreen
*screen
, int api
,
649 const __DRIconfig
*config
,
650 __DRIcontext
*shared
, void *data
)
652 __DRIcontext
*context
;
653 const struct gl_config
*modes
= (config
!= NULL
) ? &config
->modes
: NULL
;
654 void *shareCtx
= (shared
!= NULL
) ? shared
->driverPrivate
: NULL
;
657 if (!(screen
->api_mask
& (1 << api
)))
661 case __DRI_API_OPENGL
:
662 mesa_api
= API_OPENGL
;
665 mesa_api
= API_OPENGLES
;
667 case __DRI_API_GLES2
:
668 mesa_api
= API_OPENGLES2
;
674 context
= malloc(sizeof *context
);
678 context
->driScreenPriv
= screen
;
679 context
->driDrawablePriv
= NULL
;
680 context
->loaderPrivate
= data
;
682 if (!(*screen
->DriverAPI
.CreateContext
)(mesa_api
, modes
,
683 context
, shareCtx
) ) {
692 static __DRIcontext
*
693 dri2CreateNewContext(__DRIscreen
*screen
, const __DRIconfig
*config
,
694 __DRIcontext
*shared
, void *data
)
696 return dri2CreateNewContextForAPI(screen
, __DRI_API_OPENGL
,
697 config
, shared
, data
);
701 driCopyContext(__DRIcontext
*dest
, __DRIcontext
*src
, unsigned long mask
)
709 /*****************************************************************/
710 /** \name Screen handling functions */
711 /*****************************************************************/
715 * Destroy the per-screen private information.
718 * This function calls __DriverAPIRec::DestroyScreen on \p screenPrivate, calls
719 * drmClose(), and finally frees \p screenPrivate.
721 static void driDestroyScreen(__DRIscreen
*psp
)
724 /* No interaction with the X-server is possible at this point. This
725 * routine is called after XCloseDisplay, so there is no protocol
726 * stream open to the X-server anymore.
729 _mesa_destroy_shader_compiler();
731 if (psp
->DriverAPI
.DestroyScreen
)
732 (*psp
->DriverAPI
.DestroyScreen
)(psp
);
734 if (!psp
->dri2
.enabled
) {
735 (void)drmUnmap((drmAddress
)psp
->pSAREA
, SAREA_MAX
);
736 (void)drmUnmap((drmAddress
)psp
->pFB
, psp
->fbSize
);
737 (void)drmCloseOnce(psp
->fd
);
739 driDestroyOptionCache(&psp
->optionCache
);
740 driDestroyOptionInfo(&psp
->optionInfo
);
748 setupLoaderExtensions(__DRIscreen
*psp
,
749 const __DRIextension
**extensions
)
753 for (i
= 0; extensions
[i
]; i
++) {
754 if (strcmp(extensions
[i
]->name
, __DRI_GET_DRAWABLE_INFO
) == 0)
755 psp
->getDrawableInfo
= (__DRIgetDrawableInfoExtension
*) extensions
[i
];
756 if (strcmp(extensions
[i
]->name
, __DRI_DAMAGE
) == 0)
757 psp
->damage
= (__DRIdamageExtension
*) extensions
[i
];
758 if (strcmp(extensions
[i
]->name
, __DRI_SYSTEM_TIME
) == 0)
759 psp
->systemTime
= (__DRIsystemTimeExtension
*) extensions
[i
];
760 if (strcmp(extensions
[i
]->name
, __DRI_DRI2_LOADER
) == 0)
761 psp
->dri2
.loader
= (__DRIdri2LoaderExtension
*) extensions
[i
];
762 if (strcmp(extensions
[i
]->name
, __DRI_IMAGE_LOOKUP
) == 0)
763 psp
->dri2
.image
= (__DRIimageLookupExtension
*) extensions
[i
];
764 if (strcmp(extensions
[i
]->name
, __DRI_USE_INVALIDATE
) == 0)
765 psp
->dri2
.useInvalidate
= (__DRIuseInvalidateExtension
*) extensions
[i
];
770 * This is the bootstrap function for the driver. libGL supplies all of the
771 * requisite information about the system, and the driver initializes itself.
772 * This routine also fills in the linked list pointed to by \c driver_modes
773 * with the \c struct gl_config that the driver can support for windows or
778 * \param scrn Index of the screen
779 * \param ddx_version Version of the 2D DDX. This may not be meaningful for
781 * \param dri_version Version of the "server-side" DRI.
782 * \param drm_version Version of the kernel DRM.
783 * \param frame_buffer Data describing the location and layout of the
785 * \param pSAREA Pointer to the SAREA.
786 * \param fd Device handle for the DRM.
787 * \param extensions ??
788 * \param driver_modes Returns modes suppoted by the driver
789 * \param loaderPrivate ??
791 * \note There is no need to check the minimum API version in this
792 * function. Since the name of this function is versioned, it is
793 * impossible for a loader that is too old to even load this driver.
796 driCreateNewScreen(int scrn
,
797 const __DRIversion
*ddx_version
,
798 const __DRIversion
*dri_version
,
799 const __DRIversion
*drm_version
,
800 const __DRIframebuffer
*frame_buffer
,
801 drmAddress pSAREA
, int fd
,
802 const __DRIextension
**extensions
,
803 const __DRIconfig
***driver_modes
,
806 static const __DRIextension
*emptyExtensionList
[] = { NULL
};
809 if (driDriverAPI
.InitScreen
== NULL
)
812 psp
= calloc(1, sizeof *psp
);
816 setupLoaderExtensions(psp
, extensions
);
819 ** NOT_DONE: This is used by the X server to detect when the client
820 ** has died while holding the drawable lock. The client sets the
821 ** drawable lock to this value.
825 psp
->drm_version
= *drm_version
;
826 psp
->ddx_version
= *ddx_version
;
827 psp
->dri_version
= *dri_version
;
829 psp
->pSAREA
= pSAREA
;
830 psp
->lock
= (drmLock
*) &psp
->pSAREA
->lock
;
832 psp
->pFB
= frame_buffer
->base
;
833 psp
->fbSize
= frame_buffer
->size
;
834 psp
->fbStride
= frame_buffer
->stride
;
835 psp
->fbWidth
= frame_buffer
->width
;
836 psp
->fbHeight
= frame_buffer
->height
;
837 psp
->devPrivSize
= frame_buffer
->dev_priv_size
;
838 psp
->pDevPriv
= frame_buffer
->dev_priv
;
839 psp
->fbBPP
= psp
->fbStride
* 8 / frame_buffer
->width
;
841 psp
->extensions
= emptyExtensionList
;
844 psp
->dri2
.enabled
= GL_FALSE
;
846 psp
->DriverAPI
= driDriverAPI
;
847 psp
->api_mask
= (1 << __DRI_API_OPENGL
);
849 *driver_modes
= driDriverAPI
.InitScreen(psp
);
850 if (*driver_modes
== NULL
) {
862 dri2CreateNewScreen(int scrn
, int fd
,
863 const __DRIextension
**extensions
,
864 const __DRIconfig
***driver_configs
, void *data
)
866 static const __DRIextension
*emptyExtensionList
[] = { NULL
};
868 drmVersionPtr version
;
870 if (driDriverAPI
.InitScreen2
== NULL
)
873 psp
= calloc(1, sizeof(*psp
));
877 setupLoaderExtensions(psp
, extensions
);
879 version
= drmGetVersion(fd
);
881 psp
->drm_version
.major
= version
->version_major
;
882 psp
->drm_version
.minor
= version
->version_minor
;
883 psp
->drm_version
.patch
= version
->version_patchlevel
;
884 drmFreeVersion(version
);
887 psp
->extensions
= emptyExtensionList
;
890 psp
->dri2
.enabled
= GL_TRUE
;
892 psp
->DriverAPI
= driDriverAPI
;
893 psp
->api_mask
= (1 << __DRI_API_OPENGL
);
894 *driver_configs
= driDriverAPI
.InitScreen2(psp
);
895 if (*driver_configs
== NULL
) {
900 psp
->DriverAPI
= driDriverAPI
;
901 psp
->loaderPrivate
= data
;
903 driParseOptionInfo(&psp
->optionInfo
, __dri2ConfigOptions
,
904 __dri2NConfigOptions
);
905 driParseConfigFiles(&psp
->optionCache
, &psp
->optionInfo
, psp
->myNum
,
911 static const __DRIextension
**driGetExtensions(__DRIscreen
*psp
)
913 return psp
->extensions
;
916 /** Core interface */
917 const __DRIcoreExtension driCoreExtension
= {
918 { __DRI_CORE
, __DRI_CORE_VERSION
},
923 driIndexConfigAttrib
,
934 /** Legacy DRI interface */
935 const __DRIlegacyExtension driLegacyExtension
= {
936 { __DRI_LEGACY
, __DRI_LEGACY_VERSION
},
938 driCreateNewDrawable
,
942 /** DRI2 interface */
943 const __DRIdri2Extension driDRI2Extension
= {
944 { __DRI_DRI2
, __DRI_DRI2_VERSION
},
946 dri2CreateNewDrawable
,
947 dri2CreateNewContext
,
949 dri2CreateNewContextForAPI
,
954 const __DRI2configQueryExtension dri2ConfigQueryExtension
= {
955 { __DRI2_CONFIG_QUERY
, __DRI2_CONFIG_QUERY_VERSION
},
962 * Calculate amount of swap interval used between GLX buffer swaps.
964 * The usage value, on the range [0,max], is the fraction of total swap
965 * interval time used between GLX buffer swaps is calculated.
967 * \f$p = t_d / (i * t_r)\f$
969 * Where \f$t_d\f$ is the time since the last GLX buffer swap, \f$i\f$ is the
970 * swap interval (as set by \c glXSwapIntervalSGI), and \f$t_r\f$ time
971 * required for a single vertical refresh period (as returned by \c
974 * See the documentation for the GLX_MESA_swap_frame_usage extension for more
977 * \param dPriv Pointer to the private drawable structure.
978 * \return If less than a single swap interval time period was required
979 * between GLX buffer swaps, a number greater than 0 and less than
980 * 1.0 is returned. If exactly one swap interval time period is
981 * required, 1.0 is returned, and if more than one is required then
982 * a number greater than 1.0 will be returned.
984 * \sa glXSwapIntervalSGI glXGetMscRateOML
986 * \todo Instead of caching the \c glXGetMscRateOML function pointer, would it
987 * be possible to cache the sync rate?
990 driCalculateSwapUsage( __DRIdrawable
*dPriv
, int64_t last_swap_ust
,
991 int64_t current_ust
)
997 __DRIscreen
*psp
= dPriv
->driScreenPriv
;
999 if ( (*psp
->systemTime
->getMSCRate
)(dPriv
, &n
, &d
, dPriv
->loaderPrivate
) ) {
1000 interval
= (dPriv
->swap_interval
!= 0) ? dPriv
->swap_interval
: 1;
1003 /* We want to calculate
1004 * (current_UST - last_swap_UST) / (interval * us_per_refresh). We get
1005 * current_UST by calling __glXGetUST. last_swap_UST is stored in
1006 * dPriv->swap_ust. interval has already been calculated.
1008 * The only tricky part is us_per_refresh. us_per_refresh is
1009 * 1000000 / MSC_rate. We know the MSC_rate is n / d. We can flip it
1010 * around and say us_per_refresh = 1000000 * d / n. Since this goes in
1011 * the denominator of the final calculation, we calculate
1012 * (interval * 1000000 * d) and move n into the numerator.
1015 usage
= (current_ust
- last_swap_ust
);
1017 usage
/= (interval
* d
);
1025 dri2InvalidateDrawable(__DRIdrawable
*drawable
)
1027 drawable
->dri2
.stamp
++;