2
* Mesa 3-D graphics library
4
* Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
5
* Copyright (C) 2009 VMware, Inc. All Rights Reserved.
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:
14
* The above copyright notice and this permission notice shall be included
15
* in all copies or substantial portions of the Software.
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.
29
* \brief Extension handling
32
#include "util/os_misc.h"
37
#include "extensions.h"
41
struct gl_extensions _mesa_extension_override_enables;
42
struct gl_extensions _mesa_extension_override_disables;
44
#define MAX_UNRECOGNIZED_EXTENSIONS 16
47
const char *names[MAX_UNRECOGNIZED_EXTENSIONS];
48
} unrecognized_extensions;
51
* Given a member \c x of struct gl_extensions, return offset of
54
#define o(x) offsetof(struct gl_extensions, x)
57
extension_name_compare(const void *name, const void *elem)
59
const struct mesa_extension *entry = elem;
60
return strcmp(name, entry->name);
64
* Given an extension name, lookup up the corresponding member of struct
65
* gl_extensions and return that member's index. If the name is
66
* not found in the \c _mesa_extension_table, return -1.
68
* \param name Name of extension.
69
* \return Index of member in struct gl_extensions.
72
name_to_index(const char* name)
74
const struct mesa_extension *entry;
80
_mesa_extension_table, MESA_EXTENSION_COUNT,
81
sizeof(_mesa_extension_table[0]),
82
extension_name_compare);
85
return entry - _mesa_extension_table;
91
* Overrides extensions in \c ctx based on the values in
92
* _mesa_extension_override_enables and _mesa_extension_override_disables.
95
_mesa_override_extensions(struct gl_context *ctx)
98
const GLboolean *enables =
99
(GLboolean*) &_mesa_extension_override_enables;
100
const GLboolean *disables =
101
(GLboolean*) &_mesa_extension_override_disables;
102
GLboolean *ctx_ext = (GLboolean*)&ctx->Extensions;
104
for (i = 0; i < MESA_EXTENSION_COUNT; ++i) {
105
size_t offset = _mesa_extension_table[i].offset;
107
assert(!enables[offset] || !disables[offset]);
108
if (enables[offset]) {
110
} else if (disables[offset]) {
117
* Either enable or disable the named extension.
118
* \return offset of extensions withint `ext' or 0 if extension is not known
121
set_extension(struct gl_extensions *ext, int i, GLboolean state)
125
offset = i < 0 ? 0 : _mesa_extension_table[i].offset;
126
if (offset != 0 && (offset != o(dummy_true) || state != GL_FALSE)) {
127
((GLboolean *) ext)[offset] = state;
135
* \brief Free string pointed by unrecognized_extensions
137
* This string is allocated early during the first context creation by
138
* _mesa_one_time_init_extension_overrides.
141
free_unknown_extensions_strings(void)
143
free(unrecognized_extensions.env);
144
for (int i = 0; i < MAX_UNRECOGNIZED_EXTENSIONS; ++i)
145
unrecognized_extensions.names[i] = NULL;
150
* \brief Initialize extension override tables based on \c override
152
* This should be called one time early during first context initialization.
154
* \c override is a space-separated list of extensions to
155
* enable or disable. The list is processed thus:
156
* - Enable recognized extension names that are prefixed with '+'.
157
* - Disable recognized extension names that are prefixed with '-'.
158
* - Enable recognized extension names that are not prefixed.
159
* - Collect unrecognized extension names in a new string.
162
_mesa_one_time_init_extension_overrides(const char *override)
167
unsigned unknown_ext = 0;
169
memset(&_mesa_extension_override_enables, 0, sizeof(struct gl_extensions));
170
memset(&_mesa_extension_override_disables, 0, sizeof(struct gl_extensions));
172
if (override == NULL || override[0] == '\0') {
176
/* Copy 'override' because strtok() is destructive. */
177
env = strdup(override);
182
for (ext = strtok(env, " "); ext != NULL; ext = strtok(NULL, " ")) {
200
i = name_to_index(ext);
201
offset = set_extension(&_mesa_extension_override_enables, i, enable);
202
offset = set_extension(&_mesa_extension_override_disables, i, !enable);
208
if (!enable && recognized && offset <= 1) {
209
printf("Warning: extension '%s' cannot be disabled\n", ext);
210
offset = set_extension(&_mesa_extension_override_disables, i, 0);
213
if (!recognized && enable) {
214
if (unknown_ext >= MAX_UNRECOGNIZED_EXTENSIONS) {
219
_mesa_problem(NULL, "Trying to enable too many unknown extension. "
220
"Only the first %d will be honoured",
221
MAX_UNRECOGNIZED_EXTENSIONS);
224
unrecognized_extensions.names[unknown_ext] = ext;
226
_mesa_problem(NULL, "Trying to enable unknown extension: %s", ext);
234
unrecognized_extensions.env = env;
235
atexit(free_unknown_extensions_strings);
241
* \brief Initialize extension tables and enable default extensions.
243
* This should be called during context initialization.
244
* Note: Sets gl_extensions.dummy_true to true.
247
_mesa_init_extensions(struct gl_extensions *extensions)
249
GLboolean *base = (GLboolean *) extensions;
250
GLboolean *sentinel = base + o(extension_sentinel);
253
/* First, turn all extensions off. */
254
for (i = base; i != sentinel; ++i)
257
/* Then, selectively turn default extensions on. */
258
extensions->dummy_true = GL_TRUE;
260
/* Always enable these extensions for all drivers.
261
* We can't use dummy_true in extensions_table.h for these
262
* because this would make them non-disablable using
263
* _mesa_override_extensions.
265
extensions->MESA_pack_invert = GL_TRUE;
266
extensions->MESA_window_pos = GL_TRUE;
268
extensions->ARB_ES2_compatibility = GL_TRUE;
269
extensions->ARB_draw_elements_base_vertex = GL_TRUE;
270
extensions->ARB_explicit_attrib_location = GL_TRUE;
271
extensions->ARB_explicit_uniform_location = GL_TRUE;
272
extensions->ARB_fragment_coord_conventions = GL_TRUE;
273
extensions->ARB_fragment_program = GL_TRUE;
274
extensions->ARB_fragment_shader = GL_TRUE;
275
extensions->ARB_half_float_vertex = GL_TRUE;
276
extensions->ARB_internalformat_query = GL_TRUE;
277
extensions->ARB_internalformat_query2 = GL_TRUE;
278
extensions->ARB_map_buffer_range = GL_TRUE;
279
extensions->ARB_occlusion_query = GL_TRUE;
280
extensions->ARB_sync = GL_TRUE;
281
extensions->ARB_vertex_program = GL_TRUE;
282
extensions->ARB_vertex_shader = GL_TRUE;
284
extensions->EXT_EGL_image_storage = GL_TRUE;
285
extensions->EXT_gpu_program_parameters = GL_TRUE;
286
extensions->EXT_pixel_buffer_object = GL_TRUE;
287
extensions->EXT_provoking_vertex = GL_TRUE;
288
extensions->EXT_stencil_two_side = GL_TRUE;
289
extensions->EXT_texture_env_dot3 = GL_TRUE;
291
extensions->ATI_fragment_shader = GL_TRUE;
292
extensions->ATI_texture_env_combine3 = GL_TRUE;
294
extensions->MESA_framebuffer_flip_y = GL_TRUE;
296
extensions->NV_copy_image = GL_TRUE;
297
extensions->NV_fog_distance = GL_TRUE;
298
extensions->NV_texture_env_combine4 = GL_TRUE;
299
extensions->NV_texture_rectangle = GL_TRUE;
301
extensions->OES_EGL_image = GL_TRUE;
302
extensions->OES_EGL_image_external = GL_TRUE;
303
extensions->OES_draw_texture = GL_TRUE;
307
typedef unsigned short extension_index;
311
* Given an extension enum, return whether or not the extension is supported
312
* dependent on the following factors:
313
* There's driver support and the OpenGL/ES version is at least that
314
* specified in the _mesa_extension_table.
317
_mesa_extension_supported(const struct gl_context *ctx, extension_index i)
319
const bool *base = (bool *) &ctx->Extensions;
320
const struct mesa_extension *ext = _mesa_extension_table + i;
322
return (ctx->Version >= ext->version[ctx->API]) && base[ext->offset];
326
* Compare two entries of the extensions table. Sorts first by year,
329
* Arguments are indices into _mesa_extension_table.
332
extension_compare(const void *p1, const void *p2)
334
extension_index i1 = * (const extension_index *) p1;
335
extension_index i2 = * (const extension_index *) p2;
336
const struct mesa_extension *e1 = &_mesa_extension_table[i1];
337
const struct mesa_extension *e2 = &_mesa_extension_table[i2];
340
res = (int)e1->year - (int)e2->year;
343
res = strcmp(e1->name, e2->name);
351
* Construct the GL_EXTENSIONS string. Called the first time that
352
* glGetString(GL_EXTENSIONS) is called.
355
_mesa_make_extension_string(struct gl_context *ctx)
357
/* The extension string. */
359
/* Length of extension string. */
361
/* Number of extensions */
363
/* Indices of the extensions sorted by year */
364
extension_index extension_indices[MESA_EXTENSION_COUNT];
367
unsigned maxYear = ~0;
369
/* Check if the MESA_EXTENSION_MAX_YEAR env var is set */
371
const char *env = getenv("MESA_EXTENSION_MAX_YEAR");
374
_mesa_debug(ctx, "Note: limiting GL extensions to %u or earlier\n",
379
/* Compute length of the extension string. */
381
for (k = 0; k < MESA_EXTENSION_COUNT; ++k) {
382
const struct mesa_extension *i = _mesa_extension_table + k;
384
if (i->year <= maxYear &&
385
_mesa_extension_supported(ctx, k)) {
386
length += strlen(i->name) + 1; /* +1 for space */
390
for (k = 0; k < MAX_UNRECOGNIZED_EXTENSIONS; k++)
391
if (unrecognized_extensions.names[k])
392
length += 1 + strlen(unrecognized_extensions.names[k]); /* +1 for space */
394
exts = calloc(ALIGN(length + 1, 4), sizeof(char));
399
/* Sort extensions in chronological order because idTech 2/3 games
400
* (e.g., Quake3 demo) store the extension list in a fixed size buffer.
401
* Some cases truncate, while others overflow the buffer. Resulting in
402
* misrendering and crashes, respectively.
403
* Address the former here, while the latter will be addressed by setting
404
* the MESA_EXTENSION_MAX_YEAR environment variable.
407
for (k = 0; k < MESA_EXTENSION_COUNT; ++k) {
408
if (_mesa_extension_table[k].year <= maxYear &&
409
_mesa_extension_supported(ctx, k)) {
410
extension_indices[j++] = k;
414
qsort(extension_indices, count,
415
sizeof *extension_indices, extension_compare);
417
/* Build the extension string.*/
418
for (j = 0; j < count; ++j) {
419
const struct mesa_extension *i = &_mesa_extension_table[extension_indices[j]];
420
assert(_mesa_extension_supported(ctx, extension_indices[j]));
421
strcat(exts, i->name);
424
for (j = 0; j < MAX_UNRECOGNIZED_EXTENSIONS; j++) {
425
if (unrecognized_extensions.names[j]) {
426
strcat(exts, unrecognized_extensions.names[j]);
431
return (GLubyte *) exts;
435
* Return number of enabled extensions.
438
_mesa_get_extension_count(struct gl_context *ctx)
442
/* only count once */
443
if (ctx->Extensions.Count != 0)
444
return ctx->Extensions.Count;
446
for (k = 0; k < MESA_EXTENSION_COUNT; ++k) {
447
if (_mesa_extension_supported(ctx, k))
448
ctx->Extensions.Count++;
451
for (k = 0; k < MAX_UNRECOGNIZED_EXTENSIONS; ++k) {
452
if (unrecognized_extensions.names[k])
453
ctx->Extensions.Count++;
455
return ctx->Extensions.Count;
459
* Return name of i-th enabled extension
462
_mesa_get_enabled_extension(struct gl_context *ctx, GLuint index)
467
for (i = 0; i < MESA_EXTENSION_COUNT; ++i) {
468
if (_mesa_extension_supported(ctx, i)) {
470
return (const GLubyte*) _mesa_extension_table[i].name;
476
for (i = 0; i < MAX_UNRECOGNIZED_EXTENSIONS; ++i) {
477
if (unrecognized_extensions.names[i]) {
479
return (const GLubyte*) unrecognized_extensions.names[i];