dri_util.c revision aceccda56b08338e217991e54607f1c9f18fc3e6
1/* $XFree86: xc/lib/GL/dri/dri_util.c,v 1.7 2003/04/28 17:01:25 dawes Exp $ */
2/**
3 * \file dri_util.c
4 * DRI utility functions.
5 *
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
9 * drivers.
10 *
11 * Basically, these utility functions take care of some of the dirty details of
12 * screen initialization, context creation, context binding, DRM setup, etc.
13 *
14 * These functions are compiled into each DRI driver so libGL.so knows nothing
15 * about them.
16 */
17
18
19#include <assert.h>
20#include <stdarg.h>
21#include <unistd.h>
22#include <sys/mman.h>
23#include <stdio.h>
24
25#ifndef MAP_FAILED
26#define MAP_FAILED ((void *)-1)
27#endif
28
29#include "imports.h"
30#define None 0
31
32#include "dri_util.h"
33#include "drm_sarea.h"
34
35#ifndef GLX_OML_sync_control
36typedef GLboolean ( * PFNGLXGETMSCRATEOMLPROC) (__DRIdrawable *drawable, int32_t *numerator, int32_t *denominator);
37#endif
38
39/* This pointer *must* be set by the driver's __driCreateNewScreen funciton!
40 */
41const __DRIinterfaceMethods * dri_interface = NULL;
42
43/**
44 * This is used in a couple of places that call \c driCreateNewDrawable.
45 */
46static const int empty_attribute_list[1] = { None };
47
48
49/**
50 * Cached copy of the internal API version used by libGL and the client-side
51 * DRI driver.
52 */
53static int api_ver = 0;
54
55/* forward declarations */
56static int driQueryFrameTracking( void *priv,
57                                  int64_t *sbc, int64_t *missedFrames,
58                                  float *lastMissedUsage, float *usage );
59
60static void *driCreateNewDrawable(__DRIscreen *screen,
61				  const __GLcontextModes *modes,
62                                  __DRIid draw, __DRIdrawable *pdraw,
63                                  int renderType, const int *attrs);
64
65static void driDestroyDrawable(void *drawablePrivate);
66
67
68/**
69 * Print message to \c stderr if the \c LIBGL_DEBUG environment variable
70 * is set.
71 *
72 * Is called from the drivers.
73 *
74 * \param f \c printf like format string.
75 */
76void
77__driUtilMessage(const char *f, ...)
78{
79    va_list args;
80
81    if (getenv("LIBGL_DEBUG")) {
82        fprintf(stderr, "libGL error: \n");
83        va_start(args, f);
84        vfprintf(stderr, f, args);
85        va_end(args);
86        fprintf(stderr, "\n");
87    }
88}
89
90
91/*****************************************************************/
92/** \name Context (un)binding functions                          */
93/*****************************************************************/
94/*@{*/
95
96/**
97 * Unbind context.
98 *
99 * \param scrn the screen.
100 * \param gc context.
101 *
102 * \return \c GL_TRUE on success, or \c GL_FALSE on failure.
103 *
104 * \internal
105 * This function calls __DriverAPIRec::UnbindContext, and then decrements
106 * __DRIdrawablePrivateRec::refcount which must be non-zero for a successful
107 * return.
108 *
109 * While casting the opaque private pointers associated with the parameters
110 * into their respective real types it also assures they are not \c NULL.
111 */
112static GLboolean driUnbindContext(__DRIcontext *ctx)
113{
114    __DRIcontextPrivate *pcp;
115    __DRIscreenPrivate *psp;
116    __DRIdrawablePrivate *pdp;
117    __DRIdrawablePrivate *prp;
118
119    /*
120    ** Assume error checking is done properly in glXMakeCurrent before
121    ** calling driUnbindContext.
122    */
123
124    if (ctx == NULL)
125        return GL_FALSE;
126
127    pcp = (__DRIcontextPrivate *)ctx->private;
128    psp = (__DRIscreenPrivate *)pcp->driScreenPriv;
129    pdp = (__DRIdrawablePrivate *)pcp->driDrawablePriv;
130    prp = (__DRIdrawablePrivate *)pcp->driReadablePriv;
131
132    /* Let driver unbind drawable from context */
133    (*psp->DriverAPI.UnbindContext)(pcp);
134
135    if (pdp->refcount == 0) {
136	/* ERROR!!! */
137	return GL_FALSE;
138    }
139
140    pdp->refcount--;
141
142    if (prp != pdp) {
143        if (prp->refcount == 0) {
144	    /* ERROR!!! */
145	    return GL_FALSE;
146	}
147
148	prp->refcount--;
149    }
150
151
152    /* XXX this is disabled so that if we call SwapBuffers on an unbound
153     * window we can determine the last context bound to the window and
154     * use that context's lock. (BrianP, 2-Dec-2000)
155     */
156#if 0
157    /* Unbind the drawable */
158    pcp->driDrawablePriv = NULL;
159    pdp->driContextPriv = &psp->dummyContextPriv;
160#endif
161
162    return GL_TRUE;
163}
164
165
166/**
167 * This function takes both a read buffer and a draw buffer.  This is needed
168 * for \c glXMakeCurrentReadSGI or GLX 1.3's \c glXMakeContextCurrent
169 * function.
170 */
171static GLboolean DoBindContext(__DRIdrawable *pdraw,
172			       __DRIdrawable *pread,
173			       __DRIcontext *ctx)
174{
175    __DRIdrawablePrivate *pdp;
176    __DRIdrawablePrivate *prp;
177    __DRIcontextPrivate * const pcp = ctx->private;
178    __DRIscreenPrivate *psp = pcp->driScreenPriv;
179
180    pdp = (__DRIdrawablePrivate *) pdraw->private;
181    prp = (__DRIdrawablePrivate *) pread->private;
182
183    /* Bind the drawable to the context */
184    pcp->driDrawablePriv = pdp;
185    pcp->driReadablePriv = prp;
186    pdp->driContextPriv = pcp;
187    pdp->refcount++;
188    if ( pdp != prp ) {
189	prp->refcount++;
190    }
191
192    /*
193    ** Now that we have a context associated with this drawable, we can
194    ** initialize the drawable information if has not been done before.
195    */
196    if (!pdp->pStamp || *pdp->pStamp != pdp->lastStamp) {
197	DRM_SPINLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID);
198	__driUtilUpdateDrawableInfo(pdp);
199	DRM_SPINUNLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID);
200    }
201
202    if ((pdp != prp) && (!prp->pStamp || *prp->pStamp != prp->lastStamp)) {
203	DRM_SPINLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID);
204	__driUtilUpdateDrawableInfo(prp);
205	DRM_SPINUNLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID);
206    }
207
208    /* Call device-specific MakeCurrent */
209    (*psp->DriverAPI.MakeCurrent)(pcp, pdp, prp);
210
211    return GL_TRUE;
212}
213
214
215/**
216 * This function takes both a read buffer and a draw buffer.  This is needed
217 * for \c glXMakeCurrentReadSGI or GLX 1.3's \c glXMakeContextCurrent
218 * function.
219 */
220static GLboolean driBindContext(__DRIdrawable *pdraw,
221				__DRIdrawable *pread,
222				__DRIcontext * ctx)
223{
224    /*
225    ** Assume error checking is done properly in glXMakeCurrent before
226    ** calling driBindContext.
227    */
228
229    if (ctx == NULL || pdraw == None || pread == None)
230	return GL_FALSE;
231
232    return DoBindContext( pdraw, pread, ctx );
233}
234/*@}*/
235
236
237/*****************************************************************/
238/** \name Drawable handling functions                            */
239/*****************************************************************/
240/*@{*/
241
242/**
243 * Update private drawable information.
244 *
245 * \param pdp pointer to the private drawable information to update.
246 *
247 * This function basically updates the __DRIdrawablePrivate struct's
248 * cliprect information by calling \c __DRIinterfaceMethods::getDrawableInfo.
249 * This is usually called by the DRI_VALIDATE_DRAWABLE_INFO macro which
250 * compares the __DRIdrwablePrivate pStamp and lastStamp values.  If
251 * the values are different that means we have to update the clipping
252 * info.
253 */
254void
255__driUtilUpdateDrawableInfo(__DRIdrawablePrivate *pdp)
256{
257    __DRIscreenPrivate *psp;
258    __DRIcontextPrivate *pcp = pdp->driContextPriv;
259
260    if (!pcp
261	|| ((pdp != pcp->driDrawablePriv) && (pdp != pcp->driReadablePriv))) {
262	/* ERROR!!!
263	 * ...but we must ignore it. There can be many contexts bound to a
264	 * drawable.
265	 */
266    }
267
268    psp = pdp->driScreenPriv;
269    if (!psp) {
270	/* ERROR!!! */
271       _mesa_problem(NULL, "Warning! Possible infinite loop due to bug "
272		     "in file %s, line %d\n",
273		     __FILE__, __LINE__);
274	return;
275    }
276
277    if (pdp->pClipRects) {
278	_mesa_free(pdp->pClipRects);
279	pdp->pClipRects = NULL;
280    }
281
282    if (pdp->pBackClipRects) {
283	_mesa_free(pdp->pBackClipRects);
284	pdp->pBackClipRects = NULL;
285    }
286
287    DRM_SPINUNLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID);
288
289    if (! (*dri_interface->getDrawableInfo)(pdp->driScreenPriv->psc, pdp->draw,
290			  &pdp->index, &pdp->lastStamp,
291			  &pdp->x, &pdp->y, &pdp->w, &pdp->h,
292			  &pdp->numClipRects, &pdp->pClipRects,
293			  &pdp->backX,
294			  &pdp->backY,
295			  &pdp->numBackClipRects,
296			  &pdp->pBackClipRects )) {
297	/* Error -- eg the window may have been destroyed.  Keep going
298	 * with no cliprects.
299	 */
300        pdp->pStamp = &pdp->lastStamp; /* prevent endless loop */
301	pdp->numClipRects = 0;
302	pdp->pClipRects = NULL;
303	pdp->numBackClipRects = 0;
304	pdp->pBackClipRects = NULL;
305    }
306    else
307       pdp->pStamp = &(psp->pSAREA->drawableTable[pdp->index].stamp);
308
309    DRM_SPINLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID);
310
311}
312
313/*@}*/
314
315/*****************************************************************/
316/** \name GLX callbacks                                          */
317/*****************************************************************/
318/*@{*/
319
320/**
321 * Swap buffers.
322 *
323 * \param drawablePrivate opaque pointer to the per-drawable private info.
324 *
325 * \internal
326 * This function calls __DRIdrawablePrivate::swapBuffers.
327 *
328 * Is called directly from glXSwapBuffers().
329 */
330static void driSwapBuffers(void *drawablePrivate)
331{
332    __DRIdrawablePrivate *dPriv = (__DRIdrawablePrivate *) drawablePrivate;
333    drm_clip_rect_t rect;
334
335    dPriv->swapBuffers(dPriv);
336
337    /* Check that we actually have the new damage report method */
338    if (api_ver < 20070105 || dri_interface->reportDamage == NULL)
339	return;
340
341    /* Assume it's affecting the whole drawable for now */
342    rect.x1 = 0;
343    rect.y1 = 0;
344    rect.x2 = rect.x1 + dPriv->w;
345    rect.y2 = rect.y1 + dPriv->h;
346
347    /* Report the damage.  Currently, all our drivers draw directly to the
348     * front buffer, so we report the damage there rather than to the backing
349     * store (if any).
350     */
351    (*dri_interface->reportDamage)(dPriv->pdraw, dPriv->x, dPriv->y,
352				   &rect, 1, GL_TRUE);
353}
354
355/**
356 * Called directly from a number of higher-level GLX functions.
357 */
358static int driGetMSC( void *screenPrivate, int64_t *msc )
359{
360    __DRIscreenPrivate *sPriv = (__DRIscreenPrivate *) screenPrivate;
361
362    return sPriv->DriverAPI.GetMSC( sPriv, msc );
363}
364
365/**
366 * Called directly from a number of higher-level GLX functions.
367 */
368static int driGetSBC( void *drawablePrivate, int64_t *sbc )
369{
370   __DRIdrawablePrivate *dPriv = (__DRIdrawablePrivate *) drawablePrivate;
371   __DRIswapInfo  sInfo;
372   int  status;
373
374
375   status = dPriv->driScreenPriv->DriverAPI.GetSwapInfo( dPriv, & sInfo );
376   *sbc = sInfo.swap_count;
377
378   return status;
379}
380
381static int driWaitForSBC( void *drawablePriv, int64_t target_sbc,
382			  int64_t * msc, int64_t * sbc )
383{
384    __DRIdrawablePrivate *dPriv = (__DRIdrawablePrivate *) drawablePriv;
385
386    return dPriv->driScreenPriv->DriverAPI.WaitForSBC( dPriv, target_sbc,
387                                                       msc, sbc );
388}
389
390static int driWaitForMSC( void *drawablePriv, int64_t target_msc,
391			  int64_t divisor, int64_t remainder,
392			  int64_t * msc, int64_t * sbc )
393{
394    __DRIdrawablePrivate *dPriv = (__DRIdrawablePrivate *) drawablePriv;
395    __DRIswapInfo  sInfo;
396    int  status;
397
398
399    status = dPriv->driScreenPriv->DriverAPI.WaitForMSC( dPriv, target_msc,
400                                                         divisor, remainder,
401                                                         msc );
402
403    /* GetSwapInfo() may not be provided by the driver if GLX_SGI_video_sync
404     * is supported but GLX_OML_sync_control is not.  Therefore, don't return
405     * an error value if GetSwapInfo() is not implemented.
406    */
407    if ( status == 0
408         && dPriv->driScreenPriv->DriverAPI.GetSwapInfo ) {
409        status = dPriv->driScreenPriv->DriverAPI.GetSwapInfo( dPriv, & sInfo );
410        *sbc = sInfo.swap_count;
411    }
412
413    return status;
414}
415
416static int64_t driSwapBuffersMSC( void *drawablePriv, int64_t target_msc,
417				  int64_t divisor, int64_t remainder )
418{
419    __DRIdrawablePrivate *dPriv = (__DRIdrawablePrivate *) drawablePriv;
420
421    return dPriv->driScreenPriv->DriverAPI.SwapBuffersMSC( dPriv, target_msc,
422                                                           divisor,
423                                                           remainder );
424}
425
426static void driCopySubBuffer( void *drawablePrivate,
427			      int x, int y, int w, int h)
428{
429    __DRIdrawablePrivate *dPriv = (__DRIdrawablePrivate *) drawablePrivate;
430    dPriv->driScreenPriv->DriverAPI.CopySubBuffer(dPriv, x, y, w, h);
431}
432
433/**
434 * This is called via __DRIscreenRec's createNewDrawable pointer.
435 */
436static void *driCreateNewDrawable(__DRIscreen *screen,
437				  const __GLcontextModes *modes,
438				  __DRIid draw,
439				  __DRIdrawable *pdraw,
440				  int renderType,
441				  const int *attrs)
442{
443    __DRIscreenPrivate *psp;
444    __DRIdrawablePrivate *pdp;
445
446
447    pdraw->private = NULL;
448
449    /* Since pbuffers are not yet supported, no drawable attributes are
450     * supported either.
451     */
452    (void) attrs;
453
454    pdp = (__DRIdrawablePrivate *)_mesa_malloc(sizeof(__DRIdrawablePrivate));
455    if (!pdp) {
456	return NULL;
457    }
458
459    /* Ensure that modes->screen and screen are the same screen? */
460
461    if (!(*dri_interface->createDrawable)(screen, draw, &pdp->hHWDrawable)) {
462	_mesa_free(pdp);
463	return NULL;
464    }
465
466    pdp->draw = draw;
467    pdp->pdraw = pdraw;
468    pdp->refcount = 0;
469    pdp->pStamp = NULL;
470    pdp->lastStamp = 0;
471    pdp->index = 0;
472    pdp->x = 0;
473    pdp->y = 0;
474    pdp->w = 0;
475    pdp->h = 0;
476    pdp->numClipRects = 0;
477    pdp->numBackClipRects = 0;
478    pdp->pClipRects = NULL;
479    pdp->pBackClipRects = NULL;
480
481    psp = (__DRIscreenPrivate *)screen->private;
482    pdp->driScreenPriv = psp;
483    pdp->driContextPriv = &psp->dummyContextPriv;
484
485    if (!(*psp->DriverAPI.CreateBuffer)(psp, pdp, modes,
486					renderType == GLX_PIXMAP_BIT)) {
487       (void)(*dri_interface->destroyDrawable)(screen, pdp->draw);
488       _mesa_free(pdp);
489       return NULL;
490    }
491
492    pdraw->private = pdp;
493    pdraw->destroyDrawable = driDestroyDrawable;
494    pdraw->swapBuffers = driSwapBuffers;  /* called by glXSwapBuffers() */
495
496    pdraw->getSBC = driGetSBC;
497    pdraw->waitForSBC = driWaitForSBC;
498    pdraw->waitForMSC = driWaitForMSC;
499    pdraw->swapBuffersMSC = driSwapBuffersMSC;
500    pdraw->frameTracking = NULL;
501    pdraw->queryFrameTracking = driQueryFrameTracking;
502
503    if (driCompareGLXAPIVersion (20060314) >= 0)
504	pdraw->copySubBuffer = driCopySubBuffer;
505
506    /* This special default value is replaced with the configured
507     * default value when the drawable is first bound to a direct
508     * rendering context.
509     */
510    pdraw->swap_interval = (unsigned)-1;
511
512    pdp->swapBuffers = psp->DriverAPI.SwapBuffers;
513
514   return (void *) pdp;
515}
516
517static void
518driDestroyDrawable(void *drawablePrivate)
519{
520    __DRIdrawablePrivate *pdp = (__DRIdrawablePrivate *) drawablePrivate;
521    __DRIscreenPrivate *psp;
522
523    if (pdp) {
524	psp = pdp->driScreenPriv;
525        (*psp->DriverAPI.DestroyBuffer)(pdp);
526	(void)(*dri_interface->destroyDrawable)(psp->psc, pdp->draw);
527	if (pdp->pClipRects) {
528	    _mesa_free(pdp->pClipRects);
529	    pdp->pClipRects = NULL;
530	}
531	if (pdp->pBackClipRects) {
532	    _mesa_free(pdp->pBackClipRects);
533	    pdp->pBackClipRects = NULL;
534	}
535	_mesa_free(pdp);
536    }
537}
538
539/*@}*/
540
541
542/*****************************************************************/
543/** \name Context handling functions                             */
544/*****************************************************************/
545/*@{*/
546
547/**
548 * Destroy the per-context private information.
549 *
550 * \param contextPrivate opaque pointer to the per-drawable private info.
551 *
552 * \internal
553 * This function calls __DriverAPIRec::DestroyContext on \p contextPrivate, calls
554 * drmDestroyContext(), and finally frees \p contextPrivate.
555 */
556static void
557driDestroyContext(void *contextPrivate)
558{
559    __DRIcontextPrivate  *pcp   = (__DRIcontextPrivate *) contextPrivate;
560
561    if (pcp) {
562	(*pcp->driScreenPriv->DriverAPI.DestroyContext)(pcp);
563	(void) (*dri_interface->destroyContext)(pcp->driScreenPriv->psc,
564						pcp->contextID);
565	_mesa_free(pcp);
566    }
567}
568
569
570/**
571 * Create the per-drawable private driver information.
572 *
573 * \param dpy           The display handle.
574 * \param modes         Mode used to create the new context.
575 * \param render_type   Type of rendering target.  \c GLX_RGBA is the only
576 *                      type likely to ever be supported for direct-rendering.
577 * \param sharedPrivate The shared context dependent methods or \c NULL if
578 *                      non-existent.
579 * \param pctx          DRI context to receive the context dependent methods.
580 *
581 * \returns An opaque pointer to the per-context private information on
582 *          success, or \c NULL on failure.
583 *
584 * \internal
585 * This function allocates and fills a __DRIcontextPrivateRec structure.  It
586 * performs some device independent initialization and passes all the
587 * relevent information to __DriverAPIRec::CreateContext to create the
588 * context.
589 *
590 */
591static void *
592driCreateNewContext(__DRIscreen *screen, const __GLcontextModes *modes,
593		    int render_type, void *sharedPrivate, __DRIcontext *pctx)
594{
595    __DRIcontextPrivate *pcp;
596    __DRIcontextPrivate *pshare = (__DRIcontextPrivate *) sharedPrivate;
597    __DRIscreenPrivate *psp;
598    void * const shareCtx = (pshare != NULL) ? pshare->driverPrivate : NULL;
599
600    psp = (__DRIscreenPrivate *)screen->private;
601
602    pcp = (__DRIcontextPrivate *)_mesa_malloc(sizeof(__DRIcontextPrivate));
603    if (!pcp) {
604	return NULL;
605    }
606
607    if (! (*dri_interface->createContext)(screen, modes->fbconfigID,
608					  &pcp->contextID, &pcp->hHWContext)) {
609	_mesa_free(pcp);
610	return NULL;
611    }
612
613    pcp->driScreenPriv = psp;
614    pcp->driDrawablePriv = NULL;
615
616    /* When the first context is created for a screen, initialize a "dummy"
617     * context.
618     */
619
620    if (!psp->dummyContextPriv.driScreenPriv) {
621        psp->dummyContextPriv.contextID = 0;
622        psp->dummyContextPriv.hHWContext = psp->pSAREA->dummy_context;
623        psp->dummyContextPriv.driScreenPriv = psp;
624        psp->dummyContextPriv.driDrawablePriv = NULL;
625        psp->dummyContextPriv.driverPrivate = NULL;
626	/* No other fields should be used! */
627    }
628
629    pctx->destroyContext = driDestroyContext;
630    pctx->bindContext    = driBindContext;
631    pctx->unbindContext  = driUnbindContext;
632
633    if ( !(*psp->DriverAPI.CreateContext)(modes, pcp, shareCtx) ) {
634        (void) (*dri_interface->destroyContext)(screen, pcp->contextID);
635        _mesa_free(pcp);
636        return NULL;
637    }
638
639    return pcp;
640}
641/*@}*/
642
643
644/*****************************************************************/
645/** \name Screen handling functions                              */
646/*****************************************************************/
647/*@{*/
648
649/**
650 * Destroy the per-screen private information.
651 *
652 * \param dpy the display handle.
653 * \param scrn the screen number.
654 * \param screenPrivate opaque pointer to the per-screen private information.
655 *
656 * \internal
657 * This function calls __DriverAPIRec::DestroyScreen on \p screenPrivate, calls
658 * drmClose(), and finally frees \p screenPrivate.
659 */
660static void driDestroyScreen(void *screenPrivate)
661{
662    __DRIscreenPrivate *psp = (__DRIscreenPrivate *) screenPrivate;
663
664    if (psp) {
665	/* No interaction with the X-server is possible at this point.  This
666	 * routine is called after XCloseDisplay, so there is no protocol
667	 * stream open to the X-server anymore.
668	 */
669
670	if (psp->DriverAPI.DestroyScreen)
671	    (*psp->DriverAPI.DestroyScreen)(psp);
672
673	(void)drmUnmap((drmAddress)psp->pSAREA, SAREA_MAX);
674	(void)drmUnmap((drmAddress)psp->pFB, psp->fbSize);
675	(void)drmCloseOnce(psp->fd);
676	if ( psp->modes != NULL ) {
677	    (*dri_interface->destroyContextModes)( psp->modes );
678	}
679
680	_mesa_free(psp);
681    }
682}
683
684
685/**
686 * Utility function used to create a new driver-private screen structure.
687 *
688 * \param dpy   Display pointer
689 * \param scrn  Index of the screen
690 * \param psc   DRI screen data (not driver private)
691 * \param modes Linked list of known display modes.  This list is, at a
692 *              minimum, a list of modes based on the current display mode.
693 *              These roughly match the set of available X11 visuals, but it
694 *              need not be limited to X11!  The calling libGL should create
695 *              a list that will inform the driver of the current display
696 *              mode (i.e., color buffer depth, depth buffer depth, etc.).
697 * \param ddx_version Version of the 2D DDX.  This may not be meaningful for
698 *                    all drivers.
699 * \param dri_version Version of the "server-side" DRI.
700 * \param drm_version Version of the kernel DRM.
701 * \param frame_buffer Data describing the location and layout of the
702 *                     framebuffer.
703 * \param pSAREA       Pointer the the SAREA.
704 * \param fd           Device handle for the DRM.
705 * \param internal_api_version  Version of the internal interface between the
706 *                              driver and libGL.
707 * \param driverAPI Driver API functions used by other routines in dri_util.c.
708 *
709 * \note
710 * There is no need to check the minimum API version in this function.  Since
711 * the \c __driCreateNewScreen function is versioned, it is impossible for a
712 * loader that is too old to even load this driver.
713 */
714__DRIscreenPrivate *
715__driUtilCreateNewScreen(int scr, __DRIscreen *psc,
716			 __GLcontextModes * modes,
717			 const __DRIversion * ddx_version,
718			 const __DRIversion * dri_version,
719			 const __DRIversion * drm_version,
720			 const __DRIframebuffer * frame_buffer,
721			 drm_sarea_t *pSAREA,
722			 int fd,
723			 int internal_api_version,
724			 const struct __DriverAPIRec *driverAPI)
725{
726    __DRIscreenPrivate *psp;
727
728
729    api_ver = internal_api_version;
730
731    psp = (__DRIscreenPrivate *)_mesa_malloc(sizeof(__DRIscreenPrivate));
732    if (!psp) {
733	return NULL;
734    }
735
736    psp->psc = psc;
737    psp->modes = modes;
738
739    /*
740    ** NOT_DONE: This is used by the X server to detect when the client
741    ** has died while holding the drawable lock.  The client sets the
742    ** drawable lock to this value.
743    */
744    psp->drawLockID = 1;
745
746    psp->drmMajor = drm_version->major;
747    psp->drmMinor = drm_version->minor;
748    psp->drmPatch = drm_version->patch;
749    psp->ddxMajor = ddx_version->major;
750    psp->ddxMinor = ddx_version->minor;
751    psp->ddxPatch = ddx_version->patch;
752    psp->driMajor = dri_version->major;
753    psp->driMinor = dri_version->minor;
754    psp->driPatch = dri_version->patch;
755
756    /* install driver's callback functions */
757    memcpy( &psp->DriverAPI, driverAPI, sizeof(struct __DriverAPIRec) );
758
759    psp->pSAREA = pSAREA;
760
761    psp->pFB = frame_buffer->base;
762    psp->fbSize = frame_buffer->size;
763    psp->fbStride = frame_buffer->stride;
764    psp->fbWidth = frame_buffer->width;
765    psp->fbHeight = frame_buffer->height;
766    psp->devPrivSize = frame_buffer->dev_priv_size;
767    psp->pDevPriv = frame_buffer->dev_priv;
768    psp->fbBPP = psp->fbStride * 8 / frame_buffer->width;
769
770    psp->fd = fd;
771    psp->myNum = scr;
772
773    /*
774    ** Do not init dummy context here; actual initialization will be
775    ** done when the first DRI context is created.  Init screen priv ptr
776    ** to NULL to let CreateContext routine that it needs to be inited.
777    */
778    psp->dummyContextPriv.driScreenPriv = NULL;
779
780    psc->destroyScreen     = driDestroyScreen;
781    psc->createNewDrawable = driCreateNewDrawable;
782    psc->getMSC            = driGetMSC;
783    psc->createNewContext  = driCreateNewContext;
784
785    if (internal_api_version >= 20070121)
786	psc->setTexOffset  = psp->DriverAPI.setTexOffset;
787
788    if ( (psp->DriverAPI.InitDriver != NULL)
789	 && !(*psp->DriverAPI.InitDriver)(psp) ) {
790	_mesa_free( psp );
791	return NULL;
792    }
793
794
795    return psp;
796}
797
798
799/**
800 * Compare the current GLX API version with a driver supplied required version.
801 *
802 * The minimum required version is compared with the API version exported by
803 * the \c __glXGetInternalVersion function (in libGL.so).
804 *
805 * \param   required_version Minimum required internal GLX API version.
806 * \return  A tri-value return, as from strcmp is returned.  A value less
807 *          than, equal to, or greater than zero will be returned if the
808 *          internal GLX API version is less than, equal to, or greater
809 *          than \c required_version.
810 *
811 * \sa __glXGetInternalVersion().
812 */
813int driCompareGLXAPIVersion( GLint required_version )
814{
815   if ( api_ver > required_version ) {
816      return 1;
817   }
818   else if ( api_ver == required_version ) {
819      return 0;
820   }
821
822   return -1;
823}
824
825
826static int
827driQueryFrameTracking( void * priv,
828		       int64_t * sbc, int64_t * missedFrames,
829		       float * lastMissedUsage, float * usage )
830{
831   __DRIswapInfo   sInfo;
832   int             status;
833   int64_t         ust;
834   __DRIdrawablePrivate * dpriv = (__DRIdrawablePrivate *) priv;
835
836
837   status = dpriv->driScreenPriv->DriverAPI.GetSwapInfo( dpriv, & sInfo );
838   if ( status == 0 ) {
839      *sbc = sInfo.swap_count;
840      *missedFrames = sInfo.swap_missed_count;
841      *lastMissedUsage = sInfo.swap_missed_usage;
842
843      (*dri_interface->getUST)( & ust );
844      *usage = driCalculateSwapUsage( dpriv, sInfo.swap_ust, ust );
845   }
846
847   return status;
848}
849
850
851/**
852 * Calculate amount of swap interval used between GLX buffer swaps.
853 *
854 * The usage value, on the range [0,max], is the fraction of total swap
855 * interval time used between GLX buffer swaps is calculated.
856 *
857 *            \f$p = t_d / (i * t_r)\f$
858 *
859 * Where \f$t_d\f$ is the time since the last GLX buffer swap, \f$i\f$ is the
860 * swap interval (as set by \c glXSwapIntervalSGI), and \f$t_r\f$ time
861 * required for a single vertical refresh period (as returned by \c
862 * glXGetMscRateOML).
863 *
864 * See the documentation for the GLX_MESA_swap_frame_usage extension for more
865 * details.
866 *
867 * \param   dPriv  Pointer to the private drawable structure.
868 * \return  If less than a single swap interval time period was required
869 *          between GLX buffer swaps, a number greater than 0 and less than
870 *          1.0 is returned.  If exactly one swap interval time period is
871 *          required, 1.0 is returned, and if more than one is required then
872 *          a number greater than 1.0 will be returned.
873 *
874 * \sa glXSwapIntervalSGI glXGetMscRateOML
875 *
876 * \todo Instead of caching the \c glXGetMscRateOML function pointer, would it
877 *       be possible to cache the sync rate?
878 */
879float
880driCalculateSwapUsage( __DRIdrawablePrivate *dPriv, int64_t last_swap_ust,
881		       int64_t current_ust )
882{
883   int32_t   n;
884   int32_t   d;
885   int       interval;
886   float     usage = 1.0;
887
888
889   if ( (*dri_interface->getMSCRate)(dPriv->pdraw, &n, &d) ) {
890      interval = (dPriv->pdraw->swap_interval != 0)
891	  ? dPriv->pdraw->swap_interval : 1;
892
893
894      /* We want to calculate
895       * (current_UST - last_swap_UST) / (interval * us_per_refresh).  We get
896       * current_UST by calling __glXGetUST.  last_swap_UST is stored in
897       * dPriv->swap_ust.  interval has already been calculated.
898       *
899       * The only tricky part is us_per_refresh.  us_per_refresh is
900       * 1000000 / MSC_rate.  We know the MSC_rate is n / d.  We can flip it
901       * around and say us_per_refresh = 1000000 * d / n.  Since this goes in
902       * the denominator of the final calculation, we calculate
903       * (interval * 1000000 * d) and move n into the numerator.
904       */
905
906      usage = (current_ust - last_swap_ust);
907      usage *= n;
908      usage /= (interval * d);
909      usage /= 1000000.0;
910   }
911
912   return usage;
913}
914
915/*@}*/
916