extensions.c revision 7e995a2e
1/* 2 * Mesa 3-D graphics library 3 * 4 * Copyright (C) 1999-2008 Brian Paul All Rights Reserved. 5 * Copyright (C) 2009 VMware, Inc. All Rights Reserved. 6 * 7 * Permission is hereby granted, free of charge, to any person obtaining a 8 * copy of this software and associated documentation files (the "Software"), 9 * to deal in the Software without restriction, including without limitation 10 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 * and/or sell copies of the Software, and to permit persons to whom the 12 * Software is furnished to do so, subject to the following conditions: 13 * 14 * The above copyright notice and this permission notice shall be included 15 * in all copies or substantial portions of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 21 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 22 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23 * OTHER DEALINGS IN THE SOFTWARE. 24 */ 25 26 27/** 28 * \file 29 * \brief Extension handling 30 */ 31 32 33#include "glheader.h" 34#include "imports.h" 35#include "context.h" 36#include "extensions.h" 37#include "macros.h" 38#include "mtypes.h" 39 40struct gl_extensions _mesa_extension_override_enables; 41struct gl_extensions _mesa_extension_override_disables; 42static char *unrecognized_extensions = NULL; 43 44 45/** 46 * Given a member \c x of struct gl_extensions, return offset of 47 * \c x in bytes. 48 */ 49#define o(x) offsetof(struct gl_extensions, x) 50 51/** 52 * Given an extension name, lookup up the corresponding member of struct 53 * gl_extensions and return that member's index. If the name is 54 * not found in the \c _mesa_extension_table, return -1. 55 * 56 * \param name Name of extension. 57 * \return Index of member in struct gl_extensions. 58 */ 59static int 60name_to_index(const char* name) 61{ 62 unsigned i; 63 64 if (name == 0) 65 return -1; 66 67 for (i = 0; i < MESA_EXTENSION_COUNT; ++i) { 68 if (strcmp(name, _mesa_extension_table[i].name) == 0) 69 return i; 70 } 71 72 return -1; 73} 74 75/** 76 * Overrides extensions in \c ctx based on the values in 77 * _mesa_extension_override_enables and _mesa_extension_override_disables. 78 */ 79void 80_mesa_override_extensions(struct gl_context *ctx) 81{ 82 unsigned i; 83 const GLboolean *enables = 84 (GLboolean*) &_mesa_extension_override_enables; 85 const GLboolean *disables = 86 (GLboolean*) &_mesa_extension_override_disables; 87 GLboolean *ctx_ext = (GLboolean*)&ctx->Extensions; 88 89 for (i = 0; i < MESA_EXTENSION_COUNT; ++i) { 90 size_t offset = _mesa_extension_table[i].offset; 91 92 assert(!enables[offset] || !disables[offset]); 93 if (enables[offset]) { 94 ctx_ext[offset] = 1; 95 } else if (disables[offset]) { 96 ctx_ext[offset] = 0; 97 } 98 } 99} 100 101 102/** 103 * Enable all extensions suitable for a software-only renderer. 104 * This is a convenience function used by the XMesa, OSMesa, GGI drivers, etc. 105 */ 106void 107_mesa_enable_sw_extensions(struct gl_context *ctx) 108{ 109 ctx->Extensions.ARB_depth_clamp = GL_TRUE; 110 ctx->Extensions.ARB_depth_texture = GL_TRUE; 111 ctx->Extensions.ARB_draw_elements_base_vertex = GL_TRUE; 112 ctx->Extensions.ARB_draw_instanced = GL_TRUE; 113 ctx->Extensions.ARB_explicit_attrib_location = GL_TRUE; 114 ctx->Extensions.ARB_fragment_coord_conventions = GL_TRUE; 115 ctx->Extensions.ARB_fragment_program = GL_TRUE; 116 ctx->Extensions.ARB_fragment_program_shadow = GL_TRUE; 117 ctx->Extensions.ARB_fragment_shader = GL_TRUE; 118 ctx->Extensions.ARB_framebuffer_object = GL_TRUE; 119 ctx->Extensions.ARB_half_float_vertex = GL_TRUE; 120 ctx->Extensions.ARB_map_buffer_range = GL_TRUE; 121 ctx->Extensions.ARB_occlusion_query = GL_TRUE; 122 ctx->Extensions.ARB_occlusion_query2 = GL_TRUE; 123 ctx->Extensions.ARB_point_sprite = GL_TRUE; 124 ctx->Extensions.ARB_shadow = GL_TRUE; 125 ctx->Extensions.ARB_texture_border_clamp = GL_TRUE; 126 ctx->Extensions.ARB_texture_compression_bptc = GL_TRUE; 127 ctx->Extensions.ARB_texture_cube_map = GL_TRUE; 128 ctx->Extensions.ARB_texture_env_combine = GL_TRUE; 129 ctx->Extensions.ARB_texture_env_crossbar = GL_TRUE; 130 ctx->Extensions.ARB_texture_env_dot3 = GL_TRUE; 131 ctx->Extensions.ARB_texture_filter_anisotropic = GL_TRUE; 132 ctx->Extensions.ARB_texture_float = GL_TRUE; 133 ctx->Extensions.ARB_texture_mirror_clamp_to_edge = GL_TRUE; 134 ctx->Extensions.ARB_texture_non_power_of_two = GL_TRUE; 135 ctx->Extensions.ARB_texture_rg = GL_TRUE; 136 ctx->Extensions.ARB_texture_compression_rgtc = GL_TRUE; 137 ctx->Extensions.ARB_vertex_program = GL_TRUE; 138 ctx->Extensions.ARB_vertex_shader = GL_TRUE; 139 ctx->Extensions.ARB_sync = GL_TRUE; 140 ctx->Extensions.APPLE_object_purgeable = GL_TRUE; 141 ctx->Extensions.ATI_fragment_shader = GL_TRUE; 142 ctx->Extensions.ATI_texture_compression_3dc = GL_TRUE; 143 ctx->Extensions.ATI_texture_env_combine3 = GL_TRUE; 144 ctx->Extensions.ATI_texture_mirror_once = GL_TRUE; 145 ctx->Extensions.EXT_blend_color = GL_TRUE; 146 ctx->Extensions.EXT_blend_equation_separate = GL_TRUE; 147 ctx->Extensions.EXT_blend_func_separate = GL_TRUE; 148 ctx->Extensions.EXT_blend_minmax = GL_TRUE; 149 ctx->Extensions.EXT_depth_bounds_test = GL_TRUE; 150 ctx->Extensions.EXT_draw_buffers2 = GL_TRUE; 151 ctx->Extensions.EXT_pixel_buffer_object = GL_TRUE; 152 ctx->Extensions.EXT_point_parameters = GL_TRUE; 153 ctx->Extensions.EXT_provoking_vertex = GL_TRUE; 154 ctx->Extensions.EXT_stencil_two_side = GL_TRUE; 155 ctx->Extensions.EXT_texture_array = GL_TRUE; 156 ctx->Extensions.EXT_texture_compression_latc = GL_TRUE; 157 ctx->Extensions.EXT_texture_env_dot3 = GL_TRUE; 158 ctx->Extensions.EXT_texture_filter_anisotropic = GL_TRUE; 159 ctx->Extensions.EXT_texture_mirror_clamp = GL_TRUE; 160 ctx->Extensions.EXT_texture_shared_exponent = GL_TRUE; 161 ctx->Extensions.EXT_texture_sRGB = GL_TRUE; 162 ctx->Extensions.EXT_texture_sRGB_decode = GL_TRUE; 163 ctx->Extensions.EXT_texture_swizzle = GL_TRUE; 164 /*ctx->Extensions.EXT_transform_feedback = GL_TRUE;*/ 165 ctx->Extensions.EXT_vertex_array_bgra = GL_TRUE; 166 ctx->Extensions.MESA_pack_invert = GL_TRUE; 167 ctx->Extensions.MESA_ycbcr_texture = GL_TRUE; 168 ctx->Extensions.NV_conditional_render = GL_TRUE; 169 ctx->Extensions.NV_point_sprite = GL_TRUE; 170 ctx->Extensions.NV_texture_env_combine4 = GL_TRUE; 171 ctx->Extensions.NV_texture_rectangle = GL_TRUE; 172 ctx->Extensions.EXT_gpu_program_parameters = GL_TRUE; 173 ctx->Extensions.OES_standard_derivatives = GL_TRUE; 174 ctx->Extensions.TDFX_texture_compression_FXT1 = GL_TRUE; 175 ctx->Extensions.ANGLE_texture_compression_dxt = GL_TRUE; 176 ctx->Extensions.EXT_texture_compression_s3tc = GL_TRUE; 177} 178 179/** 180 * Either enable or disable the named extension. 181 * \return offset of extensions withint `ext' or 0 if extension is not known 182 */ 183static size_t 184set_extension(struct gl_extensions *ext, int i, GLboolean state) 185{ 186 size_t offset; 187 188 offset = i < 0 ? 0 : _mesa_extension_table[i].offset; 189 if (offset != 0 && (offset != o(dummy_true) || state != GL_FALSE)) { 190 ((GLboolean *) ext)[offset] = state; 191 } 192 193 return offset; 194} 195 196 197/** 198 * \brief Free string pointed by unrecognized_extensions 199 * 200 * This string is allocated early during the first context creation by 201 * _mesa_one_time_init_extension_overrides. 202 */ 203static void __attribute__((__destructor__)) 204free_unknown_extensions_strings(void) 205{ 206 free(unrecognized_extensions); 207} 208 209 210/** 211 * \brief Initialize extension override tables based on \c MESA_EXTENSION_OVERRIDE 212 * 213 * This should be called one time early during first context initialization. 214 215 * \c MESA_EXTENSION_OVERRIDE is a space-separated list of extensions to 216 * enable or disable. The list is processed thus: 217 * - Enable recognized extension names that are prefixed with '+'. 218 * - Disable recognized extension names that are prefixed with '-'. 219 * - Enable recognized extension names that are not prefixed. 220 * - Collect unrecognized extension names in a new string. 221 */ 222void 223_mesa_one_time_init_extension_overrides(struct gl_context *ctx) 224{ 225 const char *env_const = getenv("MESA_EXTENSION_OVERRIDE"); 226 char *env; 227 char *ext; 228 size_t offset; 229 unsigned unknown_ext = 0; 230 231 memset(&_mesa_extension_override_enables, 0, sizeof(struct gl_extensions)); 232 memset(&_mesa_extension_override_disables, 0, sizeof(struct gl_extensions)); 233 234 if (env_const == NULL) { 235 return; 236 } 237 238 /* Copy env_const because strtok() is destructive. */ 239 env = strdup(env_const); 240 241 if (env == NULL) 242 return; 243 244 for (ext = strtok(env, " "); ext != NULL; ext = strtok(NULL, " ")) { 245 int enable; 246 int i; 247 bool recognized; 248 switch (ext[0]) { 249 case '+': 250 enable = 1; 251 ++ext; 252 break; 253 case '-': 254 enable = 0; 255 ++ext; 256 break; 257 default: 258 enable = 1; 259 break; 260 } 261 262 i = name_to_index(ext); 263 offset = set_extension(&_mesa_extension_override_enables, i, enable); 264 offset = set_extension(&_mesa_extension_override_disables, i, !enable); 265 if (offset != 0) 266 recognized = true; 267 else 268 recognized = false; 269 270 if (!recognized && enable) { 271 if (unknown_ext >= MAX_UNRECOGNIZED_EXTENSIONS) { 272 static bool warned; 273 274 if (!warned) { 275 warned = true; 276 _mesa_problem(ctx, "Trying to enable too many unknown extension. " 277 "Only the first %d will be honoured", 278 MAX_UNRECOGNIZED_EXTENSIONS); 279 } 280 } else { 281 ctx->Extensions.unrecognized_extensions[unknown_ext] = ext; 282 unknown_ext++; 283 284 _mesa_problem(ctx, "Trying to enable unknown extension: %s", ext); 285 } 286 } 287 } 288 289 if (!unknown_ext) { 290 free(env); 291 } else { 292 unrecognized_extensions = env; 293 } 294} 295 296 297/** 298 * \brief Initialize extension tables and enable default extensions. 299 * 300 * This should be called during context initialization. 301 * Note: Sets gl_extensions.dummy_true to true. 302 */ 303void 304_mesa_init_extensions(struct gl_extensions *extensions) 305{ 306 GLboolean *base = (GLboolean *) extensions; 307 GLboolean *sentinel = base + o(extension_sentinel); 308 GLboolean *i; 309 310 /* First, turn all extensions off. */ 311 for (i = base; i != sentinel; ++i) 312 *i = GL_FALSE; 313 314 /* Then, selectively turn default extensions on. */ 315 extensions->dummy_true = GL_TRUE; 316} 317 318 319typedef unsigned short extension_index; 320 321 322/** 323 * Given an extension enum, return whether or not the extension is supported 324 * dependent on the following factors: 325 * There's driver support and the OpenGL/ES version is at least that 326 * specified in the _mesa_extension_table. 327 */ 328static inline bool 329_mesa_extension_supported(const struct gl_context *ctx, extension_index i) 330{ 331 const bool *base = (bool *) &ctx->Extensions; 332 const struct mesa_extension *ext = _mesa_extension_table + i; 333 334 return (ctx->Version >= ext->version[ctx->API]) && base[ext->offset]; 335} 336 337/** 338 * Compare two entries of the extensions table. Sorts first by year, 339 * then by name. 340 * 341 * Arguments are indices into _mesa_extension_table. 342 */ 343static int 344extension_compare(const void *p1, const void *p2) 345{ 346 extension_index i1 = * (const extension_index *) p1; 347 extension_index i2 = * (const extension_index *) p2; 348 const struct mesa_extension *e1 = &_mesa_extension_table[i1]; 349 const struct mesa_extension *e2 = &_mesa_extension_table[i2]; 350 int res; 351 352 res = (int)e1->year - (int)e2->year; 353 354 if (res == 0) { 355 res = strcmp(e1->name, e2->name); 356 } 357 358 return res; 359} 360 361 362/** 363 * Construct the GL_EXTENSIONS string. Called the first time that 364 * glGetString(GL_EXTENSIONS) is called. 365 */ 366GLubyte* 367_mesa_make_extension_string(struct gl_context *ctx) 368{ 369 /* The extension string. */ 370 char *exts = 0; 371 /* Length of extension string. */ 372 size_t length = 0; 373 /* Number of extensions */ 374 unsigned count; 375 /* Indices of the extensions sorted by year */ 376 extension_index extension_indices[MESA_EXTENSION_COUNT]; 377 unsigned k; 378 unsigned j; 379 unsigned maxYear = ~0; 380 381 /* Check if the MESA_EXTENSION_MAX_YEAR env var is set */ 382 { 383 const char *env = getenv("MESA_EXTENSION_MAX_YEAR"); 384 if (env) { 385 maxYear = atoi(env); 386 _mesa_debug(ctx, "Note: limiting GL extensions to %u or earlier\n", 387 maxYear); 388 } 389 } 390 391 /* Compute length of the extension string. */ 392 count = 0; 393 for (k = 0; k < MESA_EXTENSION_COUNT; ++k) { 394 const struct mesa_extension *i = _mesa_extension_table + k; 395 396 if (i->year <= maxYear && 397 _mesa_extension_supported(ctx, k)) { 398 length += strlen(i->name) + 1; /* +1 for space */ 399 ++count; 400 } 401 } 402 for (k = 0; k < MAX_UNRECOGNIZED_EXTENSIONS; k++) 403 if (ctx->Extensions.unrecognized_extensions[k]) 404 length += 1 + strlen(ctx->Extensions.unrecognized_extensions[k]); /* +1 for space */ 405 406 exts = calloc(ALIGN(length + 1, 4), sizeof(char)); 407 if (exts == NULL) { 408 return NULL; 409 } 410 411 /* Sort extensions in chronological order because idTech 2/3 games 412 * (e.g., Quake3 demo) store the extension list in a fixed size buffer. 413 * Some cases truncate, while others overflow the buffer. Resulting in 414 * misrendering and crashes, respectively. 415 * Address the former here, while the latter will be addressed by setting 416 * the MESA_EXTENSION_MAX_YEAR environment variable. 417 */ 418 j = 0; 419 for (k = 0; k < MESA_EXTENSION_COUNT; ++k) { 420 if (_mesa_extension_table[k].year <= maxYear && 421 _mesa_extension_supported(ctx, k)) { 422 extension_indices[j++] = k; 423 } 424 } 425 assert(j == count); 426 qsort(extension_indices, count, 427 sizeof *extension_indices, extension_compare); 428 429 /* Build the extension string.*/ 430 for (j = 0; j < count; ++j) { 431 const struct mesa_extension *i = &_mesa_extension_table[extension_indices[j]]; 432 assert(_mesa_extension_supported(ctx, extension_indices[j])); 433 strcat(exts, i->name); 434 strcat(exts, " "); 435 } 436 for (j = 0; j < MAX_UNRECOGNIZED_EXTENSIONS; j++) { 437 if (ctx->Extensions.unrecognized_extensions[j]) { 438 strcat(exts, ctx->Extensions.unrecognized_extensions[j]); 439 strcat(exts, " "); 440 } 441 } 442 443 return (GLubyte *) exts; 444} 445 446/** 447 * Return number of enabled extensions. 448 */ 449GLuint 450_mesa_get_extension_count(struct gl_context *ctx) 451{ 452 unsigned k; 453 454 /* only count once */ 455 if (ctx->Extensions.Count != 0) 456 return ctx->Extensions.Count; 457 458 for (k = 0; k < MESA_EXTENSION_COUNT; ++k) { 459 if (_mesa_extension_supported(ctx, k)) 460 ctx->Extensions.Count++; 461 } 462 463 for (k = 0; k < MAX_UNRECOGNIZED_EXTENSIONS; ++k) { 464 if (ctx->Extensions.unrecognized_extensions[k]) 465 ctx->Extensions.Count++; 466 } 467 return ctx->Extensions.Count; 468} 469 470/** 471 * Return name of i-th enabled extension 472 */ 473const GLubyte * 474_mesa_get_enabled_extension(struct gl_context *ctx, GLuint index) 475{ 476 size_t n = 0; 477 unsigned i; 478 479 for (i = 0; i < MESA_EXTENSION_COUNT; ++i) { 480 if (_mesa_extension_supported(ctx, i)) { 481 if (n == index) 482 return (const GLubyte*) _mesa_extension_table[i].name; 483 else 484 ++n; 485 } 486 } 487 488 for (i = 0; i < MAX_UNRECOGNIZED_EXTENSIONS; ++i) { 489 if (ctx->Extensions.unrecognized_extensions[i]) { 490 if (n == index) 491 return (const GLubyte*) ctx->Extensions.unrecognized_extensions[i]; 492 else 493 ++n; 494 } 495 } 496 return NULL; 497} 498