summaryrefslogtreecommitdiff
path: root/src/mesa/drivers/dri/common
diff options
context:
space:
mode:
authorIan Romanick <idr@us.ibm.com>2004-05-27 22:31:06 +0000
committerIan Romanick <idr@us.ibm.com>2004-05-27 22:31:06 +0000
commitb3981ab6e6762b4205ca5302d93be129f648a9cf (patch)
treea771880fa33d0382166438b3883cc3daac5d5519 /src/mesa/drivers/dri/common
parentaaaf38d37215aa1536ff34ec370ecfc04111af22 (diff)
Move dri_util.[ch] and glcontextmodes.[ch] from dri_client to common.
Diffstat (limited to 'src/mesa/drivers/dri/common')
-rw-r--r--src/mesa/drivers/dri/common/dri_util.c1654
-rw-r--r--src/mesa/drivers/dri/common/dri_util.h588
-rw-r--r--src/mesa/drivers/dri/common/glcontextmodes.c483
-rw-r--r--src/mesa/drivers/dri/common/glcontextmodes.h49
4 files changed, 2774 insertions, 0 deletions
diff --git a/src/mesa/drivers/dri/common/dri_util.c b/src/mesa/drivers/dri/common/dri_util.c
new file mode 100644
index 0000000000..03d92c02f2
--- /dev/null
+++ b/src/mesa/drivers/dri/common/dri_util.c
@@ -0,0 +1,1654 @@
+/* $XFree86: xc/lib/GL/dri/dri_util.c,v 1.7 2003/04/28 17:01:25 dawes Exp $ */
+/**
+ * \file dri_util.c
+ * DRI utility functions.
+ *
+ * This module acts as glue between GLX and the actual hardware driver. A DRI
+ * driver doesn't really \e have to use any of this - it's optional. But, some
+ * useful stuff is done here that otherwise would have to be duplicated in most
+ * drivers.
+ *
+ * Basically, these utility functions take care of some of the dirty details of
+ * screen initialization, context creation, context binding, DRM setup, etc.
+ *
+ * These functions are compiled into each DRI driver so libGL.so knows nothing
+ * about them.
+ *
+ * \note
+ * When \c DRI_NEW_INTERFACE_ONLY is defined, code is built / not built so
+ * that only the "new" libGL-to-driver interfaces are supported. This breaks
+ * backwards compatability. However, this may be necessary when DRI drivers
+ * are built to be used in non-XFree86 environments.
+ *
+ * \todo There are still some places in the code that need to be wrapped with
+ * \c DRI_NEW_INTERFACE_ONLY.
+ */
+
+
+#ifdef GLX_DIRECT_RENDERING
+
+#include <inttypes.h>
+#include <assert.h>
+#include <stdarg.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <X11/Xlibint.h>
+#include <Xext.h>
+#include <extutil.h>
+#include <stdio.h>
+#include "dri_util.h"
+#include "xf86dri.h"
+#include "sarea.h"
+#include "glcontextmodes.h"
+
+/*#define DRI_NEW_INTERFACE_ONLY*/
+
+/**
+ * This is used in a couple of places that call \c driCreateNewDrawable.
+ */
+static const int empty_attribute_list[1] = { None };
+
+/**
+ * Function used to determine if a drawable (window) still exists. Ideally
+ * this function comes from libGL. With older versions of libGL from XFree86
+ * we can fall-back to an internal version.
+ *
+ * \sa __driWindowExists __glXWindowExists
+ */
+static PFNGLXWINDOWEXISTSPROC window_exists;
+
+typedef Bool (*PFNGLXCREATECONTEXTWITHCONFIGPROC)( Display*, int, int, void *,
+ drmContextPtr );
+
+static PFNGLXCREATECONTEXTWITHCONFIGPROC create_context_with_config;
+
+/**
+ * Cached copy of the internal API version used by libGL and the client-side
+ * DRI driver.
+ */
+static int api_ver = 0;
+
+/* forward declarations */
+static int driQueryFrameTracking( Display * dpy, void * priv,
+ int64_t * sbc, int64_t * missedFrames, float * lastMissedUsage,
+ float * usage );
+
+static void *driCreateNewDrawable(Display *dpy, const __GLcontextModes *modes,
+ GLXDrawable draw, __DRIdrawable *pdraw, int renderType, const int *attrs);
+
+static void driDestroyDrawable(Display *dpy, void *drawablePrivate);
+
+
+
+
+#ifdef not_defined
+static Bool driFeatureOn(const char *name)
+{
+ char *env = getenv(name);
+
+ if (!env) return GL_FALSE;
+ if (!strcasecmp(env, "enable")) return GL_TRUE;
+ if (!strcasecmp(env, "1")) return GL_TRUE;
+ if (!strcasecmp(env, "on")) return GL_TRUE;
+ if (!strcasecmp(env, "true")) return GL_TRUE;
+ if (!strcasecmp(env, "t")) return GL_TRUE;
+ if (!strcasecmp(env, "yes")) return GL_TRUE;
+ if (!strcasecmp(env, "y")) return GL_TRUE;
+
+ return GL_FALSE;
+}
+#endif /* not_defined */
+
+
+/**
+ * Print message to \c stderr if the \c LIBGL_DEBUG environment variable
+ * is set.
+ *
+ * Is called from the drivers.
+ *
+ * \param f \c printf like format string.
+ */
+void
+__driUtilMessage(const char *f, ...)
+{
+ va_list args;
+
+ if (getenv("LIBGL_DEBUG")) {
+ fprintf(stderr, "libGL error: \n");
+ va_start(args, f);
+ vfprintf(stderr, f, args);
+ va_end(args);
+ fprintf(stderr, "\n");
+ }
+}
+
+
+/*****************************************************************/
+/** \name Visual utility functions */
+/*****************************************************************/
+/*@{*/
+
+#ifndef DRI_NEW_INTERFACE_ONLY
+/**
+ * Find a \c __GLcontextModes structure matching the given visual ID.
+ *
+ * \param dpy Display to search for a matching configuration.
+ * \param scrn Screen number on \c dpy to be searched.
+ * \param vid Desired \c VisualID to find.
+ *
+ * \returns A pointer to a \c __GLcontextModes structure that matches \c vid,
+ * if found, or \c NULL if no match is found.
+ */
+static const __GLcontextModes *
+findConfigMode(Display *dpy, int scrn, VisualID vid,
+ const __DRIscreen * pDRIScreen)
+{
+ if ( (pDRIScreen != NULL) && (pDRIScreen->private != NULL) ) {
+ const __DRIscreenPrivate * const psp =
+ (const __DRIscreenPrivate *) pDRIScreen->private;
+
+ return _gl_context_modes_find_visual( psp->modes, vid );
+ }
+
+ return NULL;
+}
+
+
+/**
+ * This function is a hack to work-around old versions of libGL.so that
+ * do not export \c XF86DRICreateContextWithConfig. I would modify the
+ * code to just use this function, but the stand-alone driver (i.e., DRI
+ * drivers that are built to work without XFree86) shouldn't have to know
+ * about X structures like a \c Visual.
+ */
+static Bool
+fake_XF86DRICreateContextWithConfig( Display* dpy, int screen, int configID,
+ XID* context, drmContextPtr hHWContext )
+{
+ Visual vis;
+
+ vis.visualid = configID;
+ return XF86DRICreateContext( dpy, screen, & vis, context, hHWContext );
+}
+#endif /* DRI_NEW_INTERFACE_ONLY */
+
+/*@}*/
+
+
+/*****************************************************************/
+/** \name Drawable list management */
+/*****************************************************************/
+/*@{*/
+
+static Bool __driAddDrawable(void *drawHash, __DRIdrawable *pdraw)
+{
+ __DRIdrawablePrivate *pdp = (__DRIdrawablePrivate *)pdraw->private;
+
+ if (drmHashInsert(drawHash, pdp->draw, pdraw))
+ return GL_FALSE;
+
+ return GL_TRUE;
+}
+
+static __DRIdrawable *__driFindDrawable(void *drawHash, GLXDrawable draw)
+{
+ int retcode;
+ __DRIdrawable *pdraw;
+
+ retcode = drmHashLookup(drawHash, draw, (void **)&pdraw);
+ if (retcode)
+ return NULL;
+
+ return pdraw;
+}
+
+static void __driRemoveDrawable(void *drawHash, __DRIdrawable *pdraw)
+{
+ int retcode;
+ __DRIdrawablePrivate *pdp = (__DRIdrawablePrivate *)pdraw->private;
+
+ retcode = drmHashLookup(drawHash, pdp->draw, (void **)&pdraw);
+ if (!retcode) { /* Found */
+ drmHashDelete(drawHash, pdp->draw);
+ }
+}
+
+#ifndef DRI_NEW_INTERFACE_ONLY
+static Bool __driWindowExistsFlag;
+
+static int __driWindowExistsErrorHandler(Display *dpy, XErrorEvent *xerr)
+{
+ if (xerr->error_code == BadWindow) {
+ __driWindowExistsFlag = GL_FALSE;
+ }
+ return 0;
+}
+
+/**
+ * Determine if a window associated with a \c GLXDrawable exists on the
+ * X-server.
+ *
+ * \param dpy Display associated with the drawable to be queried.
+ * \param draw \c GLXDrawable to test.
+ *
+ * \returns \c GL_TRUE if a window exists that is associated with \c draw,
+ * otherwise \c GL_FALSE is returned.
+ *
+ * \warning This function is not currently thread-safe.
+ *
+ * \deprecated
+ * \c __glXWindowExists (from libGL) is prefered over this function. Starting
+ * with the next major release of XFree86, this function will be removed.
+ * Even now this function is no longer directly called. Instead it is called
+ * via a function pointer if and only if \c __glXWindowExists does not exist.
+ *
+ * \sa __glXWindowExists glXGetProcAddress window_exists
+ */
+static Bool __driWindowExists(Display *dpy, GLXDrawable draw)
+{
+ XWindowAttributes xwa;
+ int (*oldXErrorHandler)(Display *, XErrorEvent *);
+
+ XSync(dpy, GL_FALSE);
+ __driWindowExistsFlag = GL_TRUE;
+ oldXErrorHandler = XSetErrorHandler(__driWindowExistsErrorHandler);
+ XGetWindowAttributes(dpy, draw, &xwa); /* dummy request */
+ XSetErrorHandler(oldXErrorHandler);
+ return __driWindowExistsFlag;
+}
+#endif /* DRI_NEW_INTERFACE_ONLY */
+
+/**
+ * Find drawables in the local hash that have been destroyed on the
+ * server.
+ *
+ * \param drawHash Hash-table containing all know drawables.
+ */
+static void __driGarbageCollectDrawables(void *drawHash)
+{
+ GLXDrawable draw;
+ __DRIdrawable *pdraw;
+ Display *dpy;
+
+ if (drmHashFirst(drawHash, &draw, (void **)&pdraw)) {
+ do {
+ __DRIdrawablePrivate *pdp = (__DRIdrawablePrivate *)pdraw->private;
+ dpy = pdp->driScreenPriv->display;
+ if (! (*window_exists)(dpy, draw)) {
+ /* Destroy the local drawable data in the hash table, if the
+ drawable no longer exists in the Xserver */
+ __driRemoveDrawable(drawHash, pdraw);
+ (*pdraw->destroyDrawable)(dpy, pdraw->private);
+ Xfree(pdraw);
+ }
+ } while (drmHashNext(drawHash, &draw, (void **)&pdraw));
+ }
+}
+
+/*@}*/
+
+
+/*****************************************************************/
+/** \name Context (un)binding functions */
+/*****************************************************************/
+/*@{*/
+
+/**
+ * Unbind context.
+ *
+ * \param dpy the display handle.
+ * \param scrn the screen number.
+ * \param draw drawable.
+ * \param read Current reading drawable.
+ * \param gc context.
+ *
+ * \return \c GL_TRUE on success, or \c GL_FALSE on failure.
+ *
+ * \internal
+ * This function calls __DriverAPIRec::UnbindContext, and then decrements
+ * __DRIdrawablePrivateRec::refcount which must be non-zero for a successful
+ * return.
+ *
+ * While casting the opaque private pointers associated with the parameters
+ * into their respective real types it also assures they are not \c NULL.
+ */
+static Bool driUnbindContext3(Display *dpy, int scrn,
+ GLXDrawable draw, GLXDrawable read,
+ __DRIcontext *ctx)
+{
+ __DRIscreen *pDRIScreen;
+ __DRIdrawable *pdraw;
+ __DRIdrawable *pread;
+ __DRIcontextPrivate *pcp;
+ __DRIscreenPrivate *psp;
+ __DRIdrawablePrivate *pdp;
+ __DRIdrawablePrivate *prp;
+
+ /*
+ ** Assume error checking is done properly in glXMakeCurrent before
+ ** calling driUnbindContext3.
+ */
+
+ if (ctx == NULL || draw == None || read == None) {
+ /* ERROR!!! */
+ return GL_FALSE;
+ }
+
+ pDRIScreen = __glXFindDRIScreen(dpy, scrn);
+ if ( (pDRIScreen == NULL) || (pDRIScreen->private == NULL) ) {
+ /* ERROR!!! */
+ return GL_FALSE;
+ }
+
+ psp = (__DRIscreenPrivate *)pDRIScreen->private;
+ pcp = (__DRIcontextPrivate *)ctx->private;
+
+ pdraw = __driFindDrawable(psp->drawHash, draw);
+ if (!pdraw) {
+ /* ERROR!!! */
+ return GL_FALSE;
+ }
+ pdp = (__DRIdrawablePrivate *)pdraw->private;
+
+ pread = __driFindDrawable(psp->drawHash, read);
+ if (!pread) {
+ /* ERROR!!! */
+ return GL_FALSE;
+ }
+ prp = (__DRIdrawablePrivate *)pread->private;
+
+
+ /* Let driver unbind drawable from context */
+ (*psp->DriverAPI.UnbindContext)(pcp);
+
+
+ if (pdp->refcount == 0) {
+ /* ERROR!!! */
+ return GL_FALSE;
+ }
+
+ pdp->refcount--;
+
+ if (prp != pdp) {
+ if (prp->refcount == 0) {
+ /* ERROR!!! */
+ return GL_FALSE;
+ }
+
+ prp->refcount--;
+ }
+
+
+ /* XXX this is disabled so that if we call SwapBuffers on an unbound
+ * window we can determine the last context bound to the window and
+ * use that context's lock. (BrianP, 2-Dec-2000)
+ */
+#if 0
+ /* Unbind the drawable */
+ pcp->driDrawablePriv = NULL;
+ pdp->driContextPriv = &psp->dummyContextPriv;
+#endif
+
+ return GL_TRUE;
+}
+
+
+/**
+ * This function takes both a read buffer and a draw buffer. This is needed
+ * for \c glXMakeCurrentReadSGI or GLX 1.3's \c glXMakeContextCurrent
+ * function.
+ *
+ * \bug This function calls \c driCreateNewDrawable in two places with the
+ * \c renderType hard-coded to \c GLX_WINDOW_BIT. Some checking might
+ * be needed in those places when support for pbuffers and / or pixmaps
+ * is added. Is it safe to assume that the drawable is a window?
+ */
+static Bool DoBindContext(Display *dpy,
+ GLXDrawable draw, GLXDrawable read,
+ __DRIcontext *ctx, const __GLcontextModes * modes,
+ __DRIscreenPrivate *psp)
+{
+ __DRIdrawable *pdraw;
+ __DRIdrawablePrivate *pdp;
+ __DRIdrawable *pread;
+ __DRIdrawablePrivate *prp;
+ __DRIcontextPrivate * const pcp = ctx->private;
+
+
+ /* Find the _DRIdrawable which corresponds to the writing GLXDrawable */
+ pdraw = __driFindDrawable(psp->drawHash, draw);
+ if (!pdraw) {
+ /* Allocate a new drawable */
+ pdraw = (__DRIdrawable *)Xmalloc(sizeof(__DRIdrawable));
+ if (!pdraw) {
+ /* ERROR!!! */
+ return GL_FALSE;
+ }
+
+ /* Create a new drawable */
+ driCreateNewDrawable(dpy, modes, draw, pdraw, GLX_WINDOW_BIT,
+ empty_attribute_list);
+ if (!pdraw->private) {
+ /* ERROR!!! */
+ Xfree(pdraw);
+ return GL_FALSE;
+ }
+
+ }
+ pdp = (__DRIdrawablePrivate *) pdraw->private;
+
+ /* Find the _DRIdrawable which corresponds to the reading GLXDrawable */
+ if (read == draw) {
+ /* read buffer == draw buffer */
+ prp = pdp;
+ }
+ else {
+ pread = __driFindDrawable(psp->drawHash, read);
+ if (!pread) {
+ /* Allocate a new drawable */
+ pread = (__DRIdrawable *)Xmalloc(sizeof(__DRIdrawable));
+ if (!pread) {
+ /* ERROR!!! */
+ return GL_FALSE;
+ }
+
+ /* Create a new drawable */
+ driCreateNewDrawable(dpy, modes, read, pread, GLX_WINDOW_BIT,
+ empty_attribute_list);
+ if (!pread->private) {
+ /* ERROR!!! */
+ Xfree(pread);
+ return GL_FALSE;
+ }
+ }
+ prp = (__DRIdrawablePrivate *) pread->private;
+ }
+
+ /* Bind the drawable to the context */
+ pcp->driDrawablePriv = pdp;
+ pdp->driContextPriv = pcp;
+ pdp->refcount++;
+ if ( pdp != prp ) {
+ prp->refcount++;
+ }
+
+ /*
+ ** Now that we have a context associated with this drawable, we can
+ ** initialize the drawable information if has not been done before.
+ */
+ if (!pdp->pStamp || *pdp->pStamp != pdp->lastStamp) {
+ DRM_SPINLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID);
+ __driUtilUpdateDrawableInfo(pdp);
+ DRM_SPINUNLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID);
+ }
+
+ /* Call device-specific MakeCurrent */
+ (*psp->DriverAPI.MakeCurrent)(pcp, pdp, prp);
+
+ return GL_TRUE;
+}
+
+
+/**
+ * This function takes both a read buffer and a draw buffer. This is needed
+ * for \c glXMakeCurrentReadSGI or GLX 1.3's \c glXMakeContextCurrent
+ * function.
+ */
+static Bool driBindContext3(Display *dpy, int scrn,
+ GLXDrawable draw, GLXDrawable read,
+ __DRIcontext * ctx)
+{
+ __DRIscreen *pDRIScreen;
+
+ /*
+ ** Assume error checking is done properly in glXMakeCurrent before
+ ** calling driBindContext.
+ */
+
+ if (ctx == NULL || draw == None || read == None) {
+ /* ERROR!!! */
+ return GL_FALSE;
+ }
+
+ pDRIScreen = __glXFindDRIScreen(dpy, scrn);
+ if ( (pDRIScreen == NULL) || (pDRIScreen->private == NULL) ) {
+ /* ERROR!!! */
+ return GL_FALSE;
+ }
+
+ return DoBindContext( dpy, draw, read, ctx, ctx->mode,
+ (__DRIscreenPrivate *)pDRIScreen->private );
+}
+
+
+#ifndef DRI_NEW_INTERFACE_ONLY
+/**
+ * This function takes both a read buffer and a draw buffer. This is needed
+ * for \c glXMakeCurrentReadSGI or GLX 1.3's \c glXMakeContextCurrent
+ * function.
+ */
+static Bool driBindContext2(Display *dpy, int scrn,
+ GLXDrawable draw, GLXDrawable read,
+ GLXContext gc)
+{
+ __DRIscreen *pDRIScreen;
+ const __GLcontextModes *modes;
+
+ /*
+ ** Assume error checking is done properly in glXMakeCurrent before
+ ** calling driBindContext.
+ */
+
+ if (gc == NULL || draw == None || read == None) {
+ /* ERROR!!! */
+ return GL_FALSE;
+ }
+
+ pDRIScreen = __glXFindDRIScreen(dpy, scrn);
+ modes = (driCompareGLXAPIVersion( 20040317 ) >= 0)
+ ? gc->driContext.mode
+ : findConfigMode( dpy, scrn, gc->vid, pDRIScreen );
+
+ if ( modes == NULL ) {
+ /* ERROR!!! */
+ return GL_FALSE;
+ }
+
+ /* findConfigMode will return NULL if the DRI screen or screen private
+ * are NULL.
+ */
+ assert( (pDRIScreen != NULL) && (pDRIScreen->private != NULL) );
+
+ return DoBindContext( dpy, draw, read, & gc->driContext, modes,
+ (__DRIscreenPrivate *)pDRIScreen->private );
+}
+
+static Bool driUnbindContext2(Display *dpy, int scrn,
+ GLXDrawable draw, GLXDrawable read,
+ GLXContext gc)
+{
+ return driUnbindContext3(dpy, scrn, draw, read, & gc->driContext);
+}
+
+/*
+ * Simply call bind with the same GLXDrawable for the read and draw buffers.
+ */
+static Bool driBindContext(Display *dpy, int scrn,
+ GLXDrawable draw, GLXContext gc)
+{
+ return driBindContext2(dpy, scrn, draw, draw, gc);
+}
+
+
+/*
+ * Simply call bind with the same GLXDrawable for the read and draw buffers.
+ */
+static Bool driUnbindContext(Display *dpy, int scrn,
+ GLXDrawable draw, GLXContext gc,
+ int will_rebind)
+{
+ (void) will_rebind;
+ return driUnbindContext2( dpy, scrn, draw, draw, gc );
+}
+#endif /* DRI_NEW_INTERFACE_ONLY */
+
+/*@}*/
+
+
+/*****************************************************************/
+/** \name Drawable handling functions */
+/*****************************************************************/
+/*@{*/
+
+/**
+ * Update private drawable information.
+ *
+ * \param pdp pointer to the private drawable information to update.
+ *
+ * This function basically updates the __DRIdrawablePrivate struct's
+ * cliprect information by calling \c __DRIDrawablePrivate::getInfo. This is
+ * usually called by the DRI_VALIDATE_DRAWABLE_INFO macro which
+ * compares the __DRIdrwablePrivate pStamp and lastStamp values. If
+ * the values are different that means we have to update the clipping
+ * info.
+ */
+void
+__driUtilUpdateDrawableInfo(__DRIdrawablePrivate *pdp)
+{
+ __DRIscreenPrivate *psp;
+ __DRIcontextPrivate *pcp = pdp->driContextPriv;
+
+ if (!pcp || (pdp != pcp->driDrawablePriv)) {
+ /* ERROR!!! */
+ return;
+ }
+
+ psp = pdp->driScreenPriv;
+ if (!psp) {
+ /* ERROR!!! */
+ return;
+ }
+
+ if (pdp->pClipRects) {
+ Xfree(pdp->pClipRects);
+ }
+
+ if (pdp->pBackClipRects) {
+ Xfree(pdp->pBackClipRects);
+ }
+
+ DRM_SPINUNLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID);
+
+ if (!__driFindDrawable(psp->drawHash, pdp->draw) ||
+ ! (*pdp->getInfo)(pdp->display, pdp->screen, pdp->draw,
+ &pdp->index, &pdp->lastStamp,
+ &pdp->x, &pdp->y, &pdp->w, &pdp->h,
+ &pdp->numClipRects, &pdp->pClipRects,
+ &pdp->backX,
+ &pdp->backY,
+ &pdp->numBackClipRects,
+ &pdp->pBackClipRects )) {
+ /* Error -- eg the window may have been destroyed. Keep going
+ * with no cliprects.
+ */
+ pdp->pStamp = &pdp->lastStamp; /* prevent endless loop */
+ pdp->numClipRects = 0;
+ pdp->pClipRects = NULL;
+ pdp->numBackClipRects = 0;
+ pdp->pBackClipRects = NULL;
+ }
+ else
+ pdp->pStamp = &(psp->pSAREA->drawableTable[pdp->index].stamp);
+
+ DRM_SPINLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID);
+
+}
+
+/*@}*/
+
+/*****************************************************************/
+/** \name GLX callbacks */
+/*****************************************************************/
+/*@{*/
+
+/**
+ * Swap buffers.
+ *
+ * \param dpy the display handle.
+ * \param drawablePrivate opaque pointer to the per-drawable private info.
+ *
+ * \internal
+ * This function calls __DRIdrawablePrivate::swapBuffers.
+ *
+ * Is called directly from glXSwapBuffers().
+ */
+static void driSwapBuffers( Display *dpy, void *drawablePrivate )
+{
+ __DRIdrawablePrivate *dPriv = (__DRIdrawablePrivate *) drawablePrivate;
+ dPriv->swapBuffers(dPriv);
+ (void) dpy;
+}
+
+/**
+ * Called directly from a number of higher-level GLX functions.
+ */
+static int driGetMSC( void *screenPrivate, int64_t *msc )
+{
+ __DRIscreenPrivate *sPriv = (__DRIscreenPrivate *) screenPrivate;
+
+ return sPriv->DriverAPI.GetMSC( sPriv, msc );
+}
+
+/**
+ * Called directly from a number of higher-level GLX functions.
+ */
+static int driGetSBC( Display *dpy, void *drawablePrivate, int64_t *sbc )
+{
+ __DRIdrawablePrivate *dPriv = (__DRIdrawablePrivate *) drawablePrivate;
+ __DRIswapInfo sInfo;
+ int status;
+
+
+ status = dPriv->driScreenPriv->DriverAPI.GetSwapInfo( dPriv, & sInfo );
+ *sbc = sInfo.swap_count;
+
+ return status;
+}
+
+static int driWaitForSBC( Display * dpy, void *drawablePriv,
+ int64_t target_sbc,
+ int64_t * msc, int64_t * sbc )
+{
+ __DRIdrawablePrivate *dPriv = (__DRIdrawablePrivate *) drawablePriv;
+
+ return dPriv->driScreenPriv->DriverAPI.WaitForSBC( dPriv, target_sbc,
+ msc, sbc );
+}
+
+static int driWaitForMSC( Display * dpy, void *drawablePriv,
+ int64_t target_msc,
+ int64_t divisor, int64_t remainder,
+ int64_t * msc, int64_t * sbc )
+{
+ __DRIdrawablePrivate *dPriv = (__DRIdrawablePrivate *) drawablePriv;
+ __DRIswapInfo sInfo;
+ int status;
+
+
+ status = dPriv->driScreenPriv->DriverAPI.WaitForMSC( dPriv, target_msc,
+ divisor, remainder,
+ msc );
+
+ /* GetSwapInfo() may not be provided by the driver if GLX_SGI_video_sync
+ * is supported but GLX_OML_sync_control is not. Therefore, don't return
+ * an error value if GetSwapInfo() is not implemented.
+ */
+ if ( status == 0
+ && dPriv->driScreenPriv->DriverAPI.GetSwapInfo ) {
+ status = dPriv->driScreenPriv->DriverAPI.GetSwapInfo( dPriv, & sInfo );
+ *sbc = sInfo.swap_count;
+ }
+
+ return status;
+}
+
+static int64_t driSwapBuffersMSC( Display * dpy, void *drawablePriv,
+ int64_t target_msc,
+ int64_t divisor, int64_t remainder )
+{
+ __DRIdrawablePrivate *dPriv = (__DRIdrawablePrivate *) drawablePriv;
+
+ return dPriv->driScreenPriv->DriverAPI.SwapBuffersMSC( dPriv, target_msc,
+ divisor,
+ remainder );
+}
+
+
+/**
+ * This is called via __DRIscreenRec's createNewDrawable pointer.
+ */
+static void *driCreateNewDrawable(Display *dpy,
+ const __GLcontextModes *modes,
+ GLXDrawable draw,
+ __DRIdrawable *pdraw,
+ int renderType,
+ const int *attrs)
+{
+ __DRIscreen * const pDRIScreen = __glXFindDRIScreen(dpy, modes->screen);
+ __DRIscreenPrivate *psp;
+ __DRIdrawablePrivate *pdp;
+
+
+ /* Since pbuffers are not yet supported, no drawable attributes are
+ * supported either.
+ */
+ (void) attrs;
+
+ if ( (pDRIScreen == NULL) || (pDRIScreen->private == NULL) ) {
+ return NULL;
+ }
+
+ pdp = (__DRIdrawablePrivate *)Xmalloc(sizeof(__DRIdrawablePrivate));
+ if (!pdp) {
+ return NULL;
+ }
+
+ if (!XF86DRICreateDrawable(dpy, modes->screen, draw, &pdp->hHWDrawable)) {
+ Xfree(pdp);
+ return NULL;
+ }
+
+ pdp->draw = draw;
+ pdp->pdraw = pdraw;
+ pdp->refcount = 0;
+ pdp->pStamp = NULL;
+ pdp->lastStamp = 0;
+ pdp->index = 0;
+ pdp->x = 0;
+ pdp->y = 0;
+ pdp->w = 0;
+ pdp->h = 0;
+ pdp->numClipRects = 0;
+ pdp->numBackClipRects = 0;
+ pdp->pClipRects = NULL;
+ pdp->pBackClipRects = NULL;
+ pdp->display = dpy;
+ pdp->screen = modes->screen;
+
+ psp = (__DRIscreenPrivate *)pDRIScreen->private;
+ pdp->driScreenPriv = psp;
+ pdp->driContextPriv = &psp->dummyContextPriv;
+
+ pdp->getInfo = (GetDrawableInfo *)
+ glXGetProcAddress( (const GLubyte *) "__glXGetDrawableInfo" );
+ if ( pdp->getInfo == NULL ) {
+ pdp->getInfo = XF86DRIGetDrawableInfo;
+ }
+
+ if (!(*psp->DriverAPI.CreateBuffer)(psp, pdp, modes,
+ renderType == GLX_PIXMAP_BIT)) {
+ (void)XF86DRIDestroyDrawable(dpy, modes->screen, pdp->draw);
+ Xfree(pdp);
+ return NULL;
+ }
+
+ pdraw->private = pdp;
+ pdraw->destroyDrawable = driDestroyDrawable;
+ pdraw->swapBuffers = driSwapBuffers; /* called by glXSwapBuffers() */
+
+ if ( driCompareGLXAPIVersion( 20030317 ) >= 0 ) {
+ pdraw->getSBC = driGetSBC;
+ pdraw->waitForSBC = driWaitForSBC;
+ pdraw->waitForMSC = driWaitForMSC;
+ pdraw->swapBuffersMSC = driSwapBuffersMSC;
+ pdraw->frameTracking = NULL;
+ pdraw->queryFrameTracking = driQueryFrameTracking;
+
+ /* This special default value is replaced with the configured
+ * default value when the drawable is first bound to a direct
+ * rendering context. */
+ pdraw->swap_interval = (unsigned)-1;
+ }
+
+ pdp->swapBuffers = psp->DriverAPI.SwapBuffers;
+
+ /* Add pdraw to drawable list */
+ if (!__driAddDrawable(psp->drawHash, pdraw)) {
+ /* ERROR!!! */
+ (*pdraw->destroyDrawable)(dpy, pdp);
+ Xfree(pdp);
+ pdp = NULL;
+ pdraw->private = NULL;
+ }
+
+ return (void *) pdp;
+}
+
+static __DRIdrawable *driGetDrawable(Display *dpy, GLXDrawable draw,
+ void *screenPrivate)
+{
+ __DRIscreenPrivate *psp = (__DRIscreenPrivate *) screenPrivate;
+
+ /*
+ ** Make sure this routine returns NULL if the drawable is not bound
+ ** to a direct rendering context!
+ */
+ return __driFindDrawable(psp->drawHash, draw);
+}
+
+static void driDestroyDrawable(Display *dpy, void *drawablePrivate)
+{
+ __DRIdrawablePrivate *pdp = (__DRIdrawablePrivate *) drawablePrivate;
+ __DRIscreenPrivate *psp = pdp->driScreenPriv;
+ int scrn = psp->myNum;
+
+ if (pdp) {
+ (*psp->DriverAPI.DestroyBuffer)(pdp);
+ if ((*window_exists)(dpy, pdp->draw))
+ (void)XF86DRIDestroyDrawable(dpy, scrn, pdp->draw);
+ if (pdp->pClipRects) {
+ Xfree(pdp->pClipRects);
+ pdp->pClipRects = NULL;
+ }
+ if (pdp->pBackClipRects) {
+ Xfree(pdp->pBackClipRects);
+ pdp->pBackClipRects = NULL;
+ }
+ Xfree(pdp);
+ }
+}
+
+/*@}*/
+
+
+/*****************************************************************/
+/** \name Context handling functions */
+/*****************************************************************/
+/*@{*/
+
+/**
+ * Destroy the per-context private information.
+ *
+ * \param dpy the display handle.
+ * \param scrn the screen number.
+ * \param contextPrivate opaque pointer to the per-drawable private info.
+ *
+ * \internal
+ * This function calls __DriverAPIRec::DestroyContext on \p contextPrivate, calls
+ * drmDestroyContext(), and finally frees \p contextPrivate.
+ */
+static void driDestroyContext(Display *dpy, int scrn, void *contextPrivate)
+{
+ __DRIcontextPrivate *pcp = (__DRIcontextPrivate *) contextPrivate;
+
+ if (pcp) {
+ (*pcp->driScreenPriv->DriverAPI.DestroyContext)(pcp);
+ __driGarbageCollectDrawables(pcp->driScreenPriv->drawHash);
+ (void)XF86DRIDestroyContext(dpy, scrn, pcp->contextID);
+ Xfree(pcp);
+ }
+}
+
+
+/**
+ * Create the per-drawable private driver information.
+ *
+ * \param dpy The display handle.
+ * \param modes Mode used to create the new context.
+ * \param render_type Type of rendering target. \c GLX_RGBA is the only
+ * type likely to ever be supported for direct-rendering.
+ * \param sharedPrivate The shared context dependent methods or \c NULL if
+ * non-existent.
+ * \param pctx DRI context to receive the context dependent methods.
+ *
+ * \returns An opaque pointer to the per-context private information on
+ * success, or \c NULL on failure.
+ *
+ * \internal
+ * This function allocates and fills a __DRIcontextPrivateRec structure. It
+ * performs some device independent initialization and passes all the
+ * relevent information to __DriverAPIRec::CreateContext to create the
+ * context.
+ *
+ */
+static void *
+driCreateNewContext(Display *dpy, const __GLcontextModes *modes,
+ int render_type, void *sharedPrivate, __DRIcontext *pctx)
+{
+ __DRIscreen *pDRIScreen;
+ __DRIcontextPrivate *pcp;
+ __DRIcontextPrivate *pshare = (__DRIcontextPrivate *) sharedPrivate;
+ __DRIscreenPrivate *psp;
+ void * const shareCtx = (pshare != NULL) ? pshare->driverPrivate : NULL;
+
+ pDRIScreen = __glXFindDRIScreen(dpy, modes->screen);
+ if ( (pDRIScreen == NULL) || (pDRIScreen->private == NULL) ) {
+ /* ERROR!!! */
+ return NULL;
+ }
+
+ psp = (__DRIscreenPrivate *)pDRIScreen->private;
+
+ pcp = (__DRIcontextPrivate *)Xmalloc(sizeof(__DRIcontextPrivate));
+ if (!pcp) {
+ return NULL;
+ }
+
+ if (! (*create_context_with_config)(dpy, modes->screen, modes->fbconfigID,
+ &pcp->contextID, &pcp->hHWContext)) {
+ Xfree(pcp);
+ return NULL;
+ }
+
+ pcp->display = dpy;
+ pcp->driScreenPriv = psp;
+ pcp->driDrawablePriv = NULL;
+
+ /* When the first context is created for a screen, initialize a "dummy"
+ * context.
+ */
+
+ if (!psp->dummyContextPriv.driScreenPriv) {
+ psp->dummyContextPriv.contextID = 0;
+ psp->dummyContextPriv.hHWContext = psp->pSAREA->dummy_context;
+ psp->dummyContextPriv.driScreenPriv = psp;
+ psp->dummyContextPriv.driDrawablePriv = NULL;
+ psp->dummyContextPriv.driverPrivate = NULL;
+ /* No other fields should be used! */
+ }
+
+ pctx->destroyContext = driDestroyContext;
+#ifdef DRI_NEW_INTERFACE_ONLY
+ pctx->bindContext = NULL;
+ pctx->unbindContext = NULL;
+ pctx->bindContext2 = NULL;
+ pctx->unbindContext2 = NULL;
+ pctx->bindContex3 = driBindContext3;
+ pctx->unbindContext3 = driUnbindContext3;
+#else
+ pctx->bindContext = driBindContext;
+ pctx->unbindContext = driUnbindContext;
+ if ( driCompareGLXAPIVersion( 20030606 ) >= 0 ) {
+ pctx->bindContext2 = driBindContext2;
+ pctx->unbindContext2 = driUnbindContext2;
+ }
+
+ if ( driCompareGLXAPIVersion( 20040415 ) >= 0 ) {
+ pctx->bindContext3 = driBindContext3;
+ pctx->unbindContext3 = driUnbindContext3;
+ }
+#endif
+
+ if ( !(*psp->DriverAPI.CreateContext)(modes, pcp, shareCtx) ) {
+ (void)XF86DRIDestroyContext(dpy, modes->screen, pcp->contextID);
+ Xfree(pcp);
+ return NULL;
+ }
+
+ __driGarbageCollectDrawables(pcp->driScreenPriv->drawHash);
+
+ return pcp;
+}
+
+
+#ifndef DRI_NEW_INTERFACE_ONLY
+/**
+ * Create the per-drawable private driver information.
+ *
+ * \param dpy the display handle.
+ * \param vis the visual information.
+ * \param sharedPrivate the shared context dependent methods or \c NULL if
+ * non-existent.
+ * \param pctx will receive the context dependent methods.
+ *
+ * \returns a opaque pointer to the per-context private information on success, or \c NULL
+ * on failure.
+ *
+ * \deprecated
+ * This function has been replaced by \c driCreateNewContext. In drivers
+ * built to work with XFree86, this function will continue to exist to support
+ * older versions of libGL. Starting with the next major relelase of XFree86,
+ * this function will be removed.
+ *
+ * \internal
+ * This function allocates and fills a __DRIcontextPrivateRec structure. It
+ * gets the visual, converts it into a __GLcontextModesRec and passes it
+ * to __DriverAPIRec::CreateContext to create the context.
+ */
+static void *driCreateContext(Display *dpy, XVisualInfo *vis,
+ void *sharedPrivate, __DRIcontext *pctx)
+{
+ __DRIscreen *pDRIScreen;
+ const __GLcontextModes *modes;
+
+ pDRIScreen = __glXFindDRIScreen(dpy, vis->screen);
+ if ( (pDRIScreen == NULL) || (pDRIScreen->private == NULL) ) {
+ /* ERROR!!! */
+ return NULL;
+ }
+
+
+ /* Setup a __GLcontextModes struct corresponding to vis->visualid
+ * and create the rendering context.
+ */
+
+ modes = findConfigMode(dpy, vis->screen, vis->visualid, pDRIScreen);
+ return (modes == NULL)
+ ? NULL
+ : driCreateNewContext( dpy, modes, GLX_RGBA_TYPE,
+ sharedPrivate, pctx );
+}
+#endif /* DRI_NEW_INTERFACE_ONLY */
+
+/*@}*/
+
+
+/*****************************************************************/
+/** \name Screen handling functions */
+/*****************************************************************/
+/*@{*/
+
+/**
+ * Destroy the per-screen private information.
+ *
+ * \param dpy the display handle.
+ * \param scrn the screen number.
+ * \param screenPrivate opaque pointer to the per-screen private information.
+ *
+ * \internal
+ * This function calls __DriverAPIRec::DestroyScreen on \p screenPrivate, calls
+ * drmClose(), and finally frees \p screenPrivate.
+ */
+static void driDestroyScreen(Display *dpy, int scrn, void *screenPrivate)
+{
+ __DRIscreenPrivate *psp = (__DRIscreenPrivate *) screenPrivate;
+
+ if (psp) {
+ /* No interaction with the X-server is possible at this point. This
+ * routine is called after XCloseDisplay, so there is no protocol
+ * stream open to the X-server anymore.
+ */
+
+ if (psp->DriverAPI.DestroyScreen)
+ (*psp->DriverAPI.DestroyScreen)(psp);
+
+ (void)drmUnmap((drmAddress)psp->pSAREA, SAREA_MAX);
+ (void)drmUnmap((drmAddress)psp->pFB, psp->fbSize);
+ Xfree(psp->pDevPriv);
+ (void)drmClose(psp->fd);
+ if ( psp->modes != NULL ) {
+ _gl_context_modes_destroy( psp->modes );
+ }
+ Xfree(psp);
+ }
+}
+
+
+/**
+ * Utility function used to create a new driver-private screen structure.
+ *
+ * \param dpy Display pointer
+ * \param scrn Index of the screen
+ * \param psc DRI screen data (not driver private)
+ * \param modes Linked list of known display modes. This list is, at a
+ * minimum, a list of modes based on the current display mode.
+ * These roughly match the set of available X11 visuals, but it
+ * need not be limited to X11! The calling libGL should create
+ * a list that will inform the driver of the current display
+ * mode (i.e., color buffer depth, depth buffer depth, etc.).
+ * \param ddx_version Version of the 2D DDX. This may not be meaningful for
+ * all drivers.
+ * \param dri_version Version of the "server-side" DRI.
+ * \param drm_version Version of the kernel DRM.
+ * \param frame_buffer Data describing the location and layout of the
+ * framebuffer.
+ * \param pSAREA Pointer the the SAREA.
+ * \param fd Device handle for the DRM.
+ * \param internal_api_version Version of the internal interface between the
+ * driver and libGL.
+ * \param driverAPI Driver API functions used by other routines in dri_util.c.
+ */
+__DRIscreenPrivate *
+__driUtilCreateNewScreen(Display *dpy, int scrn, __DRIscreen *psc,
+ __GLcontextModes * modes,
+ const __DRIversion * ddx_version,
+ const __DRIversion * dri_version,
+ const __DRIversion * drm_version,
+ const __DRIframebuffer * frame_buffer,
+ drmAddress pSAREA,
+ int fd,
+ int internal_api_version,
+ const struct __DriverAPIRec *driverAPI)
+{
+ __DRIscreenPrivate *psp;
+
+
+#ifdef DRI_NEW_INTERFACE_ONLY
+ if ( internal_api_version < 20040415 ) {
+ fprintf( stderr, "libGL error: libGL.so version (%08u) is too old. "
+ "20040415 or later is required.\n", internal_api_version );
+ return NULL;
+ }
+#else
+ if ( internal_api_version == 20031201 ) {
+ fprintf( stderr, "libGL error: libGL version 20031201 has critical "
+ "binary compatilibity bugs.\nlibGL error: You must upgrade "
+ "to use direct-rendering!\n" );
+ return NULL;
+ }
+#endif /* DRI_NEW_INTERFACE_ONLY */
+
+
+ window_exists = (PFNGLXWINDOWEXISTSPROC)
+ glXGetProcAddress( (const GLubyte *) "__glXWindowExists" );
+
+ if ( window_exists == NULL ) {
+#ifdef DRI_NEW_INTERFACE_ONLY
+ fprintf( stderr, "libGL error: libGL.so version (%08u) is too old. "
+ "20021128 or later is required.\n", internal_api_version );
+ return NULL;
+#else
+ window_exists = (PFNGLXWINDOWEXISTSPROC) __driWindowExists;
+#endif /* DRI_NEW_INTERFACE_ONLY */
+ }
+
+ create_context_with_config = (PFNGLXCREATECONTEXTWITHCONFIGPROC)
+ glXGetProcAddress( (const GLubyte *) "__glXCreateContextWithConfig" );
+ if ( create_context_with_config == NULL ) {
+#ifdef DRI_NEW_INTERFACE_ONLY
+ fprintf( stderr, "libGL error: libGL.so version (%08u) is too old. "
+ "20031201 or later is required.\n", internal_api_version );
+ return NULL;
+#else
+ create_context_with_config = (PFNGLXCREATECONTEXTWITHCONFIGPROC)
+ fake_XF86DRICreateContextWithConfig;
+#endif /* DRI_NEW_INTERFACE_ONLY */
+ }
+
+ api_ver = internal_api_version;
+
+ psp = (__DRIscreenPrivate *)Xmalloc(sizeof(__DRIscreenPrivate));
+ if (!psp) {
+ return NULL;
+ }
+
+ /* Create the hash table */
+ psp->drawHash = drmHashCreate();
+ if ( psp->drawHash == NULL ) {
+ Xfree( psp );
+ return NULL;
+ }
+
+ psp->display = dpy;
+ psp->myNum = scrn;
+ psp->psc = psc;
+ psp->modes = modes;
+
+ /*
+ ** NOT_DONE: This is used by the X server to detect when the client
+ ** has died while holding the drawable lock. The client sets the
+ ** drawable lock to this value.
+ */
+ psp->drawLockID = 1;
+
+ psp->drmMajor = drm_version->major;
+ psp->drmMinor = drm_version->minor;
+ psp->drmPatch = drm_version->patch;
+ psp->ddxMajor = ddx_version->major;
+ psp->ddxMinor = ddx_version->minor;
+ psp->ddxPatch = ddx_version->patch;
+ psp->driMajor = dri_version->major;
+ psp->driMinor = dri_version->minor;
+ psp->driPatch = dri_version->patch;
+
+ /* install driver's callback functions */
+ memcpy( &psp->DriverAPI, driverAPI, sizeof(struct __DriverAPIRec) );
+
+ psp->pSAREA = pSAREA;
+
+ psp->pFB = frame_buffer->base;
+ psp->fbSize = frame_buffer->size;
+ psp->fbStride = frame_buffer->stride;
+ psp->fbWidth = frame_buffer->width;
+ psp->fbHeight = frame_buffer->height;
+ psp->devPrivSize = frame_buffer->dev_priv_size;
+ psp->pDevPriv = frame_buffer->dev_priv;
+
+ psp->fd = fd;
+
+ /*
+ ** Do not init dummy context here; actual initialization will be
+ ** done when the first DRI context is created. Init screen priv ptr
+ ** to NULL to let CreateContext routine that it needs to be inited.
+ */
+ psp->dummyContextPriv.driScreenPriv = NULL;
+
+ psc->destroyScreen = driDestroyScreen;
+#ifndef DRI_NEW_INTERFACE_ONLY
+ psc->createContext = driCreateContext;
+#else
+ psc->createConteext = NULL;
+#endif
+ psc->createNewDrawable = driCreateNewDrawable;
+ psc->getDrawable = driGetDrawable;
+#ifdef DRI_NEW_INTERFACE_ONLY
+ psc->getMSC = driGetMSC;
+ psc->createNewContext = driCreateNewContext;
+#else
+ if ( driCompareGLXAPIVersion( 20030317 ) >= 0 ) {
+ psc->getMSC = driGetMSC;
+
+ if ( driCompareGLXAPIVersion( 20030824 ) >= 0 ) {
+ psc->createNewContext = driCreateNewContext;
+ }
+ }
+#endif
+
+ if ( (psp->DriverAPI.InitDriver != NULL)
+ && !(*psp->DriverAPI.InitDriver)(psp) ) {
+ Xfree( psp );
+ return NULL;
+ }
+
+
+ return psp;
+}
+
+
+#ifndef DRI_NEW_INTERFACE_ONLY
+/**
+ * Utility function used to create a new driver-private screen structure.
+ *
+ * \param dpy Display pointer.
+ * \param scrn Index of the screen.
+ * \param psc DRI screen data (not driver private)
+ * \param numConfigs Number of visual configs pointed to by \c configs.
+ * \param configs Array of GLXvisualConfigs exported by the 2D driver.
+ * \param driverAPI Driver API functions used by other routines in dri_util.c.
+ *
+ * \deprecated
+ * This function has been replaced by \c __driUtilCreateNewScreen. In drivers
+ * built to work with XFree86, this function will continue to exist to support
+ * older versions of libGL. Starting with the next major relelase of XFree86,
+ * this function will be removed.
+ */
+__DRIscreenPrivate *
+__driUtilCreateScreen(Display *dpy, int scrn, __DRIscreen *psc,
+ int numConfigs, __GLXvisualConfig *configs,
+ const struct __DriverAPIRec *driverAPI)
+{
+ int directCapable;
+ __DRIscreenPrivate *psp = NULL;
+ drmHandle hSAREA;
+ drmAddress pSAREA;
+ char *BusID;
+ __GLcontextModes *modes;
+ __GLcontextModes *temp;
+ int i;
+ __DRIversion ddx_version;
+ __DRIversion dri_version;
+ __DRIversion drm_version;
+ __DRIframebuffer framebuffer;
+ int fd = -1;
+ int status;
+ const char * err_msg;
+ const char * err_extra;
+
+
+ if (!XF86DRIQueryDirectRenderingCapable(dpy, scrn, &directCapable)
+ || !directCapable) {
+ return NULL;
+ }
+
+
+ /* Create the linked list of context modes, and populate it with the
+ * GLX visual information passed in by libGL.
+ */
+
+ modes = _gl_context_modes_create( numConfigs, sizeof(__GLcontextModes) );
+ if ( modes == NULL ) {
+ return NULL;
+ }
+
+ temp = modes;
+ for ( i = 0 ; i < numConfigs ; i++ ) {
+ assert( temp != NULL );
+ _gl_copy_visual_to_context_mode( temp, & configs[i] );
+ temp->screen = scrn;
+
+ temp = temp->next;
+ }
+
+ err_msg = "XF86DRIOpenConnection";
+ err_extra = NULL;
+
+ if (XF86DRIOpenConnection(dpy, scrn, &hSAREA, &BusID)) {
+ fd = drmOpen(NULL,BusID);
+ Xfree(BusID); /* No longer needed */
+
+ err_msg = "open DRM";
+ err_extra = strerror( -fd );
+
+ if (fd >= 0) {
+ drmMagic magic;
+
+ err_msg = "drmGetMagic";
+ err_extra = NULL;
+
+ if (!drmGetMagic(fd, &magic)) {
+ drmVersionPtr version = drmGetVersion(fd);
+ if (version) {
+ drm_version.major = version->version_major;
+ drm_version.minor = version->version_minor;
+ drm_version.patch = version->version_patchlevel;
+ drmFreeVersion(version);
+ }
+ else {
+ drm_version.major = -1;
+ drm_version.minor = -1;
+ drm_version.patch = -1;
+ }
+
+ err_msg = "XF86DRIAuthConnection";
+ if (XF86DRIAuthConnection(dpy, scrn, magic)) {
+ char *driverName;
+
+ /*
+ * Get device name (like "tdfx") and the ddx version numbers.
+ * We'll check the version in each DRI driver's "createScreen"
+ * function.
+ */
+ err_msg = "XF86DRIGetClientDriverName";
+ if (XF86DRIGetClientDriverName(dpy, scrn,
+ &ddx_version.major,
+ &ddx_version.minor,
+ &ddx_version.patch,
+ &driverName)) {
+
+ /* No longer needed. */
+ Xfree( driverName );
+
+ /*
+ * Get the DRI X extension version.
+ */
+ err_msg = "XF86DRIQueryVersion";
+ if (XF86DRIQueryVersion(dpy,
+ &dri_version.major,
+ &dri_version.minor,
+ &dri_version.patch)) {
+ drmHandle hFB;
+ int junk;
+
+ /*
+ * Get device-specific info. pDevPriv will point to a struct
+ * (such as DRIRADEONRec in xfree86/driver/ati/radeon_dri.h)
+ * that has information about the screen size, depth, pitch,
+ * ancilliary buffers, DRM mmap handles, etc.
+ */
+ err_msg = "XF86DRIGetDeviceInfo";
+ if (XF86DRIGetDeviceInfo(dpy, scrn,
+ &hFB,
+ &junk,
+ &framebuffer.size,
+ &framebuffer.stride,
+ &framebuffer.dev_priv_size,
+ &framebuffer.dev_priv)) {
+ framebuffer.width = DisplayWidth(dpy, scrn);
+ framebuffer.height = DisplayHeight(dpy, scrn);
+
+ /*
+ * Map the framebuffer region.
+ */
+ status = drmMap(fd, hFB, framebuffer.size,
+ (drmAddressPtr)&framebuffer.base);
+
+ err_msg = "drmMap of framebuffer";
+ err_extra = strerror( -status );
+
+ if ( status == 0 ) {
+ /*
+ * Map the SAREA region. Further mmap regions may be setup in
+ * each DRI driver's "createScreen" function.
+ */
+ status = drmMap(fd, hSAREA, SAREA_MAX,
+ &pSAREA);
+
+ err_msg = "drmMap of sarea";
+ err_extra = strerror( -status );
+
+ if ( status == 0 ) {
+ PFNGLXGETINTERNALVERSIONPROC get_ver;
+
+ get_ver = (PFNGLXGETINTERNALVERSIONPROC)
+ glXGetProcAddress( (const GLubyte *) "__glXGetInternalVersion" );
+
+ err_msg = "InitDriver";
+ err_extra = NULL;
+ psp = __driUtilCreateNewScreen( dpy, scrn, psc, modes,
+ & ddx_version,
+ & dri_version,
+ & drm_version,
+ & framebuffer,
+ pSAREA,
+ fd,
+ (get_ver != NULL) ? (*get_ver)() : 1,
+ driverAPI );
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if ( psp == NULL ) {
+ if ( pSAREA != MAP_FAILED ) {
+ (void)drmUnmap(pSAREA, SAREA_MAX);
+ }
+
+ if ( framebuffer.base != MAP_FAILED ) {
+ (void)drmUnmap((drmAddress)framebuffer.base, framebuffer.size);
+ }
+
+ if ( framebuffer.dev_priv != NULL ) {
+ Xfree(framebuffer.dev_priv);
+ }
+
+ if ( fd >= 0 ) {
+ (void)drmClose(fd);
+ }
+
+ if ( modes != NULL ) {
+ _gl_context_modes_destroy( modes );
+ }
+
+ (void)XF86DRICloseConnection(dpy, scrn);
+
+ if ( err_extra != NULL ) {
+ fprintf(stderr, "libGL error: %s failed (%s)\n", err_msg,
+ err_extra);
+ }
+ else {
+ fprintf(stderr, "libGL error: %s failed\n", err_msg );
+ }
+
+ fprintf(stderr, "libGL error: reverting to (slow) indirect rendering\n");
+ }
+
+ return psp;
+}
+#endif /* DRI_NEW_INTERFACE_ONLY */
+
+
+/**
+ * Compare the current GLX API version with a driver supplied required version.
+ *
+ * The minimum required version is compared with the API version exported by
+ * the \c __glXGetInternalVersion function (in libGL.so).
+ *
+ * \param required_version Minimum required internal GLX API version.
+ * \return A tri-value return, as from strcmp is returned. A value less
+ * than, equal to, or greater than zero will be returned if the
+ * internal GLX API version is less than, equal to, or greater
+ * than \c required_version.
+ *
+ * \sa __glXGetInternalVersion().
+ */
+int driCompareGLXAPIVersion( GLuint required_version )
+{
+ if ( api_ver > required_version ) {
+ return 1;
+ }
+ else if ( api_ver == required_version ) {
+ return 0;
+ }
+
+ return -1;
+}
+
+
+static int
+driQueryFrameTracking( Display * dpy, void * priv,
+ int64_t * sbc, int64_t * missedFrames,
+ float * lastMissedUsage, float * usage )
+{
+ static PFNGLXGETUSTPROC get_ust;
+ __DRIswapInfo sInfo;
+ int status;
+ int64_t ust;
+ __DRIdrawablePrivate * dpriv = (__DRIdrawablePrivate *) priv;
+
+ if ( get_ust == NULL ) {
+ get_ust = (PFNGLXGETUSTPROC) glXGetProcAddress( (const GLubyte *) "__glXGetUST" );
+ }
+
+ status = dpriv->driScreenPriv->DriverAPI.GetSwapInfo( dpriv, & sInfo );
+ if ( status == 0 ) {
+ *sbc = sInfo.swap_count;
+ *missedFrames = sInfo.swap_missed_count;
+ *lastMissedUsage = sInfo.swap_missed_usage;
+
+ (*get_ust)( & ust );
+ *usage = driCalculateSwapUsage( dpriv, sInfo.swap_ust, ust );
+ }
+
+ return status;
+}
+
+
+/**
+ * Calculate amount of swap interval used between GLX buffer swaps.
+ *
+ * The usage value, on the range [0,max], is the fraction of total swap
+ * interval time used between GLX buffer swaps is calculated.
+ *
+ * \f$p = t_d / (i * t_r)\f$
+ *
+ * Where \f$t_d\f$ is the time since the last GLX buffer swap, \f$i\f$ is the
+ * swap interval (as set by \c glXSwapIntervalSGI), and \f$t_r\f$ time
+ * required for a single vertical refresh period (as returned by \c
+ * glXGetMscRateOML).
+ *
+ * See the documentation for the GLX_MESA_swap_frame_usage extension for more
+ * details.
+ *
+ * \param dPriv Pointer to the private drawable structure.
+ * \return If less than a single swap interval time period was required
+ * between GLX buffer swaps, a number greater than 0 and less than
+ * 1.0 is returned. If exactly one swap interval time period is
+ * required, 1.0 is returned, and if more than one is required then
+ * a number greater than 1.0 will be returned.
+ *
+ * \sa glXSwapIntervalSGI glXGetMscRateOML
+ *
+ * \todo Instead of caching the \c glXGetMscRateOML function pointer, would it
+ * be possible to cache the sync rate?
+ */
+float
+driCalculateSwapUsage( __DRIdrawablePrivate *dPriv, int64_t last_swap_ust,
+ int64_t current_ust )
+{
+ static PFNGLXGETMSCRATEOMLPROC get_msc_rate = NULL;
+ int32_t n;
+ int32_t d;
+ int interval;
+ float usage = 1.0;
+
+
+ if ( get_msc_rate == NULL ) {
+ get_msc_rate = (PFNGLXGETMSCRATEOMLPROC)
+ glXGetProcAddress( (const GLubyte *) "glXGetMscRateOML" );
+ }
+
+ if ( (get_msc_rate != NULL)
+ && get_msc_rate( dPriv->display, dPriv->draw, &n, &d ) ) {
+ interval = (dPriv->pdraw->swap_interval != 0)
+ ? dPriv->pdraw->swap_interval : 1;
+
+
+ /* We want to calculate
+ * (current_UST - last_swap_UST) / (interval * us_per_refresh). We get
+ * current_UST by calling __glXGetUST. last_swap_UST is stored in
+ * dPriv->swap_ust. interval has already been calculated.
+ *
+ * The only tricky part is us_per_refresh. us_per_refresh is
+ * 1000000 / MSC_rate. We know the MSC_rate is n / d. We can flip it
+ * around and say us_per_refresh = 1000000 * d / n. Since this goes in
+ * the denominator of the final calculation, we calculate
+ * (interval * 1000000 * d) and move n into the numerator.
+ */
+
+ usage = (current_ust - last_swap_ust);
+ usage *= n;
+ usage /= (interval * d);
+ usage /= 1000000.0;
+ }
+
+ return usage;
+}
+
+/*@}*/
+
+#endif /* GLX_DIRECT_RENDERING */
diff --git a/src/mesa/drivers/dri/common/dri_util.h b/src/mesa/drivers/dri/common/dri_util.h
new file mode 100644
index 0000000000..5c198810f7
--- /dev/null
+++ b/src/mesa/drivers/dri/common/dri_util.h
@@ -0,0 +1,588 @@
+/* $XFree86: xc/lib/GL/dri/dri_util.h,v 1.1 2002/02/22 21:32:52 dawes Exp $ */
+/**
+ * \file dri_util.h
+ * DRI utility functions definitions.
+ *
+ * This module acts as glue between GLX and the actual hardware driver. A DRI
+ * driver doesn't really \e have to use any of this - it's optional. But, some
+ * useful stuff is done here that otherwise would have to be duplicated in most
+ * drivers.
+ *
+ * Basically, these utility functions take care of some of the dirty details of
+ * screen initialization, context creation, context binding, DRM setup, etc.
+ *
+ * These functions are compiled into each DRI driver so libGL.so knows nothing
+ * about them.
+ *
+ * \sa dri_util.c.
+ *
+ * \author Kevin E. Martin <kevin@precisioninsight.com>
+ * \author Brian Paul <brian@precisioninsight.com>
+ */
+
+/*
+ * Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+
+#ifndef _DRI_UTIL_H_
+#define _DRI_UTIL_H_
+
+#ifdef GLX_DIRECT_RENDERING
+
+#define CAPI /* XXX this should be globally defined somewhere */
+
+#include <inttypes.h>
+#include "glxclient.h" /* for GLXDrawable */
+/* temporary */
+/* typedef Bool ( * PFNGLXGETMSCRATEOMLPROC) (Display *dpy, GLXDrawable drawable, int32_t *numerator, int32_t *denominator); */
+#include "drm.h" /* for drm_clip_rect_t */
+#include "sarea.h" /* for XF86DRISAREAPtr */
+#include "GL/internal/glcore.h" /* for __GLcontextModes */
+
+
+typedef struct __DRIdisplayPrivateRec __DRIdisplayPrivate;
+typedef struct __DRIscreenPrivateRec __DRIscreenPrivate;
+typedef struct __DRIcontextPrivateRec __DRIcontextPrivate;
+typedef struct __DRIdrawablePrivateRec __DRIdrawablePrivate;
+typedef struct __DRIswapInfoRec __DRIswapInfo;
+
+
+/**
+ * Used by DRI_VALIDATE_DRAWABLE_INFO
+ */
+#define DRI_VALIDATE_DRAWABLE_INFO_ONCE(pDrawPriv) \
+ do { \
+ if (*(pDrawPriv->pStamp) != pDrawPriv->lastStamp) { \
+ __driUtilUpdateDrawableInfo(pDrawPriv); \
+ } \
+ } while (0)
+
+
+/**
+ * Utility macro to validate the drawable information.
+ *
+ * See __DRIdrawablePrivate::pStamp and __DRIdrawablePrivate::lastStamp.
+ */
+#define DRI_VALIDATE_DRAWABLE_INFO(psp, pdp) \
+do { \
+ while (*(pdp->pStamp) != pdp->lastStamp) { \
+ DRM_UNLOCK(psp->fd, &psp->pSAREA->lock, \
+ pdp->driContextPriv->hHWContext); \
+ \
+ DRM_SPINLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID); \
+ DRI_VALIDATE_DRAWABLE_INFO_ONCE(pdp); \
+ DRM_SPINUNLOCK(&psp->pSAREA->drawable_lock, psp->drawLockID); \
+ \
+ DRM_LIGHT_LOCK(psp->fd, &psp->pSAREA->lock, \
+ pdp->driContextPriv->hHWContext); \
+ } \
+} while (0)
+
+
+/**
+ * Driver callback functions.
+ *
+ * Each DRI driver must have one of these structures with all the pointers set
+ * to appropriate functions within the driver.
+ *
+ * When glXCreateContext() is called, for example, it'll call a helper function
+ * dri_util.c which in turn will jump through the \a CreateContext pointer in
+ * this structure.
+ */
+struct __DriverAPIRec {
+ /**
+ * Driver initialization callback
+ */
+ GLboolean (*InitDriver)(__DRIscreenPrivate *driScrnPriv);
+
+ /**
+ * Screen destruction callback
+ */
+ void (*DestroyScreen)(__DRIscreenPrivate *driScrnPriv);
+
+ /**
+ * Context creation callback
+ */
+ GLboolean (*CreateContext)(const __GLcontextModes *glVis,
+ __DRIcontextPrivate *driContextPriv,
+ void *sharedContextPrivate);
+
+ /**
+ * Context destruction callback
+ */
+ void (*DestroyContext)(__DRIcontextPrivate *driContextPriv);
+
+ /**
+ * Buffer (drawable) creation callback
+ */
+ GLboolean (*CreateBuffer)(__DRIscreenPrivate *driScrnPriv,
+ __DRIdrawablePrivate *driDrawPriv,
+ const __GLcontextModes *glVis,
+ GLboolean pixmapBuffer);
+
+ /**
+ * Buffer (drawable) destruction callback
+ */
+ void (*DestroyBuffer)(__DRIdrawablePrivate *driDrawPriv);
+
+ /**
+ * Buffer swapping callback
+ */
+ void (*SwapBuffers)(__DRIdrawablePrivate *driDrawPriv);
+
+ /**
+ * Context activation callback
+ */
+ GLboolean (*MakeCurrent)(__DRIcontextPrivate *driContextPriv,
+ __DRIdrawablePrivate *driDrawPriv,
+ __DRIdrawablePrivate *driReadPriv);
+
+ /**
+ * Context unbinding callback
+ */
+ GLboolean (*UnbindContext)(__DRIcontextPrivate *driContextPriv);
+
+ /**
+ * Full screen mode opening callback.
+ *
+ * \deprecated
+ * Full screen functionality is no longer used by DRI. Drivers should
+ * simply install a function returning \c GL_TRUE for backwards
+ * compatability.
+ *
+ * \todo
+ * Nothing calls this function anymore. Since this data structure is only
+ * accessed with in the driver (i.e., libGL never sees it), we need to
+ * remove the other cases that set this field and remove the field.
+ */
+ GLboolean (*OpenFullScreen)(__DRIcontextPrivate *driContextPriv);
+
+ /**
+ * Full screen mode closing callback.
+ *
+ * \deprecated
+ * Full screen functionality is no longer used by DRI. Drivers should
+ * simply install a function returning \c GL_TRUE for backwards
+ * compatability.
+ *
+ * \todo
+ * Nothing calls this function anymore. Since this data structure is only
+ * accessed with in the driver (i.e., libGL never sees it), we need to
+ * remove the other cases that set this field and remove the field.
+ */
+ GLboolean (*CloseFullScreen)(__DRIcontextPrivate *driContextPriv);
+
+ /**
+ * Retrieves statistics about buffer swap operations. Required if
+ * GLX_OML_sync_control or GLX_MESA_swap_frame_usage is supported.
+ */
+ int (*GetSwapInfo)( __DRIdrawablePrivate *dPriv, __DRIswapInfo * sInfo );
+
+
+ /**
+ * Required if GLX_SGI_video_sync or GLX_OML_sync_control is
+ * supported.
+ */
+ int (*GetMSC)( __DRIscreenPrivate * priv, int64_t * count );
+
+ /**
+ * These are required if GLX_OML_sync_control is supported.
+ */
+ /*@{*/
+ int (*WaitForMSC)( __DRIdrawablePrivate *priv, int64_t target_msc,
+ int64_t divisor, int64_t remainder,
+ int64_t * msc );
+ int (*WaitForSBC)( __DRIdrawablePrivate *priv, int64_t target_sbc,
+ int64_t * msc, int64_t * sbc );
+
+ int64_t (*SwapBuffersMSC)( __DRIdrawablePrivate *priv, int64_t target_msc,
+ int64_t divisor, int64_t remainder );
+ /*@}*/
+};
+
+
+struct __DRIswapInfoRec {
+ /**
+ * Number of swapBuffers operations that have been *completed*.
+ */
+ uint64_t swap_count;
+
+ /**
+ * Unadjusted system time of the last buffer swap. This is the time
+ * when the swap completed, not the time when swapBuffers was called.
+ */
+ int64_t swap_ust;
+
+ /**
+ * Number of swap operations that occurred after the swap deadline. That
+ * is if a swap happens more than swap_interval frames after the previous
+ * swap, it has missed its deadline. If swap_interval is 0, then the
+ * swap deadline is 1 frame after the previous swap.
+ */
+ uint64_t swap_missed_count;
+
+ /**
+ * Amount of time used by the last swap that missed its deadline. This
+ * is calculated as (__glXGetUST() - swap_ust) / (swap_interval *
+ * time_for_single_vrefresh)). If the actual value of swap_interval is
+ * 0, then 1 is used instead. If swap_missed_count is non-zero, this
+ * should be greater-than 1.0.
+ */
+ float swap_missed_usage;
+};
+
+
+typedef Bool (GetDrawableInfo)( Display *dpy, int scrn, Drawable draw,
+ unsigned int * index, unsigned int * stamp,
+ int * x, int * y, int * width, int * height,
+ int * numClipRects, drm_clip_rect_t * pClipRects,
+ int * backX, int * backY,
+ int * numBackClipRects, drm_clip_rect_t * pBackClipRects );
+
+
+/**
+ * Per-drawable private DRI driver information.
+ */
+struct __DRIdrawablePrivateRec {
+ /**
+ * Kernel drawable handle
+ */
+ drmDrawable hHWDrawable;
+
+ /**
+ * Driver's private drawable information.
+ *
+ * This structure is opaque.
+ */
+ void *driverPrivate;
+
+ /**
+ * X's drawable ID associated with this private drawable.
+ */
+ GLXDrawable draw;
+ __DRIdrawable *pdraw;
+
+ /**
+ * Reference count for number of context's currently bound to this
+ * drawable.
+ *
+ * Once it reaches zero, the drawable can be destroyed.
+ *
+ * \note This behavior will change with GLX 1.3.
+ */
+ int refcount;
+
+ /**
+ * Index of this drawable information in the SAREA.
+ */
+ unsigned int index;
+
+ /**
+ * Pointer to the "drawable has changed ID" stamp in the SAREA.
+ */
+ unsigned int *pStamp;
+
+ /**
+ * Last value of the stamp.
+ *
+ * If this differs from the value stored at __DRIdrawablePrivate::pStamp,
+ * then the drawable information has been modified by the X server, and the
+ * drawable information (below) should be retrieved from the X server.
+ */
+ unsigned int lastStamp;
+
+ /**
+ * \name Drawable
+ *
+ * Drawable information used in software fallbacks.
+ */
+ /*@{*/
+ int x;
+ int y;
+ int w;
+ int h;
+ int numClipRects;
+ drm_clip_rect_t *pClipRects;
+ /*@}*/
+
+ /**
+ * \name Back and depthbuffer
+ *
+ * Information about the back and depthbuffer where different from above.
+ */
+ /*@{*/
+ int backX;
+ int backY;
+ int backClipRectType;
+ int numBackClipRects;
+ drm_clip_rect_t *pBackClipRects;
+ /*@}*/
+
+ /**
+ * Pointer to context to which this drawable is currently bound.
+ */
+ __DRIcontextPrivate *driContextPriv;
+
+ /**
+ * Pointer to screen on which this drawable was created.
+ */
+ __DRIscreenPrivate *driScreenPriv;
+
+ /**
+ * \name Display and screen information.
+ *
+ * Basically just need these for when the locking code needs to call
+ * __driUtilUpdateDrawableInfo() which calls XF86DRIGetDrawableInfo().
+ */
+ /*@{*/
+ Display *display;
+ int screen;
+ /*@}*/
+
+ /**
+ * Called via glXSwapBuffers().
+ */
+ void (*swapBuffers)( __DRIdrawablePrivate *dPriv );
+
+ /**
+ * Get information about the location, size, and clip rects of the
+ * drawable within the display.
+ */
+ GetDrawableInfo * getInfo;
+};
+
+/**
+ * Per-context private driver information.
+ */
+struct __DRIcontextPrivateRec {
+ /**
+ * Kernel context handle used to access the device lock.
+ */
+ XID contextID;
+
+ /**
+ * Kernel context handle used to access the device lock.
+ */
+ drmContext hHWContext;
+
+ /**
+ * Device driver's private context data. This structure is opaque.
+ */
+ void *driverPrivate;
+
+ /**
+ * This context's display pointer.
+ */
+ Display *display;
+
+ /**
+ * Pointer to drawable currently bound to this context.
+ */
+ __DRIdrawablePrivate *driDrawablePriv;
+
+ /**
+ * Pointer to screen on which this context was created.
+ */
+ __DRIscreenPrivate *driScreenPriv;
+};
+
+/**
+ * Per-screen private driver information.
+ */
+struct __DRIscreenPrivateRec {
+ /**
+ * Display for this screen
+ */
+ Display *display;
+
+ /**
+ * Current screen's number
+ */
+ int myNum;
+
+ /**
+ * Callback functions into the hardware-specific DRI driver code.
+ */
+ struct __DriverAPIRec DriverAPI;
+
+ /**
+ * \name DDX version
+ * DDX / 2D driver version information.
+ * \todo Replace these fields with a \c __DRIversionRec.
+ */
+ /*@{*/
+ int ddxMajor;
+ int ddxMinor;
+ int ddxPatch;
+ /*@}*/
+
+ /**
+ * \name DRI version
+ * DRI X extension version information.
+ * \todo Replace these fields with a \c __DRIversionRec.
+ */
+ /*@{*/
+ int driMajor;
+ int driMinor;
+ int driPatch;
+ /*@}*/
+
+ /**
+ * \name DRM version
+ * DRM (kernel module) version information.
+ * \todo Replace these fields with a \c __DRIversionRec.
+ */
+ /*@{*/
+ int drmMajor;
+ int drmMinor;
+ int drmPatch;
+ /*@}*/
+
+ /**
+ * ID used when the client sets the drawable lock.
+ *
+ * The X server uses this value to detect if the client has died while
+ * holding the drawable lock.
+ */
+ int drawLockID;
+
+ /**
+ * File descriptor returned when the kernel device driver is opened.
+ *
+ * Used to:
+ * - authenticate client to kernel
+ * - map the frame buffer, SAREA, etc.
+ * - close the kernel device driver
+ */
+ int fd;
+
+ /**
+ * SAREA pointer
+ *
+ * Used to access:
+ * - the device lock
+ * - the device-independent per-drawable and per-context(?) information
+ */
+ XF86DRISAREAPtr pSAREA;
+
+ /**
+ * \name Direct frame buffer access information
+ * Used for software fallbacks.
+ */
+ /*@{*/
+ unsigned char *pFB;
+ int fbSize;
+ int fbOrigin;
+ int fbStride;
+ int fbWidth;
+ int fbHeight;
+ int fbBPP;
+ /*@}*/
+
+ /**
+ * \name Device-dependent private information (stored in the SAREA).
+ *
+ * This data is accessed by the client driver only.
+ */
+ /*@{*/
+ void *pDevPriv;
+ int devPrivSize;
+ /*@}*/
+
+ /**
+ * Dummy context to which drawables are bound when not bound to any
+ * other context.
+ *
+ * A dummy hHWContext is created for this context, and is used by the GL
+ * core when a hardware lock is required but the drawable is not currently
+ * bound (e.g., potentially during a SwapBuffers request). The dummy
+ * context is created when the first "real" context is created on this
+ * screen.
+ */
+ __DRIcontextPrivate dummyContextPriv;
+
+ /**
+ * Hash table to hold the drawable information for this screen.
+ */
+ void *drawHash;
+
+ /**
+ * Device-dependent private information (not stored in the SAREA).
+ *
+ * This pointer is never touched by the DRI layer.
+ */
+ void *private;
+
+ /**
+ * GLX visuals / FBConfigs for this screen. These are stored as a
+ * linked list.
+ *
+ * \note
+ * This field is \b only used in conjunction with the old interfaces. If
+ * the new interfaces are used, this field will be set to \c NULL and will
+ * not be dereferenced.
+ */
+ __GLcontextModes *modes;
+
+ /**
+ * Pointer back to the \c __DRIscreen that contains this structure.
+ */
+
+ __DRIscreen *psc;
+};
+
+
+
+extern void
+__driUtilMessage(const char *f, ...);
+
+
+extern void
+__driUtilUpdateDrawableInfo(__DRIdrawablePrivate *pdp);
+
+
+extern __DRIscreenPrivate * __driUtilCreateNewScreen( Display *dpy,
+ int scrn, __DRIscreen *psc, __GLcontextModes * modes,
+ const __DRIversion * ddx_version, const __DRIversion * dri_version,
+ const __DRIversion * drm_version, const __DRIframebuffer * frame_buffer,
+ drmAddress pSAREA, int fd, int internal_api_version,
+ const struct __DriverAPIRec *driverAPI );
+
+extern __DRIscreenPrivate *
+__driUtilCreateScreen(Display *dpy, int scrn, __DRIscreen *psc,
+ int numConfigs, __GLXvisualConfig *config,
+ const struct __DriverAPIRec *driverAPI);
+
+/* Test the version of the internal GLX API. Returns a value like strcmp. */
+extern int
+driCompareGLXAPIVersion( GLuint required_version );
+
+extern float
+driCalculateSwapUsage( __DRIdrawablePrivate *dPriv,
+ int64_t last_swap_ust, int64_t current_ust );
+
+#endif /* GLX_DIRECT_RENDERING */
+
+#endif /* _DRI_UTIL_H_ */
diff --git a/src/mesa/drivers/dri/common/glcontextmodes.c b/src/mesa/drivers/dri/common/glcontextmodes.c
new file mode 100644
index 0000000000..784ad30259
--- /dev/null
+++ b/src/mesa/drivers/dri/common/glcontextmodes.c
@@ -0,0 +1,483 @@
+/*
+ * (C) Copyright IBM Corporation 2003
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * VA LINUX SYSTEM, IBM AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * \file glcontextmodes.c
+ * Utility routines for working with \c __GLcontextModes structures. At
+ * some point most or all of these functions will be moved to the Mesa
+ * code base.
+ *
+ * \author Ian Romanick <idr@us.ibm.com>
+ */
+
+#include <X11/X.h>
+#include <GL/glx.h>
+#include "GL/glxint.h"
+
+#ifdef XFree86Server
+# include "GL/glx_ansic.h"
+extern void * __glXMalloc( size_t size );
+extern void __glXFree( void * ptr );
+# define Xmalloc __glXMalloc
+# define Xfree __glXFree
+#else
+# include <X11/Xlibint.h>
+# define __glXMemset memset
+#endif /* XFree86Server */
+
+#include "glcontextmodes.h"
+
+#define NUM_VISUAL_TYPES 6
+
+/**
+ * Convert an X visual type to a GLX visual type.
+ *
+ * \param visualType X visual type (i.e., \c TrueColor, \c StaticGray, etc.)
+ * to be converted.
+ * \return If \c visualType is a valid X visual type, a GLX visual type will
+ * be returned. Otherwise \c GLX_NONE will be returned.
+ */
+GLint
+_gl_convert_from_x_visual_type( int visualType )
+{
+ static const int glx_visual_types[ NUM_VISUAL_TYPES ] = {
+ GLX_STATIC_GRAY, GLX_GRAY_SCALE,
+ GLX_STATIC_COLOR, GLX_PSEUDO_COLOR,
+ GLX_TRUE_COLOR, GLX_DIRECT_COLOR
+ };
+
+ return ( (unsigned) visualType < NUM_VISUAL_TYPES )
+ ? glx_visual_types[ visualType ] : GLX_NONE;
+}
+
+
+/**
+ * Convert a GLX visual type to an X visual type.
+ *
+ * \param visualType GLX visual type (i.e., \c GLX_TRUE_COLOR,
+ * \c GLX_STATIC_GRAY, etc.) to be converted.
+ * \return If \c visualType is a valid GLX visual type, an X visual type will
+ * be returned. Otherwise -1 will be returned.
+ */
+GLint
+_gl_convert_to_x_visual_type( int visualType )
+{
+ static const int x_visual_types[ NUM_VISUAL_TYPES ] = {
+ TrueColor, DirectColor,
+ PseudoColor, StaticColor,
+ GrayScale, StaticGray
+ };
+
+ return ( (unsigned) (visualType - GLX_TRUE_COLOR) <= NUM_VISUAL_TYPES )
+ ? x_visual_types[ visualType - GLX_TRUE_COLOR ] : -1;
+}
+
+
+/**
+ * Copy a GLX visual config structure to a GL context mode structure. All
+ * of the fields in \c config are copied to \c mode. Additional fields in
+ * \c mode that can be derrived from the fields of \c config (i.e.,
+ * \c haveDepthBuffer) are also filled in. The remaining fields in \c mode
+ * that cannot be derrived are set to default values.
+ *
+ * \param mode Destination GL context mode.
+ * \param config Source GLX visual config.
+ *
+ * \note
+ * The \c fbconfigID and \c visualID fields of the \c __GLcontextModes
+ * structure will be set to the \c vid of the \c __GLXvisualConfig structure.
+ */
+void
+_gl_copy_visual_to_context_mode( __GLcontextModes * mode,
+ const __GLXvisualConfig * config )
+{
+ __GLcontextModes * const next = mode->next;
+
+ (void) __glXMemset( mode, 0, sizeof( __GLcontextModes ) );
+ mode->next = next;
+
+ mode->visualID = config->vid;
+ mode->visualType = _gl_convert_from_x_visual_type( config->class );
+ mode->xRenderable = GL_TRUE;
+ mode->fbconfigID = config->vid;
+ mode->drawableType = GLX_WINDOW_BIT | GLX_PIXMAP_BIT;
+
+ mode->rgbMode = (config->rgba != 0);
+ mode->renderType = (mode->rgbMode) ? GLX_RGBA_BIT : GLX_COLOR_INDEX_BIT;
+
+ mode->colorIndexMode = !(mode->rgbMode);
+ mode->doubleBufferMode = (config->doubleBuffer != 0);
+ mode->stereoMode = (config->stereo != 0);
+
+ mode->haveAccumBuffer = ((config->accumRedSize +
+ config->accumGreenSize +
+ config->accumBlueSize +
+ config->accumAlphaSize) > 0);
+ mode->haveDepthBuffer = (config->depthSize > 0);
+ mode->haveStencilBuffer = (config->stencilSize > 0);
+
+ mode->redBits = config->redSize;
+ mode->greenBits = config->greenSize;
+ mode->blueBits = config->blueSize;
+ mode->alphaBits = config->alphaSize;
+ mode->redMask = config->redMask;
+ mode->greenMask = config->greenMask;
+ mode->blueMask = config->blueMask;
+ mode->alphaMask = config->alphaMask;
+ mode->rgbBits = config->bufferSize;
+ mode->indexBits = config->bufferSize;
+
+ mode->accumRedBits = config->accumRedSize;
+ mode->accumGreenBits = config->accumGreenSize;
+ mode->accumBlueBits = config->accumBlueSize;
+ mode->accumAlphaBits = config->accumAlphaSize;
+ mode->depthBits = config->depthSize;
+ mode->stencilBits = config->stencilSize;
+
+ mode->numAuxBuffers = config->auxBuffers;
+ mode->level = config->level;
+
+ mode->visualRating = config->visualRating;
+ mode->transparentPixel = config->transparentPixel;
+ mode->transparentRed = config->transparentRed;
+ mode->transparentGreen = config->transparentGreen;
+ mode->transparentBlue = config->transparentBlue;
+ mode->transparentAlpha = config->transparentAlpha;
+ mode->transparentIndex = config->transparentIndex;
+
+ mode->swapMethod = GLX_SWAP_UNDEFINED_OML;
+}
+
+
+/**
+ * Get data from a GL context mode.
+ *
+ * \param mode GL context mode whose data is to be returned.
+ * \param attribute Attribute of \c mode that is to be returned.
+ * \param value_return Location to store the data member of \c mode.
+ * \return If \c attribute is a valid attribute of \c mode, \c Success is
+ * returned. Otherwise \c GLX_BAD_ATTRIBUTE is returned.
+ */
+int
+_gl_get_context_mode_data(const __GLcontextModes *mode, int attribute,
+ int *value_return)
+{
+ switch (attribute) {
+ case GLX_USE_GL:
+ *value_return = GL_TRUE;
+ return Success;
+ case GLX_BUFFER_SIZE:
+ *value_return = mode->rgbBits;
+ return Success;
+ case GLX_RGBA:
+ *value_return = mode->rgbMode;
+ return Success;
+ case GLX_RED_SIZE:
+ *value_return = mode->redBits;
+ return Success;
+ case GLX_GREEN_SIZE:
+ *value_return = mode->greenBits;
+ return Success;
+ case GLX_BLUE_SIZE:
+ *value_return = mode->blueBits;
+ return Success;
+ case GLX_ALPHA_SIZE:
+ *value_return = mode->alphaBits;
+ return Success;
+ case GLX_DOUBLEBUFFER:
+ *value_return = mode->doubleBufferMode;
+ return Success;
+ case GLX_STEREO:
+ *value_return = mode->stereoMode;
+ return Success;
+ case GLX_AUX_BUFFERS:
+ *value_return = mode->numAuxBuffers;
+ return Success;
+ case GLX_DEPTH_SIZE:
+ *value_return = mode->depthBits;
+ return Success;
+ case GLX_STENCIL_SIZE:
+ *value_return = mode->stencilBits;
+ return Success;
+ case GLX_ACCUM_RED_SIZE:
+ *value_return = mode->accumRedBits;
+ return Success;
+ case GLX_ACCUM_GREEN_SIZE:
+ *value_return = mode->accumGreenBits;
+ return Success;
+ case GLX_ACCUM_BLUE_SIZE:
+ *value_return = mode->accumBlueBits;
+ return Success;
+ case GLX_ACCUM_ALPHA_SIZE:
+ *value_return = mode->accumAlphaBits;
+ return Success;
+ case GLX_LEVEL:
+ *value_return = mode->level;
+ return Success;
+ case GLX_TRANSPARENT_TYPE_EXT:
+ *value_return = mode->transparentPixel;
+ return Success;
+ case GLX_TRANSPARENT_RED_VALUE:
+ *value_return = mode->transparentRed;
+ return Success;
+ case GLX_TRANSPARENT_GREEN_VALUE:
+ *value_return = mode->transparentGreen;
+ return Success;
+ case GLX_TRANSPARENT_BLUE_VALUE:
+ *value_return = mode->transparentBlue;
+ return Success;
+ case GLX_TRANSPARENT_ALPHA_VALUE:
+ *value_return = mode->transparentAlpha;
+ return Success;
+ case GLX_TRANSPARENT_INDEX_VALUE:
+ *value_return = mode->transparentIndex;
+ return Success;
+ case GLX_X_VISUAL_TYPE:
+ *value_return = mode->visualType;
+ return Success;
+ case GLX_CONFIG_CAVEAT:
+ *value_return = mode->visualRating;
+ return Success;
+ case GLX_VISUAL_ID:
+ *value_return = mode->visualID;
+ return Success;
+ case GLX_DRAWABLE_TYPE:
+ *value_return = mode->drawableType;
+ return Success;
+ case GLX_RENDER_TYPE:
+ *value_return = mode->renderType;
+ return Success;
+ case GLX_X_RENDERABLE:
+ *value_return = mode->xRenderable;
+ return Success;
+ case GLX_FBCONFIG_ID:
+ *value_return = mode->fbconfigID;
+ return Success;
+ case GLX_MAX_PBUFFER_WIDTH:
+ *value_return = mode->maxPbufferWidth;
+ return Success;
+ case GLX_MAX_PBUFFER_HEIGHT:
+ *value_return = mode->maxPbufferHeight;
+ return Success;
+ case GLX_MAX_PBUFFER_PIXELS:
+ *value_return = mode->maxPbufferPixels;
+ return Success;
+ case GLX_OPTIMAL_PBUFFER_WIDTH_SGIX:
+ *value_return = mode->optimalPbufferWidth;
+ return Success;
+ case GLX_OPTIMAL_PBUFFER_HEIGHT_SGIX:
+ *value_return = mode->optimalPbufferHeight;
+ return Success;
+ case GLX_SWAP_METHOD_OML:
+ *value_return = mode->swapMethod;
+ return Success;
+ case GLX_SAMPLE_BUFFERS_SGIS:
+ *value_return = mode->sampleBuffers;
+ return Success;
+ case GLX_SAMPLES_SGIS:
+ *value_return = mode->samples;
+ return Success;
+
+ /* Applications are NOT allowed to query GLX_VISUAL_SELECT_GROUP_SGIX.
+ * It is ONLY for communication between the GLX client and the GLX
+ * server.
+ */
+ case GLX_VISUAL_SELECT_GROUP_SGIX:
+ default:
+ return GLX_BAD_ATTRIBUTE;
+ }
+}
+
+
+/**
+ * Allocate a linked list of \c __GLcontextModes structures. The fields of
+ * each structure will be initialized to "reasonable" default values. In
+ * most cases this is the default value defined by table 3.4 of the GLX
+ * 1.3 specification. This means that most values are either initialized to
+ * zero or \c GLX_DONT_CARE (which is -1). As support for additional
+ * extensions is added, the new values will be initialized to appropriate
+ * values from the extension specification.
+ *
+ * \param count Number of structures to allocate.
+ * \param minimum_size Minimum size of a structure to allocate. This allows
+ * for differences in the version of the
+ * \c __GLcontextModes stucture used in libGL and in a
+ * DRI-based driver.
+ * \returns A pointer to the first element in a linked list of \c count
+ * stuctures on success, or \c NULL on failure.
+ *
+ * \warning Use of \c minimum_size does \b not guarantee binary compatibility.
+ * The fundamental assumption is that if the \c minimum_size
+ * specified by the driver and the size of the \c __GLcontextModes
+ * structure in libGL is the same, then the meaning of each byte in
+ * the structure is the same in both places. \b Be \b careful!
+ * Basically this means that fields have to be added in libGL and
+ * then propagated to drivers. Drivers should \b never arbitrarilly
+ * extend the \c __GLcontextModes data-structure.
+ */
+__GLcontextModes *
+_gl_context_modes_create( unsigned count, size_t minimum_size )
+{
+ const size_t size = (minimum_size > sizeof( __GLcontextModes ))
+ ? minimum_size : sizeof( __GLcontextModes );
+ __GLcontextModes * base = NULL;
+ __GLcontextModes ** next;
+ unsigned i;
+
+ next = & base;
+ for ( i = 0 ; i < count ; i++ ) {
+ *next = (__GLcontextModes *) Xmalloc( size );
+ if ( *next == NULL ) {
+ _gl_context_modes_destroy( base );
+ base = NULL;
+ break;
+ }
+
+ (void) __glXMemset( *next, 0, size );
+ (*next)->visualID = GLX_DONT_CARE;
+ (*next)->visualType = GLX_DONT_CARE;
+ (*next)->visualRating = GLX_NONE;
+ (*next)->transparentPixel = GLX_NONE;
+ (*next)->transparentRed = GLX_DONT_CARE;
+ (*next)->transparentGreen = GLX_DONT_CARE;
+ (*next)->transparentBlue = GLX_DONT_CARE;
+ (*next)->transparentAlpha = GLX_DONT_CARE;
+ (*next)->transparentIndex = GLX_DONT_CARE;
+ (*next)->xRenderable = GLX_DONT_CARE;
+ (*next)->fbconfigID = GLX_DONT_CARE;
+ (*next)->swapMethod = GLX_SWAP_UNDEFINED_OML;
+
+ next = & ((*next)->next);
+ }
+
+ return base;
+}
+
+
+/**
+ * Destroy a linked list of \c __GLcontextModes structures created by
+ * \c _gl_context_modes_create.
+ *
+ * \param modes Linked list of structures to be destroyed. All structres
+ * in the list will be freed.
+ */
+void
+_gl_context_modes_destroy( __GLcontextModes * modes )
+{
+ while ( modes != NULL ) {
+ __GLcontextModes * const next = modes->next;
+
+ Xfree( modes );
+ modes = next;
+ }
+}
+
+
+/**
+ * Find a context mode matching a Visual ID.
+ *
+ * \param modes List list of context-mode structures to be searched.
+ * \param vid Visual ID to be found.
+ * \returns A pointer to a context-mode in \c modes if \c vid was found in
+ * the list, or \c NULL if it was not.
+ */
+
+__GLcontextModes *
+_gl_context_modes_find_visual( __GLcontextModes * modes, int vid )
+{
+ while ( modes != NULL ) {
+ if ( modes->visualID == vid ) {
+ break;
+ }
+
+ modes = modes->next;
+ }
+
+ return modes;
+}
+
+
+/**
+ * Determine if two context-modes are the same. This is intended to be used
+ * by libGL implementations to compare to sets of driver generated FBconfigs.
+ *
+ * \param a Context-mode to be compared.
+ * \param b Context-mode to be compared.
+ * \returns \c GL_TRUE if the two context-modes are the same. \c GL_FALSE is
+ * returned otherwise.
+ */
+GLboolean
+_gl_context_modes_are_same( const __GLcontextModes * a,
+ const __GLcontextModes * b )
+{
+ return( (a->rgbMode == b->rgbMode) &&
+ (a->floatMode == b->floatMode) &&
+ (a->colorIndexMode == b->colorIndexMode) &&
+ (a->doubleBufferMode == b->doubleBufferMode) &&
+ (a->stereoMode == b->stereoMode) &&
+ (a->redBits == b->redBits) &&
+ (a->greenBits == b->greenBits) &&
+ (a->blueBits == b->blueBits) &&
+ (a->alphaBits == b->alphaBits) &&
+#if 0 /* For some reason these don't get set on the client-side in libGL. */
+ (a->redMask == b->redMask) &&
+ (a->greenMask == b->greenMask) &&
+ (a->blueMask == b->blueMask) &&
+ (a->alphaMask == b->alphaMask) &&
+#endif
+ (a->rgbBits == b->rgbBits) &&
+ (a->indexBits == b->indexBits) &&
+ (a->accumRedBits == b->accumRedBits) &&
+ (a->accumGreenBits == b->accumGreenBits) &&
+ (a->accumBlueBits == b->accumBlueBits) &&
+ (a->accumAlphaBits == b->accumAlphaBits) &&
+ (a->depthBits == b->depthBits) &&
+ (a->stencilBits == b->stencilBits) &&
+ (a->numAuxBuffers == b->numAuxBuffers) &&
+ (a->level == b->level) &&
+ (a->pixmapMode == b->pixmapMode) &&
+ (a->visualRating == b->visualRating) &&
+
+ (a->transparentPixel == b->transparentPixel) &&
+
+ ((a->transparentPixel != GLX_TRANSPARENT_RGB) ||
+ ((a->transparentRed == b->transparentRed) &&
+ (a->transparentGreen == b->transparentGreen) &&
+ (a->transparentBlue == b->transparentBlue) &&
+ (a->transparentAlpha == b->transparentAlpha))) &&
+
+ ((a->transparentPixel != GLX_TRANSPARENT_INDEX) ||
+ (a->transparentIndex == b->transparentIndex)) &&
+
+ (a->sampleBuffers == b->sampleBuffers) &&
+ (a->samples == b->samples) &&
+ ((a->drawableType & b->drawableType) != 0) &&
+ (a->renderType == b->renderType) &&
+ (a->maxPbufferWidth == b->maxPbufferWidth) &&
+ (a->maxPbufferHeight == b->maxPbufferHeight) &&
+ (a->maxPbufferPixels == b->maxPbufferPixels) &&
+ (a->optimalPbufferWidth == b->optimalPbufferWidth) &&
+ (a->optimalPbufferHeight == b->optimalPbufferHeight) &&
+ (a->swapMethod == b->swapMethod) );
+}
diff --git a/src/mesa/drivers/dri/common/glcontextmodes.h b/src/mesa/drivers/dri/common/glcontextmodes.h
new file mode 100644
index 0000000000..5f8fa4f311
--- /dev/null
+++ b/src/mesa/drivers/dri/common/glcontextmodes.h
@@ -0,0 +1,49 @@
+/*
+ * (C) Copyright IBM Corporation 2003
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * on the rights to use, copy, modify, merge, publish, distribute, sub
+ * license, and/or sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * VA LINUX SYSTEM, IBM AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * \file glcontextmodes.h
+ * \author Ian Romanick <idr@us.ibm.com>
+ */
+
+#ifndef GLCONTEXTMODES_H
+#define GLCONTEXTMODES_H
+
+#include "GL/internal/glcore.h"
+
+extern GLint _gl_convert_from_x_visual_type( int visualType );
+extern GLint _gl_convert_to_x_visual_type( int visualType );
+extern void _gl_copy_visual_to_context_mode( __GLcontextModes * mode,
+ const __GLXvisualConfig * config );
+extern int _gl_get_context_mode_data( const __GLcontextModes *mode,
+ int attribute, int *value_return );
+extern __GLcontextModes * _gl_context_modes_create( unsigned count,
+ size_t minimum_size );
+extern void _gl_context_modes_destroy( __GLcontextModes * modes );
+extern __GLcontextModes * _gl_context_modes_find_visual(
+ __GLcontextModes * modes, int vid );
+extern GLboolean _gl_context_modes_are_same( const __GLcontextModes * a,
+ const __GLcontextModes * b );
+
+#endif /* GLCONTEXTMODES_H */