• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
40 struct gl_extensions _mesa_extension_override_enables;
41 struct gl_extensions _mesa_extension_override_disables;
42 static 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  */
59 static int
name_to_index(const char * name)60 name_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  */
79 void
_mesa_override_extensions(struct gl_context * ctx)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  */
106 void
_mesa_enable_sw_extensions(struct gl_context * ctx)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 #ifdef TEXTURE_FLOAT_ENABLED
133    ctx->Extensions.ARB_texture_float = GL_TRUE;
134 #endif
135    ctx->Extensions.ARB_texture_mirror_clamp_to_edge = GL_TRUE;
136    ctx->Extensions.ARB_texture_non_power_of_two = GL_TRUE;
137    ctx->Extensions.ARB_texture_rg = GL_TRUE;
138    ctx->Extensions.ARB_texture_compression_rgtc = GL_TRUE;
139    ctx->Extensions.ARB_vertex_program = GL_TRUE;
140    ctx->Extensions.ARB_vertex_shader = GL_TRUE;
141    ctx->Extensions.ARB_sync = GL_TRUE;
142    ctx->Extensions.APPLE_object_purgeable = GL_TRUE;
143    ctx->Extensions.ATI_fragment_shader = GL_TRUE;
144    ctx->Extensions.ATI_texture_compression_3dc = GL_TRUE;
145    ctx->Extensions.ATI_texture_env_combine3 = GL_TRUE;
146    ctx->Extensions.ATI_texture_mirror_once = GL_TRUE;
147    ctx->Extensions.ATI_separate_stencil = GL_TRUE;
148    ctx->Extensions.EXT_blend_color = GL_TRUE;
149    ctx->Extensions.EXT_blend_equation_separate = GL_TRUE;
150    ctx->Extensions.EXT_blend_func_separate = GL_TRUE;
151    ctx->Extensions.EXT_blend_minmax = GL_TRUE;
152    ctx->Extensions.EXT_depth_bounds_test = GL_TRUE;
153    ctx->Extensions.EXT_draw_buffers2 = GL_TRUE;
154    ctx->Extensions.EXT_pixel_buffer_object = GL_TRUE;
155    ctx->Extensions.EXT_point_parameters = GL_TRUE;
156    ctx->Extensions.EXT_provoking_vertex = GL_TRUE;
157    ctx->Extensions.EXT_stencil_two_side = GL_TRUE;
158    ctx->Extensions.EXT_texture_array = GL_TRUE;
159    ctx->Extensions.EXT_texture_compression_latc = GL_TRUE;
160    ctx->Extensions.EXT_texture_env_dot3 = GL_TRUE;
161    ctx->Extensions.EXT_texture_filter_anisotropic = GL_TRUE;
162    ctx->Extensions.EXT_texture_mirror_clamp = GL_TRUE;
163    ctx->Extensions.EXT_texture_shared_exponent = GL_TRUE;
164    ctx->Extensions.EXT_texture_sRGB = GL_TRUE;
165    ctx->Extensions.EXT_texture_sRGB_decode = GL_TRUE;
166    ctx->Extensions.EXT_texture_swizzle = GL_TRUE;
167    /*ctx->Extensions.EXT_transform_feedback = GL_TRUE;*/
168    ctx->Extensions.EXT_vertex_array_bgra = GL_TRUE;
169    ctx->Extensions.MESA_pack_invert = GL_TRUE;
170    ctx->Extensions.MESA_ycbcr_texture = GL_TRUE;
171    ctx->Extensions.NV_conditional_render = GL_TRUE;
172    ctx->Extensions.NV_point_sprite = GL_TRUE;
173    ctx->Extensions.NV_texture_env_combine4 = GL_TRUE;
174    ctx->Extensions.NV_texture_rectangle = GL_TRUE;
175    ctx->Extensions.EXT_gpu_program_parameters = GL_TRUE;
176    ctx->Extensions.OES_standard_derivatives = GL_TRUE;
177    ctx->Extensions.TDFX_texture_compression_FXT1 = GL_TRUE;
178    ctx->Extensions.ANGLE_texture_compression_dxt = GL_TRUE;
179    ctx->Extensions.EXT_texture_compression_s3tc = GL_TRUE;
180 }
181 
182 /**
183  * Either enable or disable the named extension.
184  * \return offset of extensions withint `ext' or 0 if extension is not known
185  */
186 static size_t
set_extension(struct gl_extensions * ext,int i,GLboolean state)187 set_extension(struct gl_extensions *ext, int i, GLboolean state)
188 {
189    size_t offset;
190 
191    offset = i < 0 ? 0 : _mesa_extension_table[i].offset;
192    if (offset != 0 && (offset != o(dummy_true) || state != GL_FALSE)) {
193       ((GLboolean *) ext)[offset] = state;
194    }
195 
196    return offset;
197 }
198 
199 
200 /**
201  * \brief Free string pointed by unrecognized_extensions
202  *
203  * This string is allocated early during the first context creation by
204  * _mesa_one_time_init_extension_overrides.
205  */
206 static void
free_unknown_extensions_strings(void)207 free_unknown_extensions_strings(void)
208 {
209    free(unrecognized_extensions);
210 }
211 
212 
213 /**
214  * \brief Initialize extension override tables based on \c MESA_EXTENSION_OVERRIDE
215  *
216  * This should be called one time early during first context initialization.
217 
218  * \c MESA_EXTENSION_OVERRIDE is a space-separated list of extensions to
219  * enable or disable. The list is processed thus:
220  *    - Enable recognized extension names that are prefixed with '+'.
221  *    - Disable recognized extension names that are prefixed with '-'.
222  *    - Enable recognized extension names that are not prefixed.
223  *    - Collect unrecognized extension names in a new string.
224  */
225 void
_mesa_one_time_init_extension_overrides(struct gl_context * ctx)226 _mesa_one_time_init_extension_overrides(struct gl_context *ctx)
227 {
228    const char *env_const = getenv("MESA_EXTENSION_OVERRIDE");
229    char *env;
230    char *ext;
231    size_t offset;
232    unsigned unknown_ext = 0;
233 
234    memset(&_mesa_extension_override_enables, 0, sizeof(struct gl_extensions));
235    memset(&_mesa_extension_override_disables, 0, sizeof(struct gl_extensions));
236 
237    if (env_const == NULL) {
238       return;
239    }
240 
241    /* Copy env_const because strtok() is destructive. */
242    env = strdup(env_const);
243 
244    if (env == NULL)
245       return;
246 
247    for (ext = strtok(env, " "); ext != NULL; ext = strtok(NULL, " ")) {
248       int enable;
249       int i;
250       bool recognized;
251       switch (ext[0]) {
252       case '+':
253          enable = 1;
254          ++ext;
255          break;
256       case '-':
257          enable = 0;
258          ++ext;
259          break;
260       default:
261          enable = 1;
262          break;
263       }
264 
265       i = name_to_index(ext);
266       offset = set_extension(&_mesa_extension_override_enables, i, enable);
267       offset = set_extension(&_mesa_extension_override_disables, i, !enable);
268       if (offset != 0)
269          recognized = true;
270       else
271          recognized = false;
272 
273       if (!recognized && enable) {
274          if (unknown_ext >= MAX_UNRECOGNIZED_EXTENSIONS) {
275             static bool warned;
276 
277             if (!warned) {
278                warned = true;
279                _mesa_problem(ctx, "Trying to enable too many unknown extension. "
280                                   "Only the first %d will be honoured",
281                                   MAX_UNRECOGNIZED_EXTENSIONS);
282             }
283          } else {
284             ctx->Extensions.unrecognized_extensions[unknown_ext] = ext;
285             unknown_ext++;
286 
287             _mesa_problem(ctx, "Trying to enable unknown extension: %s", ext);
288          }
289       }
290    }
291 
292    if (!unknown_ext) {
293       free(env);
294    } else {
295       unrecognized_extensions = env;
296       atexit(free_unknown_extensions_strings);
297    }
298 }
299 
300 
301 /**
302  * \brief Initialize extension tables and enable default extensions.
303  *
304  * This should be called during context initialization.
305  * Note: Sets gl_extensions.dummy_true to true.
306  */
307 void
_mesa_init_extensions(struct gl_extensions * extensions)308 _mesa_init_extensions(struct gl_extensions *extensions)
309 {
310    GLboolean *base = (GLboolean *) extensions;
311    GLboolean *sentinel = base + o(extension_sentinel);
312    GLboolean *i;
313 
314    /* First, turn all extensions off. */
315    for (i = base; i != sentinel; ++i)
316       *i = GL_FALSE;
317 
318    /* Then, selectively turn default extensions on. */
319    extensions->dummy_true = GL_TRUE;
320 }
321 
322 
323 typedef unsigned short extension_index;
324 
325 
326 /**
327  * Given an extension enum, return whether or not the extension is supported
328  * dependent on the following factors:
329  * There's driver support and the OpenGL/ES version is at least that
330  * specified in the _mesa_extension_table.
331  */
332 static inline bool
_mesa_extension_supported(const struct gl_context * ctx,extension_index i)333 _mesa_extension_supported(const struct gl_context *ctx, extension_index i)
334 {
335    const bool *base = (bool *) &ctx->Extensions;
336    const struct mesa_extension *ext = _mesa_extension_table + i;
337 
338    return (ctx->Version >= ext->version[ctx->API]) && base[ext->offset];
339 }
340 
341 
342 /**
343  * Construct the GL_EXTENSIONS string.  Called the first time that
344  * glGetString(GL_EXTENSIONS) is called.
345  */
346 GLubyte*
_mesa_make_extension_string(struct gl_context * ctx)347 _mesa_make_extension_string(struct gl_context *ctx)
348 {
349    /* The extension string. */
350    char *exts = 0;
351    /* Length of extension string. */
352    size_t length = 0;
353    /* Number of extensions */
354    unsigned count;
355    /* Indices of the extensions sorted by year */
356    extension_index extension_indices[MESA_EXTENSION_COUNT];
357    unsigned k;
358    unsigned j;
359    unsigned maxYear = ~0;
360 
361    /* Check if the MESA_EXTENSION_MAX_YEAR env var is set */
362    {
363       const char *env = getenv("MESA_EXTENSION_MAX_YEAR");
364       if (env) {
365          maxYear = atoi(env);
366          _mesa_debug(ctx, "Note: limiting GL extensions to %u or earlier\n",
367                      maxYear);
368       }
369    }
370 
371    /* Compute length of the extension string. */
372    count = 0;
373    for (k = 0; k < MESA_EXTENSION_COUNT; ++k) {
374       const struct mesa_extension *i = _mesa_extension_table + k;
375 
376       if (i->year <= maxYear &&
377           _mesa_extension_supported(ctx, k)) {
378          length += strlen(i->name) + 1; /* +1 for space */
379          extension_indices[count++] = k;
380       }
381    }
382    for (k = 0; k < MAX_UNRECOGNIZED_EXTENSIONS; k++)
383       if (ctx->Extensions.unrecognized_extensions[k])
384          length += 1 + strlen(ctx->Extensions.unrecognized_extensions[k]); /* +1 for space */
385 
386    exts = calloc(ALIGN(length + 1, 4), sizeof(char));
387    if (exts == NULL) {
388       return NULL;
389    }
390 
391    /* Build the extension string.*/
392    for (j = 0; j < count; ++j) {
393       const struct mesa_extension *i = &_mesa_extension_table[extension_indices[j]];
394       assert(_mesa_extension_supported(ctx, extension_indices[j]));
395       strcat(exts, i->name);
396       strcat(exts, " ");
397    }
398    for (j = 0; j < MAX_UNRECOGNIZED_EXTENSIONS; j++) {
399       if (ctx->Extensions.unrecognized_extensions[j]) {
400          strcat(exts, ctx->Extensions.unrecognized_extensions[j]);
401          strcat(exts, " ");
402       }
403    }
404 
405    return (GLubyte *) exts;
406 }
407 
408 /**
409  * Return number of enabled extensions.
410  */
411 GLuint
_mesa_get_extension_count(struct gl_context * ctx)412 _mesa_get_extension_count(struct gl_context *ctx)
413 {
414    unsigned k;
415 
416    /* only count once */
417    if (ctx->Extensions.Count != 0)
418       return ctx->Extensions.Count;
419 
420    for (k = 0; k < MESA_EXTENSION_COUNT; ++k) {
421       if (_mesa_extension_supported(ctx, k))
422 	 ctx->Extensions.Count++;
423    }
424 
425    for (k = 0; k < MAX_UNRECOGNIZED_EXTENSIONS; ++k) {
426       if (ctx->Extensions.unrecognized_extensions[k])
427 	 ctx->Extensions.Count++;
428    }
429    return ctx->Extensions.Count;
430 }
431 
432 /**
433  * Return name of i-th enabled extension
434  */
435 const GLubyte *
_mesa_get_enabled_extension(struct gl_context * ctx,GLuint index)436 _mesa_get_enabled_extension(struct gl_context *ctx, GLuint index)
437 {
438    size_t n = 0;
439    unsigned i;
440 
441    for (i = 0; i < MESA_EXTENSION_COUNT; ++i) {
442       if (_mesa_extension_supported(ctx, i)) {
443          if (n == index)
444             return (const GLubyte*) _mesa_extension_table[i].name;
445          else
446             ++n;
447       }
448    }
449 
450    for (i = 0; i < MAX_UNRECOGNIZED_EXTENSIONS; ++i) {
451       if (ctx->Extensions.unrecognized_extensions[i]) {
452          if (n == index)
453             return (const GLubyte*) ctx->Extensions.unrecognized_extensions[i];
454          else
455             ++n;
456       }
457    }
458    return NULL;
459 }
460