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