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