summaryrefslogtreecommitdiff
path: root/src/mesa/drivers/dri/common
diff options
context:
space:
mode:
authorJon Smirl <jonsmirl@gmail.com>2003-10-21 06:05:39 +0000
committerJon Smirl <jonsmirl@gmail.com>2003-10-21 06:05:39 +0000
commitbcc6eddd335e97d49ed2ef3a1440f94d58dce12d (patch)
treeff4883dd4da6ce65500940aebe2c268716311fe6 /src/mesa/drivers/dri/common
parent906449753f126f74ad3321d0af897f6609880c17 (diff)
Update DRI drivers to current DRI CVS and make them work.
Diffstat (limited to 'src/mesa/drivers/dri/common')
-rw-r--r--src/mesa/drivers/dri/common/mm.c3
-rw-r--r--src/mesa/drivers/dri/common/texmem.c96
-rw-r--r--src/mesa/drivers/dri/common/texmem.h2
-rw-r--r--src/mesa/drivers/dri/common/vblank.c64
-rw-r--r--src/mesa/drivers/dri/common/vblank.h4
-rw-r--r--src/mesa/drivers/dri/common/xmlconfig.c862
-rw-r--r--src/mesa/drivers/dri/common/xmlconfig.h125
-rw-r--r--src/mesa/drivers/dri/common/xmlpool.h203
8 files changed, 1326 insertions, 33 deletions
diff --git a/src/mesa/drivers/dri/common/mm.c b/src/mesa/drivers/dri/common/mm.c
index b3be95471d..6572ccd991 100644
--- a/src/mesa/drivers/dri/common/mm.c
+++ b/src/mesa/drivers/dri/common/mm.c
@@ -27,14 +27,13 @@
#include <stdio.h>
#include "mm.h"
-#include "hwlog.h"
void mmDumpMemInfo( memHeap_t *heap )
{
TMemBlock *p;
- fprintf(stderr, "Memory heap %p:\n", heap);
+ fprintf(stderr, "Memory heap %p:\n", (void *)heap);
if (heap == 0) {
fprintf(stderr, " heap == 0\n");
} else {
diff --git a/src/mesa/drivers/dri/common/texmem.c b/src/mesa/drivers/dri/common/texmem.c
index a8878b694d..4ed05219db 100644
--- a/src/mesa/drivers/dri/common/texmem.c
+++ b/src/mesa/drivers/dri/common/texmem.c
@@ -1,6 +1,6 @@
/*
* Copyright 2000-2001 VA Linux Systems, Inc.
- * (c) Copyright IBM Corporation 2002
+ * (C) Copyright IBM Corporation 2002, 2003
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
@@ -46,6 +46,7 @@
#include "texmem.h"
#include "simple_list.h"
#include "imports.h"
+#include "macros.h"
#include <assert.h>
@@ -156,22 +157,22 @@ static void printLocalLRU( driTexHeap * heap, const char *callername )
continue;
if (!t->tObj) {
fprintf( stderr, "Placeholder (%p) %d at 0x%x sz 0x%x\n",
- t,
+ (void *)t,
t->memBlock->ofs / sz,
t->memBlock->ofs,
t->memBlock->size );
} else {
fprintf( stderr, "Texture (%p) at 0x%x sz 0x%x\n",
- t,
+ (void *)t,
t->memBlock->ofs,
t->memBlock->size );
}
}
foreach ( t, heap->swapped_objects ) {
if (!t->tObj) {
- fprintf( stderr, "Swapped Placeholder (%p)\n", t );
+ fprintf( stderr, "Swapped Placeholder (%p)\n", (void *)t );
} else {
- fprintf( stderr, "Swapped Texture (%p)\n", t );
+ fprintf( stderr, "Swapped Texture (%p)\n", (void *)t );
}
}
@@ -190,7 +191,7 @@ static void printGlobalLRU( driTexHeap * heap, const char *callername )
int i, j;
fprintf( stderr, "%s in %s:\nGlobal LRU, heap %d list %p:\n",
- __FUNCTION__, callername, heap->heapId, list );
+ __FUNCTION__, callername, heap->heapId, (void *)list );
for ( i = 0, j = heap->nrRegions ; i < heap->nrRegions ; i++ ) {
fprintf( stderr, "list[%d] age %d next %d prev %d in_use %d\n",
@@ -323,9 +324,9 @@ void driDestroyTextureObject( driTextureObject * t )
if ( 0 ) {
fprintf( stderr, "[%s:%d] freeing %p (tObj = %p, DriverData = %p)\n",
__FILE__, __LINE__,
- t,
- (t != NULL) ? t->tObj : NULL,
- (t != NULL && t->tObj != NULL) ? t->tObj->DriverData : NULL );
+ (void *)t,
+ (void *)((t != NULL) ? t->tObj : NULL),
+ (void *)((t != NULL && t->tObj != NULL) ? t->tObj->DriverData : NULL ));
}
if ( t != NULL ) {
@@ -355,7 +356,7 @@ void driDestroyTextureObject( driTextureObject * t )
}
if ( 0 ) {
- fprintf( stderr, "[%s:%d] done freeing %p\n", __FILE__, __LINE__, t );
+ fprintf( stderr, "[%s:%d] done freeing %p\n", __FILE__, __LINE__, (void *)t );
}
}
@@ -645,7 +646,7 @@ driCreateTextureHeap( unsigned heap_id, void * context, unsigned size,
if ( 0 )
fprintf( stderr, "%s( %u, %p, %u, %u, %u )\n",
__FUNCTION__,
- heap_id, context, size, alignmentShift, nr_regions );
+ heap_id, (void *)context, size, alignmentShift, nr_regions );
heap = (driTexHeap *) CALLOC( sizeof( driTexHeap ) );
if ( heap != NULL ) {
@@ -688,7 +689,7 @@ driCreateTextureHeap( unsigned heap_id, void * context, unsigned size,
if ( 0 )
- fprintf( stderr, "%s returning %p\n", __FUNCTION__, heap );
+ fprintf( stderr, "%s returning %p\n", __FUNCTION__, (void *)heap );
return heap;
}
@@ -894,7 +895,7 @@ get_max_size( unsigned nr_heaps,
/**
* Given the amount of texture memory, the number of texture units, and the
* maximum size of a texel, calculate the maximum texture size the driver can
- * adverteise.
+ * advertise.
*
* \param heaps Texture heaps for this card
* \param nr_heap Number of texture heaps
@@ -1097,7 +1098,7 @@ driValidateTextureHeaps( driTexHeap * const * texture_heaps,
if ( !check_in_heap( t, heap ) ) {
fprintf( stderr, "%s memory block for texture object @ %p not "
"found in heap #%d\n",
- __FUNCTION__, t, i );
+ __FUNCTION__, (void *)t, i );
return GL_FALSE;
}
@@ -1105,7 +1106,7 @@ driValidateTextureHeaps( driTexHeap * const * texture_heaps,
if ( t->totalSize > t->memBlock->size ) {
fprintf( stderr, "%s: Memory block for texture object @ %p is "
"only %u bytes, but %u are required\n",
- __FUNCTION__, t, t->totalSize, t->memBlock->size );
+ __FUNCTION__, (void *)t, t->totalSize, t->memBlock->size );
return GL_FALSE;
}
@@ -1159,15 +1160,76 @@ driValidateTextureHeaps( driTexHeap * const * texture_heaps,
foreach ( t, swapped ) {
if ( t->memBlock != NULL ) {
fprintf( stderr, "%s: Swapped texobj %p has non-NULL memblock %p\n",
- __FUNCTION__, t, t->memBlock );
+ __FUNCTION__, (void *)t, (void *)t->memBlock );
return GL_FALSE;
}
i++;
}
#if 0
- fprintf( stderr, "%s: swapped texture count = %u\n", i );
+ fprintf( stderr, "%s: swapped texture count = %u\n", __FUNCTION__, i );
#endif
return GL_TRUE;
}
+
+
+
+
+/****************************************************************************/
+/**
+ * Compute which mipmap levels that really need to be sent to the hardware.
+ * This depends on the base image size, GL_TEXTURE_MIN_LOD,
+ * GL_TEXTURE_MAX_LOD, GL_TEXTURE_BASE_LEVEL, and GL_TEXTURE_MAX_LEVEL.
+ */
+
+void
+driCalculateTextureFirstLastLevel( driTextureObject * t )
+{
+ struct gl_texture_object * const tObj = t->tObj;
+ const struct gl_texture_image * const baseImage =
+ tObj->Image[tObj->BaseLevel];
+
+ /* These must be signed values. MinLod and MaxLod can be negative numbers,
+ * and having firstLevel and lastLevel as signed prevents the need for
+ * extra sign checks.
+ */
+ int firstLevel;
+ int lastLevel;
+
+ /* Yes, this looks overly complicated, but it's all needed.
+ */
+
+ switch (tObj->Target) {
+ case GL_TEXTURE_1D:
+ case GL_TEXTURE_2D:
+ case GL_TEXTURE_3D:
+ case GL_TEXTURE_CUBE_MAP:
+ if (tObj->MinFilter == GL_NEAREST || tObj->MinFilter == GL_LINEAR) {
+ /* GL_NEAREST and GL_LINEAR only care about GL_TEXTURE_BASE_LEVEL.
+ */
+
+ firstLevel = lastLevel = tObj->BaseLevel;
+ }
+ else {
+ firstLevel = tObj->BaseLevel + (GLint)(tObj->MinLod + 0.5);
+ firstLevel = MAX2(firstLevel, tObj->BaseLevel);
+ lastLevel = tObj->BaseLevel + (GLint)(tObj->MaxLod + 0.5);
+ lastLevel = MAX2(lastLevel, t->tObj->BaseLevel);
+ lastLevel = MIN2(lastLevel, t->tObj->BaseLevel + baseImage->MaxLog2);
+ lastLevel = MIN2(lastLevel, t->tObj->MaxLevel);
+ lastLevel = MAX2(firstLevel, lastLevel); /* need at least one level */
+ }
+ break;
+ case GL_TEXTURE_RECTANGLE_NV:
+ case GL_TEXTURE_4D_SGIS:
+ firstLevel = lastLevel = 0;
+ break;
+ default:
+ return;
+ }
+
+ /* save these values */
+ t->firstLevel = firstLevel;
+ t->lastLevel = lastLevel;
+}
diff --git a/src/mesa/drivers/dri/common/texmem.h b/src/mesa/drivers/dri/common/texmem.h
index 7199704612..9afbb0c865 100644
--- a/src/mesa/drivers/dri/common/texmem.h
+++ b/src/mesa/drivers/dri/common/texmem.h
@@ -290,4 +290,6 @@ void driInitTextureObjects( GLcontext *ctx, driTextureObject * swapped,
GLboolean driValidateTextureHeaps( driTexHeap * const * texture_heaps,
unsigned nr_heaps, const driTextureObject * swapped );
+extern void driCalculateTextureFirstLastLevel( driTextureObject * t );
+
#endif /* DRI_TEXMEM_H */
diff --git a/src/mesa/drivers/dri/common/vblank.c b/src/mesa/drivers/dri/common/vblank.c
index e91dd65260..d20f743bc9 100644
--- a/src/mesa/drivers/dri/common/vblank.c
+++ b/src/mesa/drivers/dri/common/vblank.c
@@ -33,6 +33,7 @@
#include "macros.h"
#include "dd.h"
#include "vblank.h"
+#include "xmlpool.h"
/****************************************************************************/
@@ -127,7 +128,7 @@ int driWaitForMSC32( __DRIdrawablePrivate *priv,
if ( drmWaitVBlank( priv->driScreenPriv->fd, &vbl ) != 0 ) {
/* FIXME: This doesn't seem like the right thing to return here.
*/
-#ifndef _SOLO
+#ifndef _SOLO
return GLX_BAD_CONTEXT;
#else
return -1;
@@ -163,9 +164,9 @@ int driWaitForMSC32( __DRIdrawablePrivate *priv,
/* FIXME: This doesn't seem like the right thing to return here.
*/
#ifndef _SOLO
- return GLX_BAD_CONTEXT;
+ return GLX_BAD_CONTEXT;
#else
- return -1;
+ return -1;
#endif
}
}
@@ -183,20 +184,35 @@ int driWaitForMSC32( __DRIdrawablePrivate *priv,
/****************************************************************************/
/**
* Gets a set of default vertical-blank-wait flags based on the internal GLX
- * API version and several environment variables.
+ * API version and several configuration options.
*/
-GLuint driGetDefaultVBlankFlags( void )
+GLuint driGetDefaultVBlankFlags( const driOptionCache *optionCache )
{
GLuint flags = 0;
-
+ int vblank_mode;
flags |= (driCompareGLXAPIVersion( 20030317 ) >= 0)
? VBLANK_FLAG_INTERVAL : 0;
- flags |= (getenv("LIBGL_SYNC_REFRESH") != NULL)
- ? VBLANK_FLAG_SYNC : 0;
- flags |= (getenv("LIBGL_THROTTLE_REFRESH") != NULL)
- ? VBLANK_FLAG_THROTTLE : 0;
+
+ if ( driCheckOption( optionCache, "vblank_mode", DRI_ENUM ) )
+ vblank_mode = driQueryOptioni( optionCache, "vblank_mode" );
+ else
+ vblank_mode = DRI_CONF_VBLANK_DEF_INTERVAL_1;
+
+ switch (vblank_mode) {
+ case DRI_CONF_VBLANK_NEVER:
+ flags = 0;
+ break;
+ case DRI_CONF_VBLANK_DEF_INTERVAL_0:
+ break;
+ case DRI_CONF_VBLANK_DEF_INTERVAL_1:
+ flags |= VBLANK_FLAG_THROTTLE;
+ break;
+ case DRI_CONF_VBLANK_ALWAYS_SYNC:
+ flags |= VBLANK_FLAG_SYNC;
+ break;
+ }
return flags;
}
@@ -204,6 +220,22 @@ GLuint driGetDefaultVBlankFlags( void )
/****************************************************************************/
/**
+ * Sets the default swap interval when the drawable is first bound to a
+ * direct rendering context.
+ */
+
+void driDrawableInitVBlank( __DRIdrawablePrivate *priv, GLuint flags )
+{
+#ifndef _SOLO
+ if ( priv->pdraw->swap_interval == (unsigned)-1 ) {
+ priv->pdraw->swap_interval = (flags & VBLANK_FLAG_THROTTLE) != 0 ? 1 : 0;
+ }
+#endif
+}
+
+
+/****************************************************************************/
+/**
* Wrapper to call \c drmWaitVBlank. The main purpose of this function is to
* wrap the error message logging. The error message should only be logged
* the first time the \c drmWaitVBlank fails. If \c drmWaitVBlank is
@@ -265,7 +297,10 @@ driWaitForVBlank( const __DRIdrawablePrivate *priv, GLuint * vbl_seq,
*missed_deadline = GL_FALSE;
- if ( (flags & VBLANK_FLAG_NO_IRQ) != 0 ) {
+ if ( (flags & (VBLANK_FLAG_INTERVAL |
+ VBLANK_FLAG_THROTTLE |
+ VBLANK_FLAG_SYNC)) == 0 ||
+ (flags & VBLANK_FLAG_NO_IRQ) != 0 ) {
return 0;
}
@@ -293,11 +328,14 @@ driWaitForVBlank( const __DRIdrawablePrivate *priv, GLuint * vbl_seq,
vbl.request.type = DRM_VBLANK_ABSOLUTE;
if ( (flags & VBLANK_FLAG_INTERVAL) != 0 ) {
-#ifndef _SOLO
+#ifndef _SOLO
interval = priv->pdraw->swap_interval;
#else
interval = 0;
-#endif
+#endif
+ /* this must have been initialized when the drawable was first bound
+ * to a direct rendering context. */
+ assert ( interval != (unsigned)-1 );
}
else if ( (flags & VBLANK_FLAG_THROTTLE) != 0 ) {
interval = 1;
diff --git a/src/mesa/drivers/dri/common/vblank.h b/src/mesa/drivers/dri/common/vblank.h
index 3dab4ead3c..d460d7a84a 100644
--- a/src/mesa/drivers/dri/common/vblank.h
+++ b/src/mesa/drivers/dri/common/vblank.h
@@ -32,6 +32,7 @@
#include "context.h"
#include "dri_util.h"
+#include "xmlconfig.h"
#define VBLANK_FLAG_INTERVAL (1U << 0) /* Respect the swap_interval setting
*/
@@ -45,7 +46,8 @@
extern int driGetMSC32( __DRIscreenPrivate * priv, int64_t * count );
extern int driWaitForMSC32( __DRIdrawablePrivate *priv,
int64_t target_msc, int64_t divisor, int64_t remainder, int64_t * msc );
-extern GLuint driGetDefaultVBlankFlags( void );
+extern GLuint driGetDefaultVBlankFlags( const driOptionCache *optionCache );
+extern void driDrawableInitVBlank ( __DRIdrawablePrivate *priv, GLuint flags );
extern int driWaitForVBlank( const __DRIdrawablePrivate *priv,
GLuint * vbl_seq, GLuint flags, GLboolean * missed_deadline );
diff --git a/src/mesa/drivers/dri/common/xmlconfig.c b/src/mesa/drivers/dri/common/xmlconfig.c
new file mode 100644
index 0000000000..a6d4c8ab94
--- /dev/null
+++ b/src/mesa/drivers/dri/common/xmlconfig.c
@@ -0,0 +1,862 @@
+/*
+ * XML DRI client-side driver configuration
+ * Copyright (C) 2003 Felix Kuehling
+ *
+ * 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, sublicense,
+ * 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 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 NONINFRINGEMENT. IN NO EVENT SHALL
+ * FELIX KUEHLING, OR ANY OTHER CONTRIBUTORS 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 xmlconfig.c
+ * \brief Driver-independent client-side part of the XML configuration
+ * \author Felix Kuehling
+ */
+
+#include "glheader.h"
+
+#include <string.h>
+#include <assert.h>
+#include <expat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include "imports.h"
+#include "dri_util.h"
+#include "xmlconfig.h"
+
+/*
+ * OS dependent ways of getting the name of the running program
+ */
+#if (defined(__unix__) || defined(unix)) && !defined(USG)
+#include <sys/param.h>
+#endif
+
+#undef GET_PROGRAM_NAME
+
+#if defined(__GNU_LIBRARY__) || defined(__GLIBC__)
+# define GET_PROGRAM_NAME() program_invocation_short_name
+#elif defined(__FreeBSD__) && (__FreeBSD__ >= 2)
+# include <osreldate.h>
+# if (__FreeBSD_version >= 440000)
+# include <stdlib.h>
+# define GET_PROGRAM_NAME() getprogname()
+# endif
+#elif defined(__NetBSD__) && defined(__NetBSD_Version) && (__NetBSD_Version >= 106000100)
+# include <stdlib.h>
+# define GET_PROGRAM_NAME() getprogname()
+#endif
+
+#if !defined(GET_PROGRAM_NAME)
+# if defined(OpenBSD) || defined(NetBSD)
+/* This is a hack. It's said to work on OpenBSD, NetBSD and GNU. It's
+ * used as a last resort, if there is no documented facility available. */
+static const char *__getProgramName () {
+ extern const char *__progname;
+ return progname;
+}
+# define GET_PROGRAM_NAME() __getProgramName()
+# else
+# define GET_PROGRAM_NAME() ""
+# warning "Per application configuration won't with your OS version work."
+# endif
+#endif
+
+/** \brief Find an option in an option cache with the name as key */
+static GLuint findOption (const driOptionCache *cache, const char *name) {
+ GLuint len = strlen (name);
+ GLuint size = 1 << cache->tableSize, mask = size - 1;
+ GLuint hash = 0;
+ GLuint i, shift;
+
+ /* compute a hash from the variable length name */
+ for (i = 0, shift = 0; i < len; ++i, shift = (shift+8) & 31)
+ hash += (GLuint)name[i] << shift;
+ hash *= hash;
+ hash = (hash >> (16-cache->tableSize/2)) & mask;
+
+ /* this is just the starting point of the linear search for the option */
+ for (i = 0; i < size; ++i, hash = (hash+1) & mask) {
+ /* if we hit an empty entry then the option is not defined (yet) */
+ if (cache->info[hash].name == 0)
+ break;
+ else if (!strcmp (name, cache->info[hash].name))
+ break;
+ }
+ /* this assertion fails if the hash table is full */
+ assert (i < size);
+
+ return hash;
+}
+
+/** \brief Count the real number of options in an option cache */
+static GLuint countOptions (const driOptionCache *cache) {
+ GLuint size = 1 << cache->tableSize;
+ GLuint i, count = 0;
+ for (i = 0; i < size; ++i)
+ if (cache->info[i].name)
+ count++;
+ return count;
+}
+
+/** \brief Like strdup but using MALLOC and with error checking. */
+#define XSTRDUP(dest,source) do { \
+ GLuint len = strlen (source); \
+ if (!(dest = MALLOC (len+1))) { \
+ fprintf (stderr, "%s: %d: out of memory.\n", __FILE__, __LINE__); \
+ abort(); \
+ } \
+ memcpy (dest, source, len+1); \
+} while (0)
+
+static int compare (const void *a, const void *b) {
+ return strcmp (*(char *const*)a, *(char *const*)b);
+}
+/** \brief Binary search in a string array. */
+static GLuint bsearchStr (const XML_Char *name,
+ const XML_Char *elems[], GLuint count) {
+ const XML_Char **found;
+ found = bsearch (&name, elems, count, sizeof (XML_Char *), compare);
+ if (found)
+ return found - elems;
+ else
+ return count;
+}
+
+/** \brief Parse a value of a given type. */
+static GLboolean parseValue (driOptionValue *v, driOptionType type,
+ const XML_Char *string) {
+ const XML_Char *tail;
+ /* skip leading white-space */
+ string += strspn (string, " \f\n\r\t\v");
+ switch (type) {
+ case DRI_BOOL:
+ if (!strcmp (string, "false")) {
+ v->_bool = GL_FALSE;
+ tail = string + 5;
+ } else if (!strcmp (string, "true")) {
+ v->_bool = GL_TRUE;
+ tail = string + 4;
+ }
+ else
+ return GL_FALSE;
+ break;
+ case DRI_ENUM: /* enum is just a special integer */
+ case DRI_INT:
+ v->_int = strtol (string, (char **)&tail, 0);
+ break;
+ case DRI_FLOAT:
+ v->_float = strtod (string, (char **)&tail);
+ break;
+ }
+
+ if (tail == string)
+ return GL_FALSE; /* empty string (or containing only white-space) */
+ /* skip trailing white space */
+ if (*tail)
+ tail += strspn (tail, " \f\n\r\t\v");
+ if (*tail)
+ return GL_FALSE; /* something left over that is not part of value */
+
+ return GL_TRUE;
+}
+
+/** \brief Parse a list of ranges of type info->type. */
+static GLboolean parseRanges (driOptionInfo *info, const XML_Char *string) {
+ XML_Char *cp, *range;
+ GLuint nRanges, i;
+ driOptionRange *ranges;
+
+ XSTRDUP (cp, string);
+ /* pass 1: determine the number of ranges (number of commas + 1) */
+ range = cp;
+ for (nRanges = 1; *range; ++range)
+ if (*range == ',')
+ ++nRanges;
+
+ if ((ranges = MALLOC (nRanges*sizeof(driOptionRange))) == NULL) {
+ fprintf (stderr, "%s: %d: out of memory.\n", __FILE__, __LINE__);
+ abort();
+ }
+
+ /* pass 2: parse all ranges into preallocated array */
+ range = cp;
+ for (i = 0; i < nRanges; ++i) {
+ XML_Char *end, *sep;
+ assert (range);
+ end = strchr (range, ',');
+ if (end)
+ *end = '\0';
+ sep = strchr (range, ':');
+ if (sep) { /* non-empty interval */
+ *sep = '\0';
+ if (!parseValue (&ranges[i].start, info->type, range) ||
+ !parseValue (&ranges[i].end, info->type, sep+1))
+ break;
+ if (info->type == DRI_INT &&
+ ranges[i].start._int > ranges[i].end._int)
+ break;
+ if (info->type == DRI_FLOAT &&
+ ranges[i].start._float > ranges[i].end._float)
+ break;
+ } else { /* empty interval */
+ if (!parseValue (&ranges[i].start, info->type, range))
+ break;
+ ranges[i].end = ranges[i].start;
+ }
+ if (end)
+ range = end+1;
+ else
+ range = NULL;
+ }
+ FREE (cp);
+ if (i < nRanges) {
+ FREE (ranges);
+ return GL_FALSE;
+ } else
+ assert (range == NULL);
+
+ info->nRanges = nRanges;
+ info->ranges = ranges;
+ return GL_TRUE;
+}
+
+/** \brief Check if a value is in one of info->ranges. */
+static GLboolean checkValue (const driOptionValue *v, const driOptionInfo *info) {
+ GLuint i;
+ assert (info->type != DRI_BOOL); /* should be caught by the parser */
+ if (info->nRanges == 0)
+ return GL_TRUE;
+ switch (info->type) {
+ case DRI_ENUM: /* enum is just a special integer */
+ case DRI_INT:
+ for (i = 0; i < info->nRanges; ++i)
+ if (v->_int >= info->ranges[i].start._int &&
+ v->_int <= info->ranges[i].end._int)
+ return GL_TRUE;
+ break;
+ case DRI_FLOAT:
+ for (i = 0; i < info->nRanges; ++i)
+ if (v->_float >= info->ranges[i].start._float &&
+ v->_float <= info->ranges[i].end._float)
+ return GL_TRUE;
+ break;
+ default:
+ assert (0); /* should never happen */
+ }
+ return GL_FALSE;
+}
+
+/** \brief Output a warning message. */
+#define XML_WARNING1(msg) do {\
+ __driUtilMessage ("Warning in %s line %d, column %d: "msg, data->name, \
+ XML_GetCurrentLineNumber(data->parser), \
+ XML_GetCurrentColumnNumber(data->parser)); \
+} while (0)
+#define XML_WARNING(msg,args...) do { \
+ __driUtilMessage ("Warning in %s line %d, column %d: "msg, data->name, \
+ XML_GetCurrentLineNumber(data->parser), \
+ XML_GetCurrentColumnNumber(data->parser), \
+ args); \
+} while (0)
+/** \brief Output an error message. */
+#define XML_ERROR1(msg) do { \
+ __driUtilMessage ("Error in %s line %d, column %d: "msg, data->name, \
+ XML_GetCurrentLineNumber(data->parser), \
+ XML_GetCurrentColumnNumber(data->parser)); \
+} while (0)
+#define XML_ERROR(msg,args...) do { \
+ __driUtilMessage ("Error in %s line %d, column %d: "msg, data->name, \
+ XML_GetCurrentLineNumber(data->parser), \
+ XML_GetCurrentColumnNumber(data->parser), \
+ args); \
+} while (0)
+/** \brief Output a fatal error message and abort. */
+#define XML_FATAL1(msg) do { \
+ fprintf (stderr, "Fatal error in %s line %d, column %d: "msg"\n", \
+ data->name, \
+ XML_GetCurrentLineNumber(data->parser), \
+ XML_GetCurrentColumnNumber(data->parser)); \
+ abort();\
+} while (0)
+#define XML_FATAL(msg,args...) do { \
+ fprintf (stderr, "Fatal error in %s line %d, column %d: "msg"\n", \
+ data->name, \
+ XML_GetCurrentLineNumber(data->parser), \
+ XML_GetCurrentColumnNumber(data->parser), \
+ args); \
+ abort();\
+} while (0)
+
+/** \brief Parser context for __driConfigOptions. */
+struct OptInfoData {
+ const char *name;
+ XML_Parser parser;
+ driOptionCache *cache;
+ GLboolean inDriInfo;
+ GLboolean inSection;
+ GLboolean inDesc;
+ GLboolean inOption;
+ GLboolean inEnum;
+ int curOption;
+};
+
+/** \brief Elements in __driConfigOptions. */
+enum OptInfoElem {
+ OI_DESCRIPTION = 0, OI_DRIINFO, OI_ENUM, OI_OPTION, OI_SECTION, OI_COUNT
+};
+static const XML_Char *OptInfoElems[] = {
+ "description", "driinfo", "enum", "option", "section"
+};
+
+/** \brief Parse attributes of an enum element.
+ *
+ * We're not actually interested in the data. Just make sure this is ok
+ * for external configuration tools.
+ */
+static void parseEnumAttr (struct OptInfoData *data, const XML_Char **attr) {
+ GLuint i;
+ const XML_Char *value = NULL, *text = NULL;
+ driOptionValue v;
+ GLuint opt = data->curOption;
+ for (i = 0; attr[i]; i += 2) {
+ if (!strcmp (attr[i], "value")) value = attr[i+1];
+ else if (!strcmp (attr[i], "text")) text = attr[i+1];
+ else XML_FATAL("illegal enum attribute: %s.", attr[i]);
+ }
+ if (!value) XML_FATAL1 ("value attribute missing in enum.");
+ if (!text) XML_FATAL1 ("text attribute missing in enum.");
+ if (!parseValue (&v, data->cache->info[opt].type, value))
+ XML_FATAL ("illegal enum value: %s.", value);
+ if (!checkValue (&v, &data->cache->info[opt]))
+ XML_FATAL ("enum value out of valid range: %s.", value);
+}
+
+/** \brief Parse attributes of a description element.
+ *
+ * We're not actually interested in the data. Just make sure this is ok
+ * for external configuration tools.
+ */
+static void parseDescAttr (struct OptInfoData *data, const XML_Char **attr) {
+ GLuint i;
+ const XML_Char *lang = NULL, *text = NULL;
+ for (i = 0; attr[i]; i += 2) {
+ if (!strcmp (attr[i], "lang")) lang = attr[i+1];
+ else if (!strcmp (attr[i], "text")) text = attr[i+1];
+ else XML_FATAL("illegal description attribute: %s.", attr[i]);
+ }
+ if (!lang) XML_FATAL1 ("lang attribute missing in description.");
+ if (!text) XML_FATAL1 ("text attribute missing in description.");
+}
+
+/** \brief Parse attributes of an option element. */
+static void parseOptInfoAttr (struct OptInfoData *data, const XML_Char **attr) {
+ enum OptAttr {OA_DEFAULT = 0, OA_NAME, OA_TYPE, OA_VALID, OA_COUNT};
+ static const XML_Char *optAttr[] = {"default", "name", "type", "valid"};
+ const XML_Char *attrVal[OA_COUNT] = {NULL, NULL, NULL, NULL};
+ const char *defaultVal;
+ driOptionCache *cache = data->cache;
+ GLuint opt, i;
+ for (i = 0; attr[i]; i += 2) {
+ GLuint attrName = bsearchStr (attr[i], optAttr, OA_COUNT);
+ if (attrName >= OA_COUNT)
+ XML_FATAL ("illegal option attribute: %s", attr[i]);
+ attrVal[attrName] = attr[i+1];
+ }
+ if (!attrVal[OA_NAME]) XML_FATAL1 ("name attribute missing in option.");
+ if (!attrVal[OA_TYPE]) XML_FATAL1 ("type attribute missing in option.");
+ if (!attrVal[OA_DEFAULT]) XML_FATAL1 ("default attribute missing in option.");
+
+ opt = findOption (cache, attrVal[OA_NAME]);
+ if (cache->info[opt].name)
+ XML_FATAL ("option %s redefined.", attrVal[OA_NAME]);
+ data->curOption = opt;
+
+ XSTRDUP (cache->info[opt].name, attrVal[OA_NAME]);
+
+ if (!strcmp (attrVal[OA_TYPE], "bool"))
+ cache->info[opt].type = DRI_BOOL;
+ else if (!strcmp (attrVal[OA_TYPE], "enum"))
+ cache->info[opt].type = DRI_ENUM;
+ else if (!strcmp (attrVal[OA_TYPE], "int"))
+ cache->info[opt].type = DRI_INT;
+ else if (!strcmp (attrVal[OA_TYPE], "float"))
+ cache->info[opt].type = DRI_FLOAT;
+ else
+ XML_FATAL ("illegal type in option: %s.", attrVal[OA_TYPE]);
+
+ defaultVal = getenv (cache->info[opt].name);
+ if (defaultVal != NULL) {
+ /* don't use XML_WARNING, we want the user to see this! */
+ fprintf (stderr,
+ "ATTENTION: default value of option %s overridden by environment.\n",
+ cache->info[opt].name);
+ } else
+ defaultVal = attrVal[OA_DEFAULT];
+ if (!parseValue (&cache->values[opt], cache->info[opt].type, defaultVal))
+ XML_FATAL ("illegal default value: %s.", defaultVal);
+
+ if (attrVal[OA_VALID]) {
+ if (cache->info[opt].type == DRI_BOOL)
+ XML_FATAL1 ("boolean option with valid attribute.");
+ if (!parseRanges (&cache->info[opt], attrVal[OA_VALID]))
+ XML_FATAL ("illegal valid attribute: %s.", attrVal[OA_VALID]);
+ if (!checkValue (&cache->values[opt], &cache->info[opt]))
+ XML_FATAL ("default value out of valid range '%s': %s.",
+ attrVal[OA_VALID], defaultVal);
+ } else if (cache->info[opt].type == DRI_ENUM) {
+ XML_FATAL1 ("valid attribute missing in option (mandatory for enums).");
+ } else {
+ cache->info[opt].nRanges = 0;
+ cache->info[opt].ranges = NULL;
+ }
+}
+
+/** \brief Handler for start element events. */
+static void optInfoStartElem (void *userData, const XML_Char *name,
+ const XML_Char **attr) {
+ struct OptInfoData *data = (struct OptInfoData *)userData;
+ enum OptInfoElem elem = bsearchStr (name, OptInfoElems, OI_COUNT);
+ switch (elem) {
+ case OI_DRIINFO:
+ if (data->inDriInfo)
+ XML_FATAL1 ("nested <driinfo> elements.");
+ if (attr[0])
+ XML_FATAL1 ("attributes specified on <driinfo> element.");
+ data->inDriInfo = GL_TRUE;
+ break;
+ case OI_SECTION:
+ if (!data->inDriInfo)
+ XML_FATAL1 ("<section> must be inside <driinfo>.");
+ if (data->inSection)
+ XML_FATAL1 ("nested <section> elements.");
+ if (attr[0])
+ XML_FATAL1 ("attributes specified on <section> element.");
+ data->inSection = GL_TRUE;
+ break;
+ case OI_DESCRIPTION:
+ if (!data->inSection && !data->inOption)
+ XML_FATAL1 ("<description> must be inside <description> or <option.");
+ if (data->inDesc)
+ XML_FATAL1 ("nested <description> elements.");
+ data->inDesc = GL_TRUE;
+ parseDescAttr (data, attr);
+ break;
+ case OI_OPTION:
+ if (!data->inSection)
+ XML_FATAL1 ("<option> must be inside <section>.");
+ if (data->inDesc)
+ XML_FATAL1 ("<option> nested in <description> element.");
+ if (data->inOption)
+ XML_FATAL1 ("nested <option> elements.");
+ data->inOption = GL_TRUE;
+ parseOptInfoAttr (data, attr);
+ break;
+ case OI_ENUM:
+ if (!(data->inOption && data->inDesc))
+ XML_FATAL1 ("<enum> must be inside <option> and <description>.");
+ if (data->inEnum)
+ XML_FATAL1 ("nested <enum> elements.");
+ data->inEnum = GL_TRUE;
+ parseEnumAttr (data, attr);
+ break;
+ default:
+ XML_FATAL ("unknown element: %s.", name);
+ }
+}
+
+/** \brief Handler for end element events. */
+static void optInfoEndElem (void *userData, const XML_Char *name) {
+ struct OptInfoData *data = (struct OptInfoData *)userData;
+ enum OptInfoElem elem = bsearchStr (name, OptInfoElems, OI_COUNT);
+ switch (elem) {
+ case OI_DRIINFO:
+ data->inDriInfo = GL_FALSE;
+ break;
+ case OI_SECTION:
+ data->inSection = GL_FALSE;
+ break;
+ case OI_DESCRIPTION:
+ data->inDesc = GL_FALSE;
+ break;
+ case OI_OPTION:
+ data->inOption = GL_FALSE;
+ break;
+ case OI_ENUM:
+ data->inEnum = GL_FALSE;
+ break;
+ default:
+ assert (0); /* should have been caught by StartElem */
+ }
+}
+
+void driParseOptionInfo (driOptionCache *info) {
+ XML_Parser p;
+ int status;
+ struct OptInfoData userData;
+ struct OptInfoData *data = &userData;
+ GLuint nOptions;
+
+ /* determine hash table size and allocate memory */
+ GLuint size, log2size;
+ for (size = 1, log2size = 0; size < __driNConfigOptions*3/2;
+ size <<= 1, ++log2size);
+ info->tableSize = log2size;
+ info->info = CALLOC (size * sizeof (driOptionInfo));
+ info->values = CALLOC (size * sizeof (driOptionInfo));
+ if (info->info == NULL || info->values == NULL) {
+ fprintf (stderr, "%s: %d: out of memory.\n", __FILE__, __LINE__);
+ abort();
+ }
+
+ p = XML_ParserCreate ("UTF-8"); /* always UTF-8 */
+ XML_SetElementHandler (p, optInfoStartElem, optInfoEndElem);
+ XML_SetUserData (p, data);
+
+ userData.name = "__driConfigOptions";
+ userData.parser = p;
+ userData.cache = info;
+ userData.inDriInfo = GL_FALSE;
+ userData.inSection = GL_FALSE;
+ userData.inDesc = GL_FALSE;
+ userData.inOption = GL_FALSE;
+ userData.inEnum = GL_FALSE;
+ userData.curOption = -1;
+
+ status = XML_Parse (p, __driConfigOptions, strlen (__driConfigOptions), 1);
+ if (!status)
+ XML_FATAL ("%s.", XML_ErrorString(XML_GetErrorCode(p)));
+
+ XML_ParserFree (p);
+
+ /* Check if the actual number of options matches __driNConfigOptions.
+ * A mismatch is not fatal (a hash table overflow would be) but we
+ * want the driver developer's attention anyway. */
+ nOptions = countOptions (info);
+ if (nOptions != __driNConfigOptions) {
+ fprintf (stderr,
+ "Error: __driNConfigOptions (%u) does not match the actual number of options in\n"
+ " __driConfigOptions (%u).\n",
+ __driNConfigOptions, nOptions);
+ }
+}
+
+/** \brief Parser context for configuration files. */
+struct OptConfData {
+ const char *name;
+ XML_Parser parser;
+ driOptionCache *cache;
+ GLint screenNum;
+ const char *driverName, *execName;
+ GLuint ignoringDevice;
+ GLuint ignoringApp;
+ GLuint inDriConf;
+ GLuint inDevice;
+ GLuint inApp;
+ GLuint inOption;
+};
+
+/** \brief Elements in configuration files. */
+enum OptConfElem {
+ OC_APPLICATION = 0, OC_DEVICE, OC_DRICONF, OC_OPTION, OC_COUNT
+};
+static const XML_Char *OptConfElems[] = {
+ "application", "device", "driconf", "option"
+};
+
+/** \brief Parse attributes of a device element. */
+static void parseDeviceAttr (struct OptConfData *data, const XML_Char **attr) {
+ GLuint i;
+ const XML_Char *driver = NULL, *screen = NULL;
+ for (i = 0; attr[i]; i += 2) {
+ if (!strcmp (attr[i], "driver")) driver = attr[i+1];
+ else if (!strcmp (attr[i], "screen")) screen = attr[i+1];
+ else XML_WARNING("unkown device attribute: %s.", attr[i]);
+ }
+ if (driver && strcmp (driver, data->driverName))
+ data->ignoringDevice = data->inDevice;
+ else if (screen) {
+ driOptionValue screenNum;
+ if (!parseValue (&screenNum, DRI_INT, screen))
+ XML_WARNING("illegal screen number: %s.", screen);
+ else if (screenNum._int != data->screenNum)
+ data->ignoringDevice = data->inDevice;
+ }
+}
+
+/** \brief Parse attributes of an application element. */
+static void parseAppAttr (struct OptConfData *data, const XML_Char **attr) {
+ GLuint i;
+ const XML_Char *name = NULL, *exec = NULL;
+ for (i = 0; attr[i]; i += 2) {
+ if (!strcmp (attr[i], "name")) name = attr[i+1];
+ else if (!strcmp (attr[i], "executable")) exec = attr[i+1];
+ else XML_WARNING("unkown application attribute: %s.", attr[i]);
+ }
+ if (exec && strcmp (exec, data->execName))
+ data->ignoringApp = data->inApp;
+}
+
+/** \brief Parse attributes of an option element. */
+static void parseOptConfAttr (struct OptConfData *data, const XML_Char **attr) {
+ GLuint i;
+ const XML_Char *name = NULL, *value = NULL;
+ for (i = 0; attr[i]; i += 2) {
+ if (!strcmp (attr[i], "name")) name = attr[i+1];
+ else if (!strcmp (attr[i], "value")) value = attr[i+1];
+ else XML_WARNING("unkown option attribute: %s.", attr[i]);
+ }
+ if (!name) XML_WARNING1 ("name attribute missing in option.");
+ if (!value) XML_WARNING1 ("value attribute missing in option.");
+ if (name && value) {
+ driOptionCache *cache = data->cache;
+ GLuint opt = findOption (cache, name);
+ if (cache->info[opt].name == NULL)
+ XML_WARNING ("undefined option: %s.", name);
+ else if (getenv (cache->info[opt].name))
+ /* don't use XML_WARNING, we want the user to see this! */
+ fprintf (stderr, "ATTENTION: option value of option %s ignored.\n",
+ cache->info[opt].name);
+ else if (!parseValue (&cache->values[opt], cache->info[opt].type, value))
+ XML_WARNING ("illegal option value: %s.", value);
+ }
+}
+
+/** \brief Handler for start element events. */
+static void optConfStartElem (void *userData, const XML_Char *name,
+ const XML_Char **attr) {
+ struct OptConfData *data = (struct OptConfData *)userData;
+ enum OptConfElem elem = bsearchStr (name, OptConfElems, OC_COUNT);
+ switch (elem) {
+ case OC_DRICONF:
+ if (data->inDriConf)
+ XML_WARNING1 ("nested <driconf> elements.");
+ if (attr[0])
+ XML_WARNING1 ("attributes specified on <driconf> element.");
+ data->inDriConf++;
+ break;
+ case OC_DEVICE:
+ if (!data->inDriConf)
+ XML_WARNING1 ("<device> should be inside <driconf>.");
+ if (data->inDevice)
+ XML_WARNING1 ("nested <device> elements.");
+ data->inDevice++;
+ if (!data->ignoringDevice && !data->ignoringApp)
+ parseDeviceAttr (data, attr);
+ break;
+ case OC_APPLICATION:
+ if (!data->inDevice)
+ XML_WARNING1 ("<application> should be inside <device>.");
+ if (data->inApp)
+ XML_WARNING1 ("nested <application> elements.");
+ data->inApp++;
+ if (!data->ignoringDevice && !data->ignoringApp)
+ parseAppAttr (data, attr);
+ break;
+ case OC_OPTION:
+ if (!data->inApp)
+ XML_WARNING1 ("<option> should be inside <application>.");
+ if (data->inOption)
+ XML_WARNING1 ("nested <option> elements.");
+ data->inOption++;
+ if (!data->ignoringDevice && !data->ignoringApp)
+ parseOptConfAttr (data, attr);
+ break;
+ default:
+ XML_WARNING ("unknown element: %s.", name);
+ }
+}
+
+/** \brief Handler for end element events. */
+static void optConfEndElem (void *userData, const XML_Char *name) {
+ struct OptConfData *data = (struct OptConfData *)userData;
+ enum OptConfElem elem = bsearchStr (name, OptConfElems, OC_COUNT);
+ switch (elem) {
+ case OC_DRICONF:
+ data->inDriConf--;
+ break;
+ case OC_DEVICE:
+ if (data->inDevice-- == data->ignoringDevice)
+ data->ignoringDevice = 0;
+ break;
+ case OC_APPLICATION:
+ if (data->inApp-- == data->ignoringApp)
+ data->ignoringApp = 0;
+ break;
+ case OC_OPTION:
+ data->inOption--;
+ break;
+ default:
+ /* unknown element, warning was produced on start tag */;
+ }
+}
+
+/** \brief Initialize an option cache based on info */
+static void initOptionCache (driOptionCache *cache, driOptionCache *info) {
+ cache->info = info->info;
+ cache->tableSize = info->tableSize;
+ cache->values = MALLOC ((1<<info->tableSize) * sizeof (driOptionValue));
+ if (cache->values == NULL) {
+ fprintf (stderr, "%s: %d: out of memory.\n", __FILE__, __LINE__);
+ abort();
+ }
+ memcpy (cache->values, info->values,
+ (1<<info->tableSize) * sizeof (driOptionValue));
+}
+
+/** \brief Parse the named configuration file */
+static void parseOneConfigFile (XML_Parser p) {
+#define BUF_SIZE 0x1000
+ struct OptConfData *data = (struct OptConfData *)XML_GetUserData (p);
+ int status;
+ int fd;
+
+ if ((fd = open (data->name, O_RDONLY)) == -1) {
+ __driUtilMessage ("Can't open configuration file %s: %s.",
+ data->name, strerror (errno));
+ return;
+ }
+
+ while (1) {
+ int bytesRead;
+ void *buffer = XML_GetBuffer (p, BUF_SIZE);
+ if (!buffer) {
+ __driUtilMessage ("Can't allocate parser buffer.");
+ break;
+ }
+ bytesRead = read (fd, buffer, BUF_SIZE);
+ if (bytesRead == -1) {
+ __driUtilMessage ("Error reading from configuration file %s: %s.",
+ data->name, strerror (errno));
+ break;
+ }
+ status = XML_ParseBuffer (p, bytesRead, bytesRead == 0);
+ if (!status) {
+ XML_ERROR ("%s.", XML_ErrorString(XML_GetErrorCode(p)));
+ break;
+ }
+ if (bytesRead == 0)
+ break;
+ }
+
+ close (fd);
+#undef BUF_SIZE
+}
+
+void driParseConfigFiles (driOptionCache *cache, driOptionCache *info,
+ GLint screenNum, const char *driverName) {
+ char *filenames[2] = {"/etc/drirc", NULL};
+ char *home;
+ GLuint i;
+ struct OptConfData userData;
+
+ initOptionCache (cache, info);
+
+ userData.cache = cache;
+ userData.screenNum = screenNum;
+ userData.driverName = driverName;
+#ifndef _SOLO
+ userData.execName = GET_PROGRAM_NAME();
+#else
+ userData.execName = "Solo";
+#endif
+
+ if ((home = getenv ("HOME"))) {
+ GLuint len = strlen (home);
+ filenames[1] = MALLOC (len + 7+1);
+ if (filenames[1] == NULL)
+ __driUtilMessage ("Can't allocate memory for %s/.drirc.", home);
+ else {
+ memcpy (filenames[1], home, len);
+ memcpy (filenames[1] + len, "/.drirc", 7+1);
+ }
+ }
+
+ for (i = 0; i < 2; ++i) {
+ XML_Parser p;
+ if (filenames[i] == NULL)
+ continue;
+
+ p = XML_ParserCreate (NULL); /* use encoding specified by file */
+ XML_SetElementHandler (p, optConfStartElem, optConfEndElem);
+ XML_SetUserData (p, &userData);
+ userData.parser = p;
+ userData.name = filenames[i];
+ userData.ignoringDevice = 0;
+ userData.ignoringApp = 0;
+ userData.inDriConf = 0;
+ userData.inDevice = 0;
+ userData.inApp = 0;
+ userData.inOption = 0;
+
+ parseOneConfigFile (p);
+ XML_ParserFree (p);
+ }
+
+ if (filenames[1])
+ FREE (filenames[1]);
+}
+
+void driDestroyOptionInfo (driOptionCache *info) {
+ driDestroyOptionCache (info);
+ if (info->info) {
+ GLuint i, size = 1 << info->tableSize;
+ for (i = 0; i < size; ++i) {
+ if (info->info[i].name) {
+ FREE (info->info[i].name);
+ if (info->info[i].ranges)
+ FREE (info->info[i].ranges);
+ }
+ }
+ FREE (info->info);
+ }
+}
+
+void driDestroyOptionCache (driOptionCache *cache) {
+ if (cache->values)
+ FREE (cache->values);
+}
+
+GLboolean driCheckOption (const driOptionCache *cache, const char *name,
+ driOptionType type) {
+ GLuint i = findOption (cache, name);
+ return cache->info[i].name != NULL && cache->info[i].type == type;
+}
+
+GLboolean driQueryOptionb (const driOptionCache *cache, const char *name) {
+ GLuint i = findOption (cache, name);
+ /* make sure the option is defined and has the correct type */
+ assert (cache->info[i].name != NULL);
+ assert (cache->info[i].type == DRI_BOOL);
+ return cache->values[i]._bool;
+}
+
+GLint driQueryOptioni (const driOptionCache *cache, const char *name) {
+ GLuint i = findOption (cache, name);
+ /* make sure the option is defined and has the correct type */
+ assert (cache->info[i].name != NULL);
+ assert (cache->info[i].type == DRI_INT || cache->info[i].type == DRI_ENUM);
+ return cache->values[i]._int;
+}
+
+GLfloat driQueryOptionf (const driOptionCache *cache, const char *name) {
+ GLuint i = findOption (cache, name);
+ /* make sure the option is defined and has the correct type */
+ assert (cache->info[i].name != NULL);
+ assert (cache->info[i].type == DRI_FLOAT);
+ return cache->values[i]._float;
+}
diff --git a/src/mesa/drivers/dri/common/xmlconfig.h b/src/mesa/drivers/dri/common/xmlconfig.h
new file mode 100644
index 0000000000..710e328e01
--- /dev/null
+++ b/src/mesa/drivers/dri/common/xmlconfig.h
@@ -0,0 +1,125 @@
+/*
+ * XML DRI client-side driver configuration
+ * Copyright (C) 2003 Felix Kuehling
+ *
+ * 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, sublicense,
+ * 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 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 NONINFRINGEMENT. IN NO EVENT SHALL
+ * FELIX KUEHLING, OR ANY OTHER CONTRIBUTORS 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 xmlconfig.h
+ * \brief Driver-independent client-side part of the XML configuration
+ * \author Felix Kuehling
+ */
+
+#ifndef __XMLCONFIG_H
+#define __XMLCONFIG_H
+
+/** \brief Option data types */
+typedef enum driOptionType {
+ DRI_BOOL, DRI_ENUM, DRI_INT, DRI_FLOAT
+} driOptionType;
+
+/** \brief Option value */
+typedef union driOptionValue {
+ GLboolean _bool; /**< \brief Boolean */
+ GLint _int; /**< \brief Integer or Enum */
+ GLfloat _float; /**< \brief Floating-point */
+} driOptionValue;
+
+/** \brief Single range of valid values
+ *
+ * For empty ranges (a single value) start == end */
+typedef struct driOptionRange {
+ driOptionValue start; /**< \brief Start */
+ driOptionValue end; /**< \brief End */
+} driOptionRange;
+
+/** \brief Information about an option */
+typedef struct driOptionInfo {
+ char *name; /**< \brief Name */
+ driOptionType type; /**< \brief Type */
+ driOptionRange *ranges; /**< \brief Array of ranges */
+ GLuint nRanges; /**< \brief Number of ranges */
+} driOptionInfo;
+
+/** \brief Option cache
+ *
+ * \li One in <driver>Screen caching option info and the default values
+ * \li One in each <driver>Context with the actual values for that context */
+typedef struct driOptionCache {
+ driOptionInfo *info;
+ /**< \brief Array of option infos
+ *
+ * Points to the same array in the screen and all contexts */
+ driOptionValue *values;
+ /**< \brief Array of option values
+ *
+ * \li Default values in screen
+ * \li Actual values in contexts
+ */
+ GLuint tableSize;
+ /**< \brief Size of the arrays
+ *
+ * Depending on the hash function this may differ from __driNConfigOptions.
+ * In the current implementation it's not actually a size but log2(size).
+ * The value is the same in the screen and all contexts. */
+} driOptionCache;
+
+/** \brief XML document describing available options
+ *
+ * This must be defined in a driver-specific soure file. xmlpool.h
+ * defines helper macros and common options. */
+extern const char __driConfigOptions[];
+/** \brief The number of options supported by a driver
+ *
+ * This is used to choose an appropriate hash table size. So any value
+ * larger than the actual number of options will work. */
+extern const GLuint __driNConfigOptions;
+
+/** \brief Parse XML option info from __driConfigOptions
+ *
+ * To be called in <driver>CreateScreen */
+void driParseOptionInfo (driOptionCache *info);
+/** \brief Initialize option cache from info and parse configuration files
+ *
+ * To be called in <driver>CreateContext. screenNum and driverName select
+ * device sections. */
+void driParseConfigFiles (driOptionCache *cache, driOptionCache *info,
+ GLint screenNum, const char *driverName);
+/** \brief Destroy option info
+ *
+ * To be called in <driver>DestroyScreen */
+void driDestroyOptionInfo (driOptionCache *info);
+/** \brief Destroy option cache
+ *
+ * To be called in <driver>DestroyContext */
+void driDestroyOptionCache (driOptionCache *cache);
+
+/** \brief Check if there exists a certain option */
+GLboolean driCheckOption (const driOptionCache *cache, const char *name,
+ driOptionType type);
+
+/** \brief Query a boolean option value */
+GLboolean driQueryOptionb (const driOptionCache *cache, const char *name);
+/** \brief Query an integer option value */
+GLint driQueryOptioni (const driOptionCache *cache, const char *name);
+/** \brief Query a floating-point option value */
+GLfloat driQueryOptionf (const driOptionCache *cache, const char *name);
+
+#endif
diff --git a/src/mesa/drivers/dri/common/xmlpool.h b/src/mesa/drivers/dri/common/xmlpool.h
new file mode 100644
index 0000000000..c155373478
--- /dev/null
+++ b/src/mesa/drivers/dri/common/xmlpool.h
@@ -0,0 +1,203 @@
+/* -*- mode:C; coding: mult-utf-8-unix -*-
+ *
+ * !!! Important: This file is encoded in UTF-8 !!!
+ *
+ * Note (Emacs): You need Mule. In Debian the package is called
+ * mule-ucs.
+ *
+ * Note (Emacs): You may have to enable multibyte characters in the
+ * Mule customization group or by setting
+ * default-enable-multibyte-characters to t in your .emacs:
+ */
+/*
+ * XML DRI client-side driver configuration
+ * Copyright (C) 2003 Felix Kuehling
+ *
+ * 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, sublicense,
+ * 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 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 NONINFRINGEMENT. IN NO EVENT SHALL
+ * FELIX KUEHLING, OR ANY OTHER CONTRIBUTORS 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 xmlpool.h
+ * \brief Pool of common options
+ * \author Felix Kuehling
+ *
+ * This file defines macros that can be used to construct driConfigOptions
+ * in the drivers.
+ */
+
+#ifndef __XMLPOOL_H
+#define __XMLPOOL_H
+
+/*
+ * generic macros
+ */
+
+/** \brief Begin __driConfigOptions */
+#define DRI_CONF_BEGIN \
+"<driinfo>\n"
+
+/** \brief End __driConfigOptions */
+#define DRI_CONF_END \
+"</driinfo>\n"
+
+/** \brief Begin a section of related options */
+#define DRI_CONF_SECTION_BEGIN \
+"<section>\n"
+
+/** \brief End a section of related options */
+#define DRI_CONF_SECTION_END \
+"</section>\n"
+
+/** \brief Begin an option definition */
+#define DRI_CONF_OPT_BEGIN(name,type,def) \
+"<option name=\""#name"\" type=\""#type"\" default=\""#def"\">\n"
+
+/** \brief Begin an option definition with restrictions on valid values */
+#define DRI_CONF_OPT_BEGIN_V(name,type,def,valid) \
+"<option name=\""#name"\" type=\""#type"\" default=\""#def"\" valid=\""valid"\">\n"
+
+/** \brief End an option description */
+#define DRI_CONF_OPT_END \
+"</option>\n"
+
+/** \brief A verbal description in a specified language (empty version) */
+#define DRI_CONF_DESC(lang,text) \
+"<description lang=\""#lang"\" text=\""text"\"/>\n"
+
+/** \brief A verbal description in a specified language */
+#define DRI_CONF_DESC_BEGIN(lang,text) \
+"<description lang=\""#lang"\" text=\""text"\">\n"
+
+/** \brief End a description */
+#define DRI_CONF_DESC_END \
+"</description>\n"
+
+/** \brief A verbal description of an enum value */
+#define DRI_CONF_ENUM(value,text) \
+"<enum value=\""#value"\" text=\""text"\"/>\n"
+
+/*
+ * predefined option sections and options with multi-lingual descriptions
+ */
+
+/** \brief Debugging options */
+#define DRI_CONF_SECTION_DEBUG \
+DRI_CONF_SECTION_BEGIN \
+ DRI_CONF_DESC(en,"Debugging") \
+ DRI_CONF_DESC(de,"Fehlersuche")
+
+#define DRI_CONF_NO_RAST(def) \
+DRI_CONF_OPT_BEGIN(no_rast,bool,def) \
+ DRI_CONF_DESC(en,"Disable 3D acceleration") \
+ DRI_CONF_DESC(de,"3D-Beschleunigung abschalten") \
+DRI_CONF_OPT_END
+
+#define DRI_CONF_PERFORMANCE_BOXES(def) \
+DRI_CONF_OPT_BEGIN(performance_boxes,bool,def) \
+ DRI_CONF_DESC(en,"Show performance boxes") \
+ DRI_CONF_DESC(de,"Zeige Performanceboxen") \
+DRI_CONF_OPT_END
+
+#define DRI_CONF_DEBUG_DMA(def) \
+DRI_CONF_OPT_BEGIN(debug_dma,bool,def) \
+ DRI_CONF_DESC(en,"Debug DMA buffers") \
+ DRI_CONF_DESC(de,"DMA Puffer debuggen") \
+DRI_CONF_OPT_END
+
+
+/** \brief Texture-related options */
+#define DRI_CONF_SECTION_QUALITY \
+DRI_CONF_SECTION_BEGIN \
+ DRI_CONF_DESC(en,"Image Quality") \
+ DRI_CONF_DESC(de,"Bildqualität")
+
+#define DRI_CONF_PREFERRED_BPT(def,valid) \
+DRI_CONF_OPT_BEGIN_V(preferred_bpt,enum,def,valid) \
+ DRI_CONF_DESC_BEGIN(en,"Preferred texture color depth") \
+ DRI_CONF_ENUM(0,"Same as frame buffer") \
+ DRI_CONF_DESC_END \
+ DRI_CONF_DESC_BEGIN(de,"Bevorzugte Textur Farbtiefe") \
+ DRI_CONF_ENUM(0,"So wie der Framebuffer") \
+ DRI_CONF_DESC_END \
+DRI_CONF_OPT_END
+
+/** \brief Performance-related options */
+#define DRI_CONF_SECTION_PERFORMANCE \
+DRI_CONF_SECTION_BEGIN \
+ DRI_CONF_DESC(en,"Performance") \
+ DRI_CONF_DESC(de,"Leistung")
+
+#define DRI_CONF_TCL_SW 0
+#define DRI_CONF_TCL_PIPELINED 1
+#define DRI_CONF_TCL_VTXFMT 2
+#define DRI_CONF_TCL_CODEGEN 3
+#define DRI_CONF_TCL_MODE(def) \
+DRI_CONF_OPT_BEGIN_V(tcl_mode,enum,def,"0:3") \
+ DRI_CONF_DESC_BEGIN(en,"TCL mode (Transformation, Clipping, Lighting)") \
+ DRI_CONF_ENUM(0,"Software") \
+ DRI_CONF_ENUM(1,"TCL stage in MESA pipeline") \
+ DRI_CONF_ENUM(2,"Bypass MESA's pipeline") \
+ DRI_CONF_ENUM(3,"Bypass MESA's pipeline with state-based code generation") \
+ DRI_CONF_DESC_END \
+ DRI_CONF_DESC_BEGIN(de,"TCL Modus (Transformation, Clipping, Licht)") \
+ DRI_CONF_ENUM(0,"Software") \
+ DRI_CONF_ENUM(1,"TCL Stufe in MESA Pipeline") \
+ DRI_CONF_ENUM(2,"Umgehe MESA's Pipeline") \
+ DRI_CONF_ENUM(3,"Umgehe MESA's Pipeline mit zustandsbasierter Codegenerierung") \
+ DRI_CONF_DESC_END \
+DRI_CONF_OPT_END
+
+#define DRI_CONF_FTHROTTLE_BUSY 0
+#define DRI_CONF_FTHROTTLE_USLEEPS 1
+#define DRI_CONF_FTHROTTLE_IRQS 2
+#define DRI_CONF_FTHROTTLE_MODE(def) \
+DRI_CONF_OPT_BEGIN_V(fthrottle_mode,enum,def,"0:2") \
+ DRI_CONF_DESC_BEGIN(en,"Frame throttling") \
+ DRI_CONF_ENUM(0,"Busy waiting") \
+ DRI_CONF_ENUM(1,"Usleeps") \
+ DRI_CONF_ENUM(2,"Software interrupts") \
+ DRI_CONF_DESC_END \
+ DRI_CONF_DESC_BEGIN(de,"Framethrottling") \
+ DRI_CONF_ENUM(0,"Aktives Warten") \
+ DRI_CONF_ENUM(1,"Usleeps") \
+ DRI_CONF_ENUM(2,"Sortware Interrutps") \
+ DRI_CONF_DESC_END \
+DRI_CONF_OPT_END
+
+#define DRI_CONF_VBLANK_NEVER 0
+#define DRI_CONF_VBLANK_DEF_INTERVAL_0 1
+#define DRI_CONF_VBLANK_DEF_INTERVAL_1 2
+#define DRI_CONF_VBLANK_ALWAYS_SYNC 3
+#define DRI_CONF_VBLANK_MODE(def) \
+DRI_CONF_OPT_BEGIN_V(vblank_mode,enum,def,"0:3") \
+ DRI_CONF_DESC_BEGIN(en,"Synchronization with vertical refresh (swap intervals)") \
+ DRI_CONF_ENUM(0,"Never, FPS rulez!") \
+ DRI_CONF_ENUM(1,"Application preference, default interval 0") \
+ DRI_CONF_ENUM(2,"Application preference, default interval 1") \
+ DRI_CONF_ENUM(3,"Application preference, always synchronize with refresh") \
+ DRI_CONF_DESC_END \
+ DRI_CONF_DESC_BEGIN(de,"Synchronisation mit dem vertikalen Bildaufbau (swap intervals)") \
+ DRI_CONF_ENUM(0,"Niemals, immer die maximale Framerate") \
+ DRI_CONF_ENUM(1,"Anwendung entscheidet, Standardinterval 0") \
+ DRI_CONF_ENUM(2,"Anwendung entscheidet, Standardinterval 1") \
+ DRI_CONF_ENUM(3,"Anwendung entscheidet, immer mit Bildaufbau synchronisieren") \
+ DRI_CONF_DESC_END \
+DRI_CONF_OPT_END
+
+#endif