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