Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
5564 | serge | 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 |
||
27 | #include "imports.h" |
||
28 | #include "mtypes.h" |
||
29 | #include "version.h" |
||
30 | #include "git_sha1.h" |
||
31 | |||
32 | /** |
||
33 | * Scans 'string' to see if it ends with 'ending'. |
||
34 | */ |
||
35 | static bool |
||
36 | check_for_ending(const char *string, const char *ending) |
||
37 | { |
||
38 | const size_t len1 = strlen(string); |
||
39 | const size_t len2 = strlen(ending); |
||
40 | |||
41 | if (len2 > len1) |
||
42 | return false; |
||
43 | |||
44 | return strcmp(string + (len1 - len2), ending) == 0; |
||
45 | } |
||
46 | |||
47 | /** |
||
48 | * Returns the gl override data |
||
49 | * |
||
50 | * version > 0 indicates there is an override requested |
||
51 | * fwd_context is only valid if version > 0 |
||
52 | */ |
||
53 | static void |
||
54 | get_gl_override(int *version, bool *fwd_context, bool *compat_context) |
||
55 | { |
||
56 | const char *env_var = "MESA_GL_VERSION_OVERRIDE"; |
||
57 | const char *version_str; |
||
58 | int major, minor, n; |
||
59 | static int override_version = -1; |
||
60 | static bool fc_suffix = false; |
||
61 | static bool compat_suffix = false; |
||
62 | |||
63 | if (override_version < 0) { |
||
64 | override_version = 0; |
||
65 | |||
66 | version_str = getenv(env_var); |
||
67 | if (version_str) { |
||
68 | fc_suffix = check_for_ending(version_str, "FC"); |
||
69 | compat_suffix = check_for_ending(version_str, "COMPAT"); |
||
70 | |||
71 | n = sscanf(version_str, "%u.%u", &major, &minor); |
||
72 | if (n != 2) { |
||
73 | fprintf(stderr, "error: invalid value for %s: %s\n", |
||
74 | env_var, version_str); |
||
75 | override_version = 0; |
||
76 | } else { |
||
77 | override_version = major * 10 + minor; |
||
78 | if (override_version < 30 && fc_suffix) { |
||
79 | fprintf(stderr, "error: invalid value for %s: %s\n", |
||
80 | env_var, version_str); |
||
81 | } |
||
82 | } |
||
83 | } |
||
84 | } |
||
85 | |||
86 | *version = override_version; |
||
87 | *fwd_context = fc_suffix; |
||
88 | *compat_context = compat_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 | bool |
||
127 | _mesa_override_gl_version_contextless(struct gl_constants *consts, |
||
128 | gl_api *apiOut, GLuint *versionOut) |
||
129 | { |
||
130 | int version; |
||
131 | bool fwd_context, compat_context; |
||
132 | |||
133 | get_gl_override(&version, &fwd_context, &compat_context); |
||
134 | |||
135 | if (version > 0) { |
||
136 | *versionOut = version; |
||
137 | if (version >= 30 && fwd_context) { |
||
138 | *apiOut = API_OPENGL_CORE; |
||
139 | consts->ContextFlags |= GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT; |
||
140 | } else if (version >= 31 && !compat_context) { |
||
141 | *apiOut = API_OPENGL_CORE; |
||
142 | } else { |
||
143 | *apiOut = API_OPENGL_COMPAT; |
||
144 | } |
||
145 | return true; |
||
146 | } |
||
147 | return false; |
||
148 | } |
||
149 | |||
150 | void |
||
151 | _mesa_override_gl_version(struct gl_context *ctx) |
||
152 | { |
||
153 | if (_mesa_override_gl_version_contextless(&ctx->Const, &ctx->API, |
||
154 | &ctx->Version)) { |
||
155 | create_version_string(ctx, ""); |
||
156 | } |
||
157 | } |
||
158 | |||
159 | /** |
||
160 | * Returns the gl override value |
||
161 | * |
||
162 | * version > 0 indicates there is an override requested |
||
163 | */ |
||
164 | int |
||
165 | _mesa_get_gl_version_override(void) |
||
166 | { |
||
167 | int version; |
||
168 | bool fwd_context, compat_context; |
||
169 | |||
170 | get_gl_override(&version, &fwd_context, &compat_context); |
||
171 | |||
172 | return version; |
||
173 | } |
||
174 | |||
175 | /** |
||
176 | * Override the context's GLSL version if the environment variable |
||
177 | * MESA_GLSL_VERSION_OVERRIDE is set. Valid values for |
||
178 | * MESA_GLSL_VERSION_OVERRIDE are integers, such as "130". |
||
179 | */ |
||
180 | void |
||
181 | _mesa_override_glsl_version(struct gl_constants *consts) |
||
182 | { |
||
183 | const char *env_var = "MESA_GLSL_VERSION_OVERRIDE"; |
||
184 | const char *version; |
||
185 | int n; |
||
186 | |||
187 | version = getenv(env_var); |
||
188 | if (!version) { |
||
189 | return; |
||
190 | } |
||
191 | |||
192 | n = sscanf(version, "%u", &consts->GLSLVersion); |
||
193 | if (n != 1) { |
||
194 | fprintf(stderr, "error: invalid value for %s: %s\n", env_var, version); |
||
195 | return; |
||
196 | } |
||
197 | } |
||
198 | |||
199 | /** |
||
200 | * Examine enabled GL extensions to determine GL version. |
||
201 | */ |
||
202 | static GLuint |
||
203 | compute_version(const struct gl_extensions *extensions, |
||
204 | const struct gl_constants *consts, gl_api api) |
||
205 | { |
||
206 | GLuint major, minor, version; |
||
207 | |||
208 | const bool ver_1_3 = (extensions->ARB_texture_border_clamp && |
||
209 | extensions->ARB_texture_cube_map && |
||
210 | extensions->ARB_texture_env_combine && |
||
211 | extensions->ARB_texture_env_dot3); |
||
212 | const bool ver_1_4 = (ver_1_3 && |
||
213 | extensions->ARB_depth_texture && |
||
214 | extensions->ARB_shadow && |
||
215 | extensions->ARB_texture_env_crossbar && |
||
216 | extensions->EXT_blend_color && |
||
217 | extensions->EXT_blend_func_separate && |
||
218 | extensions->EXT_blend_minmax && |
||
219 | extensions->EXT_point_parameters); |
||
220 | const bool ver_1_5 = (ver_1_4 && |
||
221 | extensions->ARB_occlusion_query); |
||
222 | const bool ver_2_0 = (ver_1_5 && |
||
223 | extensions->ARB_point_sprite && |
||
224 | extensions->ARB_vertex_shader && |
||
225 | extensions->ARB_fragment_shader && |
||
226 | extensions->ARB_texture_non_power_of_two && |
||
227 | extensions->EXT_blend_equation_separate && |
||
228 | |||
229 | /* Technically, 2.0 requires the functionality of the |
||
230 | * EXT version. Enable 2.0 if either extension is |
||
231 | * available, and assume that a driver that only |
||
232 | * exposes the ATI extension will fallback to |
||
233 | * software when necessary. |
||
234 | */ |
||
235 | (extensions->EXT_stencil_two_side |
||
236 | || extensions->ATI_separate_stencil)); |
||
237 | const bool ver_2_1 = (ver_2_0 && |
||
238 | extensions->EXT_pixel_buffer_object && |
||
239 | extensions->EXT_texture_sRGB); |
||
240 | const bool ver_3_0 = (ver_2_1 && |
||
241 | consts->GLSLVersion >= 130 && |
||
242 | (consts->MaxSamples >= 4 || consts->FakeSWMSAA) && |
||
243 | (api == API_OPENGL_CORE || |
||
244 | extensions->ARB_color_buffer_float) && |
||
245 | extensions->ARB_depth_buffer_float && |
||
246 | extensions->ARB_half_float_vertex && |
||
247 | extensions->ARB_map_buffer_range && |
||
248 | extensions->ARB_shader_texture_lod && |
||
249 | extensions->ARB_texture_float && |
||
250 | extensions->ARB_texture_rg && |
||
251 | extensions->ARB_texture_compression_rgtc && |
||
252 | extensions->EXT_draw_buffers2 && |
||
253 | extensions->ARB_framebuffer_object && |
||
254 | extensions->EXT_framebuffer_sRGB && |
||
255 | extensions->EXT_packed_float && |
||
256 | extensions->EXT_texture_array && |
||
257 | extensions->EXT_texture_shared_exponent && |
||
258 | extensions->EXT_transform_feedback && |
||
259 | extensions->NV_conditional_render); |
||
260 | const bool ver_3_1 = (ver_3_0 && |
||
261 | consts->GLSLVersion >= 140 && |
||
262 | extensions->ARB_draw_instanced && |
||
263 | extensions->ARB_texture_buffer_object && |
||
264 | extensions->ARB_uniform_buffer_object && |
||
265 | extensions->EXT_texture_snorm && |
||
266 | extensions->NV_primitive_restart && |
||
267 | extensions->NV_texture_rectangle && |
||
268 | consts->Program[MESA_SHADER_VERTEX].MaxTextureImageUnits >= 16); |
||
269 | const bool ver_3_2 = (ver_3_1 && |
||
270 | consts->GLSLVersion >= 150 && |
||
271 | extensions->ARB_depth_clamp && |
||
272 | extensions->ARB_draw_elements_base_vertex && |
||
273 | extensions->ARB_fragment_coord_conventions && |
||
274 | extensions->EXT_provoking_vertex && |
||
275 | extensions->ARB_seamless_cube_map && |
||
276 | extensions->ARB_sync && |
||
277 | extensions->ARB_texture_multisample && |
||
278 | extensions->EXT_vertex_array_bgra); |
||
279 | const bool ver_3_3 = (ver_3_2 && |
||
280 | consts->GLSLVersion >= 330 && |
||
281 | extensions->ARB_blend_func_extended && |
||
282 | extensions->ARB_explicit_attrib_location && |
||
283 | extensions->ARB_instanced_arrays && |
||
284 | extensions->ARB_occlusion_query2 && |
||
285 | extensions->ARB_shader_bit_encoding && |
||
286 | extensions->ARB_texture_rgb10_a2ui && |
||
287 | extensions->ARB_timer_query && |
||
288 | extensions->ARB_vertex_type_2_10_10_10_rev && |
||
289 | extensions->EXT_texture_swizzle); |
||
290 | /* ARB_sampler_objects is always enabled in mesa */ |
||
291 | |||
292 | const bool ver_4_0 = (ver_3_3 && |
||
293 | consts->GLSLVersion >= 400 && |
||
294 | extensions->ARB_draw_buffers_blend && |
||
295 | extensions->ARB_draw_indirect && |
||
296 | extensions->ARB_gpu_shader5 && |
||
297 | extensions->ARB_gpu_shader_fp64 && |
||
298 | extensions->ARB_sample_shading && |
||
299 | false /*extensions->ARB_shader_subroutine*/ && |
||
300 | extensions->ARB_tessellation_shader && |
||
301 | extensions->ARB_texture_buffer_object_rgb32 && |
||
302 | extensions->ARB_texture_cube_map_array && |
||
303 | extensions->ARB_texture_query_lod && |
||
304 | extensions->ARB_transform_feedback2 && |
||
305 | extensions->ARB_transform_feedback3); |
||
306 | const bool ver_4_1 = (ver_4_0 && |
||
307 | consts->GLSLVersion >= 410 && |
||
308 | extensions->ARB_ES2_compatibility && |
||
309 | extensions->ARB_shader_precision && |
||
310 | extensions->ARB_vertex_attrib_64bit && |
||
311 | extensions->ARB_viewport_array); |
||
312 | const bool ver_4_2 = (ver_4_1 && |
||
313 | consts->GLSLVersion >= 420 && |
||
314 | extensions->ARB_base_instance && |
||
315 | extensions->ARB_conservative_depth && |
||
316 | extensions->ARB_internalformat_query && |
||
317 | extensions->ARB_shader_atomic_counters && |
||
318 | extensions->ARB_shader_image_load_store && |
||
319 | extensions->ARB_shading_language_420pack && |
||
320 | extensions->ARB_shading_language_packing && |
||
321 | extensions->ARB_texture_compression_bptc && |
||
322 | extensions->ARB_transform_feedback_instanced); |
||
323 | |||
324 | if (ver_4_2) { |
||
325 | major = 4; |
||
326 | minor = 2; |
||
327 | } |
||
328 | else if (ver_4_1) { |
||
329 | major = 4; |
||
330 | minor = 1; |
||
331 | } |
||
332 | else if (ver_4_0) { |
||
333 | major = 4; |
||
334 | minor = 0; |
||
335 | } |
||
336 | else if (ver_3_3) { |
||
337 | major = 3; |
||
338 | minor = 3; |
||
339 | } |
||
340 | else if (ver_3_2) { |
||
341 | major = 3; |
||
342 | minor = 2; |
||
343 | } |
||
344 | else if (ver_3_1) { |
||
345 | major = 3; |
||
346 | minor = 1; |
||
347 | } |
||
348 | else if (ver_3_0) { |
||
349 | major = 3; |
||
350 | minor = 0; |
||
351 | } |
||
352 | else if (ver_2_1) { |
||
353 | major = 2; |
||
354 | minor = 1; |
||
355 | } |
||
356 | else if (ver_2_0) { |
||
357 | major = 2; |
||
358 | minor = 0; |
||
359 | } |
||
360 | else if (ver_1_5) { |
||
361 | major = 1; |
||
362 | minor = 5; |
||
363 | } |
||
364 | else if (ver_1_4) { |
||
365 | major = 1; |
||
366 | minor = 4; |
||
367 | } |
||
368 | else if (ver_1_3) { |
||
369 | major = 1; |
||
370 | minor = 3; |
||
371 | } |
||
372 | else { |
||
373 | major = 1; |
||
374 | minor = 2; |
||
375 | } |
||
376 | |||
377 | version = major * 10 + minor; |
||
378 | |||
379 | if (api == API_OPENGL_CORE && version < 31) |
||
380 | return 0; |
||
381 | |||
382 | return version; |
||
383 | } |
||
384 | |||
385 | static GLuint |
||
386 | compute_version_es1(const struct gl_extensions *extensions) |
||
387 | { |
||
388 | /* OpenGL ES 1.0 is derived from OpenGL 1.3 */ |
||
389 | const bool ver_1_0 = (extensions->ARB_texture_env_combine && |
||
390 | extensions->ARB_texture_env_dot3); |
||
391 | /* OpenGL ES 1.1 is derived from OpenGL 1.5 */ |
||
392 | const bool ver_1_1 = (ver_1_0 && |
||
393 | extensions->EXT_point_parameters); |
||
394 | |||
395 | if (ver_1_1) { |
||
396 | return 11; |
||
397 | } else if (ver_1_0) { |
||
398 | return 10; |
||
399 | } else { |
||
400 | return 0; |
||
401 | } |
||
402 | } |
||
403 | |||
404 | static GLuint |
||
405 | compute_version_es2(const struct gl_extensions *extensions) |
||
406 | { |
||
407 | /* OpenGL ES 2.0 is derived from OpenGL 2.0 */ |
||
408 | const bool ver_2_0 = (extensions->ARB_texture_cube_map && |
||
409 | extensions->EXT_blend_color && |
||
410 | extensions->EXT_blend_func_separate && |
||
411 | extensions->EXT_blend_minmax && |
||
412 | extensions->ARB_vertex_shader && |
||
413 | extensions->ARB_fragment_shader && |
||
414 | extensions->ARB_texture_non_power_of_two && |
||
415 | extensions->EXT_blend_equation_separate); |
||
416 | /* FINISHME: This list isn't quite right. */ |
||
417 | const bool ver_3_0 = (extensions->ARB_half_float_vertex && |
||
418 | extensions->ARB_internalformat_query && |
||
419 | extensions->ARB_map_buffer_range && |
||
420 | extensions->ARB_shader_texture_lod && |
||
421 | extensions->ARB_texture_float && |
||
422 | extensions->ARB_texture_rg && |
||
423 | extensions->ARB_depth_buffer_float && |
||
424 | extensions->EXT_draw_buffers2 && |
||
425 | /* extensions->ARB_framebuffer_object && */ |
||
426 | extensions->EXT_framebuffer_sRGB && |
||
427 | extensions->EXT_packed_float && |
||
428 | extensions->EXT_texture_array && |
||
429 | extensions->EXT_texture_shared_exponent && |
||
430 | extensions->EXT_transform_feedback && |
||
431 | extensions->ARB_draw_instanced && |
||
432 | extensions->ARB_uniform_buffer_object && |
||
433 | extensions->EXT_texture_snorm && |
||
434 | extensions->NV_primitive_restart && |
||
435 | extensions->OES_depth_texture_cube_map); |
||
436 | if (ver_3_0) { |
||
437 | return 30; |
||
438 | } else if (ver_2_0) { |
||
439 | return 20; |
||
440 | } else { |
||
441 | return 0; |
||
442 | } |
||
443 | } |
||
444 | |||
445 | GLuint |
||
446 | _mesa_get_version(const struct gl_extensions *extensions, |
||
447 | struct gl_constants *consts, gl_api api) |
||
448 | { |
||
449 | switch (api) { |
||
450 | case API_OPENGL_COMPAT: |
||
451 | /* Disable GLSL 1.40 and later for legacy contexts. |
||
452 | * This disallows creation of the GL 3.1 compatibility context. */ |
||
453 | if (consts->GLSLVersion > 130) { |
||
454 | consts->GLSLVersion = 130; |
||
455 | } |
||
456 | /* fall through */ |
||
457 | case API_OPENGL_CORE: |
||
458 | return compute_version(extensions, consts, api); |
||
459 | case API_OPENGLES: |
||
460 | return compute_version_es1(extensions); |
||
461 | case API_OPENGLES2: |
||
462 | return compute_version_es2(extensions); |
||
463 | } |
||
464 | return 0; |
||
465 | } |
||
466 | |||
467 | /** |
||
468 | * Set the context's Version and VersionString fields. |
||
469 | * This should only be called once as part of context initialization |
||
470 | * or to perform version check for GLX_ARB_create_context_profile. |
||
471 | */ |
||
472 | void |
||
473 | _mesa_compute_version(struct gl_context *ctx) |
||
474 | { |
||
475 | if (ctx->Version) |
||
476 | return; |
||
477 | |||
478 | ctx->Version = _mesa_get_version(&ctx->Extensions, &ctx->Const, ctx->API); |
||
479 | |||
480 | /* Make sure that the GLSL version lines up with the GL version. In some |
||
481 | * cases it can be too high, e.g. if an extension is missing. |
||
482 | */ |
||
483 | if (ctx->API == API_OPENGL_CORE) { |
||
484 | switch (ctx->Version) { |
||
485 | case 31: |
||
486 | ctx->Const.GLSLVersion = 140; |
||
487 | break; |
||
488 | case 32: |
||
489 | ctx->Const.GLSLVersion = 150; |
||
490 | break; |
||
491 | default: |
||
492 | ctx->Const.GLSLVersion = ctx->Version * 10; |
||
493 | break; |
||
494 | } |
||
495 | } |
||
496 | |||
497 | switch (ctx->API) { |
||
498 | case API_OPENGL_COMPAT: |
||
499 | case API_OPENGL_CORE: |
||
500 | create_version_string(ctx, ""); |
||
501 | break; |
||
502 | |||
503 | case API_OPENGLES: |
||
504 | if (!ctx->Version) { |
||
505 | _mesa_problem(ctx, "Incomplete OpenGL ES 1.0 support."); |
||
506 | return; |
||
507 | } |
||
508 | create_version_string(ctx, "OpenGL ES-CM "); |
||
509 | break; |
||
510 | |||
511 | case API_OPENGLES2: |
||
512 | if (!ctx->Version) { |
||
513 | _mesa_problem(ctx, "Incomplete OpenGL ES 2.0 support."); |
||
514 | return; |
||
515 | } |
||
516 | create_version_string(ctx, "OpenGL ES "); |
||
517 | break; |
||
518 | } |
||
519 | }>>> |