extensions.c revision d63b28c1
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 *extra_extensions = NULL;
43static char *cant_disable_extensions = NULL;
44
45enum {
46   DISABLE = 0,
47   GLL = 1 << API_OPENGL_COMPAT,       /* GL Legacy / Compatibility */
48   GLC = 1 << API_OPENGL_CORE,  /* GL Core */
49   GL  = (1 << API_OPENGL_COMPAT) | (1 << API_OPENGL_CORE),
50   ES1 = 1 << API_OPENGLES,
51   ES2 = 1 << API_OPENGLES2,
52   ES3 = 1 << (API_OPENGL_LAST + 1),
53};
54
55/**
56 * \brief An element of the \c extension_table.
57 */
58struct extension {
59   /** Name of extension, such as "GL_ARB_depth_clamp". */
60   const char *name;
61
62   /** Offset (in bytes) of the corresponding member in struct gl_extensions. */
63   size_t offset;
64
65   /** Set of API's in which the extension exists, as a bitset. */
66   uint8_t api_set;
67
68   /** Year the extension was proposed or approved.  Used to sort the
69    * extension string chronologically. */
70   uint16_t year;
71};
72
73
74/**
75 * Given a member \c x of struct gl_extensions, return offset of
76 * \c x in bytes.
77 */
78#define o(x) offsetof(struct gl_extensions, x)
79
80
81/**
82 * \brief Table of supported OpenGL extensions for all API's.
83 */
84static const struct extension extension_table[] = {
85   /* ARB Extensions */
86   { "GL_ARB_ES2_compatibility",                   o(ARB_ES2_compatibility),                   GL,             2009 },
87   { "GL_ARB_ES3_compatibility",                   o(ARB_ES3_compatibility),                   GL,             2012 },
88   { "GL_ARB_arrays_of_arrays",                    o(ARB_arrays_of_arrays),                    GL,             2012 },
89   { "GL_ARB_base_instance",                       o(ARB_base_instance),                       GL,             2011 },
90   { "GL_ARB_blend_func_extended",                 o(ARB_blend_func_extended),                 GL,             2009 },
91   { "GL_ARB_buffer_storage",                      o(ARB_buffer_storage),                      GL,             2013 },
92   { "GL_ARB_clear_buffer_object",                 o(dummy_true),                              GL,             2012 },
93   { "GL_ARB_clear_texture",                       o(ARB_clear_texture),                       GL,             2013 },
94   { "GL_ARB_color_buffer_float",                  o(ARB_color_buffer_float),                  GL,             2004 },
95   { "GL_ARB_compressed_texture_pixel_storage",    o(dummy_true),                              GL,             2011 },
96   { "GL_ARB_compute_shader",                      o(ARB_compute_shader),                      GL,             2012 },
97   { "GL_ARB_conditional_render_inverted",         o(ARB_conditional_render_inverted),         GL,             2014 },
98   { "GL_ARB_copy_buffer",                         o(dummy_true),                              GL,             2008 },
99   { "GL_ARB_copy_image",                          o(ARB_copy_image),                          GL,             2012 },
100   { "GL_ARB_conservative_depth",                  o(ARB_conservative_depth),                  GL,             2011 },
101   { "GL_ARB_debug_output",                        o(dummy_true),                              GL,             2009 },
102   { "GL_ARB_depth_buffer_float",                  o(ARB_depth_buffer_float),                  GL,             2008 },
103   { "GL_ARB_depth_clamp",                         o(ARB_depth_clamp),                         GL,             2003 },
104   { "GL_ARB_depth_texture",                       o(ARB_depth_texture),                       GLL,            2001 },
105   { "GL_ARB_derivative_control",                  o(ARB_derivative_control),                  GL,             2014 },
106   { "GL_ARB_draw_buffers",                        o(dummy_true),                              GL,             2002 },
107   { "GL_ARB_draw_buffers_blend",                  o(ARB_draw_buffers_blend),                  GL,             2009 },
108   { "GL_ARB_draw_elements_base_vertex",           o(ARB_draw_elements_base_vertex),           GL,             2009 },
109   { "GL_ARB_draw_indirect",                       o(ARB_draw_indirect),                       GLC,            2010 },
110   { "GL_ARB_draw_instanced",                      o(ARB_draw_instanced),                      GL,             2008 },
111   { "GL_ARB_explicit_attrib_location",            o(ARB_explicit_attrib_location),            GL,             2009 },
112   { "GL_ARB_explicit_uniform_location",           o(ARB_explicit_uniform_location),           GL,             2012 },
113   { "GL_ARB_fragment_coord_conventions",          o(ARB_fragment_coord_conventions),          GL,             2009 },
114   { "GL_ARB_fragment_layer_viewport",             o(ARB_fragment_layer_viewport),             GLC,            2012 },
115   { "GL_ARB_fragment_program",                    o(ARB_fragment_program),                    GLL,            2002 },
116   { "GL_ARB_fragment_program_shadow",             o(ARB_fragment_program_shadow),             GLL,            2003 },
117   { "GL_ARB_fragment_shader",                     o(ARB_fragment_shader),                     GL,             2002 },
118   { "GL_ARB_framebuffer_object",                  o(ARB_framebuffer_object),                  GL,             2005 },
119   { "GL_ARB_framebuffer_sRGB",                    o(EXT_framebuffer_sRGB),                    GL,             1998 },
120   { "GL_ARB_get_program_binary",                  o(dummy_true),                              GL,             2010 },
121   { "GL_ARB_gpu_shader5",                         o(ARB_gpu_shader5),                         GLC,            2010 },
122   { "GL_ARB_half_float_pixel",                    o(dummy_true),                              GL,             2003 },
123   { "GL_ARB_half_float_vertex",                   o(ARB_half_float_vertex),                   GL,             2008 },
124   { "GL_ARB_instanced_arrays",                    o(ARB_instanced_arrays),                    GL,             2008 },
125   { "GL_ARB_internalformat_query",                o(ARB_internalformat_query),                GL,             2011 },
126   { "GL_ARB_invalidate_subdata",                  o(dummy_true),                              GL,             2012 },
127   { "GL_ARB_map_buffer_alignment",                o(dummy_true),                              GL,             2011 },
128   { "GL_ARB_map_buffer_range",                    o(ARB_map_buffer_range),                    GL,             2008 },
129   { "GL_ARB_multi_bind",                          o(dummy_true),                              GL,             2013 },
130   { "GL_ARB_multi_draw_indirect",                 o(ARB_draw_indirect),                       GLC,            2012 },
131   { "GL_ARB_multisample",                         o(dummy_true),                              GLL,            1994 },
132   { "GL_ARB_multitexture",                        o(dummy_true),                              GLL,            1998 },
133   { "GL_ARB_occlusion_query2",                    o(ARB_occlusion_query2),                    GL,             2003 },
134   { "GL_ARB_occlusion_query",                     o(ARB_occlusion_query),                     GLL,            2001 },
135   { "GL_ARB_pixel_buffer_object",                 o(EXT_pixel_buffer_object),                 GL,             2004 },
136   { "GL_ARB_point_parameters",                    o(EXT_point_parameters),                    GLL,            1997 },
137   { "GL_ARB_point_sprite",                        o(ARB_point_sprite),                        GL,             2003 },
138   { "GL_ARB_provoking_vertex",                    o(EXT_provoking_vertex),                    GL,             2009 },
139   { "GL_ARB_robustness",                          o(dummy_true),                              GL,             2010 },
140   { "GL_ARB_sample_shading",                      o(ARB_sample_shading),                      GL,             2009 },
141   { "GL_ARB_sampler_objects",                     o(dummy_true),                              GL,             2009 },
142   { "GL_ARB_seamless_cube_map",                   o(ARB_seamless_cube_map),                   GL,             2009 },
143   { "GL_ARB_seamless_cubemap_per_texture",        o(AMD_seamless_cubemap_per_texture),        GL,             2013 },
144   { "GL_ARB_separate_shader_objects",             o(dummy_true),                              GL,             2010 },
145   { "GL_ARB_shader_atomic_counters",              o(ARB_shader_atomic_counters),              GL,             2011 },
146   { "GL_ARB_shader_bit_encoding",                 o(ARB_shader_bit_encoding),                 GL,             2010 },
147   { "GL_ARB_shader_image_load_store",             o(ARB_shader_image_load_store),             GL,             2011 },
148   { "GL_ARB_shader_objects",                      o(dummy_true),                              GL,             2002 },
149   { "GL_ARB_shader_stencil_export",               o(ARB_shader_stencil_export),               GL,             2009 },
150   { "GL_ARB_shader_texture_lod",                  o(ARB_shader_texture_lod),                  GL,             2009 },
151   { "GL_ARB_shading_language_100",                o(dummy_true),                              GLL,            2003 },
152   { "GL_ARB_shading_language_packing",            o(ARB_shading_language_packing),            GL,             2011 },
153   { "GL_ARB_shading_language_420pack",            o(ARB_shading_language_420pack),            GL,             2011 },
154   { "GL_ARB_shadow",                              o(ARB_shadow),                              GLL,            2001 },
155   { "GL_ARB_stencil_texturing",                   o(ARB_stencil_texturing),                   GL,             2012 },
156   { "GL_ARB_sync",                                o(ARB_sync),                                GL,             2003 },
157   { "GL_ARB_texture_barrier",                     o(NV_texture_barrier),                      GL,             2014 },
158   { "GL_ARB_texture_border_clamp",                o(ARB_texture_border_clamp),                GLL,            2000 },
159   { "GL_ARB_texture_buffer_object",               o(ARB_texture_buffer_object),               GLC,            2008 },
160   { "GL_ARB_texture_buffer_object_rgb32",         o(ARB_texture_buffer_object_rgb32),         GLC,            2009 },
161   { "GL_ARB_texture_buffer_range",                o(ARB_texture_buffer_range),                GLC,            2012 },
162   { "GL_ARB_texture_compression",                 o(dummy_true),                              GLL,            2000 },
163   { "GL_ARB_texture_compression_bptc",            o(ARB_texture_compression_bptc),            GL,             2010 },
164   { "GL_ARB_texture_compression_rgtc",            o(ARB_texture_compression_rgtc),            GL,             2004 },
165   { "GL_ARB_texture_cube_map",                    o(ARB_texture_cube_map),                    GLL,            1999 },
166   { "GL_ARB_texture_cube_map_array",              o(ARB_texture_cube_map_array),              GL,             2009 },
167   { "GL_ARB_texture_env_add",                     o(dummy_true),                              GLL,            1999 },
168   { "GL_ARB_texture_env_combine",                 o(ARB_texture_env_combine),                 GLL,            2001 },
169   { "GL_ARB_texture_env_crossbar",                o(ARB_texture_env_crossbar),                GLL,            2001 },
170   { "GL_ARB_texture_env_dot3",                    o(ARB_texture_env_dot3),                    GLL,            2001 },
171   { "GL_ARB_texture_float",                       o(ARB_texture_float),                       GL,             2004 },
172   { "GL_ARB_texture_gather",                      o(ARB_texture_gather),                      GL,             2009 },
173   { "GL_ARB_texture_mirrored_repeat",             o(dummy_true),                              GLL,            2001 },
174   { "GL_ARB_texture_mirror_clamp_to_edge",        o(ARB_texture_mirror_clamp_to_edge),        GL,             2013 },
175   { "GL_ARB_texture_multisample",                 o(ARB_texture_multisample),                 GL,             2009 },
176   { "GL_ARB_texture_non_power_of_two",            o(ARB_texture_non_power_of_two),            GL,             2003 },
177   { "GL_ARB_texture_query_levels",                o(ARB_texture_query_levels),                GL,             2012 },
178   { "GL_ARB_texture_query_lod",                   o(ARB_texture_query_lod),                   GL,             2009 },
179   { "GL_ARB_texture_rectangle",                   o(NV_texture_rectangle),                    GL,             2004 },
180   { "GL_ARB_texture_rgb10_a2ui",                  o(ARB_texture_rgb10_a2ui),                  GL,             2009 },
181   { "GL_ARB_texture_rg",                          o(ARB_texture_rg),                          GL,             2008 },
182   { "GL_ARB_texture_storage",                     o(dummy_true),                              GL,             2011 },
183   { "GL_ARB_texture_storage_multisample",         o(ARB_texture_multisample),                 GL,             2012 },
184   { "GL_ARB_texture_view",                        o(ARB_texture_view),                        GL,             2012 },
185   { "GL_ARB_texture_swizzle",                     o(EXT_texture_swizzle),                     GL,             2008 },
186   { "GL_ARB_timer_query",                         o(ARB_timer_query),                         GL,             2010 },
187   { "GL_ARB_transform_feedback2",                 o(ARB_transform_feedback2),                 GL,             2010 },
188   { "GL_ARB_transform_feedback3",                 o(ARB_transform_feedback3),                 GL,             2010 },
189   { "GL_ARB_transform_feedback_instanced",        o(ARB_transform_feedback_instanced),        GL,             2011 },
190   { "GL_ARB_transpose_matrix",                    o(dummy_true),                              GLL,            1999 },
191   { "GL_ARB_uniform_buffer_object",               o(ARB_uniform_buffer_object),               GL,             2009 },
192   { "GL_ARB_vertex_array_bgra",                   o(EXT_vertex_array_bgra),                   GL,             2008 },
193   { "GL_ARB_vertex_array_object",                 o(dummy_true),                              GL,             2006 },
194   { "GL_ARB_vertex_attrib_binding",               o(dummy_true),                              GL,             2012 },
195   { "GL_ARB_vertex_buffer_object",                o(dummy_true),                              GLL,            2003 },
196   { "GL_ARB_vertex_program",                      o(ARB_vertex_program),                      GLL,            2002 },
197   { "GL_ARB_vertex_shader",                       o(ARB_vertex_shader),                       GL,             2002 },
198   { "GL_ARB_vertex_type_10f_11f_11f_rev",         o(ARB_vertex_type_10f_11f_11f_rev),         GL,             2013 },
199   { "GL_ARB_vertex_type_2_10_10_10_rev",          o(ARB_vertex_type_2_10_10_10_rev),          GL,             2009 },
200   { "GL_ARB_viewport_array",                      o(ARB_viewport_array),                      GLC,            2010 },
201   { "GL_ARB_window_pos",                          o(dummy_true),                              GLL,            2001 },
202   /* EXT extensions */
203   { "GL_EXT_abgr",                                o(dummy_true),                              GL,             1995 },
204   { "GL_EXT_bgra",                                o(dummy_true),                              GLL,            1995 },
205   { "GL_EXT_blend_color",                         o(EXT_blend_color),                         GLL,            1995 },
206   { "GL_EXT_blend_equation_separate",             o(EXT_blend_equation_separate),             GL,             2003 },
207   { "GL_EXT_blend_func_separate",                 o(EXT_blend_func_separate),                 GLL,            1999 },
208   { "GL_EXT_discard_framebuffer",                 o(dummy_true),                                    ES1 | ES2, 2009 },
209   { "GL_EXT_blend_minmax",                        o(EXT_blend_minmax),                        GLL | ES1 | ES2, 1995 },
210   { "GL_EXT_blend_subtract",                      o(dummy_true),                              GLL,            1995 },
211   { "GL_EXT_compiled_vertex_array",               o(dummy_true),                              GLL,            1996 },
212   { "GL_EXT_copy_texture",                        o(dummy_true),                              GLL,            1995 },
213   { "GL_EXT_depth_bounds_test",                   o(EXT_depth_bounds_test),                   GL,             2002 },
214   { "GL_EXT_draw_buffers2",                       o(EXT_draw_buffers2),                       GL,             2006 },
215   { "GL_EXT_draw_instanced",                      o(ARB_draw_instanced),                      GL,             2006 },
216   { "GL_EXT_draw_range_elements",                 o(dummy_true),                              GLL,            1997 },
217   { "GL_EXT_fog_coord",                           o(dummy_true),                              GLL,            1999 },
218   { "GL_EXT_framebuffer_blit",                    o(dummy_true),                              GL,             2005 },
219   { "GL_EXT_framebuffer_multisample",             o(EXT_framebuffer_multisample),             GL,             2005 },
220   { "GL_EXT_framebuffer_multisample_blit_scaled", o(EXT_framebuffer_multisample_blit_scaled), GL,             2011 },
221   { "GL_EXT_framebuffer_object",                  o(dummy_true),                              GLL,            2000 },
222   { "GL_EXT_framebuffer_sRGB",                    o(EXT_framebuffer_sRGB),                    GL,             1998 },
223   { "GL_EXT_gpu_program_parameters",              o(EXT_gpu_program_parameters),              GLL,            2006 },
224   { "GL_EXT_gpu_shader4",                         o(EXT_gpu_shader4),                         GL,             2006 },
225   { "GL_EXT_map_buffer_range",                    o(ARB_map_buffer_range),                          ES1 | ES2, 2012 },
226   { "GL_EXT_multi_draw_arrays",                   o(dummy_true),                              GLL | ES1 | ES2, 1999 },
227   { "GL_EXT_packed_depth_stencil",                o(dummy_true),                              GL,             2005 },
228   { "GL_EXT_packed_float",                        o(EXT_packed_float),                        GL,             2004 },
229   { "GL_EXT_packed_pixels",                       o(dummy_true),                              GLL,            1997 },
230   { "GL_EXT_pixel_buffer_object",                 o(EXT_pixel_buffer_object),                 GL,             2004 },
231   { "GL_EXT_point_parameters",                    o(EXT_point_parameters),                    GLL,            1997 },
232   { "GL_EXT_polygon_offset",                      o(dummy_true),                              GLL,            1995 },
233   { "GL_EXT_provoking_vertex",                    o(EXT_provoking_vertex),                    GL,             2009 },
234   { "GL_EXT_rescale_normal",                      o(dummy_true),                              GLL,            1997 },
235   { "GL_EXT_secondary_color",                     o(dummy_true),                              GLL,            1999 },
236   { "GL_EXT_separate_shader_objects",             o(dummy_true),                                         ES2, 2013 },
237   { "GL_EXT_separate_specular_color",             o(dummy_true),                              GLL,            1997 },
238   { "GL_EXT_shader_integer_mix",                  o(EXT_shader_integer_mix),                  GL       | ES3, 2013 },
239   { "GL_EXT_shadow_funcs",                        o(ARB_shadow),                              GLL,            2002 },
240   { "GL_EXT_stencil_two_side",                    o(EXT_stencil_two_side),                    GLL,            2001 },
241   { "GL_EXT_stencil_wrap",                        o(dummy_true),                              GLL,            2002 },
242   { "GL_EXT_subtexture",                          o(dummy_true),                              GLL,            1995 },
243   { "GL_EXT_texture3D",                           o(EXT_texture3D),                           GLL,            1996 },
244   { "GL_EXT_texture_array",                       o(EXT_texture_array),                       GL,             2006 },
245   { "GL_EXT_texture_compression_dxt1",            o(ANGLE_texture_compression_dxt),           GL | ES1 | ES2, 2004 },
246   { "GL_ANGLE_texture_compression_dxt3",          o(ANGLE_texture_compression_dxt),           GL | ES1 | ES2, 2011 },
247   { "GL_ANGLE_texture_compression_dxt5",          o(ANGLE_texture_compression_dxt),           GL | ES1 | ES2, 2011 },
248   { "GL_EXT_texture_compression_latc",            o(EXT_texture_compression_latc),            GL,             2006 },
249   { "GL_EXT_texture_compression_rgtc",            o(ARB_texture_compression_rgtc),            GL,             2004 },
250   { "GL_EXT_texture_compression_s3tc",            o(EXT_texture_compression_s3tc),            GL,             2000 },
251   { "GL_EXT_texture_cube_map",                    o(ARB_texture_cube_map),                    GLL,            2001 },
252   { "GL_EXT_texture_edge_clamp",                  o(dummy_true),                              GLL,            1997 },
253   { "GL_EXT_texture_env_add",                     o(dummy_true),                              GLL,            1999 },
254   { "GL_EXT_texture_env_combine",                 o(dummy_true),                              GLL,            2000 },
255   { "GL_EXT_texture_env_dot3",                    o(EXT_texture_env_dot3),                    GLL,            2000 },
256   { "GL_EXT_texture_filter_anisotropic",          o(EXT_texture_filter_anisotropic),          GL | ES1 | ES2, 1999 },
257   { "GL_EXT_texture_format_BGRA8888",             o(dummy_true),                                   ES1 | ES2, 2005 },
258   { "GL_EXT_texture_rg",                          o(ARB_texture_rg),                                     ES2, 2011 },
259   { "GL_EXT_read_format_bgra",                    o(dummy_true),                                   ES1 | ES2, 2009 },
260   { "GL_EXT_texture_integer",                     o(EXT_texture_integer),                     GL,             2006 },
261   { "GL_EXT_texture_lod_bias",                    o(dummy_true),                              GLL | ES1,      1999 },
262   { "GL_EXT_texture_mirror_clamp",                o(EXT_texture_mirror_clamp),                GL,             2004 },
263   { "GL_EXT_texture_object",                      o(dummy_true),                              GLL,            1995 },
264   { "GL_EXT_texture",                             o(dummy_true),                              GLL,            1996 },
265   { "GL_EXT_texture_rectangle",                   o(NV_texture_rectangle),                    GLL,            2004 },
266   { "GL_EXT_texture_shared_exponent",             o(EXT_texture_shared_exponent),             GL,             2004 },
267   { "GL_EXT_texture_snorm",                       o(EXT_texture_snorm),                       GL,             2009 },
268   { "GL_EXT_texture_sRGB",                        o(EXT_texture_sRGB),                        GL,             2004 },
269   { "GL_EXT_texture_sRGB_decode",                 o(EXT_texture_sRGB_decode),                        GL,      2006 },
270   { "GL_EXT_texture_swizzle",                     o(EXT_texture_swizzle),                     GL,             2008 },
271   { "GL_EXT_texture_type_2_10_10_10_REV",         o(dummy_true),                                         ES2, 2008 },
272   { "GL_EXT_timer_query",                         o(EXT_timer_query),                         GL,             2006 },
273   { "GL_EXT_transform_feedback",                  o(EXT_transform_feedback),                  GL,             2011 },
274   { "GL_EXT_unpack_subimage",                     o(dummy_true),                                         ES2, 2011 },
275   { "GL_EXT_vertex_array_bgra",                   o(EXT_vertex_array_bgra),                   GL,             2008 },
276   { "GL_EXT_vertex_array",                        o(dummy_true),                              GLL,            1995 },
277   { "GL_EXT_color_buffer_float",                  o(dummy_true),                                         ES3, 2013 },
278
279   /* OES extensions */
280   { "GL_OES_blend_equation_separate",             o(EXT_blend_equation_separate),                  ES1,       2009 },
281   { "GL_OES_blend_func_separate",                 o(EXT_blend_func_separate),                      ES1,       2009 },
282   { "GL_OES_blend_subtract",                      o(dummy_true),                                   ES1,       2009 },
283   { "GL_OES_byte_coordinates",                    o(dummy_true),                                   ES1,       2002 },
284   { "GL_OES_compressed_ETC1_RGB8_texture",        o(OES_compressed_ETC1_RGB8_texture),             ES1 | ES2, 2005 },
285   { "GL_OES_compressed_paletted_texture",         o(dummy_true),                                   ES1,       2003 },
286   { "GL_OES_depth24",                             o(dummy_true),                                   ES1 | ES2, 2005 },
287   { "GL_OES_depth32",                             o(dummy_false),                     DISABLE,                2005 },
288   { "GL_OES_depth_texture",                       o(ARB_depth_texture),                                  ES2, 2006 },
289   { "GL_OES_depth_texture_cube_map",              o(OES_depth_texture_cube_map),                         ES2, 2012 },
290   { "GL_OES_draw_texture",                        o(OES_draw_texture),                             ES1,       2004 },
291   /*  FIXME: Mesa expects GL_OES_EGL_image to be available in OpenGL contexts. */
292   { "GL_OES_EGL_image",                           o(OES_EGL_image),                           GL | ES1 | ES2, 2006 },
293   { "GL_OES_EGL_image_external",                  o(OES_EGL_image_external),                       ES1 | ES2, 2010 },
294   { "GL_OES_element_index_uint",                  o(dummy_true),                                   ES1 | ES2, 2005 },
295   { "GL_OES_fbo_render_mipmap",                   o(dummy_true),                                   ES1 | ES2, 2005 },
296   { "GL_OES_fixed_point",                         o(dummy_true),                                   ES1,       2002 },
297   { "GL_OES_framebuffer_object",                  o(dummy_true),                                   ES1,       2005 },
298   { "GL_OES_get_program_binary",                  o(dummy_true),                                         ES2, 2008 },
299   { "GL_OES_mapbuffer",                           o(dummy_true),                                   ES1 | ES2, 2005 },
300   { "GL_OES_packed_depth_stencil",                o(dummy_true),                                   ES1 | ES2, 2007 },
301   { "GL_OES_point_size_array",                    o(dummy_true),                                   ES1,       2004 },
302   { "GL_OES_point_sprite",                        o(ARB_point_sprite),                             ES1,       2004 },
303   { "GL_OES_query_matrix",                        o(dummy_true),                                   ES1,       2003 },
304   { "GL_OES_read_format",                         o(dummy_true),                              GL | ES1,       2003 },
305   { "GL_OES_rgb8_rgba8",                          o(dummy_true),                                   ES1 | ES2, 2005 },
306   { "GL_OES_single_precision",                    o(dummy_true),                                   ES1,       2003 },
307   { "GL_OES_standard_derivatives",                o(OES_standard_derivatives),                           ES2, 2005 },
308   { "GL_OES_stencil1",                            o(dummy_false),                     DISABLE,                2005 },
309   { "GL_OES_stencil4",                            o(dummy_false),                     DISABLE,                2005 },
310   { "GL_OES_stencil8",                            o(dummy_true),                                   ES1 | ES2, 2005 },
311   { "GL_OES_stencil_wrap",                        o(dummy_true),                                   ES1,       2002 },
312   { "GL_OES_surfaceless_context",                 o(dummy_true),                                   ES1 | ES2, 2012 },
313   { "GL_OES_texture_3D",                          o(EXT_texture3D),                                      ES2, 2005 },
314   { "GL_OES_texture_cube_map",                    o(ARB_texture_cube_map),                         ES1,       2007 },
315   { "GL_OES_texture_env_crossbar",                o(ARB_texture_env_crossbar),                     ES1,       2005 },
316   { "GL_OES_texture_mirrored_repeat",             o(dummy_true),                                   ES1,       2005 },
317   { "GL_OES_texture_npot",                        o(ARB_texture_non_power_of_two),                 ES1 | ES2, 2005 },
318   { "GL_OES_vertex_array_object",                 o(dummy_true),                                   ES1 | ES2, 2010 },
319
320   /* KHR extensions */
321   { "GL_KHR_debug",                               o(dummy_true),                              GL,             2012 },
322
323   /* Vendor extensions */
324   { "GL_3DFX_texture_compression_FXT1",           o(TDFX_texture_compression_FXT1),           GL,             1999 },
325   { "GL_AMD_conservative_depth",                  o(ARB_conservative_depth),                  GL,             2009 },
326   { "GL_AMD_draw_buffers_blend",                  o(ARB_draw_buffers_blend),                  GL,             2009 },
327   { "GL_AMD_performance_monitor",                 o(AMD_performance_monitor),                 GL,             2007 },
328   { "GL_AMD_seamless_cubemap_per_texture",        o(AMD_seamless_cubemap_per_texture),        GL,             2009 },
329   { "GL_AMD_shader_stencil_export",               o(ARB_shader_stencil_export),               GL,             2009 },
330   { "GL_AMD_shader_trinary_minmax",               o(dummy_true),                              GL,             2012 },
331   { "GL_AMD_vertex_shader_layer",                 o(AMD_vertex_shader_layer),                 GLC,            2012 },
332   { "GL_AMD_vertex_shader_viewport_index",        o(AMD_vertex_shader_viewport_index),        GLC,            2012 },
333   { "GL_APPLE_object_purgeable",                  o(APPLE_object_purgeable),                  GL,             2006 },
334   { "GL_APPLE_packed_pixels",                     o(dummy_true),                              GLL,            2002 },
335   { "GL_APPLE_texture_max_level",                 o(dummy_true),                                   ES1 | ES2, 2009 },
336   { "GL_APPLE_vertex_array_object",               o(dummy_true),                              GLL,            2002 },
337   { "GL_ATI_blend_equation_separate",             o(EXT_blend_equation_separate),             GL,             2003 },
338   { "GL_ATI_draw_buffers",                        o(dummy_true),                              GLL,            2002 },
339   { "GL_ATI_fragment_shader",                     o(ATI_fragment_shader),                     GLL,            2001 },
340   { "GL_ATI_separate_stencil",                    o(ATI_separate_stencil),                    GLL,            2006 },
341   { "GL_ATI_texture_compression_3dc",             o(ATI_texture_compression_3dc),             GL,             2004 },
342   { "GL_ATI_texture_env_combine3",                o(ATI_texture_env_combine3),                GLL,            2002 },
343   { "GL_ATI_texture_float",                       o(ARB_texture_float),                       GL,             2002 },
344   { "GL_ATI_texture_mirror_once",                 o(ATI_texture_mirror_once),                 GL,             2006 },
345   { "GL_IBM_multimode_draw_arrays",               o(dummy_true),                              GL,             1998 },
346   { "GL_IBM_rasterpos_clip",                      o(dummy_true),                              GLL,            1996 },
347   { "GL_IBM_texture_mirrored_repeat",             o(dummy_true),                              GLL,            1998 },
348   { "GL_INGR_blend_func_separate",                o(EXT_blend_func_separate),                 GLL,            1999 },
349   { "GL_INTEL_performance_query",                 o(INTEL_performance_query),                       GL | ES2, 2013 },
350   { "GL_MESA_pack_invert",                        o(MESA_pack_invert),                        GL,             2002 },
351   { "GL_MESA_texture_signed_rgba",                o(EXT_texture_snorm),                       GL,             2009 },
352   { "GL_MESA_window_pos",                         o(dummy_true),                              GLL,            2000 },
353   { "GL_MESA_ycbcr_texture",                      o(MESA_ycbcr_texture),                      GL,             2002 },
354   { "GL_NV_blend_square",                         o(dummy_true),                              GLL,            1999 },
355   { "GL_NV_conditional_render",                   o(NV_conditional_render),                   GL,             2008 },
356   { "GL_NV_depth_clamp",                          o(ARB_depth_clamp),                         GL,             2001 },
357   { "GL_NV_draw_buffers",                         o(dummy_true),                                         ES2, 2011 },
358   { "GL_NV_fbo_color_attachments",                o(dummy_true),                                         ES2, 2010 },
359   { "GL_NV_fog_distance",                         o(NV_fog_distance),                         GLL,            2001 },
360   { "GL_NV_fragment_program_option",              o(NV_fragment_program_option),              GLL,            2005 },
361   { "GL_NV_light_max_exponent",                   o(dummy_true),                              GLL,            1999 },
362   { "GL_NV_packed_depth_stencil",                 o(dummy_true),                              GL,             2000 },
363   { "GL_NV_point_sprite",                         o(NV_point_sprite),                         GL,             2001 },
364   { "GL_NV_primitive_restart",                    o(NV_primitive_restart),                    GLL,            2002 },
365   { "GL_NV_read_buffer",                          o(dummy_true),                              ES2,            2011 },
366   { "GL_NV_texgen_reflection",                    o(dummy_true),                              GLL,            1999 },
367   { "GL_NV_texture_barrier",                      o(NV_texture_barrier),                      GL,             2009 },
368   { "GL_NV_texture_env_combine4",                 o(NV_texture_env_combine4),                 GLL,            1999 },
369   { "GL_NV_texture_rectangle",                    o(NV_texture_rectangle),                    GLL,            2000 },
370   { "GL_NV_vdpau_interop",                        o(NV_vdpau_interop),                        GL,             2010 },
371   { "GL_S3_s3tc",                                 o(ANGLE_texture_compression_dxt),           GL,             1999 },
372   { "GL_SGIS_generate_mipmap",                    o(dummy_true),                              GLL,            1997 },
373   { "GL_SGIS_texture_border_clamp",               o(ARB_texture_border_clamp),                GLL,            1997 },
374   { "GL_SGIS_texture_edge_clamp",                 o(dummy_true),                              GLL,            1997 },
375   { "GL_SGIS_texture_lod",                        o(dummy_true),                              GLL,            1997 },
376   { "GL_SUN_multi_draw_arrays",                   o(dummy_true),                              GLL,            1999 },
377
378   { 0, 0, 0, 0 },
379};
380
381
382/**
383 * Given an extension name, lookup up the corresponding member of struct
384 * gl_extensions and return that member's offset (in bytes).  If the name is
385 * not found in the \c extension_table, return 0.
386 *
387 * \param name Name of extension.
388 * \return Offset of member in struct gl_extensions.
389 */
390static size_t
391name_to_offset(const char* name)
392{
393   const struct extension *i;
394
395   if (name == 0)
396      return 0;
397
398   for (i = extension_table; i->name != 0; ++i) {
399      if (strcmp(name, i->name) == 0)
400	 return i->offset;
401   }
402
403   return 0;
404}
405
406/**
407 * Overrides extensions in \c ctx based on the values in
408 * _mesa_extension_override_enables and _mesa_extension_override_disables.
409 */
410static void
411override_extensions_in_context(struct gl_context *ctx)
412{
413   const struct extension *i;
414   const GLboolean *enables =
415      (GLboolean*) &_mesa_extension_override_enables;
416   const GLboolean *disables =
417      (GLboolean*) &_mesa_extension_override_disables;
418   GLboolean *ctx_ext = (GLboolean*)&ctx->Extensions;
419
420   for (i = extension_table; i->name != 0; ++i) {
421      size_t offset = i->offset;
422      assert(!enables[offset] || !disables[offset]);
423      if (enables[offset]) {
424         ctx_ext[offset] = 1;
425      } else if (disables[offset]) {
426         ctx_ext[offset] = 0;
427      }
428   }
429}
430
431
432/**
433 * Enable all extensions suitable for a software-only renderer.
434 * This is a convenience function used by the XMesa, OSMesa, GGI drivers, etc.
435 */
436void
437_mesa_enable_sw_extensions(struct gl_context *ctx)
438{
439   ctx->Extensions.ARB_depth_clamp = GL_TRUE;
440   ctx->Extensions.ARB_depth_texture = GL_TRUE;
441   ctx->Extensions.ARB_draw_elements_base_vertex = GL_TRUE;
442   ctx->Extensions.ARB_draw_instanced = GL_TRUE;
443   ctx->Extensions.ARB_explicit_attrib_location = GL_TRUE;
444   ctx->Extensions.ARB_fragment_coord_conventions = GL_TRUE;
445   ctx->Extensions.ARB_fragment_program = GL_TRUE;
446   ctx->Extensions.ARB_fragment_program_shadow = GL_TRUE;
447   ctx->Extensions.ARB_fragment_shader = GL_TRUE;
448   ctx->Extensions.ARB_framebuffer_object = GL_TRUE;
449   ctx->Extensions.ARB_half_float_vertex = GL_TRUE;
450   ctx->Extensions.ARB_map_buffer_range = GL_TRUE;
451   ctx->Extensions.ARB_occlusion_query = GL_TRUE;
452   ctx->Extensions.ARB_occlusion_query2 = GL_TRUE;
453   ctx->Extensions.ARB_point_sprite = GL_TRUE;
454   ctx->Extensions.ARB_shadow = GL_TRUE;
455   ctx->Extensions.ARB_texture_border_clamp = GL_TRUE;
456   ctx->Extensions.ARB_texture_compression_bptc = GL_TRUE;
457   ctx->Extensions.ARB_texture_cube_map = GL_TRUE;
458   ctx->Extensions.ARB_texture_env_combine = GL_TRUE;
459   ctx->Extensions.ARB_texture_env_crossbar = GL_TRUE;
460   ctx->Extensions.ARB_texture_env_dot3 = GL_TRUE;
461#ifdef TEXTURE_FLOAT_ENABLED
462   ctx->Extensions.ARB_texture_float = GL_TRUE;
463#endif
464   ctx->Extensions.ARB_texture_mirror_clamp_to_edge = GL_TRUE;
465   ctx->Extensions.ARB_texture_non_power_of_two = GL_TRUE;
466   ctx->Extensions.ARB_texture_rg = GL_TRUE;
467   ctx->Extensions.ARB_texture_compression_rgtc = GL_TRUE;
468   ctx->Extensions.ARB_vertex_program = GL_TRUE;
469   ctx->Extensions.ARB_vertex_shader = GL_TRUE;
470   ctx->Extensions.ARB_sync = GL_TRUE;
471   ctx->Extensions.APPLE_object_purgeable = GL_TRUE;
472   ctx->Extensions.ATI_fragment_shader = GL_TRUE;
473   ctx->Extensions.ATI_texture_compression_3dc = GL_TRUE;
474   ctx->Extensions.ATI_texture_env_combine3 = GL_TRUE;
475   ctx->Extensions.ATI_texture_mirror_once = GL_TRUE;
476   ctx->Extensions.ATI_separate_stencil = GL_TRUE;
477   ctx->Extensions.EXT_blend_color = GL_TRUE;
478   ctx->Extensions.EXT_blend_equation_separate = GL_TRUE;
479   ctx->Extensions.EXT_blend_func_separate = GL_TRUE;
480   ctx->Extensions.EXT_blend_minmax = GL_TRUE;
481   ctx->Extensions.EXT_depth_bounds_test = GL_TRUE;
482   ctx->Extensions.EXT_draw_buffers2 = GL_TRUE;
483   ctx->Extensions.EXT_pixel_buffer_object = GL_TRUE;
484   ctx->Extensions.EXT_point_parameters = GL_TRUE;
485   ctx->Extensions.EXT_provoking_vertex = GL_TRUE;
486   ctx->Extensions.EXT_stencil_two_side = GL_TRUE;
487   ctx->Extensions.EXT_texture_array = GL_TRUE;
488   ctx->Extensions.EXT_texture_compression_latc = GL_TRUE;
489   ctx->Extensions.EXT_texture_env_dot3 = GL_TRUE;
490   ctx->Extensions.EXT_texture_filter_anisotropic = GL_TRUE;
491   ctx->Extensions.EXT_texture_mirror_clamp = GL_TRUE;
492   ctx->Extensions.EXT_texture_shared_exponent = GL_TRUE;
493   ctx->Extensions.EXT_texture_sRGB = GL_TRUE;
494   ctx->Extensions.EXT_texture_sRGB_decode = GL_TRUE;
495   ctx->Extensions.EXT_texture_swizzle = GL_TRUE;
496   /*ctx->Extensions.EXT_transform_feedback = GL_TRUE;*/
497   ctx->Extensions.EXT_vertex_array_bgra = GL_TRUE;
498   ctx->Extensions.MESA_pack_invert = GL_TRUE;
499   ctx->Extensions.MESA_ycbcr_texture = GL_TRUE;
500   ctx->Extensions.NV_conditional_render = GL_TRUE;
501   ctx->Extensions.NV_point_sprite = GL_TRUE;
502   ctx->Extensions.NV_texture_env_combine4 = GL_TRUE;
503   ctx->Extensions.NV_texture_rectangle = GL_TRUE;
504   ctx->Extensions.NV_fragment_program_option = GL_TRUE;
505   ctx->Extensions.EXT_gpu_program_parameters = GL_TRUE;
506   ctx->Extensions.OES_standard_derivatives = GL_TRUE;
507   ctx->Extensions.TDFX_texture_compression_FXT1 = GL_TRUE;
508   if (ctx->Mesa_DXTn) {
509      ctx->Extensions.ANGLE_texture_compression_dxt = GL_TRUE;
510      ctx->Extensions.EXT_texture_compression_s3tc = GL_TRUE;
511   }
512}
513
514/**
515 * Either enable or disable the named extension.
516 * \return offset of extensions withint `ext' or 0 if extension is not known
517 */
518static size_t
519set_extension(struct gl_extensions *ext, const char *name, GLboolean state)
520{
521   size_t offset;
522
523   offset = name_to_offset(name);
524   if (offset != 0 && (offset != o(dummy_true) || state != GL_FALSE)) {
525      ((GLboolean *) ext)[offset] = state;
526   }
527
528   return offset;
529}
530
531/**
532 * \brief Apply the \c MESA_EXTENSION_OVERRIDE environment variable.
533 *
534 * \c MESA_EXTENSION_OVERRIDE is a space-separated list of extensions to
535 * enable or disable. The list is processed thus:
536 *    - Enable recognized extension names that are prefixed with '+'.
537 *    - Disable recognized extension names that are prefixed with '-'.
538 *    - Enable recognized extension names that are not prefixed.
539 *    - Collect unrecognized extension names in a new string.
540 *
541 * \c MESA_EXTENSION_OVERRIDE was previously parsed during
542 * _mesa_one_time_init_extension_overrides. We just use the results of that
543 * parsing in this function.
544 *
545 * \return Space-separated list of unrecognized extension names (which must
546 *    be freed). Does not return \c NULL.
547 */
548static char *
549get_extension_override( struct gl_context *ctx )
550{
551   override_extensions_in_context(ctx);
552
553   if (cant_disable_extensions != NULL) {
554      _mesa_problem(ctx,
555                    "Trying to disable permanently enabled extensions: %s",
556	            cant_disable_extensions);
557   }
558
559   if (extra_extensions == NULL) {
560      return calloc(1, sizeof(char));
561   } else {
562      _mesa_problem(ctx, "Trying to enable unknown extensions: %s",
563                    extra_extensions);
564      return strdup(extra_extensions);
565   }
566}
567
568
569/**
570 * \brief Free extra_extensions and cant_disable_extensions strings
571 *
572 * These strings are allocated early during the first context creation by
573 * _mesa_one_time_init_extension_overrides.
574 */
575static void __attribute__((__destructor__))
576free_unknown_extensions_strings(void)
577{
578   free(extra_extensions);
579   free(cant_disable_extensions);
580}
581
582
583/**
584 * \brief Initialize extension override tables.
585 *
586 * This should be called one time early during first context initialization.
587 */
588void
589_mesa_one_time_init_extension_overrides(void)
590{
591   const char *env_const = _mesa_getenv("MESA_EXTENSION_OVERRIDE");
592   char *env;
593   char *ext;
594   int len;
595   size_t offset;
596
597   /* atexit(free_unknown_extensions_strings); */
598
599   memset(&_mesa_extension_override_enables, 0, sizeof(struct gl_extensions));
600   memset(&_mesa_extension_override_disables, 0, sizeof(struct gl_extensions));
601
602   if (env_const == NULL) {
603      return;
604   }
605
606   /* extra_exts: List of unrecognized extensions. */
607   extra_extensions = calloc(ALIGN(strlen(env_const) + 2, 4), sizeof(char));
608   cant_disable_extensions = calloc(ALIGN(strlen(env_const) + 2, 4), sizeof(char));
609
610   /* Copy env_const because strtok() is destructive. */
611   env = strdup(env_const);
612   for (ext = strtok(env, " "); ext != NULL; ext = strtok(NULL, " ")) {
613      int enable;
614      bool recognized;
615      switch (ext[0]) {
616      case '+':
617         enable = 1;
618         ++ext;
619         break;
620      case '-':
621         enable = 0;
622         ++ext;
623         break;
624      default:
625         enable = 1;
626         break;
627      }
628
629      offset = set_extension(&_mesa_extension_override_enables, ext, enable);
630      if (offset != 0 && (offset != o(dummy_true) || enable != GL_FALSE)) {
631         ((GLboolean *) &_mesa_extension_override_disables)[offset] = !enable;
632         recognized = true;
633      } else {
634         recognized = false;
635      }
636
637      if (!recognized) {
638         if (enable) {
639            strcat(extra_extensions, ext);
640            strcat(extra_extensions, " ");
641         } else if (offset == o(dummy_true)) {
642            strcat(cant_disable_extensions, ext);
643            strcat(cant_disable_extensions, " ");
644         }
645      }
646   }
647
648   free(env);
649
650   /* Remove trailing space, and free if unused. */
651   len = strlen(extra_extensions);
652   if (len == 0) {
653      free(extra_extensions);
654      extra_extensions = NULL;
655   } else if (extra_extensions[len - 1] == ' ') {
656      extra_extensions[len - 1] = '\0';
657   }
658   len = strlen(cant_disable_extensions);
659   if (len == 0) {
660      free(cant_disable_extensions);
661      cant_disable_extensions = NULL;
662   } else if (cant_disable_extensions[len - 1] == ' ') {
663      cant_disable_extensions[len - 1] = '\0';
664   }
665}
666
667
668/**
669 * \brief Initialize extension tables and enable default extensions.
670 *
671 * This should be called during context initialization.
672 * Note: Sets gl_extensions.dummy_true to true.
673 */
674void
675_mesa_init_extensions(struct gl_extensions *extensions)
676{
677   GLboolean *base = (GLboolean *) extensions;
678   GLboolean *sentinel = base + o(extension_sentinel);
679   GLboolean *i;
680
681   /* First, turn all extensions off. */
682   for (i = base; i != sentinel; ++i)
683      *i = GL_FALSE;
684
685   /* Then, selectively turn default extensions on. */
686   extensions->dummy_true = GL_TRUE;
687   extensions->EXT_texture3D = GL_TRUE;
688}
689
690
691typedef unsigned short extension_index;
692
693
694/**
695 * Compare two entries of the extensions table.  Sorts first by year,
696 * then by name.
697 *
698 * Arguments are indices into extension_table.
699 */
700static int
701extension_compare(const void *p1, const void *p2)
702{
703   extension_index i1 = * (const extension_index *) p1;
704   extension_index i2 = * (const extension_index *) p2;
705   const struct extension *e1 = &extension_table[i1];
706   const struct extension *e2 = &extension_table[i2];
707   int res;
708
709   res = (int)e1->year - (int)e2->year;
710
711   if (res == 0) {
712      res = strcmp(e1->name, e2->name);
713   }
714
715   return res;
716}
717
718
719/**
720 * Construct the GL_EXTENSIONS string.  Called the first time that
721 * glGetString(GL_EXTENSIONS) is called.
722 */
723GLubyte*
724_mesa_make_extension_string(struct gl_context *ctx)
725{
726   /* The extension string. */
727   char *exts = 0;
728   /* Length of extension string. */
729   size_t length = 0;
730   /* Number of extensions */
731   unsigned count;
732   /* Indices of the extensions sorted by year */
733   extension_index *extension_indices;
734   /* String of extra extensions. */
735   char *extra_extensions = get_extension_override(ctx);
736   GLboolean *base = (GLboolean *) &ctx->Extensions;
737   const struct extension *i;
738   unsigned j;
739   unsigned maxYear = ~0;
740   unsigned api_set = (1 << ctx->API);
741   if (_mesa_is_gles3(ctx))
742      api_set |= ES3;
743
744   /* Check if the MESA_EXTENSION_MAX_YEAR env var is set */
745   {
746      const char *env = getenv("MESA_EXTENSION_MAX_YEAR");
747      if (env) {
748         maxYear = atoi(env);
749         _mesa_debug(ctx, "Note: limiting GL extensions to %u or earlier\n",
750                     maxYear);
751      }
752   }
753
754   /* Compute length of the extension string. */
755   count = 0;
756   for (i = extension_table; i->name != 0; ++i) {
757      if (base[i->offset] &&
758          i->year <= maxYear &&
759          (i->api_set & api_set)) {
760	 length += strlen(i->name) + 1; /* +1 for space */
761	 ++count;
762      }
763   }
764   if (extra_extensions != NULL)
765      length += 1 + strlen(extra_extensions); /* +1 for space */
766
767   exts = calloc(ALIGN(length + 1, 4), sizeof(char));
768   if (exts == NULL) {
769      free(extra_extensions);
770      return NULL;
771   }
772
773   extension_indices = malloc(count * sizeof(extension_index));
774   if (extension_indices == NULL) {
775      free(exts);
776      free(extra_extensions);
777      return NULL;
778   }
779
780   /* Sort extensions in chronological order because certain old applications
781    * (e.g., Quake3 demo) store the extension list in a static size buffer so
782    * chronologically order ensure that the extensions that such applications
783    * expect will fit into that buffer.
784    */
785   j = 0;
786   for (i = extension_table; i->name != 0; ++i) {
787      if (base[i->offset] &&
788          i->year <= maxYear &&
789          (i->api_set & api_set)) {
790         extension_indices[j++] = i - extension_table;
791      }
792   }
793   assert(j == count);
794   qsort(extension_indices, count,
795         sizeof *extension_indices, extension_compare);
796
797   /* Build the extension string.*/
798   for (j = 0; j < count; ++j) {
799      i = &extension_table[extension_indices[j]];
800      assert(base[i->offset] && (i->api_set & api_set));
801      strcat(exts, i->name);
802      strcat(exts, " ");
803   }
804   free(extension_indices);
805   if (extra_extensions != 0) {
806      strcat(exts, extra_extensions);
807      free(extra_extensions);
808   }
809
810   return (GLubyte *) exts;
811}
812
813/**
814 * Return number of enabled extensions.
815 */
816GLuint
817_mesa_get_extension_count(struct gl_context *ctx)
818{
819   GLboolean *base;
820   const struct extension *i;
821   unsigned api_set = (1 << ctx->API);
822   if (_mesa_is_gles3(ctx))
823      api_set |= ES3;
824
825   /* only count once */
826   if (ctx->Extensions.Count != 0)
827      return ctx->Extensions.Count;
828
829   base = (GLboolean *) &ctx->Extensions;
830   for (i = extension_table; i->name != 0; ++i) {
831      if (base[i->offset] && (i->api_set & api_set)) {
832	 ctx->Extensions.Count++;
833      }
834   }
835   return ctx->Extensions.Count;
836}
837
838/**
839 * Return name of i-th enabled extension
840 */
841const GLubyte *
842_mesa_get_enabled_extension(struct gl_context *ctx, GLuint index)
843{
844   const GLboolean *base;
845   size_t n;
846   const struct extension *i;
847   unsigned api_set = (1 << ctx->API);
848   if (_mesa_is_gles3(ctx))
849      api_set |= ES3;
850
851   base = (GLboolean*) &ctx->Extensions;
852   n = 0;
853   for (i = extension_table; i->name != 0; ++i) {
854      if (base[i->offset] && (i->api_set & api_set)) {
855         if (n == index)
856            return (const GLubyte*) i->name;
857         else
858            ++n;
859      }
860   }
861
862   return NULL;
863}
864