dri_util.c revision a249ad756f72835c5894e389150207b98532e114
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 * \note
18 * When \c DRI_NEW_INTERFACE_ONLY is defined, code is built / not built so
19 * that only the "new" libGL-to-driver interfaces are supported.  This breaks
20 * backwards compatability.  However, this may be necessary when DRI drivers
21 * are built to be used in non-XFree86 environments.
22 *
23 * \todo There are still some places in the code that need to be wrapped with
24 *       \c DRI_NEW_INTERFACE_ONLY.
25 */
26
27
28#ifdef GLX_DIRECT_RENDERING
29
30#include <inttypes.h>
31#include <assert.h>
32#include <stdarg.h>
33#include <unistd.h>
34#include <sys/mman.h>
35#include <X11/Xlibint.h>
36#include <Xext.h>
37#include <extutil.h>
38#include <stdio.h>
39#include "dri_util.h"
40#include "xf86dri.h"
41#include "sarea.h"
42#include "glcontextmodes.h"
43
44/*#define DRI_NEW_INTERFACE_ONLY*/
45
46#ifndef GLX_OML_sync_control
47typedef Bool ( * PFNGLXGETMSCRATEOMLPROC) (Display *dpy, GLXDrawable drawable, int32_t *numerator, int32_t *denominator);
48#endif
49
50/**
51 * This is used in a couple of places that call \c driCreateNewDrawable.
52 */
53static const int empty_attribute_list[1] = { None };
54
55/**
56 * Function used to determine if a drawable (window) still exists.  Ideally
57 * this function comes from libGL.  With older versions of libGL from XFree86
58 * we can fall-back to an internal version.
59 *
60 * \sa __driWindowExists __glXWindowExists
61 */
62static PFNGLXWINDOWEXISTSPROC window_exists;
63
64typedef Bool (*PFNGLXCREATECONTEXTWITHCONFIGPROC)( Display*, int, int, void *,
65    drmContextPtr );
66
67static PFNGLXCREATECONTEXTWITHCONFIGPROC create_context_with_config;
68
69/**
70 * Cached copy of the internal API version used by libGL and the client-side
71 * DRI driver.
72 */
73static int api_ver = 0;
74
75/* forward declarations */
76static int driQueryFrameTracking( Display * dpy, void * priv,
77    int64_t * sbc, int64_t * missedFrames, float * lastMissedUsage,
78    float * usage );
79
80static void *driCreateNewDrawable(Display *dpy, const __GLcontextModes *modes,
81    GLXDrawable draw, __DRIdrawable *pdraw, int renderType, const int *attrs);
82
83static void driDestroyDrawable(Display *dpy, void *drawablePrivate);
84
85
86
87
88#ifdef not_defined
89static Bool driFeatureOn(const char *name)
90{
91    char *env = getenv(name);
92
93    if (!env) return GL_FALSE;
94    if (!strcasecmp(env, "enable")) return GL_TRUE;
95    if (!strcasecmp(env, "1"))      return GL_TRUE;
96    if (!strcasecmp(env, "on"))     return GL_TRUE;
97    if (!strcasecmp(env, "true"))   return GL_TRUE;
98    if (!strcasecmp(env, "t"))      return GL_TRUE;
99    if (!strcasecmp(env, "yes"))    return GL_TRUE;
100    if (!strcasecmp(env, "y"))      return GL_TRUE;
101
102    return GL_FALSE;
103}
104#endif /* not_defined */
105
106
107/**
108 * Print message to \c stderr if the \c LIBGL_DEBUG environment variable
109 * is set.
110 *
111 * Is called from the drivers.
112 *
113 * \param f \c printf like format string.
114 */
115void
116__driUtilMessage(const char *f, ...)
117{
118    va_list args;
119
120    if (getenv("LIBGL_DEBUG")) {
121        fprintf(stderr, "libGL error: \n");
122        va_start(args, f);
123        vfprintf(stderr, f, args);
124        va_end(args);
125        fprintf(stderr, "\n");
126    }
127}
128
129
130/*****************************************************************/
131/** \name Visual utility functions                               */
132/*****************************************************************/
133/*@{*/
134
135#ifndef DRI_NEW_INTERFACE_ONLY
136/**
137 * Find a \c __GLcontextModes structure matching the given visual ID.
138 *
139 * \param dpy   Display to search for a matching configuration.
140 * \param scrn  Screen number on \c dpy to be searched.
141 * \param vid   Desired \c VisualID to find.
142 *
143 * \returns A pointer to a \c __GLcontextModes structure that matches \c vid,
144 *          if found, or \c NULL if no match is found.
145 */
146static const __GLcontextModes *
147findConfigMode(Display *dpy, int scrn, VisualID vid,
148	       const __DRIscreen * pDRIScreen)
149{
150    if ( (pDRIScreen != NULL) && (pDRIScreen->private != NULL) ) {
151	const __DRIscreenPrivate * const psp =
152	    (const __DRIscreenPrivate *) pDRIScreen->private;
153
154	return _gl_context_modes_find_visual( psp->modes, vid );
155    }
156
157    return NULL;
158}
159
160
161/**
162 * This function is a hack to work-around old versions of libGL.so that
163 * do not export \c XF86DRICreateContextWithConfig.  I would modify the
164 * code to just use this function, but the stand-alone driver (i.e., DRI
165 * drivers that are built to work without XFree86) shouldn't have to know
166 * about X structures like a \c Visual.
167 */
168static Bool
169fake_XF86DRICreateContextWithConfig( Display* dpy, int screen, int configID,
170				     XID* context, drmContextPtr hHWContext )
171{
172    Visual  vis;
173
174    vis.visualid = configID;
175    return XF86DRICreateContext( dpy, screen, & vis, context, hHWContext );
176}
177#endif /* DRI_NEW_INTERFACE_ONLY */
178
179/*@}*/
180
181
182/*****************************************************************/
183/** \name Drawable list management */
184/*****************************************************************/
185/*@{*/
186
187static Bool __driAddDrawable(void *drawHash, __DRIdrawable *pdraw)
188{
189    __DRIdrawablePrivate *pdp = (__DRIdrawablePrivate *)pdraw->private;
190
191    if (drmHashInsert(drawHash, pdp->draw, pdraw))
192	return GL_FALSE;
193
194    return GL_TRUE;
195}
196
197static __DRIdrawable *__driFindDrawable(void *drawHash, GLXDrawable draw)
198{
199    int retcode;
200    __DRIdrawable *pdraw;
201
202    retcode = drmHashLookup(drawHash, draw, (void **)&pdraw);
203    if (retcode)
204	return NULL;
205
206    return pdraw;
207}
208
209static void __driRemoveDrawable(void *drawHash, __DRIdrawable *pdraw)
210{
211    int retcode;
212    __DRIdrawablePrivate *pdp = (__DRIdrawablePrivate *)pdraw->private;
213
214    retcode = drmHashLookup(drawHash, pdp->draw, (void **)&pdraw);
215    if (!retcode) { /* Found */
216	drmHashDelete(drawHash, pdp->draw);
217    }
218}
219
220#ifndef DRI_NEW_INTERFACE_ONLY
221static Bool __driWindowExistsFlag;
222
223static int __driWindowExistsErrorHandler(Display *dpy, XErrorEvent *xerr)
224{
225    if (xerr->error_code == BadWindow) {
226	__driWindowExistsFlag = GL_FALSE;
227    }
228    return 0;
229}
230
231/**
232 * Determine if a window associated with a \c GLXDrawable exists on the
233 * X-server.
234 *
235 * \param dpy  Display associated with the drawable to be queried.
236 * \param draw \c GLXDrawable to test.
237 *
238 * \returns \c GL_TRUE if a window exists that is associated with \c draw,
239 *          otherwise \c GL_FALSE is returned.
240 *
241 * \warning This function is not currently thread-safe.
242 *
243 * \deprecated
244 * \c __glXWindowExists (from libGL) is prefered over this function.  Starting
245 * with the next major release of XFree86, this function will be removed.
246 * Even now this function is no longer directly called.  Instead it is called
247 * via a function pointer if and only if \c __glXWindowExists does not exist.
248 *
249 * \sa __glXWindowExists glXGetProcAddress window_exists
250 */
251static Bool __driWindowExists(Display *dpy, GLXDrawable draw)
252{
253    XWindowAttributes xwa;
254    int (*oldXErrorHandler)(Display *, XErrorEvent *);
255
256    XSync(dpy, GL_FALSE);
257    __driWindowExistsFlag = GL_TRUE;
258    oldXErrorHandler = XSetErrorHandler(__driWindowExistsErrorHandler);
259    XGetWindowAttributes(dpy, draw, &xwa); /* dummy request */
260    XSetErrorHandler(oldXErrorHandler);
261    return __driWindowExistsFlag;
262}
263#endif /* DRI_NEW_INTERFACE_ONLY */
264
265/**
266 * Find drawables in the local hash that have been destroyed on the
267 * server.
268 *
269 * \param drawHash  Hash-table containing all know drawables.
270 */
271static void __driGarbageCollectDrawables(void *drawHash)
272{
273    GLXDrawable draw;
274    __DRIdrawable *pdraw;
275    Display *dpy;
276
277    if (drmHashFirst(drawHash, &draw, (void **)&pdraw)) {
278	do {
279	    __DRIdrawablePrivate *pdp = (__DRIdrawablePrivate *)pdraw->private;
280	    dpy = pdp->driScreenPriv->display;
281	    if (! (*window_exists)(dpy, draw)) {
282		/* Destroy the local drawable data in the hash table, if the
283		   drawable no longer exists in the Xserver */
284		__driRemoveDrawable(drawHash, pdraw);
285		(*pdraw->destroyDrawable)(dpy, pdraw->private);
286		Xfree(pdraw);
287	    }
288	} while (drmHashNext(drawHash, &draw, (void **)&pdraw));
289    }
290}
291
292/*@}*/
293
294
295/*****************************************************************/
296/** \name Context (un)binding functions                          */
297/*****************************************************************/
298/*@{*/
299
300/**
301 * Unbind context.
302 *
303 * \param dpy the display handle.
304 * \param scrn the screen number.
305 * \param draw drawable.
306 * \param read Current reading drawable.
307 * \param gc context.
308 *
309 * \return \c GL_TRUE on success, or \c GL_FALSE on failure.
310 *
311 * \internal
312 * This function calls __DriverAPIRec::UnbindContext, and then decrements
313 * __DRIdrawablePrivateRec::refcount which must be non-zero for a successful
314 * return.
315 *
316 * While casting the opaque private pointers associated with the parameters
317 * into their respective real types it also assures they are not \c NULL.
318 */
319static Bool driUnbindContext3(Display *dpy, int scrn,
320			      GLXDrawable draw, GLXDrawable read,
321			      __DRIcontext *ctx)
322{
323    __DRIscreen *pDRIScreen;
324    __DRIdrawable *pdraw;
325    __DRIdrawable *pread;
326    __DRIcontextPrivate *pcp;
327    __DRIscreenPrivate *psp;
328    __DRIdrawablePrivate *pdp;
329    __DRIdrawablePrivate *prp;
330
331    /*
332    ** Assume error checking is done properly in glXMakeCurrent before
333    ** calling driUnbindContext3.
334    */
335
336    if (ctx == NULL || draw == None || read == None) {
337	/* ERROR!!! */
338	return GL_FALSE;
339    }
340
341    pDRIScreen = __glXFindDRIScreen(dpy, scrn);
342    if ( (pDRIScreen == NULL) || (pDRIScreen->private == NULL) ) {
343	/* ERROR!!! */
344	return GL_FALSE;
345    }
346
347    psp = (__DRIscreenPrivate *)pDRIScreen->private;
348    pcp = (__DRIcontextPrivate *)ctx->private;
349
350    pdraw = __driFindDrawable(psp->drawHash, draw);
351    if (!pdraw) {
352	/* ERROR!!! */
353	return GL_FALSE;
354    }
355    pdp = (__DRIdrawablePrivate *)pdraw->private;
356
357    pread = __driFindDrawable(psp->drawHash, read);
358    if (!pread) {
359	/* ERROR!!! */
360	return GL_FALSE;
361    }
362    prp = (__DRIdrawablePrivate *)pread->private;
363
364
365    /* Let driver unbind drawable from context */
366    (*psp->DriverAPI.UnbindContext)(pcp);
367
368
369    if (pdp->refcount == 0) {
370	/* ERROR!!! */
371	return GL_FALSE;
372    }
373
374    pdp->refcount--;
375
376    if (prp != pdp) {
377        if (prp->refcount == 0) {
378	    /* ERROR!!! */
379	    return GL_FALSE;
380	}
381
382	prp->refcount--;
383    }
384
385
386    /* XXX this is disabled so that if we call SwapBuffers on an unbound
387     * window we can determine the last context bound to the window and
388     * use that context's lock. (BrianP, 2-Dec-2000)
389     */
390#if 0
391    /* Unbind the drawable */
392    pcp->driDrawablePriv = NULL;
393    pdp->driContextPriv = &psp->dummyContextPriv;
394#endif
395
396    return GL_TRUE;
397}
398
399
400/**
401 * This function takes both a read buffer and a draw buffer.  This is needed
402 * for \c glXMakeCurrentReadSGI or GLX 1.3's \c glXMakeContextCurrent
403 * function.
404 *
405 * \bug This function calls \c driCreateNewDrawable in two places with the
406 *      \c renderType hard-coded to \c GLX_WINDOW_BIT.  Some checking might
407 *      be needed in those places when support for pbuffers and / or pixmaps
408 *      is added.  Is it safe to assume that the drawable is a window?
409 */
410static Bool DoBindContext(Display *dpy,
411			  GLXDrawable draw, GLXDrawable read,
412			  __DRIcontext *ctx, const __GLcontextModes * modes,
413			  __DRIscreenPrivate *psp)
414{
415    __DRIdrawable *pdraw;
416    __DRIdrawablePrivate *pdp;
417    __DRIdrawable *pread;
418    __DRIdrawablePrivate *prp;
419    __DRIcontextPrivate * const pcp = ctx->private;
420
421
422    /* Find the _DRIdrawable which corresponds to the writing GLXDrawable */
423    pdraw = __driFindDrawable(psp->drawHash, draw);
424    if (!pdraw) {
425	/* Allocate a new drawable */
426	pdraw = (__DRIdrawable *)Xmalloc(sizeof(__DRIdrawable));
427	if (!pdraw) {
428	    /* ERROR!!! */
429	    return GL_FALSE;
430	}
431
432	/* Create a new drawable */
433	driCreateNewDrawable(dpy, modes, draw, pdraw, GLX_WINDOW_BIT,
434			     empty_attribute_list);
435	if (!pdraw->private) {
436	    /* ERROR!!! */
437	    Xfree(pdraw);
438	    return GL_FALSE;
439	}
440
441    }
442    pdp = (__DRIdrawablePrivate *) pdraw->private;
443
444    /* Find the _DRIdrawable which corresponds to the reading GLXDrawable */
445    if (read == draw) {
446        /* read buffer == draw buffer */
447        prp = pdp;
448    }
449    else {
450        pread = __driFindDrawable(psp->drawHash, read);
451        if (!pread) {
452            /* Allocate a new drawable */
453            pread = (__DRIdrawable *)Xmalloc(sizeof(__DRIdrawable));
454            if (!pread) {
455                /* ERROR!!! */
456                return GL_FALSE;
457            }
458
459            /* Create a new drawable */
460	    driCreateNewDrawable(dpy, modes, read, pread, GLX_WINDOW_BIT,
461				 empty_attribute_list);
462            if (!pread->private) {
463                /* ERROR!!! */
464                Xfree(pread);
465                return GL_FALSE;
466            }
467        }
468        prp = (__DRIdrawablePrivate *) pread->private;
469    }
470
471    /* Bind the drawable to the context */
472    pcp->driDrawablePriv = pdp;
473    pdp->driContextPriv = pcp;
474    pdp->refcount++;
475    if ( pdp != prp ) {
476	prp->refcount++;
477    }
478
479    /*
480    ** Now that we have a context associated with this drawable, we can
481    ** initialize the drawable information if has not been done before.
482    */
483    if (!pdp->pStamp || *pdp->pStamp != pdp->lastStamp) {
484	DRM_SPINLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID);
485	__driUtilUpdateDrawableInfo(pdp);
486	DRM_SPINUNLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID);
487    }
488
489    /* Call device-specific MakeCurrent */
490    (*psp->DriverAPI.MakeCurrent)(pcp, pdp, prp);
491
492    return GL_TRUE;
493}
494
495
496/**
497 * This function takes both a read buffer and a draw buffer.  This is needed
498 * for \c glXMakeCurrentReadSGI or GLX 1.3's \c glXMakeContextCurrent
499 * function.
500 */
501static Bool driBindContext3(Display *dpy, int scrn,
502                            GLXDrawable draw, GLXDrawable read,
503                            __DRIcontext * ctx)
504{
505    __DRIscreen *pDRIScreen;
506
507    /*
508    ** Assume error checking is done properly in glXMakeCurrent before
509    ** calling driBindContext.
510    */
511
512    if (ctx == NULL || draw == None || read == None) {
513	/* ERROR!!! */
514	return GL_FALSE;
515    }
516
517    pDRIScreen = __glXFindDRIScreen(dpy, scrn);
518    if ( (pDRIScreen == NULL) || (pDRIScreen->private == NULL) ) {
519	/* ERROR!!! */
520	return GL_FALSE;
521    }
522
523    return DoBindContext( dpy, draw, read, ctx, ctx->mode,
524			  (__DRIscreenPrivate *)pDRIScreen->private );
525}
526
527
528#ifndef DRI_NEW_INTERFACE_ONLY
529/**
530 * This function takes both a read buffer and a draw buffer.  This is needed
531 * for \c glXMakeCurrentReadSGI or GLX 1.3's \c glXMakeContextCurrent
532 * function.
533 */
534static Bool driBindContext2(Display *dpy, int scrn,
535                            GLXDrawable draw, GLXDrawable read,
536                            GLXContext gc)
537{
538    __DRIscreen *pDRIScreen;
539    const __GLcontextModes *modes;
540
541    /*
542    ** Assume error checking is done properly in glXMakeCurrent before
543    ** calling driBindContext.
544    */
545
546    if (gc == NULL || draw == None || read == None) {
547	/* ERROR!!! */
548	return GL_FALSE;
549    }
550
551    pDRIScreen = __glXFindDRIScreen(dpy, scrn);
552    modes = (driCompareGLXAPIVersion( 20040317 ) >= 0)
553	? gc->driContext.mode
554	: findConfigMode( dpy, scrn, gc->vid, pDRIScreen );
555
556    if ( modes == NULL ) {
557	/* ERROR!!! */
558	return GL_FALSE;
559    }
560
561    /* findConfigMode will return NULL if the DRI screen or screen private
562     * are NULL.
563     */
564    assert( (pDRIScreen != NULL) && (pDRIScreen->private != NULL) );
565
566    return DoBindContext( dpy, draw, read, & gc->driContext, modes,
567			  (__DRIscreenPrivate *)pDRIScreen->private );
568}
569
570static Bool driUnbindContext2(Display *dpy, int scrn,
571			      GLXDrawable draw, GLXDrawable read,
572			      GLXContext gc)
573{
574    return driUnbindContext3(dpy, scrn, draw, read, & gc->driContext);
575}
576
577/*
578 * Simply call bind with the same GLXDrawable for the read and draw buffers.
579 */
580static Bool driBindContext(Display *dpy, int scrn,
581                           GLXDrawable draw, GLXContext gc)
582{
583    return driBindContext2(dpy, scrn, draw, draw, gc);
584}
585
586
587/*
588 * Simply call bind with the same GLXDrawable for the read and draw buffers.
589 */
590static Bool driUnbindContext(Display *dpy, int scrn,
591                             GLXDrawable draw, GLXContext gc,
592                             int will_rebind)
593{
594   (void) will_rebind;
595   return driUnbindContext2( dpy, scrn, draw, draw, gc );
596}
597#endif /* DRI_NEW_INTERFACE_ONLY */
598
599/*@}*/
600
601
602/*****************************************************************/
603/** \name Drawable handling functions                            */
604/*****************************************************************/
605/*@{*/
606
607/**
608 * Update private drawable information.
609 *
610 * \param pdp pointer to the private drawable information to update.
611 *
612 * This function basically updates the __DRIdrawablePrivate struct's
613 * cliprect information by calling \c __DRIDrawablePrivate::getInfo.  This is
614 * usually called by the DRI_VALIDATE_DRAWABLE_INFO macro which
615 * compares the __DRIdrwablePrivate pStamp and lastStamp values.  If
616 * the values are different that means we have to update the clipping
617 * info.
618 */
619void
620__driUtilUpdateDrawableInfo(__DRIdrawablePrivate *pdp)
621{
622    __DRIscreenPrivate *psp;
623    __DRIcontextPrivate *pcp = pdp->driContextPriv;
624
625    if (!pcp || (pdp != pcp->driDrawablePriv)) {
626	/* ERROR!!! */
627	return;
628    }
629
630    psp = pdp->driScreenPriv;
631    if (!psp) {
632	/* ERROR!!! */
633	return;
634    }
635
636    if (pdp->pClipRects) {
637	Xfree(pdp->pClipRects);
638    }
639
640    if (pdp->pBackClipRects) {
641	Xfree(pdp->pBackClipRects);
642    }
643
644    DRM_SPINUNLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID);
645
646    if (!__driFindDrawable(psp->drawHash, pdp->draw) ||
647	! (*pdp->getInfo)(pdp->display, pdp->screen, pdp->draw,
648			  &pdp->index, &pdp->lastStamp,
649			  &pdp->x, &pdp->y, &pdp->w, &pdp->h,
650			  &pdp->numClipRects, &pdp->pClipRects,
651			  &pdp->backX,
652			  &pdp->backY,
653			  &pdp->numBackClipRects,
654			  &pdp->pBackClipRects )) {
655	/* Error -- eg the window may have been destroyed.  Keep going
656	 * with no cliprects.
657	 */
658        pdp->pStamp = &pdp->lastStamp; /* prevent endless loop */
659	pdp->numClipRects = 0;
660	pdp->pClipRects = NULL;
661	pdp->numBackClipRects = 0;
662	pdp->pBackClipRects = NULL;
663    }
664    else
665       pdp->pStamp = &(psp->pSAREA->drawableTable[pdp->index].stamp);
666
667    DRM_SPINLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID);
668
669}
670
671/*@}*/
672
673/*****************************************************************/
674/** \name GLX callbacks                                          */
675/*****************************************************************/
676/*@{*/
677
678/**
679 * Swap buffers.
680 *
681 * \param dpy the display handle.
682 * \param drawablePrivate opaque pointer to the per-drawable private info.
683 *
684 * \internal
685 * This function calls __DRIdrawablePrivate::swapBuffers.
686 *
687 * Is called directly from glXSwapBuffers().
688 */
689static void driSwapBuffers( Display *dpy, void *drawablePrivate )
690{
691    __DRIdrawablePrivate *dPriv = (__DRIdrawablePrivate *) drawablePrivate;
692    dPriv->swapBuffers(dPriv);
693    (void) dpy;
694}
695
696/**
697 * Called directly from a number of higher-level GLX functions.
698 */
699static int driGetMSC( void *screenPrivate, int64_t *msc )
700{
701    __DRIscreenPrivate *sPriv = (__DRIscreenPrivate *) screenPrivate;
702
703    return sPriv->DriverAPI.GetMSC( sPriv, msc );
704}
705
706/**
707 * Called directly from a number of higher-level GLX functions.
708 */
709static int driGetSBC( Display *dpy, void *drawablePrivate, int64_t *sbc )
710{
711   __DRIdrawablePrivate *dPriv = (__DRIdrawablePrivate *) drawablePrivate;
712   __DRIswapInfo  sInfo;
713   int  status;
714
715
716   status = dPriv->driScreenPriv->DriverAPI.GetSwapInfo( dPriv, & sInfo );
717   *sbc = sInfo.swap_count;
718
719   return status;
720}
721
722static int driWaitForSBC( Display * dpy, void *drawablePriv,
723			  int64_t target_sbc,
724			  int64_t * msc, int64_t * sbc )
725{
726    __DRIdrawablePrivate *dPriv = (__DRIdrawablePrivate *) drawablePriv;
727
728    return dPriv->driScreenPriv->DriverAPI.WaitForSBC( dPriv, target_sbc,
729                                                       msc, sbc );
730}
731
732static int driWaitForMSC( Display * dpy, void *drawablePriv,
733			  int64_t target_msc,
734			  int64_t divisor, int64_t remainder,
735			  int64_t * msc, int64_t * sbc )
736{
737    __DRIdrawablePrivate *dPriv = (__DRIdrawablePrivate *) drawablePriv;
738    __DRIswapInfo  sInfo;
739    int  status;
740
741
742    status = dPriv->driScreenPriv->DriverAPI.WaitForMSC( dPriv, target_msc,
743                                                         divisor, remainder,
744                                                         msc );
745
746    /* GetSwapInfo() may not be provided by the driver if GLX_SGI_video_sync
747     * is supported but GLX_OML_sync_control is not.  Therefore, don't return
748     * an error value if GetSwapInfo() is not implemented.
749    */
750    if ( status == 0
751         && dPriv->driScreenPriv->DriverAPI.GetSwapInfo ) {
752        status = dPriv->driScreenPriv->DriverAPI.GetSwapInfo( dPriv, & sInfo );
753        *sbc = sInfo.swap_count;
754    }
755
756    return status;
757}
758
759static int64_t driSwapBuffersMSC( Display * dpy, void *drawablePriv,
760				  int64_t target_msc,
761				  int64_t divisor, int64_t remainder )
762{
763    __DRIdrawablePrivate *dPriv = (__DRIdrawablePrivate *) drawablePriv;
764
765    return dPriv->driScreenPriv->DriverAPI.SwapBuffersMSC( dPriv, target_msc,
766                                                           divisor,
767                                                           remainder );
768}
769
770
771/**
772 * This is called via __DRIscreenRec's createNewDrawable pointer.
773 */
774static void *driCreateNewDrawable(Display *dpy,
775				  const __GLcontextModes *modes,
776				  GLXDrawable draw,
777				  __DRIdrawable *pdraw,
778				  int renderType,
779				  const int *attrs)
780{
781    __DRIscreen * const pDRIScreen = __glXFindDRIScreen(dpy, modes->screen);
782    __DRIscreenPrivate *psp;
783    __DRIdrawablePrivate *pdp;
784
785
786    /* Since pbuffers are not yet supported, no drawable attributes are
787     * supported either.
788     */
789    (void) attrs;
790
791    if ( (pDRIScreen == NULL) || (pDRIScreen->private == NULL) ) {
792	return NULL;
793    }
794
795    pdp = (__DRIdrawablePrivate *)Xmalloc(sizeof(__DRIdrawablePrivate));
796    if (!pdp) {
797	return NULL;
798    }
799
800    if (!XF86DRICreateDrawable(dpy, modes->screen, draw, &pdp->hHWDrawable)) {
801	Xfree(pdp);
802	return NULL;
803    }
804
805    pdp->draw = draw;
806    pdp->pdraw = pdraw;
807    pdp->refcount = 0;
808    pdp->pStamp = NULL;
809    pdp->lastStamp = 0;
810    pdp->index = 0;
811    pdp->x = 0;
812    pdp->y = 0;
813    pdp->w = 0;
814    pdp->h = 0;
815    pdp->numClipRects = 0;
816    pdp->numBackClipRects = 0;
817    pdp->pClipRects = NULL;
818    pdp->pBackClipRects = NULL;
819    pdp->display = dpy;
820    pdp->screen = modes->screen;
821
822    psp = (__DRIscreenPrivate *)pDRIScreen->private;
823    pdp->driScreenPriv = psp;
824    pdp->driContextPriv = &psp->dummyContextPriv;
825
826    pdp->getInfo = (GetDrawableInfo *)
827	glXGetProcAddress( (const GLubyte *) "__glXGetDrawableInfo" );
828    if ( pdp->getInfo == NULL ) {
829	pdp->getInfo = XF86DRIGetDrawableInfo;
830    }
831
832    if (!(*psp->DriverAPI.CreateBuffer)(psp, pdp, modes,
833					renderType == GLX_PIXMAP_BIT)) {
834       (void)XF86DRIDestroyDrawable(dpy, modes->screen, pdp->draw);
835       Xfree(pdp);
836       return NULL;
837    }
838
839    pdraw->private = pdp;
840    pdraw->destroyDrawable = driDestroyDrawable;
841    pdraw->swapBuffers = driSwapBuffers;  /* called by glXSwapBuffers() */
842
843    if ( driCompareGLXAPIVersion( 20030317 ) >= 0 ) {
844        pdraw->getSBC = driGetSBC;
845        pdraw->waitForSBC = driWaitForSBC;
846        pdraw->waitForMSC = driWaitForMSC;
847        pdraw->swapBuffersMSC = driSwapBuffersMSC;
848        pdraw->frameTracking = NULL;
849        pdraw->queryFrameTracking = driQueryFrameTracking;
850
851        /* This special default value is replaced with the configured
852	 * default value when the drawable is first bound to a direct
853	 * rendering context. */
854        pdraw->swap_interval = (unsigned)-1;
855    }
856
857    pdp->swapBuffers = psp->DriverAPI.SwapBuffers;
858
859    /* Add pdraw to drawable list */
860    if (!__driAddDrawable(psp->drawHash, pdraw)) {
861	/* ERROR!!! */
862	(*pdraw->destroyDrawable)(dpy, pdp);
863	Xfree(pdp);
864	pdp = NULL;
865	pdraw->private = NULL;
866    }
867
868   return (void *) pdp;
869}
870
871static __DRIdrawable *driGetDrawable(Display *dpy, GLXDrawable draw,
872					 void *screenPrivate)
873{
874    __DRIscreenPrivate *psp = (__DRIscreenPrivate *) screenPrivate;
875
876    /*
877    ** Make sure this routine returns NULL if the drawable is not bound
878    ** to a direct rendering context!
879    */
880    return __driFindDrawable(psp->drawHash, draw);
881}
882
883static void driDestroyDrawable(Display *dpy, void *drawablePrivate)
884{
885    __DRIdrawablePrivate *pdp = (__DRIdrawablePrivate *) drawablePrivate;
886    __DRIscreenPrivate *psp = pdp->driScreenPriv;
887    int scrn = psp->myNum;
888
889    if (pdp) {
890        (*psp->DriverAPI.DestroyBuffer)(pdp);
891	if ((*window_exists)(dpy, pdp->draw))
892	    (void)XF86DRIDestroyDrawable(dpy, scrn, pdp->draw);
893	if (pdp->pClipRects) {
894	    Xfree(pdp->pClipRects);
895	    pdp->pClipRects = NULL;
896	}
897	if (pdp->pBackClipRects) {
898	    Xfree(pdp->pBackClipRects);
899	    pdp->pBackClipRects = NULL;
900	}
901	Xfree(pdp);
902    }
903}
904
905/*@}*/
906
907
908/*****************************************************************/
909/** \name Context handling functions                             */
910/*****************************************************************/
911/*@{*/
912
913/**
914 * Destroy the per-context private information.
915 *
916 * \param dpy the display handle.
917 * \param scrn the screen number.
918 * \param contextPrivate opaque pointer to the per-drawable private info.
919 *
920 * \internal
921 * This function calls __DriverAPIRec::DestroyContext on \p contextPrivate, calls
922 * drmDestroyContext(), and finally frees \p contextPrivate.
923 */
924static void driDestroyContext(Display *dpy, int scrn, void *contextPrivate)
925{
926    __DRIcontextPrivate  *pcp   = (__DRIcontextPrivate *) contextPrivate;
927
928    if (pcp) {
929	(*pcp->driScreenPriv->DriverAPI.DestroyContext)(pcp);
930	__driGarbageCollectDrawables(pcp->driScreenPriv->drawHash);
931	(void)XF86DRIDestroyContext(dpy, scrn, pcp->contextID);
932	Xfree(pcp);
933    }
934}
935
936
937/**
938 * Create the per-drawable private driver information.
939 *
940 * \param dpy           The display handle.
941 * \param modes         Mode used to create the new context.
942 * \param render_type   Type of rendering target.  \c GLX_RGBA is the only
943 *                      type likely to ever be supported for direct-rendering.
944 * \param sharedPrivate The shared context dependent methods or \c NULL if
945 *                      non-existent.
946 * \param pctx          DRI context to receive the context dependent methods.
947 *
948 * \returns An opaque pointer to the per-context private information on
949 *          success, or \c NULL on failure.
950 *
951 * \internal
952 * This function allocates and fills a __DRIcontextPrivateRec structure.  It
953 * performs some device independent initialization and passes all the
954 * relevent information to __DriverAPIRec::CreateContext to create the
955 * context.
956 *
957 */
958static void *
959driCreateNewContext(Display *dpy, const __GLcontextModes *modes,
960		    int render_type, void *sharedPrivate, __DRIcontext *pctx)
961{
962    __DRIscreen *pDRIScreen;
963    __DRIcontextPrivate *pcp;
964    __DRIcontextPrivate *pshare = (__DRIcontextPrivate *) sharedPrivate;
965    __DRIscreenPrivate *psp;
966    void * const shareCtx = (pshare != NULL) ? pshare->driverPrivate : NULL;
967
968    pDRIScreen = __glXFindDRIScreen(dpy, modes->screen);
969    if ( (pDRIScreen == NULL) || (pDRIScreen->private == NULL) ) {
970	/* ERROR!!! */
971	return NULL;
972    }
973
974    psp = (__DRIscreenPrivate *)pDRIScreen->private;
975
976    pcp = (__DRIcontextPrivate *)Xmalloc(sizeof(__DRIcontextPrivate));
977    if (!pcp) {
978	return NULL;
979    }
980
981    if (! (*create_context_with_config)(dpy, modes->screen, modes->fbconfigID,
982					&pcp->contextID, &pcp->hHWContext)) {
983	Xfree(pcp);
984	return NULL;
985    }
986
987    pcp->display = dpy;
988    pcp->driScreenPriv = psp;
989    pcp->driDrawablePriv = NULL;
990
991    /* When the first context is created for a screen, initialize a "dummy"
992     * context.
993     */
994
995    if (!psp->dummyContextPriv.driScreenPriv) {
996        psp->dummyContextPriv.contextID = 0;
997        psp->dummyContextPriv.hHWContext = psp->pSAREA->dummy_context;
998        psp->dummyContextPriv.driScreenPriv = psp;
999        psp->dummyContextPriv.driDrawablePriv = NULL;
1000        psp->dummyContextPriv.driverPrivate = NULL;
1001	/* No other fields should be used! */
1002    }
1003
1004    pctx->destroyContext = driDestroyContext;
1005#ifdef DRI_NEW_INTERFACE_ONLY
1006    pctx->bindContext    = NULL;
1007    pctx->unbindContext  = NULL;
1008    pctx->bindContext2   = NULL;
1009    pctx->unbindContext2 = NULL;
1010    pctx->bindContext3   = driBindContext3;
1011    pctx->unbindContext3 = driUnbindContext3;
1012#else
1013    pctx->bindContext    = driBindContext;
1014    pctx->unbindContext  = driUnbindContext;
1015    if ( driCompareGLXAPIVersion( 20030606 ) >= 0 ) {
1016        pctx->bindContext2   = driBindContext2;
1017        pctx->unbindContext2 = driUnbindContext2;
1018    }
1019
1020    if ( driCompareGLXAPIVersion( 20040415 ) >= 0 ) {
1021        pctx->bindContext3   = driBindContext3;
1022        pctx->unbindContext3 = driUnbindContext3;
1023    }
1024#endif
1025
1026    if ( !(*psp->DriverAPI.CreateContext)(modes, pcp, shareCtx) ) {
1027        (void)XF86DRIDestroyContext(dpy, modes->screen, pcp->contextID);
1028        Xfree(pcp);
1029        return NULL;
1030    }
1031
1032    __driGarbageCollectDrawables(pcp->driScreenPriv->drawHash);
1033
1034    return pcp;
1035}
1036
1037
1038#ifndef DRI_NEW_INTERFACE_ONLY
1039/**
1040 * Create the per-drawable private driver information.
1041 *
1042 * \param dpy the display handle.
1043 * \param vis the visual information.
1044 * \param sharedPrivate the shared context dependent methods or \c NULL if
1045 *                      non-existent.
1046 * \param pctx will receive the context dependent methods.
1047 *
1048 * \returns a opaque pointer to the per-context private information on success, or \c NULL
1049 * on failure.
1050 *
1051 * \deprecated
1052 * This function has been replaced by \c driCreateNewContext.  In drivers
1053 * built to work with XFree86, this function will continue to exist to support
1054 * older versions of libGL.  Starting with the next major relelase of XFree86,
1055 * this function will be removed.
1056 *
1057 * \internal
1058 * This function allocates and fills a __DRIcontextPrivateRec structure.  It
1059 * gets the visual, converts it into a __GLcontextModesRec and passes it
1060 * to __DriverAPIRec::CreateContext to create the context.
1061 */
1062static void *driCreateContext(Display *dpy, XVisualInfo *vis,
1063                              void *sharedPrivate, __DRIcontext *pctx)
1064{
1065    __DRIscreen *pDRIScreen;
1066    const __GLcontextModes *modes;
1067
1068    pDRIScreen = __glXFindDRIScreen(dpy, vis->screen);
1069    if ( (pDRIScreen == NULL) || (pDRIScreen->private == NULL) ) {
1070	/* ERROR!!! */
1071	return NULL;
1072    }
1073
1074
1075    /* Setup a __GLcontextModes struct corresponding to vis->visualid
1076     * and create the rendering context.
1077     */
1078
1079    modes = findConfigMode(dpy, vis->screen, vis->visualid, pDRIScreen);
1080    return (modes == NULL)
1081	? NULL
1082	: driCreateNewContext( dpy, modes, GLX_RGBA_TYPE,
1083			       sharedPrivate, pctx );
1084}
1085#endif /* DRI_NEW_INTERFACE_ONLY */
1086
1087/*@}*/
1088
1089
1090/*****************************************************************/
1091/** \name Screen handling functions                              */
1092/*****************************************************************/
1093/*@{*/
1094
1095/**
1096 * Destroy the per-screen private information.
1097 *
1098 * \param dpy the display handle.
1099 * \param scrn the screen number.
1100 * \param screenPrivate opaque pointer to the per-screen private information.
1101 *
1102 * \internal
1103 * This function calls __DriverAPIRec::DestroyScreen on \p screenPrivate, calls
1104 * drmClose(), and finally frees \p screenPrivate.
1105 */
1106static void driDestroyScreen(Display *dpy, int scrn, void *screenPrivate)
1107{
1108    __DRIscreenPrivate *psp = (__DRIscreenPrivate *) screenPrivate;
1109
1110    if (psp) {
1111	/* No interaction with the X-server is possible at this point.  This
1112	 * routine is called after XCloseDisplay, so there is no protocol
1113	 * stream open to the X-server anymore.
1114	 */
1115
1116	if (psp->DriverAPI.DestroyScreen)
1117	    (*psp->DriverAPI.DestroyScreen)(psp);
1118
1119	(void)drmUnmap((drmAddress)psp->pSAREA, SAREA_MAX);
1120	(void)drmUnmap((drmAddress)psp->pFB, psp->fbSize);
1121	Xfree(psp->pDevPriv);
1122	(void)drmClose(psp->fd);
1123	if ( psp->modes != NULL ) {
1124	    _gl_context_modes_destroy( psp->modes );
1125	}
1126	Xfree(psp);
1127    }
1128}
1129
1130
1131/**
1132 * Utility function used to create a new driver-private screen structure.
1133 *
1134 * \param dpy   Display pointer
1135 * \param scrn  Index of the screen
1136 * \param psc   DRI screen data (not driver private)
1137 * \param modes Linked list of known display modes.  This list is, at a
1138 *              minimum, a list of modes based on the current display mode.
1139 *              These roughly match the set of available X11 visuals, but it
1140 *              need not be limited to X11!  The calling libGL should create
1141 *              a list that will inform the driver of the current display
1142 *              mode (i.e., color buffer depth, depth buffer depth, etc.).
1143 * \param ddx_version Version of the 2D DDX.  This may not be meaningful for
1144 *                    all drivers.
1145 * \param dri_version Version of the "server-side" DRI.
1146 * \param drm_version Version of the kernel DRM.
1147 * \param frame_buffer Data describing the location and layout of the
1148 *                     framebuffer.
1149 * \param pSAREA       Pointer the the SAREA.
1150 * \param fd           Device handle for the DRM.
1151 * \param internal_api_version  Version of the internal interface between the
1152 *                              driver and libGL.
1153 * \param driverAPI Driver API functions used by other routines in dri_util.c.
1154 */
1155__DRIscreenPrivate *
1156__driUtilCreateNewScreen(Display *dpy, int scrn, __DRIscreen *psc,
1157			 __GLcontextModes * modes,
1158			 const __DRIversion * ddx_version,
1159			 const __DRIversion * dri_version,
1160			 const __DRIversion * drm_version,
1161			 const __DRIframebuffer * frame_buffer,
1162			 drmAddress pSAREA,
1163			 int fd,
1164			 int internal_api_version,
1165			 const struct __DriverAPIRec *driverAPI)
1166{
1167    __DRIscreenPrivate *psp;
1168
1169
1170#ifdef DRI_NEW_INTERFACE_ONLY
1171    if ( internal_api_version < 20040415 ) {
1172	fprintf( stderr, "libGL error: libGL.so version (%08u) is too old.  "
1173		 "20040415 or later is required.\n", internal_api_version );
1174	return NULL;
1175    }
1176#else
1177    if ( internal_api_version == 20031201 ) {
1178	fprintf( stderr, "libGL error: libGL version 20031201 has critical "
1179		 "binary compatilibity bugs.\nlibGL error: You must upgrade "
1180		 "to use direct-rendering!\n" );
1181	return NULL;
1182    }
1183#endif /* DRI_NEW_INTERFACE_ONLY */
1184
1185
1186    window_exists = (PFNGLXWINDOWEXISTSPROC)
1187	glXGetProcAddress( (const GLubyte *) "__glXWindowExists" );
1188
1189    if ( window_exists == NULL ) {
1190#ifdef DRI_NEW_INTERFACE_ONLY
1191	fprintf( stderr, "libGL error: libGL.so version (%08u) is too old.  "
1192		 "20021128 or later is required.\n", internal_api_version );
1193	return NULL;
1194#else
1195	window_exists = (PFNGLXWINDOWEXISTSPROC) __driWindowExists;
1196#endif /* DRI_NEW_INTERFACE_ONLY */
1197    }
1198
1199    create_context_with_config = (PFNGLXCREATECONTEXTWITHCONFIGPROC)
1200	glXGetProcAddress( (const GLubyte *) "__glXCreateContextWithConfig" );
1201    if ( create_context_with_config == NULL ) {
1202#ifdef DRI_NEW_INTERFACE_ONLY
1203	fprintf( stderr, "libGL error: libGL.so version (%08u) is too old.  "
1204		 "20031201 or later is required.\n", internal_api_version );
1205	return NULL;
1206#else
1207	create_context_with_config = (PFNGLXCREATECONTEXTWITHCONFIGPROC)
1208	    fake_XF86DRICreateContextWithConfig;
1209#endif /* DRI_NEW_INTERFACE_ONLY */
1210    }
1211
1212    api_ver = internal_api_version;
1213
1214    psp = (__DRIscreenPrivate *)Xmalloc(sizeof(__DRIscreenPrivate));
1215    if (!psp) {
1216	return NULL;
1217    }
1218
1219    /* Create the hash table */
1220    psp->drawHash = drmHashCreate();
1221    if ( psp->drawHash == NULL ) {
1222	Xfree( psp );
1223	return NULL;
1224    }
1225
1226    psp->display = dpy;
1227    psp->myNum = scrn;
1228    psp->psc = psc;
1229    psp->modes = modes;
1230
1231    /*
1232    ** NOT_DONE: This is used by the X server to detect when the client
1233    ** has died while holding the drawable lock.  The client sets the
1234    ** drawable lock to this value.
1235    */
1236    psp->drawLockID = 1;
1237
1238    psp->drmMajor = drm_version->major;
1239    psp->drmMinor = drm_version->minor;
1240    psp->drmPatch = drm_version->patch;
1241    psp->ddxMajor = ddx_version->major;
1242    psp->ddxMinor = ddx_version->minor;
1243    psp->ddxPatch = ddx_version->patch;
1244    psp->driMajor = dri_version->major;
1245    psp->driMinor = dri_version->minor;
1246    psp->driPatch = dri_version->patch;
1247
1248    /* install driver's callback functions */
1249    memcpy( &psp->DriverAPI, driverAPI, sizeof(struct __DriverAPIRec) );
1250
1251    psp->pSAREA = pSAREA;
1252
1253    psp->pFB = frame_buffer->base;
1254    psp->fbSize = frame_buffer->size;
1255    psp->fbStride = frame_buffer->stride;
1256    psp->fbWidth = frame_buffer->width;
1257    psp->fbHeight = frame_buffer->height;
1258    psp->devPrivSize = frame_buffer->dev_priv_size;
1259    psp->pDevPriv = frame_buffer->dev_priv;
1260
1261    psp->fd = fd;
1262
1263    /*
1264    ** Do not init dummy context here; actual initialization will be
1265    ** done when the first DRI context is created.  Init screen priv ptr
1266    ** to NULL to let CreateContext routine that it needs to be inited.
1267    */
1268    psp->dummyContextPriv.driScreenPriv = NULL;
1269
1270    psc->destroyScreen     = driDestroyScreen;
1271#ifndef DRI_NEW_INTERFACE_ONLY
1272    psc->createContext     = driCreateContext;
1273#else
1274    psc->createContext     = NULL;
1275#endif
1276    psc->createNewDrawable = driCreateNewDrawable;
1277    psc->getDrawable       = driGetDrawable;
1278#ifdef DRI_NEW_INTERFACE_ONLY
1279    psc->getMSC            = driGetMSC;
1280    psc->createNewContext  = driCreateNewContext;
1281#else
1282    if ( driCompareGLXAPIVersion( 20030317 ) >= 0 ) {
1283        psc->getMSC        = driGetMSC;
1284
1285	if ( driCompareGLXAPIVersion( 20030824 ) >= 0 ) {
1286	    psc->createNewContext = driCreateNewContext;
1287	}
1288    }
1289#endif
1290
1291    if ( (psp->DriverAPI.InitDriver != NULL)
1292	 && !(*psp->DriverAPI.InitDriver)(psp) ) {
1293	Xfree( psp );
1294	return NULL;
1295    }
1296
1297
1298    return psp;
1299}
1300
1301
1302#ifndef DRI_NEW_INTERFACE_ONLY
1303/**
1304 * Utility function used to create a new driver-private screen structure.
1305 *
1306 * \param dpy        Display pointer.
1307 * \param scrn       Index of the screen.
1308 * \param psc        DRI screen data (not driver private)
1309 * \param numConfigs Number of visual configs pointed to by \c configs.
1310 * \param configs    Array of GLXvisualConfigs exported by the 2D driver.
1311 * \param driverAPI Driver API functions used by other routines in dri_util.c.
1312 *
1313 * \deprecated
1314 * This function has been replaced by \c __driUtilCreateNewScreen.  In drivers
1315 * built to work with XFree86, this function will continue to exist to support
1316 * older versions of libGL.  Starting with the next major relelase of XFree86,
1317 * this function will be removed.
1318 */
1319__DRIscreenPrivate *
1320__driUtilCreateScreen(Display *dpy, int scrn, __DRIscreen *psc,
1321                      int numConfigs, __GLXvisualConfig *configs,
1322                      const struct __DriverAPIRec *driverAPI)
1323{
1324    int directCapable;
1325    __DRIscreenPrivate *psp = NULL;
1326    drmHandle hSAREA;
1327    drmAddress pSAREA;
1328    char *BusID;
1329    __GLcontextModes *modes;
1330    __GLcontextModes *temp;
1331    int   i;
1332    __DRIversion   ddx_version;
1333    __DRIversion   dri_version;
1334    __DRIversion   drm_version;
1335    __DRIframebuffer  framebuffer;
1336    int   fd = -1;
1337    int   status;
1338    const char * err_msg;
1339    const char * err_extra;
1340
1341
1342    if (!XF86DRIQueryDirectRenderingCapable(dpy, scrn, &directCapable)
1343	|| !directCapable) {
1344	return NULL;
1345    }
1346
1347
1348    /* Create the linked list of context modes, and populate it with the
1349     * GLX visual information passed in by libGL.
1350     */
1351
1352    modes = _gl_context_modes_create( numConfigs, sizeof(__GLcontextModes) );
1353    if ( modes == NULL ) {
1354	return NULL;
1355    }
1356
1357    temp = modes;
1358    for ( i = 0 ; i < numConfigs ; i++ ) {
1359	assert( temp != NULL );
1360	_gl_copy_visual_to_context_mode( temp, & configs[i] );
1361	temp->screen = scrn;
1362
1363	temp = temp->next;
1364    }
1365
1366    err_msg = "XF86DRIOpenConnection";
1367    err_extra = NULL;
1368
1369    if (XF86DRIOpenConnection(dpy, scrn, &hSAREA, &BusID)) {
1370	fd = drmOpen(NULL,BusID);
1371	Xfree(BusID); /* No longer needed */
1372
1373	err_msg = "open DRM";
1374	err_extra = strerror( -fd );
1375
1376	if (fd >= 0) {
1377	    drmMagic magic;
1378
1379	    err_msg = "drmGetMagic";
1380	    err_extra = NULL;
1381
1382	    if (!drmGetMagic(fd, &magic)) {
1383		drmVersionPtr version = drmGetVersion(fd);
1384		if (version) {
1385		    drm_version.major = version->version_major;
1386		    drm_version.minor = version->version_minor;
1387		    drm_version.patch = version->version_patchlevel;
1388		    drmFreeVersion(version);
1389		}
1390		else {
1391		    drm_version.major = -1;
1392		    drm_version.minor = -1;
1393		    drm_version.patch = -1;
1394		}
1395
1396		err_msg = "XF86DRIAuthConnection";
1397		if (XF86DRIAuthConnection(dpy, scrn, magic)) {
1398		    char *driverName;
1399
1400		    /*
1401		     * Get device name (like "tdfx") and the ddx version numbers.
1402		     * We'll check the version in each DRI driver's "createScreen"
1403		     * function.
1404		     */
1405		    err_msg = "XF86DRIGetClientDriverName";
1406		    if (XF86DRIGetClientDriverName(dpy, scrn,
1407						   &ddx_version.major,
1408						   &ddx_version.minor,
1409						   &ddx_version.patch,
1410						   &driverName)) {
1411
1412			/* No longer needed. */
1413			Xfree( driverName );
1414
1415			/*
1416			 * Get the DRI X extension version.
1417			 */
1418			err_msg = "XF86DRIQueryVersion";
1419			if (XF86DRIQueryVersion(dpy,
1420						&dri_version.major,
1421						&dri_version.minor,
1422						&dri_version.patch)) {
1423			    drmHandle  hFB;
1424			    int        junk;
1425
1426			    /*
1427			     * Get device-specific info.  pDevPriv will point to a struct
1428			     * (such as DRIRADEONRec in xfree86/driver/ati/radeon_dri.h)
1429			     * that has information about the screen size, depth, pitch,
1430			     * ancilliary buffers, DRM mmap handles, etc.
1431			     */
1432			    err_msg = "XF86DRIGetDeviceInfo";
1433			    if (XF86DRIGetDeviceInfo(dpy, scrn,
1434						     &hFB,
1435						     &junk,
1436						     &framebuffer.size,
1437						     &framebuffer.stride,
1438						     &framebuffer.dev_priv_size,
1439						     &framebuffer.dev_priv)) {
1440				framebuffer.width = DisplayWidth(dpy, scrn);
1441				framebuffer.height = DisplayHeight(dpy, scrn);
1442
1443				/*
1444				 * Map the framebuffer region.
1445				 */
1446				status = drmMap(fd, hFB, framebuffer.size,
1447						(drmAddressPtr)&framebuffer.base);
1448
1449				err_msg = "drmMap of framebuffer";
1450				err_extra = strerror( -status );
1451
1452				if ( status == 0 ) {
1453				    /*
1454				     * Map the SAREA region.  Further mmap regions may be setup in
1455				     * each DRI driver's "createScreen" function.
1456				     */
1457				    status = drmMap(fd, hSAREA, SAREA_MAX,
1458						    &pSAREA);
1459
1460				    err_msg = "drmMap of sarea";
1461				    err_extra = strerror( -status );
1462
1463				    if ( status == 0 ) {
1464					PFNGLXGETINTERNALVERSIONPROC get_ver;
1465
1466					get_ver = (PFNGLXGETINTERNALVERSIONPROC)
1467					    glXGetProcAddress( (const GLubyte *) "__glXGetInternalVersion" );
1468
1469					err_msg = "InitDriver";
1470					err_extra = NULL;
1471					psp = __driUtilCreateNewScreen( dpy, scrn, psc, modes,
1472									& ddx_version,
1473									& dri_version,
1474									& drm_version,
1475									& framebuffer,
1476									pSAREA,
1477									fd,
1478									(get_ver != NULL) ? (*get_ver)() : 1,
1479									driverAPI );
1480				    }
1481				}
1482			    }
1483			}
1484		    }
1485		}
1486	    }
1487	}
1488    }
1489
1490    if ( psp == NULL ) {
1491	if ( pSAREA != MAP_FAILED ) {
1492	    (void)drmUnmap(pSAREA, SAREA_MAX);
1493	}
1494
1495	if ( framebuffer.base != MAP_FAILED ) {
1496	    (void)drmUnmap((drmAddress)framebuffer.base, framebuffer.size);
1497	}
1498
1499	if ( framebuffer.dev_priv != NULL ) {
1500	    Xfree(framebuffer.dev_priv);
1501	}
1502
1503	if ( fd >= 0 ) {
1504	    (void)drmClose(fd);
1505	}
1506
1507	if ( modes != NULL ) {
1508	    _gl_context_modes_destroy( modes );
1509	}
1510
1511	(void)XF86DRICloseConnection(dpy, scrn);
1512
1513	if ( err_extra != NULL ) {
1514	    fprintf(stderr, "libGL error: %s failed (%s)\n", err_msg,
1515		    err_extra);
1516	}
1517	else {
1518	    fprintf(stderr, "libGL error: %s failed\n", err_msg );
1519	}
1520
1521        fprintf(stderr, "libGL error: reverting to (slow) indirect rendering\n");
1522    }
1523
1524    return psp;
1525}
1526#endif /* DRI_NEW_INTERFACE_ONLY */
1527
1528
1529/**
1530 * Compare the current GLX API version with a driver supplied required version.
1531 *
1532 * The minimum required version is compared with the API version exported by
1533 * the \c __glXGetInternalVersion function (in libGL.so).
1534 *
1535 * \param   required_version Minimum required internal GLX API version.
1536 * \return  A tri-value return, as from strcmp is returned.  A value less
1537 *          than, equal to, or greater than zero will be returned if the
1538 *          internal GLX API version is less than, equal to, or greater
1539 *          than \c required_version.
1540 *
1541 * \sa __glXGetInternalVersion().
1542 */
1543int driCompareGLXAPIVersion( GLuint required_version )
1544{
1545   if ( api_ver > required_version ) {
1546      return 1;
1547   }
1548   else if ( api_ver == required_version ) {
1549      return 0;
1550   }
1551
1552   return -1;
1553}
1554
1555
1556static int
1557driQueryFrameTracking( Display * dpy, void * priv,
1558		       int64_t * sbc, int64_t * missedFrames,
1559		       float * lastMissedUsage, float * usage )
1560{
1561   static PFNGLXGETUSTPROC   get_ust;
1562   __DRIswapInfo   sInfo;
1563   int             status;
1564   int64_t         ust;
1565   __DRIdrawablePrivate * dpriv = (__DRIdrawablePrivate *) priv;
1566
1567   if ( get_ust == NULL ) {
1568      get_ust = (PFNGLXGETUSTPROC) glXGetProcAddress( (const GLubyte *) "__glXGetUST" );
1569   }
1570
1571   status = dpriv->driScreenPriv->DriverAPI.GetSwapInfo( dpriv, & sInfo );
1572   if ( status == 0 ) {
1573      *sbc = sInfo.swap_count;
1574      *missedFrames = sInfo.swap_missed_count;
1575      *lastMissedUsage = sInfo.swap_missed_usage;
1576
1577      (*get_ust)( & ust );
1578      *usage = driCalculateSwapUsage( dpriv, sInfo.swap_ust, ust );
1579   }
1580
1581   return status;
1582}
1583
1584
1585/**
1586 * Calculate amount of swap interval used between GLX buffer swaps.
1587 *
1588 * The usage value, on the range [0,max], is the fraction of total swap
1589 * interval time used between GLX buffer swaps is calculated.
1590 *
1591 *            \f$p = t_d / (i * t_r)\f$
1592 *
1593 * Where \f$t_d\f$ is the time since the last GLX buffer swap, \f$i\f$ is the
1594 * swap interval (as set by \c glXSwapIntervalSGI), and \f$t_r\f$ time
1595 * required for a single vertical refresh period (as returned by \c
1596 * glXGetMscRateOML).
1597 *
1598 * See the documentation for the GLX_MESA_swap_frame_usage extension for more
1599 * details.
1600 *
1601 * \param   dPriv  Pointer to the private drawable structure.
1602 * \return  If less than a single swap interval time period was required
1603 *          between GLX buffer swaps, a number greater than 0 and less than
1604 *          1.0 is returned.  If exactly one swap interval time period is
1605 *          required, 1.0 is returned, and if more than one is required then
1606 *          a number greater than 1.0 will be returned.
1607 *
1608 * \sa glXSwapIntervalSGI glXGetMscRateOML
1609 *
1610 * \todo Instead of caching the \c glXGetMscRateOML function pointer, would it
1611 *       be possible to cache the sync rate?
1612 */
1613float
1614driCalculateSwapUsage( __DRIdrawablePrivate *dPriv, int64_t last_swap_ust,
1615		       int64_t current_ust )
1616{
1617   static PFNGLXGETMSCRATEOMLPROC get_msc_rate = NULL;
1618   int32_t   n;
1619   int32_t   d;
1620   int       interval;
1621   float     usage = 1.0;
1622
1623
1624   if ( get_msc_rate == NULL ) {
1625      get_msc_rate = (PFNGLXGETMSCRATEOMLPROC)
1626	  glXGetProcAddress( (const GLubyte *) "glXGetMscRateOML" );
1627   }
1628
1629   if ( (get_msc_rate != NULL)
1630	&& get_msc_rate( dPriv->display, dPriv->draw, &n, &d ) ) {
1631      interval = (dPriv->pdraw->swap_interval != 0)
1632	  ? dPriv->pdraw->swap_interval : 1;
1633
1634
1635      /* We want to calculate
1636       * (current_UST - last_swap_UST) / (interval * us_per_refresh).  We get
1637       * current_UST by calling __glXGetUST.  last_swap_UST is stored in
1638       * dPriv->swap_ust.  interval has already been calculated.
1639       *
1640       * The only tricky part is us_per_refresh.  us_per_refresh is
1641       * 1000000 / MSC_rate.  We know the MSC_rate is n / d.  We can flip it
1642       * around and say us_per_refresh = 1000000 * d / n.  Since this goes in
1643       * the denominator of the final calculation, we calculate
1644       * (interval * 1000000 * d) and move n into the numerator.
1645       */
1646
1647      usage = (current_ust - last_swap_ust);
1648      usage *= n;
1649      usage /= (interval * d);
1650      usage /= 1000000.0;
1651   }
1652
1653   return usage;
1654}
1655
1656/*@}*/
1657
1658#endif /* GLX_DIRECT_RENDERING */
1659