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 <stdio.h>
     34 #include <stdlib.h>
     35 #include <stdbool.h>
     36 #include <stdint.h>
     37 #include "main/macros.h"
     38 #include "main/mtypes.h"
     39 #include "main/cpuinfo.h"
     40 #include "main/extensions.h"
     41 #include "utils.h"
     42 #include "dri_util.h"
     43 
     44 /**
     45  * Create the \c GL_RENDERER string for DRI drivers.
     46  *
     47  * Almost all DRI drivers use a \c GL_RENDERER string of the form:
     48  *
     49  *    "Mesa DRI <chip> <driver date> <AGP speed) <CPU information>"
     50  *
     51  * Using the supplied chip name, driver data, and AGP speed, this function
     52  * creates the string.
     53  *
     54  * \param buffer         Buffer to hold the \c GL_RENDERER string.
     55  * \param hardware_name  Name of the hardware.
     56  * \param agp_mode       AGP mode (speed).
     57  *
     58  * \returns
     59  * The length of the string stored in \c buffer.  This does \b not include
     60  * the terminating \c NUL character.
     61  */
     62 unsigned
     63 driGetRendererString( char * buffer, const char * hardware_name,
     64 		      GLuint agp_mode )
     65 {
     66    unsigned offset;
     67    char *cpu;
     68 
     69    offset = sprintf( buffer, "Mesa DRI %s", hardware_name );
     70 
     71    /* Append any AGP-specific information.
     72     */
     73    switch ( agp_mode ) {
     74    case 1:
     75    case 2:
     76    case 4:
     77    case 8:
     78       offset += sprintf( & buffer[ offset ], " AGP %ux", agp_mode );
     79       break;
     80 
     81    default:
     82       break;
     83    }
     84 
     85    /* Append any CPU-specific information.
     86     */
     87    cpu = _mesa_get_cpu_string();
     88    if (cpu) {
     89       offset += sprintf(buffer + offset, " %s", cpu);
     90       free(cpu);
     91    }
     92 
     93    return offset;
     94 }
     95 
     96 
     97 /**
     98  * Creates a set of \c struct gl_config that a driver will expose.
     99  *
    100  * A set of \c struct gl_config will be created based on the supplied
    101  * parameters.  The number of modes processed will be 2 *
    102  * \c num_depth_stencil_bits * \c num_db_modes.
    103  *
    104  * For the most part, data is just copied from \c depth_bits, \c stencil_bits,
    105  * \c db_modes, and \c visType into each \c struct gl_config element.
    106  * However, the meanings of \c fb_format and \c fb_type require further
    107  * explanation.  The \c fb_format specifies which color components are in
    108  * each pixel and what the default order is.  For example, \c GL_RGB specifies
    109  * that red, green, blue are available and red is in the "most significant"
    110  * position and blue is in the "least significant".  The \c fb_type specifies
    111  * the bit sizes of each component and the actual ordering.  For example, if
    112  * \c GL_UNSIGNED_SHORT_5_6_5_REV is specified with \c GL_RGB, bits [15:11]
    113  * are the blue value, bits [10:5] are the green value, and bits [4:0] are
    114  * the red value.
    115  *
    116  * One sublte issue is the combination of \c GL_RGB  or \c GL_BGR and either
    117  * of the \c GL_UNSIGNED_INT_8_8_8_8 modes.  The resulting mask values in the
    118  * \c struct gl_config structure is \b identical to the \c GL_RGBA or
    119  * \c GL_BGRA case, except the \c alphaMask is zero.  This means that, as
    120  * far as this routine is concerned, \c GL_RGB with \c GL_UNSIGNED_INT_8_8_8_8
    121  * still uses 32-bits.
    122  *
    123  * If in doubt, look at the tables used in the function.
    124  *
    125  * \param ptr_to_modes  Pointer to a pointer to a linked list of
    126  *                      \c struct gl_config.  Upon completion, a pointer to
    127  *                      the next element to be process will be stored here.
    128  *                      If the function fails and returns \c GL_FALSE, this
    129  *                      value will be unmodified, but some elements in the
    130  *                      linked list may be modified.
    131  * \param format        Mesa mesa_format enum describing the pixel format
    132  * \param depth_bits    Array of depth buffer sizes to be exposed.
    133  * \param stencil_bits  Array of stencil buffer sizes to be exposed.
    134  * \param num_depth_stencil_bits  Number of entries in both \c depth_bits and
    135  *                      \c stencil_bits.
    136  * \param db_modes      Array of buffer swap modes.  If an element has a
    137  *                      value of \c GLX_NONE, then it represents a
    138  *                      single-buffered mode.  Other valid values are
    139  *                      \c GLX_SWAP_EXCHANGE_OML, \c GLX_SWAP_COPY_OML, and
    140  *                      \c GLX_SWAP_UNDEFINED_OML.  See the
    141  *                      GLX_OML_swap_method extension spec for more details.
    142  * \param num_db_modes  Number of entries in \c db_modes.
    143  * \param msaa_samples  Array of msaa sample count. 0 represents a visual
    144  *                      without a multisample buffer.
    145  * \param num_msaa_modes Number of entries in \c msaa_samples.
    146  * \param enable_accum  Add an accum buffer to the configs
    147  * \param color_depth_match Whether the color depth must match the zs depth
    148  *                          This forces 32-bit color to have 24-bit depth, and
    149  *                          16-bit color to have 16-bit depth.
    150  *
    151  * \returns
    152  * Pointer to any array of pointers to the \c __DRIconfig structures created
    153  * for the specified formats.  If there is an error, \c NULL is returned.
    154  * Currently the only cause of failure is a bad parameter (i.e., unsupported
    155  * \c format).
    156  */
    157 __DRIconfig **
    158 driCreateConfigs(mesa_format format,
    159 		 const uint8_t * depth_bits, const uint8_t * stencil_bits,
    160 		 unsigned num_depth_stencil_bits,
    161 		 const GLenum * db_modes, unsigned num_db_modes,
    162 		 const uint8_t * msaa_samples, unsigned num_msaa_modes,
    163 		 GLboolean enable_accum, GLboolean color_depth_match)
    164 {
    165    static const uint32_t masks_table[][4] = {
    166       /* MESA_FORMAT_B5G6R5_UNORM */
    167       { 0x0000F800, 0x000007E0, 0x0000001F, 0x00000000 },
    168       /* MESA_FORMAT_B8G8R8X8_UNORM */
    169       { 0x00FF0000, 0x0000FF00, 0x000000FF, 0x00000000 },
    170       /* MESA_FORMAT_B8G8R8A8_UNORM */
    171       { 0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000 },
    172       /* MESA_FORMAT_B10G10R10X2_UNORM */
    173       { 0x3FF00000, 0x000FFC00, 0x000003FF, 0x00000000 },
    174       /* MESA_FORMAT_B10G10R10A2_UNORM */
    175       { 0x3FF00000, 0x000FFC00, 0x000003FF, 0xC0000000 },
    176       /* MESA_FORMAT_R8G8B8A8_UNORM */
    177       { 0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000 },
    178       /* MESA_FORMAT_R8G8B8X8_UNORM */
    179       { 0x000000FF, 0x0000FF00, 0x00FF0000, 0x00000000 },
    180    };
    181 
    182    const uint32_t * masks;
    183    __DRIconfig **configs, **c;
    184    struct gl_config *modes;
    185    unsigned i, j, k, h;
    186    unsigned num_modes;
    187    unsigned num_accum_bits = (enable_accum) ? 2 : 1;
    188    int red_bits;
    189    int green_bits;
    190    int blue_bits;
    191    int alpha_bits;
    192    bool is_srgb;
    193 
    194    switch (format) {
    195    case MESA_FORMAT_B5G6R5_UNORM:
    196       masks = masks_table[0];
    197       break;
    198    case MESA_FORMAT_B8G8R8X8_UNORM:
    199    case MESA_FORMAT_B8G8R8X8_SRGB:
    200       masks = masks_table[1];
    201       break;
    202    case MESA_FORMAT_B8G8R8A8_UNORM:
    203    case MESA_FORMAT_B8G8R8A8_SRGB:
    204       masks = masks_table[2];
    205       break;
    206    case MESA_FORMAT_R8G8B8A8_UNORM:
    207       masks = masks_table[5];
    208       break;
    209    case MESA_FORMAT_R8G8B8X8_UNORM:
    210       masks = masks_table[6];
    211       break;
    212    case MESA_FORMAT_B10G10R10X2_UNORM:
    213       masks = masks_table[3];
    214       break;
    215    case MESA_FORMAT_B10G10R10A2_UNORM:
    216       masks = masks_table[4];
    217       break;
    218    default:
    219       fprintf(stderr, "[%s:%u] Unknown framebuffer type %s (%d).\n",
    220               __func__, __LINE__,
    221               _mesa_get_format_name(format), format);
    222       return NULL;
    223    }
    224 
    225    red_bits = _mesa_get_format_bits(format, GL_RED_BITS);
    226    green_bits = _mesa_get_format_bits(format, GL_GREEN_BITS);
    227    blue_bits = _mesa_get_format_bits(format, GL_BLUE_BITS);
    228    alpha_bits = _mesa_get_format_bits(format, GL_ALPHA_BITS);
    229    is_srgb = _mesa_get_format_color_encoding(format) == GL_SRGB;
    230 
    231    num_modes = num_depth_stencil_bits * num_db_modes * num_accum_bits * num_msaa_modes;
    232    configs = calloc(num_modes + 1, sizeof *configs);
    233    if (configs == NULL)
    234        return NULL;
    235 
    236     c = configs;
    237     for ( k = 0 ; k < num_depth_stencil_bits ; k++ ) {
    238 	for ( i = 0 ; i < num_db_modes ; i++ ) {
    239 	    for ( h = 0 ; h < num_msaa_modes; h++ ) {
    240 	    	for ( j = 0 ; j < num_accum_bits ; j++ ) {
    241 		    if (color_depth_match &&
    242 			(depth_bits[k] || stencil_bits[k])) {
    243 			/* Depth can really only be 0, 16, 24, or 32. A 32-bit
    244 			 * color format still matches 24-bit depth, as there
    245 			 * is an implicit 8-bit stencil. So really we just
    246 			 * need to make sure that color/depth are both 16 or
    247 			 * both non-16.
    248 			 */
    249 			if ((depth_bits[k] + stencil_bits[k] == 16) !=
    250 			    (red_bits + green_bits + blue_bits + alpha_bits == 16))
    251 			    continue;
    252 		    }
    253 
    254 		    *c = malloc (sizeof **c);
    255 		    modes = &(*c)->modes;
    256 		    c++;
    257 
    258 		    memset(modes, 0, sizeof *modes);
    259 		    modes->redBits   = red_bits;
    260 		    modes->greenBits = green_bits;
    261 		    modes->blueBits  = blue_bits;
    262 		    modes->alphaBits = alpha_bits;
    263 		    modes->redMask   = masks[0];
    264 		    modes->greenMask = masks[1];
    265 		    modes->blueMask  = masks[2];
    266 		    modes->alphaMask = masks[3];
    267 		    modes->rgbBits   = modes->redBits + modes->greenBits
    268 		    	+ modes->blueBits + modes->alphaBits;
    269 
    270 		    modes->accumRedBits   = 16 * j;
    271 		    modes->accumGreenBits = 16 * j;
    272 		    modes->accumBlueBits  = 16 * j;
    273 		    modes->accumAlphaBits = (masks[3] != 0) ? 16 * j : 0;
    274 		    modes->visualRating = (j == 0) ? GLX_NONE : GLX_SLOW_CONFIG;
    275 
    276 		    modes->stencilBits = stencil_bits[k];
    277 		    modes->depthBits = depth_bits[k];
    278 
    279 		    modes->transparentPixel = GLX_NONE;
    280 		    modes->transparentRed = GLX_DONT_CARE;
    281 		    modes->transparentGreen = GLX_DONT_CARE;
    282 		    modes->transparentBlue = GLX_DONT_CARE;
    283 		    modes->transparentAlpha = GLX_DONT_CARE;
    284 		    modes->transparentIndex = GLX_DONT_CARE;
    285 		    modes->rgbMode = GL_TRUE;
    286 
    287 		    if ( db_modes[i] == GLX_NONE ) {
    288 		    	modes->doubleBufferMode = GL_FALSE;
    289 		    }
    290 		    else {
    291 		    	modes->doubleBufferMode = GL_TRUE;
    292 		    	modes->swapMethod = db_modes[i];
    293 		    }
    294 
    295 		    modes->samples = msaa_samples[h];
    296 		    modes->sampleBuffers = modes->samples ? 1 : 0;
    297 
    298 
    299 		    modes->haveAccumBuffer = ((modes->accumRedBits +
    300 					   modes->accumGreenBits +
    301 					   modes->accumBlueBits +
    302 					   modes->accumAlphaBits) > 0);
    303 		    modes->haveDepthBuffer = (modes->depthBits > 0);
    304 		    modes->haveStencilBuffer = (modes->stencilBits > 0);
    305 
    306 		    modes->bindToTextureRgb = GL_TRUE;
    307 		    modes->bindToTextureRgba = GL_TRUE;
    308 		    modes->bindToMipmapTexture = GL_FALSE;
    309 		    modes->bindToTextureTargets =
    310 			__DRI_ATTRIB_TEXTURE_1D_BIT |
    311 			__DRI_ATTRIB_TEXTURE_2D_BIT |
    312 			__DRI_ATTRIB_TEXTURE_RECTANGLE_BIT;
    313 
    314 		    modes->yInverted = GL_TRUE;
    315 		    modes->sRGBCapable = is_srgb;
    316 		}
    317 	    }
    318 	}
    319     }
    320     *c = NULL;
    321 
    322     return configs;
    323 }
    324 
    325 __DRIconfig **driConcatConfigs(__DRIconfig **a,
    326 			       __DRIconfig **b)
    327 {
    328     __DRIconfig **all;
    329     int i, j, index;
    330 
    331     if (a == NULL || a[0] == NULL)
    332        return b;
    333     else if (b == NULL || b[0] == NULL)
    334        return a;
    335 
    336     i = 0;
    337     while (a[i] != NULL)
    338 	i++;
    339     j = 0;
    340     while (b[j] != NULL)
    341 	j++;
    342 
    343     all = malloc((i + j + 1) * sizeof *all);
    344     index = 0;
    345     for (i = 0; a[i] != NULL; i++)
    346 	all[index++] = a[i];
    347     for (j = 0; b[j] != NULL; j++)
    348 	all[index++] = b[j];
    349     all[index++] = NULL;
    350 
    351     free(a);
    352     free(b);
    353 
    354     return all;
    355 }
    356 
    357 #define __ATTRIB(attrib, field) \
    358     { attrib, offsetof(struct gl_config, field) }
    359 
    360 static const struct { unsigned int attrib, offset; } attribMap[] = {
    361     __ATTRIB(__DRI_ATTRIB_BUFFER_SIZE,			rgbBits),
    362     __ATTRIB(__DRI_ATTRIB_LEVEL,			level),
    363     __ATTRIB(__DRI_ATTRIB_RED_SIZE,			redBits),
    364     __ATTRIB(__DRI_ATTRIB_GREEN_SIZE,			greenBits),
    365     __ATTRIB(__DRI_ATTRIB_BLUE_SIZE,			blueBits),
    366     __ATTRIB(__DRI_ATTRIB_ALPHA_SIZE,			alphaBits),
    367     __ATTRIB(__DRI_ATTRIB_DEPTH_SIZE,			depthBits),
    368     __ATTRIB(__DRI_ATTRIB_STENCIL_SIZE,			stencilBits),
    369     __ATTRIB(__DRI_ATTRIB_ACCUM_RED_SIZE,		accumRedBits),
    370     __ATTRIB(__DRI_ATTRIB_ACCUM_GREEN_SIZE,		accumGreenBits),
    371     __ATTRIB(__DRI_ATTRIB_ACCUM_BLUE_SIZE,		accumBlueBits),
    372     __ATTRIB(__DRI_ATTRIB_ACCUM_ALPHA_SIZE,		accumAlphaBits),
    373     __ATTRIB(__DRI_ATTRIB_SAMPLE_BUFFERS,		sampleBuffers),
    374     __ATTRIB(__DRI_ATTRIB_SAMPLES,			samples),
    375     __ATTRIB(__DRI_ATTRIB_DOUBLE_BUFFER,		doubleBufferMode),
    376     __ATTRIB(__DRI_ATTRIB_STEREO,			stereoMode),
    377     __ATTRIB(__DRI_ATTRIB_AUX_BUFFERS,			numAuxBuffers),
    378     __ATTRIB(__DRI_ATTRIB_TRANSPARENT_TYPE,		transparentPixel),
    379     __ATTRIB(__DRI_ATTRIB_TRANSPARENT_INDEX_VALUE,	transparentPixel),
    380     __ATTRIB(__DRI_ATTRIB_TRANSPARENT_RED_VALUE,	transparentRed),
    381     __ATTRIB(__DRI_ATTRIB_TRANSPARENT_GREEN_VALUE,	transparentGreen),
    382     __ATTRIB(__DRI_ATTRIB_TRANSPARENT_BLUE_VALUE,	transparentBlue),
    383     __ATTRIB(__DRI_ATTRIB_TRANSPARENT_ALPHA_VALUE,	transparentAlpha),
    384     __ATTRIB(__DRI_ATTRIB_RED_MASK,			redMask),
    385     __ATTRIB(__DRI_ATTRIB_GREEN_MASK,			greenMask),
    386     __ATTRIB(__DRI_ATTRIB_BLUE_MASK,			blueMask),
    387     __ATTRIB(__DRI_ATTRIB_ALPHA_MASK,			alphaMask),
    388     __ATTRIB(__DRI_ATTRIB_MAX_PBUFFER_WIDTH,		maxPbufferWidth),
    389     __ATTRIB(__DRI_ATTRIB_MAX_PBUFFER_HEIGHT,		maxPbufferHeight),
    390     __ATTRIB(__DRI_ATTRIB_MAX_PBUFFER_PIXELS,		maxPbufferPixels),
    391     __ATTRIB(__DRI_ATTRIB_OPTIMAL_PBUFFER_WIDTH,	optimalPbufferWidth),
    392     __ATTRIB(__DRI_ATTRIB_OPTIMAL_PBUFFER_HEIGHT,	optimalPbufferHeight),
    393     __ATTRIB(__DRI_ATTRIB_SWAP_METHOD,			swapMethod),
    394     __ATTRIB(__DRI_ATTRIB_BIND_TO_TEXTURE_RGB,		bindToTextureRgb),
    395     __ATTRIB(__DRI_ATTRIB_BIND_TO_TEXTURE_RGBA,		bindToTextureRgba),
    396     __ATTRIB(__DRI_ATTRIB_BIND_TO_MIPMAP_TEXTURE,	bindToMipmapTexture),
    397     __ATTRIB(__DRI_ATTRIB_BIND_TO_TEXTURE_TARGETS,	bindToTextureTargets),
    398     __ATTRIB(__DRI_ATTRIB_YINVERTED,			yInverted),
    399     __ATTRIB(__DRI_ATTRIB_FRAMEBUFFER_SRGB_CAPABLE,	sRGBCapable),
    400 
    401     /* The struct field doesn't matter here, these are handled by the
    402      * switch in driGetConfigAttribIndex.  We need them in the array
    403      * so the iterator includes them though.*/
    404     __ATTRIB(__DRI_ATTRIB_RENDER_TYPE,			level),
    405     __ATTRIB(__DRI_ATTRIB_CONFIG_CAVEAT,		level),
    406     __ATTRIB(__DRI_ATTRIB_SWAP_METHOD,			level)
    407 };
    408 
    409 
    410 /**
    411  * Return the value of a configuration attribute.  The attribute is
    412  * indicated by the index.
    413  */
    414 static int
    415 driGetConfigAttribIndex(const __DRIconfig *config,
    416 			unsigned int index, unsigned int *value)
    417 {
    418     switch (attribMap[index].attrib) {
    419     case __DRI_ATTRIB_RENDER_TYPE:
    420         /* no support for color index mode */
    421 	*value = __DRI_ATTRIB_RGBA_BIT;
    422 	break;
    423     case __DRI_ATTRIB_CONFIG_CAVEAT:
    424 	if (config->modes.visualRating == GLX_NON_CONFORMANT_CONFIG)
    425 	    *value = __DRI_ATTRIB_NON_CONFORMANT_CONFIG;
    426 	else if (config->modes.visualRating == GLX_SLOW_CONFIG)
    427 	    *value = __DRI_ATTRIB_SLOW_BIT;
    428 	else
    429 	    *value = 0;
    430 	break;
    431     case __DRI_ATTRIB_SWAP_METHOD:
    432         /* XXX no return value??? */
    433 	break;
    434 
    435     default:
    436         /* any other int-sized field */
    437 	*value = *(unsigned int *)
    438 	    ((char *) &config->modes + attribMap[index].offset);
    439 
    440 	break;
    441     }
    442 
    443     return GL_TRUE;
    444 }
    445 
    446 
    447 /**
    448  * Get the value of a configuration attribute.
    449  * \param attrib  the attribute (one of the _DRI_ATTRIB_x tokens)
    450  * \param value  returns the attribute's value
    451  * \return 1 for success, 0 for failure
    452  */
    453 int
    454 driGetConfigAttrib(const __DRIconfig *config,
    455 		   unsigned int attrib, unsigned int *value)
    456 {
    457     unsigned i;
    458 
    459     for (i = 0; i < ARRAY_SIZE(attribMap); i++)
    460 	if (attribMap[i].attrib == attrib)
    461 	    return driGetConfigAttribIndex(config, i, value);
    462 
    463     return GL_FALSE;
    464 }
    465 
    466 
    467 /**
    468  * Get a configuration attribute name and value, given an index.
    469  * \param index  which field of the __DRIconfig to query
    470  * \param attrib  returns the attribute name (one of the _DRI_ATTRIB_x tokens)
    471  * \param value  returns the attribute's value
    472  * \return 1 for success, 0 for failure
    473  */
    474 int
    475 driIndexConfigAttrib(const __DRIconfig *config, int index,
    476 		     unsigned int *attrib, unsigned int *value)
    477 {
    478     if (index >= 0 && index < ARRAY_SIZE(attribMap)) {
    479 	*attrib = attribMap[index].attrib;
    480 	return driGetConfigAttribIndex(config, index, value);
    481     }
    482 
    483     return GL_FALSE;
    484 }
    485 
    486 /**
    487  * Implement queries for values that are common across all Mesa drivers
    488  *
    489  * Currently only the following queries are supported by this function:
    490  *
    491  *     - \c __DRI2_RENDERER_VERSION
    492  *     - \c __DRI2_RENDERER_PREFERRED_PROFILE
    493  *     - \c __DRI2_RENDERER_OPENGL_CORE_PROFILE_VERSION
    494  *     - \c __DRI2_RENDERER_OPENGL_COMPATIBLITY_PROFILE_VERSION
    495  *     - \c __DRI2_RENDERER_ES_PROFILE_VERSION
    496  *     - \c __DRI2_RENDERER_ES2_PROFILE_VERSION
    497  *
    498  * \returns
    499  * Zero if a recognized value of \c param is supplied, -1 otherwise.
    500  */
    501 int
    502 driQueryRendererIntegerCommon(__DRIscreen *psp, int param, unsigned int *value)
    503 {
    504    switch (param) {
    505    case __DRI2_RENDERER_VERSION: {
    506       static const char *const ver = PACKAGE_VERSION;
    507       char *endptr;
    508       int v[3];
    509 
    510       v[0] = strtol(ver, &endptr, 10);
    511       assert(endptr[0] == '.');
    512       if (endptr[0] != '.')
    513          return -1;
    514 
    515       v[1] = strtol(endptr + 1, &endptr, 10);
    516       assert(endptr[0] == '.');
    517       if (endptr[0] != '.')
    518          return -1;
    519 
    520       v[2] = strtol(endptr + 1, &endptr, 10);
    521 
    522       value[0] = v[0];
    523       value[1] = v[1];
    524       value[2] = v[2];
    525       return 0;
    526    }
    527    case __DRI2_RENDERER_PREFERRED_PROFILE:
    528       value[0] = (psp->max_gl_core_version != 0)
    529          ? (1U << __DRI_API_OPENGL_CORE) : (1U << __DRI_API_OPENGL);
    530       return 0;
    531    case __DRI2_RENDERER_OPENGL_CORE_PROFILE_VERSION:
    532       value[0] = psp->max_gl_core_version / 10;
    533       value[1] = psp->max_gl_core_version % 10;
    534       return 0;
    535    case __DRI2_RENDERER_OPENGL_COMPATIBILITY_PROFILE_VERSION:
    536       value[0] = psp->max_gl_compat_version / 10;
    537       value[1] = psp->max_gl_compat_version % 10;
    538       return 0;
    539    case __DRI2_RENDERER_OPENGL_ES_PROFILE_VERSION:
    540       value[0] = psp->max_gl_es1_version / 10;
    541       value[1] = psp->max_gl_es1_version % 10;
    542       return 0;
    543    case __DRI2_RENDERER_OPENGL_ES2_PROFILE_VERSION:
    544       value[0] = psp->max_gl_es2_version / 10;
    545       value[1] = psp->max_gl_es2_version % 10;
    546       return 0;
    547    default:
    548       break;
    549    }
    550 
    551    return -1;
    552 }
    553