Home | History | Annotate | Download | only in common
      1 /*
      2  * (C) Copyright IBM Corporation 2002, 2004
      3  * All Rights Reserved.
      4  *
      5  * Permission is hereby granted, free of charge, to any person obtaining a
      6  * copy of this software and associated documentation files (the "Software"),
      7  * to deal in the Software without restriction, including without limitation
      8  * on the rights to use, copy, modify, merge, publish, distribute, sub
      9  * license, and/or sell copies of the Software, and to permit persons to whom
     10  * the Software is furnished to do so, subject to the following conditions:
     11  *
     12  * The above copyright notice and this permission notice (including the next
     13  * paragraph) shall be included in all copies or substantial portions of the
     14  * Software.
     15  *
     16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     18  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.  IN NO EVENT SHALL
     19  * VA LINUX SYSTEM, IBM AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
     20  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
     21  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
     22  * USE OR OTHER DEALINGS IN THE SOFTWARE.
     23  */
     24 
     25 /**
     26  * \file utils.c
     27  * Utility functions for DRI drivers.
     28  *
     29  * \author Ian Romanick <idr (at) us.ibm.com>
     30  */
     31 
     32 #include <string.h>
     33 #include <stdlib.h>
     34 #include "main/mtypes.h"
     35 #include "main/cpuinfo.h"
     36 #include "main/extensions.h"
     37 #include "utils.h"
     38 
     39 
     40 unsigned
     41 driParseDebugString( const char * debug,
     42 		     const struct dri_debug_control * control  )
     43 {
     44    unsigned   flag;
     45 
     46 
     47    flag = 0;
     48    if ( debug != NULL ) {
     49       while( control->string != NULL ) {
     50 	 if ( !strcmp( debug, "all" ) ||
     51 	      strstr( debug, control->string ) != NULL ) {
     52 	    flag |= control->flag;
     53 	 }
     54 
     55 	 control++;
     56       }
     57    }
     58 
     59    return flag;
     60 }
     61 
     62 
     63 
     64 /**
     65  * Create the \c GL_RENDERER string for DRI drivers.
     66  *
     67  * Almost all DRI drivers use a \c GL_RENDERER string of the form:
     68  *
     69  *    "Mesa DRI <chip> <driver date> <AGP speed) <CPU information>"
     70  *
     71  * Using the supplied chip name, driver data, and AGP speed, this function
     72  * creates the string.
     73  *
     74  * \param buffer         Buffer to hold the \c GL_RENDERER string.
     75  * \param hardware_name  Name of the hardware.
     76  * \param agp_mode       AGP mode (speed).
     77  *
     78  * \returns
     79  * The length of the string stored in \c buffer.  This does \b not include
     80  * the terminating \c NUL character.
     81  */
     82 unsigned
     83 driGetRendererString( char * buffer, const char * hardware_name,
     84 		      GLuint agp_mode )
     85 {
     86    unsigned offset;
     87    char *cpu;
     88 
     89    offset = sprintf( buffer, "Mesa DRI %s", hardware_name );
     90 
     91    /* Append any AGP-specific information.
     92     */
     93    switch ( agp_mode ) {
     94    case 1:
     95    case 2:
     96    case 4:
     97    case 8:
     98       offset += sprintf( & buffer[ offset ], " AGP %ux", agp_mode );
     99       break;
    100 
    101    default:
    102       break;
    103    }
    104 
    105    /* Append any CPU-specific information.
    106     */
    107    cpu = _mesa_get_cpu_string();
    108    if (cpu) {
    109       offset += sprintf(buffer + offset, " %s", cpu);
    110       free(cpu);
    111    }
    112 
    113    return offset;
    114 }
    115 
    116 
    117 /**
    118  * Creates a set of \c struct gl_config that a driver will expose.
    119  *
    120  * A set of \c struct gl_config will be created based on the supplied
    121  * parameters.  The number of modes processed will be 2 *
    122  * \c num_depth_stencil_bits * \c num_db_modes.
    123  *
    124  * For the most part, data is just copied from \c depth_bits, \c stencil_bits,
    125  * \c db_modes, and \c visType into each \c struct gl_config element.
    126  * However, the meanings of \c fb_format and \c fb_type require further
    127  * explanation.  The \c fb_format specifies which color components are in
    128  * each pixel and what the default order is.  For example, \c GL_RGB specifies
    129  * that red, green, blue are available and red is in the "most significant"
    130  * position and blue is in the "least significant".  The \c fb_type specifies
    131  * the bit sizes of each component and the actual ordering.  For example, if
    132  * \c GL_UNSIGNED_SHORT_5_6_5_REV is specified with \c GL_RGB, bits [15:11]
    133  * are the blue value, bits [10:5] are the green value, and bits [4:0] are
    134  * the red value.
    135  *
    136  * One sublte issue is the combination of \c GL_RGB  or \c GL_BGR and either
    137  * of the \c GL_UNSIGNED_INT_8_8_8_8 modes.  The resulting mask values in the
    138  * \c struct gl_config structure is \b identical to the \c GL_RGBA or
    139  * \c GL_BGRA case, except the \c alphaMask is zero.  This means that, as
    140  * far as this routine is concerned, \c GL_RGB with \c GL_UNSIGNED_INT_8_8_8_8
    141  * still uses 32-bits.
    142  *
    143  * If in doubt, look at the tables used in the function.
    144  *
    145  * \param ptr_to_modes  Pointer to a pointer to a linked list of
    146  *                      \c struct gl_config.  Upon completion, a pointer to
    147  *                      the next element to be process will be stored here.
    148  *                      If the function fails and returns \c GL_FALSE, this
    149  *                      value will be unmodified, but some elements in the
    150  *                      linked list may be modified.
    151  * \param fb_format     Format of the framebuffer.  Currently only \c GL_RGB,
    152  *                      \c GL_RGBA, \c GL_BGR, and \c GL_BGRA are supported.
    153  * \param fb_type       Type of the pixels in the framebuffer.  Currently only
    154  *                      \c GL_UNSIGNED_SHORT_5_6_5,
    155  *                      \c GL_UNSIGNED_SHORT_5_6_5_REV,
    156  *                      \c GL_UNSIGNED_INT_8_8_8_8, and
    157  *                      \c GL_UNSIGNED_INT_8_8_8_8_REV are supported.
    158  * \param depth_bits    Array of depth buffer sizes to be exposed.
    159  * \param stencil_bits  Array of stencil buffer sizes to be exposed.
    160  * \param num_depth_stencil_bits  Number of entries in both \c depth_bits and
    161  *                      \c stencil_bits.
    162  * \param db_modes      Array of buffer swap modes.  If an element has a
    163  *                      value of \c GLX_NONE, then it represents a
    164  *                      single-buffered mode.  Other valid values are
    165  *                      \c GLX_SWAP_EXCHANGE_OML, \c GLX_SWAP_COPY_OML, and
    166  *                      \c GLX_SWAP_UNDEFINED_OML.  See the
    167  *                      GLX_OML_swap_method extension spec for more details.
    168  * \param num_db_modes  Number of entries in \c db_modes.
    169  * \param msaa_samples  Array of msaa sample count. 0 represents a visual
    170  *                      without a multisample buffer.
    171  * \param num_msaa_modes Number of entries in \c msaa_samples.
    172  * \param visType       GLX visual type.  Usually either \c GLX_TRUE_COLOR or
    173  *                      \c GLX_DIRECT_COLOR.
    174  *
    175  * \returns
    176  * \c GL_TRUE on success or \c GL_FALSE on failure.  Currently the only
    177  * cause of failure is a bad parameter (i.e., unsupported \c fb_format or
    178  * \c fb_type).
    179  *
    180  * \todo
    181  * There is currently no way to support packed RGB modes (i.e., modes with
    182  * exactly 3 bytes per pixel) or floating-point modes.  This could probably
    183  * be done by creating some new, private enums with clever names likes
    184  * \c GL_UNSIGNED_3BYTE_8_8_8, \c GL_4FLOAT_32_32_32_32,
    185  * \c GL_4HALF_16_16_16_16, etc.  We can cross that bridge when we come to it.
    186  */
    187 __DRIconfig **
    188 driCreateConfigs(GLenum fb_format, GLenum fb_type,
    189 		 const uint8_t * depth_bits, const uint8_t * stencil_bits,
    190 		 unsigned num_depth_stencil_bits,
    191 		 const GLenum * db_modes, unsigned num_db_modes,
    192 		 const uint8_t * msaa_samples, unsigned num_msaa_modes,
    193 		 GLboolean enable_accum)
    194 {
    195    static const uint8_t bits_table[4][4] = {
    196      /* R  G  B  A */
    197       { 3, 3, 2, 0 }, /* Any GL_UNSIGNED_BYTE_3_3_2 */
    198       { 5, 6, 5, 0 }, /* Any GL_UNSIGNED_SHORT_5_6_5 */
    199       { 8, 8, 8, 0 }, /* Any RGB with any GL_UNSIGNED_INT_8_8_8_8 */
    200       { 8, 8, 8, 8 }  /* Any RGBA with any GL_UNSIGNED_INT_8_8_8_8 */
    201    };
    202 
    203    static const uint32_t masks_table_rgb[6][4] = {
    204       { 0x000000E0, 0x0000001C, 0x00000003, 0x00000000 }, /* 3_3_2       */
    205       { 0x00000007, 0x00000038, 0x000000C0, 0x00000000 }, /* 2_3_3_REV   */
    206       { 0x0000F800, 0x000007E0, 0x0000001F, 0x00000000 }, /* 5_6_5       */
    207       { 0x0000001F, 0x000007E0, 0x0000F800, 0x00000000 }, /* 5_6_5_REV   */
    208       { 0xFF000000, 0x00FF0000, 0x0000FF00, 0x00000000 }, /* 8_8_8_8     */
    209       { 0x000000FF, 0x0000FF00, 0x00FF0000, 0x00000000 }  /* 8_8_8_8_REV */
    210    };
    211 
    212    static const uint32_t masks_table_rgba[6][4] = {
    213       { 0x000000E0, 0x0000001C, 0x00000003, 0x00000000 }, /* 3_3_2       */
    214       { 0x00000007, 0x00000038, 0x000000C0, 0x00000000 }, /* 2_3_3_REV   */
    215       { 0x0000F800, 0x000007E0, 0x0000001F, 0x00000000 }, /* 5_6_5       */
    216       { 0x0000001F, 0x000007E0, 0x0000F800, 0x00000000 }, /* 5_6_5_REV   */
    217       { 0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF }, /* 8_8_8_8     */
    218       { 0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000 }, /* 8_8_8_8_REV */
    219    };
    220 
    221    static const uint32_t masks_table_bgr[6][4] = {
    222       { 0x00000007, 0x00000038, 0x000000C0, 0x00000000 }, /* 3_3_2       */
    223       { 0x000000E0, 0x0000001C, 0x00000003, 0x00000000 }, /* 2_3_3_REV   */
    224       { 0x0000001F, 0x000007E0, 0x0000F800, 0x00000000 }, /* 5_6_5       */
    225       { 0x0000F800, 0x000007E0, 0x0000001F, 0x00000000 }, /* 5_6_5_REV   */
    226       { 0x0000FF00, 0x00FF0000, 0xFF000000, 0x00000000 }, /* 8_8_8_8     */
    227       { 0x00FF0000, 0x0000FF00, 0x000000FF, 0x00000000 }, /* 8_8_8_8_REV */
    228    };
    229 
    230    static const uint32_t masks_table_bgra[6][4] = {
    231       { 0x00000007, 0x00000038, 0x000000C0, 0x00000000 }, /* 3_3_2       */
    232       { 0x000000E0, 0x0000001C, 0x00000003, 0x00000000 }, /* 2_3_3_REV   */
    233       { 0x0000001F, 0x000007E0, 0x0000F800, 0x00000000 }, /* 5_6_5       */
    234       { 0x0000F800, 0x000007E0, 0x0000001F, 0x00000000 }, /* 5_6_5_REV   */
    235       { 0x0000FF00, 0x00FF0000, 0xFF000000, 0x000000FF }, /* 8_8_8_8     */
    236       { 0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000 }, /* 8_8_8_8_REV */
    237    };
    238 
    239    static const uint8_t bytes_per_pixel[6] = {
    240       1, /* 3_3_2       */
    241       1, /* 2_3_3_REV   */
    242       2, /* 5_6_5       */
    243       2, /* 5_6_5_REV   */
    244       4, /* 8_8_8_8     */
    245       4  /* 8_8_8_8_REV */
    246    };
    247 
    248    const uint8_t  * bits;
    249    const uint32_t * masks;
    250    int index;
    251    __DRIconfig **configs, **c;
    252    struct gl_config *modes;
    253    unsigned i, j, k, h;
    254    unsigned num_modes;
    255    unsigned num_accum_bits = (enable_accum) ? 2 : 1;
    256 
    257    switch ( fb_type ) {
    258       case GL_UNSIGNED_BYTE_3_3_2:
    259 	 index = 0;
    260 	 break;
    261       case GL_UNSIGNED_BYTE_2_3_3_REV:
    262 	 index = 1;
    263 	 break;
    264       case GL_UNSIGNED_SHORT_5_6_5:
    265 	 index = 2;
    266 	 break;
    267       case GL_UNSIGNED_SHORT_5_6_5_REV:
    268 	 index = 3;
    269 	 break;
    270       case GL_UNSIGNED_INT_8_8_8_8:
    271 	 index = 4;
    272 	 break;
    273       case GL_UNSIGNED_INT_8_8_8_8_REV:
    274 	 index = 5;
    275 	 break;
    276       default:
    277 	 fprintf( stderr, "[%s:%u] Unknown framebuffer type 0x%04x.\n",
    278                __FUNCTION__, __LINE__, fb_type );
    279 	 return NULL;
    280    }
    281 
    282 
    283    /* Valid types are GL_UNSIGNED_SHORT_5_6_5 and GL_UNSIGNED_INT_8_8_8_8 and
    284     * the _REV versions.
    285     *
    286     * Valid formats are GL_RGBA, GL_RGB, and GL_BGRA.
    287     */
    288 
    289    switch ( fb_format ) {
    290       case GL_RGB:
    291          masks = masks_table_rgb[ index ];
    292          break;
    293 
    294       case GL_RGBA:
    295          masks = masks_table_rgba[ index ];
    296          break;
    297 
    298       case GL_BGR:
    299          masks = masks_table_bgr[ index ];
    300          break;
    301 
    302       case GL_BGRA:
    303          masks = masks_table_bgra[ index ];
    304          break;
    305 
    306       default:
    307          fprintf( stderr, "[%s:%u] Unknown framebuffer format 0x%04x.\n",
    308                __FUNCTION__, __LINE__, fb_format );
    309          return NULL;
    310    }
    311 
    312    switch ( bytes_per_pixel[ index ] ) {
    313       case 1:
    314 	 bits = bits_table[0];
    315 	 break;
    316       case 2:
    317 	 bits = bits_table[1];
    318 	 break;
    319       default:
    320 	 bits = ((fb_format == GL_RGB) || (fb_format == GL_BGR))
    321 	    ? bits_table[2]
    322 	    : bits_table[3];
    323 	 break;
    324    }
    325 
    326    num_modes = num_depth_stencil_bits * num_db_modes * num_accum_bits * num_msaa_modes;
    327    configs = calloc(1, (num_modes + 1) * sizeof *configs);
    328    if (configs == NULL)
    329        return NULL;
    330 
    331     c = configs;
    332     for ( k = 0 ; k < num_depth_stencil_bits ; k++ ) {
    333 	for ( i = 0 ; i < num_db_modes ; i++ ) {
    334 	    for ( h = 0 ; h < num_msaa_modes; h++ ) {
    335 	    	for ( j = 0 ; j < num_accum_bits ; j++ ) {
    336 		    *c = malloc (sizeof **c);
    337 		    modes = &(*c)->modes;
    338 		    c++;
    339 
    340 		    memset(modes, 0, sizeof *modes);
    341 		    modes->redBits   = bits[0];
    342 		    modes->greenBits = bits[1];
    343 		    modes->blueBits  = bits[2];
    344 		    modes->alphaBits = bits[3];
    345 		    modes->redMask   = masks[0];
    346 		    modes->greenMask = masks[1];
    347 		    modes->blueMask  = masks[2];
    348 		    modes->alphaMask = masks[3];
    349 		    modes->rgbBits   = modes->redBits + modes->greenBits
    350 		    	+ modes->blueBits + modes->alphaBits;
    351 
    352 		    modes->accumRedBits   = 16 * j;
    353 		    modes->accumGreenBits = 16 * j;
    354 		    modes->accumBlueBits  = 16 * j;
    355 		    modes->accumAlphaBits = (masks[3] != 0) ? 16 * j : 0;
    356 		    modes->visualRating = (j == 0) ? GLX_NONE : GLX_SLOW_CONFIG;
    357 
    358 		    modes->stencilBits = stencil_bits[k];
    359 		    modes->depthBits = depth_bits[k];
    360 
    361 		    modes->transparentPixel = GLX_NONE;
    362 		    modes->transparentRed = GLX_DONT_CARE;
    363 		    modes->transparentGreen = GLX_DONT_CARE;
    364 		    modes->transparentBlue = GLX_DONT_CARE;
    365 		    modes->transparentAlpha = GLX_DONT_CARE;
    366 		    modes->transparentIndex = GLX_DONT_CARE;
    367 		    modes->rgbMode = GL_TRUE;
    368 
    369 		    if ( db_modes[i] == GLX_NONE ) {
    370 		    	modes->doubleBufferMode = GL_FALSE;
    371 		    }
    372 		    else {
    373 		    	modes->doubleBufferMode = GL_TRUE;
    374 		    	modes->swapMethod = db_modes[i];
    375 		    }
    376 
    377 		    modes->samples = msaa_samples[h];
    378 		    modes->sampleBuffers = modes->samples ? 1 : 0;
    379 
    380 
    381 		    modes->haveAccumBuffer = ((modes->accumRedBits +
    382 					   modes->accumGreenBits +
    383 					   modes->accumBlueBits +
    384 					   modes->accumAlphaBits) > 0);
    385 		    modes->haveDepthBuffer = (modes->depthBits > 0);
    386 		    modes->haveStencilBuffer = (modes->stencilBits > 0);
    387 
    388 		    modes->bindToTextureRgb = GL_TRUE;
    389 		    modes->bindToTextureRgba = GL_TRUE;
    390 		    modes->bindToMipmapTexture = GL_FALSE;
    391 		    modes->bindToTextureTargets =
    392 			__DRI_ATTRIB_TEXTURE_1D_BIT |
    393 			__DRI_ATTRIB_TEXTURE_2D_BIT |
    394 			__DRI_ATTRIB_TEXTURE_RECTANGLE_BIT;
    395 
    396 		    modes->sRGBCapable = GL_FALSE;
    397 		}
    398 	    }
    399 	}
    400     }
    401     *c = NULL;
    402 
    403     return configs;
    404 }
    405 
    406 __DRIconfig **driConcatConfigs(__DRIconfig **a,
    407 			       __DRIconfig **b)
    408 {
    409     __DRIconfig **all;
    410     int i, j, index;
    411 
    412     if (a == NULL || a[0] == NULL)
    413        return b;
    414     else if (b == NULL || b[0] == NULL)
    415        return a;
    416 
    417     i = 0;
    418     while (a[i] != NULL)
    419 	i++;
    420     j = 0;
    421     while (b[j] != NULL)
    422 	j++;
    423 
    424     all = malloc((i + j + 1) * sizeof *all);
    425     index = 0;
    426     for (i = 0; a[i] != NULL; i++)
    427 	all[index++] = a[i];
    428     for (j = 0; b[j] != NULL; j++)
    429 	all[index++] = b[j];
    430     all[index++] = NULL;
    431 
    432     free(a);
    433     free(b);
    434 
    435     return all;
    436 }
    437 
    438 #define __ATTRIB(attrib, field) \
    439     { attrib, offsetof(struct gl_config, field) }
    440 
    441 static const struct { unsigned int attrib, offset; } attribMap[] = {
    442     __ATTRIB(__DRI_ATTRIB_BUFFER_SIZE,			rgbBits),
    443     __ATTRIB(__DRI_ATTRIB_LEVEL,			level),
    444     __ATTRIB(__DRI_ATTRIB_RED_SIZE,			redBits),
    445     __ATTRIB(__DRI_ATTRIB_GREEN_SIZE,			greenBits),
    446     __ATTRIB(__DRI_ATTRIB_BLUE_SIZE,			blueBits),
    447     __ATTRIB(__DRI_ATTRIB_ALPHA_SIZE,			alphaBits),
    448     __ATTRIB(__DRI_ATTRIB_DEPTH_SIZE,			depthBits),
    449     __ATTRIB(__DRI_ATTRIB_STENCIL_SIZE,			stencilBits),
    450     __ATTRIB(__DRI_ATTRIB_ACCUM_RED_SIZE,		accumRedBits),
    451     __ATTRIB(__DRI_ATTRIB_ACCUM_GREEN_SIZE,		accumGreenBits),
    452     __ATTRIB(__DRI_ATTRIB_ACCUM_BLUE_SIZE,		accumBlueBits),
    453     __ATTRIB(__DRI_ATTRIB_ACCUM_ALPHA_SIZE,		accumAlphaBits),
    454     __ATTRIB(__DRI_ATTRIB_SAMPLE_BUFFERS,		sampleBuffers),
    455     __ATTRIB(__DRI_ATTRIB_SAMPLES,			samples),
    456     __ATTRIB(__DRI_ATTRIB_DOUBLE_BUFFER,		doubleBufferMode),
    457     __ATTRIB(__DRI_ATTRIB_STEREO,			stereoMode),
    458     __ATTRIB(__DRI_ATTRIB_AUX_BUFFERS,			numAuxBuffers),
    459     __ATTRIB(__DRI_ATTRIB_TRANSPARENT_TYPE,		transparentPixel),
    460     __ATTRIB(__DRI_ATTRIB_TRANSPARENT_INDEX_VALUE,	transparentPixel),
    461     __ATTRIB(__DRI_ATTRIB_TRANSPARENT_RED_VALUE,	transparentRed),
    462     __ATTRIB(__DRI_ATTRIB_TRANSPARENT_GREEN_VALUE,	transparentGreen),
    463     __ATTRIB(__DRI_ATTRIB_TRANSPARENT_BLUE_VALUE,	transparentBlue),
    464     __ATTRIB(__DRI_ATTRIB_TRANSPARENT_ALPHA_VALUE,	transparentAlpha),
    465     __ATTRIB(__DRI_ATTRIB_FLOAT_MODE,			floatMode),
    466     __ATTRIB(__DRI_ATTRIB_RED_MASK,			redMask),
    467     __ATTRIB(__DRI_ATTRIB_GREEN_MASK,			greenMask),
    468     __ATTRIB(__DRI_ATTRIB_BLUE_MASK,			blueMask),
    469     __ATTRIB(__DRI_ATTRIB_ALPHA_MASK,			alphaMask),
    470     __ATTRIB(__DRI_ATTRIB_MAX_PBUFFER_WIDTH,		maxPbufferWidth),
    471     __ATTRIB(__DRI_ATTRIB_MAX_PBUFFER_HEIGHT,		maxPbufferHeight),
    472     __ATTRIB(__DRI_ATTRIB_MAX_PBUFFER_PIXELS,		maxPbufferPixels),
    473     __ATTRIB(__DRI_ATTRIB_OPTIMAL_PBUFFER_WIDTH,	optimalPbufferWidth),
    474     __ATTRIB(__DRI_ATTRIB_OPTIMAL_PBUFFER_HEIGHT,	optimalPbufferHeight),
    475     __ATTRIB(__DRI_ATTRIB_SWAP_METHOD,			swapMethod),
    476     __ATTRIB(__DRI_ATTRIB_BIND_TO_TEXTURE_RGB,		bindToTextureRgb),
    477     __ATTRIB(__DRI_ATTRIB_BIND_TO_TEXTURE_RGBA,		bindToTextureRgba),
    478     __ATTRIB(__DRI_ATTRIB_BIND_TO_MIPMAP_TEXTURE,	bindToMipmapTexture),
    479     __ATTRIB(__DRI_ATTRIB_BIND_TO_TEXTURE_TARGETS,	bindToTextureTargets),
    480     __ATTRIB(__DRI_ATTRIB_YINVERTED,			yInverted),
    481     __ATTRIB(__DRI_ATTRIB_FRAMEBUFFER_SRGB_CAPABLE,	sRGBCapable),
    482 
    483     /* The struct field doesn't matter here, these are handled by the
    484      * switch in driGetConfigAttribIndex.  We need them in the array
    485      * so the iterator includes them though.*/
    486     __ATTRIB(__DRI_ATTRIB_RENDER_TYPE,			level),
    487     __ATTRIB(__DRI_ATTRIB_CONFIG_CAVEAT,		level),
    488     __ATTRIB(__DRI_ATTRIB_SWAP_METHOD,			level)
    489 };
    490 
    491 #define ARRAY_SIZE(a) (sizeof (a) / sizeof ((a)[0]))
    492 
    493 
    494 /**
    495  * Return the value of a configuration attribute.  The attribute is
    496  * indicated by the index.
    497  */
    498 static int
    499 driGetConfigAttribIndex(const __DRIconfig *config,
    500 			unsigned int index, unsigned int *value)
    501 {
    502     switch (attribMap[index].attrib) {
    503     case __DRI_ATTRIB_RENDER_TYPE:
    504         /* no support for color index mode */
    505 	*value = __DRI_ATTRIB_RGBA_BIT;
    506 	break;
    507     case __DRI_ATTRIB_CONFIG_CAVEAT:
    508 	if (config->modes.visualRating == GLX_NON_CONFORMANT_CONFIG)
    509 	    *value = __DRI_ATTRIB_NON_CONFORMANT_CONFIG;
    510 	else if (config->modes.visualRating == GLX_SLOW_CONFIG)
    511 	    *value = __DRI_ATTRIB_SLOW_BIT;
    512 	else
    513 	    *value = 0;
    514 	break;
    515     case __DRI_ATTRIB_SWAP_METHOD:
    516         /* XXX no return value??? */
    517 	break;
    518 
    519     case __DRI_ATTRIB_FLOAT_MODE:
    520         /* this field is not int-sized */
    521         *value = config->modes.floatMode;
    522         break;
    523 
    524     default:
    525         /* any other int-sized field */
    526 	*value = *(unsigned int *)
    527 	    ((char *) &config->modes + attribMap[index].offset);
    528 
    529 	break;
    530     }
    531 
    532     return GL_TRUE;
    533 }
    534 
    535 
    536 /**
    537  * Get the value of a configuration attribute.
    538  * \param attrib  the attribute (one of the _DRI_ATTRIB_x tokens)
    539  * \param value  returns the attribute's value
    540  * \return 1 for success, 0 for failure
    541  */
    542 int
    543 driGetConfigAttrib(const __DRIconfig *config,
    544 		   unsigned int attrib, unsigned int *value)
    545 {
    546     int i;
    547 
    548     for (i = 0; i < ARRAY_SIZE(attribMap); i++)
    549 	if (attribMap[i].attrib == attrib)
    550 	    return driGetConfigAttribIndex(config, i, value);
    551 
    552     return GL_FALSE;
    553 }
    554 
    555 
    556 /**
    557  * Get a configuration attribute name and value, given an index.
    558  * \param index  which field of the __DRIconfig to query
    559  * \param attrib  returns the attribute name (one of the _DRI_ATTRIB_x tokens)
    560  * \param value  returns the attribute's value
    561  * \return 1 for success, 0 for failure
    562  */
    563 int
    564 driIndexConfigAttrib(const __DRIconfig *config, int index,
    565 		     unsigned int *attrib, unsigned int *value)
    566 {
    567     if (index >= 0 && index < ARRAY_SIZE(attribMap)) {
    568 	*attrib = attribMap[index].attrib;
    569 	return driGetConfigAttribIndex(config, index, value);
    570     }
    571 
    572     return GL_FALSE;
    573 }
    574