mesa: Change "BRIAN PAUL" to "THE AUTHORS" in license text.
[mesa.git] / src / mesa / main / version.c
1 /*
2 * Mesa 3-D graphics library
3 *
4 * Copyright (C) 2010 VMware, Inc. All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
20 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 */
23
24
25 #include "imports.h"
26 #include "mtypes.h"
27 #include "version.h"
28 #include "git_sha1.h"
29
30 /**
31 * Scans 'string' to see if it ends with 'ending'.
32 */
33 static GLboolean
34 check_for_ending(const char *string, const char *ending)
35 {
36 int len1, len2;
37
38 len1 = strlen(string);
39 len2 = strlen(ending);
40
41 if (len2 > len1) {
42 return GL_FALSE;
43 }
44
45 if (strcmp(string + (len1 - len2), ending) == 0) {
46 return GL_TRUE;
47 } else {
48 return GL_FALSE;
49 }
50 }
51
52 /**
53 * Returns the gl override data
54 *
55 * version > 0 indicates there is an override requested
56 * fwd_context is only valid if version > 0
57 */
58 static void
59 get_gl_override(int *version, GLboolean *fwd_context)
60 {
61 const char *env_var = "MESA_GL_VERSION_OVERRIDE";
62 const char *version_str;
63 int major, minor, n;
64 static int override_version = -1;
65 static GLboolean fc_suffix = GL_FALSE;
66
67 if (override_version < 0) {
68 override_version = 0;
69
70 version_str = getenv(env_var);
71 if (version_str) {
72 fc_suffix = check_for_ending(version_str, "FC");
73
74 n = sscanf(version_str, "%u.%u", &major, &minor);
75 if (n != 2) {
76 fprintf(stderr, "error: invalid value for %s: %s\n", env_var, version_str);
77 override_version = 0;
78 } else {
79 override_version = major * 10 + minor;
80 if (override_version < 30 && fc_suffix) {
81 fprintf(stderr, "error: invalid value for %s: %s\n", env_var, version_str);
82 }
83 }
84 }
85 }
86
87 *version = override_version;
88 *fwd_context = fc_suffix;
89 }
90
91 /**
92 * Builds the MESA version string.
93 */
94 static void
95 create_version_string(struct gl_context *ctx, const char *prefix)
96 {
97 static const int max = 100;
98
99 ctx->VersionString = malloc(max);
100 if (ctx->VersionString) {
101 _mesa_snprintf(ctx->VersionString, max,
102 "%s%u.%u%s Mesa " PACKAGE_VERSION
103 #ifdef MESA_GIT_SHA1
104 " (" MESA_GIT_SHA1 ")"
105 #endif
106 ,
107 prefix,
108 ctx->Version / 10, ctx->Version % 10,
109 (ctx->API == API_OPENGL_CORE) ? " (Core Profile)" : ""
110 );
111 }
112 }
113
114 /**
115 * Override the context's version and/or API type if the
116 * environment variable MESA_GL_VERSION_OVERRIDE is set.
117 *
118 * Example uses of MESA_GL_VERSION_OVERRIDE:
119 *
120 * 2.1: select a compatibility (non-Core) profile with GL version 2.1
121 * 3.0: select a compatibility (non-Core) profile with GL version 3.0
122 * 3.0FC: select a Core+Forward Compatible profile with GL version 3.0
123 * 3.1: select a Core profile with GL version 3.1
124 * 3.1FC: select a Core+Forward Compatible profile with GL version 3.1
125 */
126 void
127 _mesa_override_gl_version(struct gl_context *ctx)
128 {
129 int version;
130 GLboolean fwd_context;
131
132 get_gl_override(&version, &fwd_context);
133
134 if (version > 0) {
135 ctx->Version = version;
136 if (version >= 30 && fwd_context) {
137 ctx->API = API_OPENGL_CORE;
138 ctx->Const.ContextFlags |= GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT;
139 } else if (version >= 31) {
140 ctx->API = API_OPENGL_CORE;
141 } else {
142 ctx->API = API_OPENGL_COMPAT;
143 }
144 create_version_string(ctx, "");
145 }
146 }
147
148 /**
149 * Returns the gl override value
150 *
151 * version > 0 indicates there is an override requested
152 */
153 int
154 _mesa_get_gl_version_override(void)
155 {
156 int version;
157 GLboolean fwd_context;
158
159 get_gl_override(&version, &fwd_context);
160
161 return version;
162 }
163
164 /**
165 * Override the context's GLSL version if the environment variable
166 * MESA_GLSL_VERSION_OVERRIDE is set. Valid values for
167 * MESA_GLSL_VERSION_OVERRIDE are integers, such as "130".
168 */
169 void
170 _mesa_override_glsl_version(struct gl_context *ctx)
171 {
172 const char *env_var = "MESA_GLSL_VERSION_OVERRIDE";
173 const char *version;
174 int n;
175
176 version = getenv(env_var);
177 if (!version) {
178 return;
179 }
180
181 n = sscanf(version, "%u", &ctx->Const.GLSLVersion);
182 if (n != 1) {
183 fprintf(stderr, "error: invalid value for %s: %s\n", env_var, version);
184 return;
185 }
186 }
187
188 /**
189 * Examine enabled GL extensions to determine GL version.
190 */
191 static void
192 compute_version(struct gl_context *ctx)
193 {
194 GLuint major, minor;
195
196 const GLboolean ver_1_3 = (ctx->Extensions.ARB_texture_border_clamp &&
197 ctx->Extensions.ARB_texture_cube_map &&
198 ctx->Extensions.ARB_texture_env_combine &&
199 ctx->Extensions.ARB_texture_env_dot3);
200 const GLboolean ver_1_4 = (ver_1_3 &&
201 ctx->Extensions.ARB_depth_texture &&
202 ctx->Extensions.ARB_shadow &&
203 ctx->Extensions.ARB_texture_env_crossbar &&
204 ctx->Extensions.EXT_blend_color &&
205 ctx->Extensions.EXT_blend_func_separate &&
206 ctx->Extensions.EXT_blend_minmax &&
207 ctx->Extensions.EXT_fog_coord &&
208 ctx->Extensions.EXT_point_parameters &&
209 ctx->Extensions.EXT_secondary_color);
210 const GLboolean ver_1_5 = (ver_1_4 &&
211 ctx->Extensions.ARB_occlusion_query &&
212 ctx->Extensions.EXT_shadow_funcs);
213 const GLboolean ver_2_0 = (ver_1_5 &&
214 ctx->Extensions.ARB_point_sprite &&
215 ctx->Extensions.ARB_shader_objects &&
216 ctx->Extensions.ARB_vertex_shader &&
217 ctx->Extensions.ARB_fragment_shader &&
218 ctx->Extensions.ARB_texture_non_power_of_two &&
219 ctx->Extensions.EXT_blend_equation_separate &&
220
221 /* Technically, 2.0 requires the functionality
222 * of the EXT version. Enable 2.0 if either
223 * extension is available, and assume that a
224 * driver that only exposes the ATI extension
225 * will fallback to software when necessary.
226 */
227 (ctx->Extensions.EXT_stencil_two_side
228 || ctx->Extensions.ATI_separate_stencil));
229 const GLboolean ver_2_1 = (ver_2_0 &&
230 ctx->Const.GLSLVersion >= 120 &&
231 ctx->Extensions.EXT_pixel_buffer_object &&
232 ctx->Extensions.EXT_texture_sRGB);
233 const GLboolean ver_3_0 = (ver_2_1 &&
234 ctx->Const.GLSLVersion >= 130 &&
235 ctx->Const.MaxSamples >= 4 &&
236 (ctx->API == API_OPENGL_CORE ||
237 ctx->Extensions.ARB_color_buffer_float) &&
238 ctx->Extensions.ARB_depth_buffer_float &&
239 ctx->Extensions.ARB_half_float_pixel &&
240 ctx->Extensions.ARB_half_float_vertex &&
241 ctx->Extensions.ARB_map_buffer_range &&
242 ctx->Extensions.ARB_shader_texture_lod &&
243 ctx->Extensions.ARB_texture_float &&
244 ctx->Extensions.ARB_texture_rg &&
245 ctx->Extensions.ARB_texture_compression_rgtc &&
246 ctx->Extensions.EXT_draw_buffers2 &&
247 ctx->Extensions.ARB_framebuffer_object &&
248 ctx->Extensions.EXT_framebuffer_sRGB &&
249 ctx->Extensions.EXT_packed_float &&
250 ctx->Extensions.EXT_texture_array &&
251 ctx->Extensions.EXT_texture_shared_exponent &&
252 ctx->Extensions.EXT_transform_feedback &&
253 ctx->Extensions.NV_conditional_render);
254 const GLboolean ver_3_1 = (ver_3_0 &&
255 ctx->Const.GLSLVersion >= 140 &&
256 ctx->Extensions.ARB_draw_instanced &&
257 ctx->Extensions.ARB_texture_buffer_object &&
258 ctx->Extensions.ARB_uniform_buffer_object &&
259 ctx->Extensions.EXT_texture_snorm &&
260 ctx->Extensions.NV_primitive_restart &&
261 ctx->Extensions.NV_texture_rectangle &&
262 ctx->Const.MaxVertexTextureImageUnits >= 16);
263 const GLboolean ver_3_2 = (ver_3_1 &&
264 ctx->Const.GLSLVersion >= 150 &&
265 ctx->Extensions.ARB_depth_clamp &&
266 ctx->Extensions.ARB_draw_elements_base_vertex &&
267 ctx->Extensions.ARB_fragment_coord_conventions &&
268 ctx->Extensions.ARB_geometry_shader4 &&
269 ctx->Extensions.EXT_provoking_vertex &&
270 ctx->Extensions.ARB_seamless_cube_map &&
271 ctx->Extensions.ARB_sync &&
272 ctx->Extensions.ARB_texture_multisample &&
273 ctx->Extensions.EXT_vertex_array_bgra);
274 const GLboolean ver_3_3 = (ver_3_2 &&
275 ctx->Const.GLSLVersion >= 330 &&
276 ctx->Extensions.ARB_blend_func_extended &&
277 ctx->Extensions.ARB_explicit_attrib_location &&
278 ctx->Extensions.ARB_instanced_arrays &&
279 ctx->Extensions.ARB_occlusion_query2 &&
280 ctx->Extensions.ARB_shader_bit_encoding &&
281 ctx->Extensions.ARB_texture_rgb10_a2ui &&
282 ctx->Extensions.ARB_timer_query &&
283 ctx->Extensions.ARB_vertex_type_2_10_10_10_rev &&
284 ctx->Extensions.EXT_texture_swizzle);
285 /* ARB_sampler_objects is always enabled in mesa */
286
287 if (ver_3_3) {
288 major = 3;
289 minor = 3;
290 }
291 else if (ver_3_2) {
292 major = 3;
293 minor = 2;
294 }
295 else if (ver_3_1) {
296 major = 3;
297 minor = 1;
298 }
299 else if (ver_3_0) {
300 major = 3;
301 minor = 0;
302 }
303 else if (ver_2_1) {
304 major = 2;
305 minor = 1;
306 }
307 else if (ver_2_0) {
308 major = 2;
309 minor = 0;
310 }
311 else if (ver_1_5) {
312 major = 1;
313 minor = 5;
314 }
315 else if (ver_1_4) {
316 major = 1;
317 minor = 4;
318 }
319 else if (ver_1_3) {
320 major = 1;
321 minor = 3;
322 }
323 else {
324 major = 1;
325 minor = 2;
326 }
327
328 ctx->Version = major * 10 + minor;
329
330 create_version_string(ctx, "");
331 }
332
333 static void
334 compute_version_es1(struct gl_context *ctx)
335 {
336 /* OpenGL ES 1.0 is derived from OpenGL 1.3 */
337 const GLboolean ver_1_0 = (ctx->Extensions.ARB_texture_env_combine &&
338 ctx->Extensions.ARB_texture_env_dot3);
339 /* OpenGL ES 1.1 is derived from OpenGL 1.5 */
340 const GLboolean ver_1_1 = (ver_1_0 &&
341 ctx->Extensions.EXT_point_parameters);
342
343 if (ver_1_1) {
344 ctx->Version = 11;
345 } else if (ver_1_0) {
346 ctx->Version = 10;
347 } else {
348 _mesa_problem(ctx, "Incomplete OpenGL ES 1.0 support.");
349 }
350
351 create_version_string(ctx, "OpenGL ES-CM ");
352 }
353
354 static void
355 compute_version_es2(struct gl_context *ctx)
356 {
357 /* OpenGL ES 2.0 is derived from OpenGL 2.0 */
358 const GLboolean ver_2_0 = (ctx->Extensions.ARB_texture_cube_map &&
359 ctx->Extensions.EXT_blend_color &&
360 ctx->Extensions.EXT_blend_func_separate &&
361 ctx->Extensions.EXT_blend_minmax &&
362 ctx->Extensions.ARB_shader_objects &&
363 ctx->Extensions.ARB_vertex_shader &&
364 ctx->Extensions.ARB_fragment_shader &&
365 ctx->Extensions.ARB_texture_non_power_of_two &&
366 ctx->Extensions.EXT_blend_equation_separate);
367 /* FINISHME: This list isn't quite right. */
368 const GLboolean ver_3_0 = (ctx->Extensions.ARB_half_float_vertex &&
369 ctx->Extensions.ARB_internalformat_query &&
370 ctx->Extensions.ARB_map_buffer_range &&
371 ctx->Extensions.ARB_shader_texture_lod &&
372 ctx->Extensions.ARB_texture_float &&
373 ctx->Extensions.ARB_texture_rg &&
374 ctx->Extensions.ARB_texture_compression_rgtc &&
375 ctx->Extensions.EXT_draw_buffers2 &&
376 /* ctx->Extensions.ARB_framebuffer_object && */
377 ctx->Extensions.EXT_framebuffer_sRGB &&
378 ctx->Extensions.EXT_packed_float &&
379 ctx->Extensions.EXT_texture_array &&
380 ctx->Extensions.EXT_texture_shared_exponent &&
381 ctx->Extensions.EXT_transform_feedback &&
382 ctx->Extensions.NV_conditional_render &&
383 ctx->Extensions.ARB_draw_instanced &&
384 ctx->Extensions.ARB_uniform_buffer_object &&
385 ctx->Extensions.EXT_texture_snorm &&
386 ctx->Extensions.NV_primitive_restart &&
387 ctx->Extensions.OES_depth_texture_cube_map);
388 if (ver_3_0) {
389 ctx->Version = 30;
390 } else if (ver_2_0) {
391 ctx->Version = 20;
392 } else {
393 _mesa_problem(ctx, "Incomplete OpenGL ES 2.0 support.");
394 }
395
396 create_version_string(ctx, "OpenGL ES ");
397 }
398
399 /**
400 * Set the context's Version and VersionString fields.
401 * This should only be called once as part of context initialization
402 * or to perform version check for GLX_ARB_create_context_profile.
403 */
404 void
405 _mesa_compute_version(struct gl_context *ctx)
406 {
407 if (ctx->Version)
408 return;
409
410 switch (ctx->API) {
411 case API_OPENGL_COMPAT:
412 /* Disable GLSL 1.40 and later for legacy contexts.
413 * This disallows creation of the GL 3.1 compatibility context. */
414 if (ctx->Const.GLSLVersion > 130) {
415 ctx->Const.GLSLVersion = 130;
416 }
417 /* fall through */
418 case API_OPENGL_CORE:
419 compute_version(ctx);
420 break;
421 case API_OPENGLES:
422 compute_version_es1(ctx);
423 break;
424 case API_OPENGLES2:
425 compute_version_es2(ctx);
426 break;
427 }
428
429 }