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