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  * Override the context's GL version if the environment variable
32  * MESA_GL_VERSION_OVERRIDE is set. Valid values of MESA_GL_VERSION_OVERRIDE
33  * are point-separated version numbers, such as "3.0".
34  */
35 static void
override_version(struct gl_context * ctx)36 override_version(struct gl_context *ctx)
37 {
38    const char *env_var = "MESA_GL_VERSION_OVERRIDE";
39    const char *version;
40    int n;
41    int major, minor;
42 
43    version = getenv(env_var);
44    if (!version) {
45       return;
46    }
47 
48    n = sscanf(version, "%u.%u", &major, &minor);
49    if (n != 2) {
50       fprintf(stderr, "error: invalid value for %s: %s\n", env_var, version);
51       return;
52    }
53 
54    ctx->Version = major * 10 + minor;
55 }
56 
57 /**
58  * Override the context's GLSL version if the environment variable
59  * MESA_GLSL_VERSION_OVERRIDE is set. Valid values for
60  * MESA_GLSL_VERSION_OVERRIDE are integers, such as "130".
61  */
62 void
_mesa_override_glsl_version(struct gl_context * ctx)63 _mesa_override_glsl_version(struct gl_context *ctx)
64 {
65    const char *env_var = "MESA_GLSL_VERSION_OVERRIDE";
66    const char *version;
67    int n;
68 
69    version = getenv(env_var);
70    if (!version) {
71       return;
72    }
73 
74    n = sscanf(version, "%u", &ctx->Const.GLSLVersion);
75    if (n != 1) {
76       fprintf(stderr, "error: invalid value for %s: %s\n", env_var, version);
77       return;
78    }
79 }
80 
81 /**
82  * Examine enabled GL extensions to determine GL version.
83  */
84 static void
compute_version(struct gl_context * ctx)85 compute_version(struct gl_context *ctx)
86 {
87    GLuint major, minor;
88    static const int max = 100;
89 
90    const GLboolean ver_1_3 = (ctx->Extensions.ARB_texture_border_clamp &&
91                               ctx->Extensions.ARB_texture_cube_map &&
92                               ctx->Extensions.ARB_texture_env_combine &&
93                               ctx->Extensions.ARB_texture_env_dot3);
94    const GLboolean ver_1_4 = (ver_1_3 &&
95                               ctx->Extensions.ARB_depth_texture &&
96                               ctx->Extensions.ARB_shadow &&
97                               ctx->Extensions.ARB_texture_env_crossbar &&
98                               ctx->Extensions.ARB_window_pos &&
99                               ctx->Extensions.EXT_blend_color &&
100                               ctx->Extensions.EXT_blend_func_separate &&
101                               ctx->Extensions.EXT_blend_minmax &&
102                               ctx->Extensions.EXT_fog_coord &&
103                               ctx->Extensions.EXT_point_parameters &&
104                               ctx->Extensions.EXT_secondary_color);
105    const GLboolean ver_1_5 = (ver_1_4 &&
106                               ctx->Extensions.ARB_occlusion_query &&
107                               ctx->Extensions.EXT_shadow_funcs);
108    const GLboolean ver_2_0 = (ver_1_5 &&
109                               ctx->Extensions.ARB_point_sprite &&
110                               ctx->Extensions.ARB_shader_objects &&
111                               ctx->Extensions.ARB_vertex_shader &&
112                               ctx->Extensions.ARB_fragment_shader &&
113                               ctx->Extensions.ARB_texture_non_power_of_two &&
114                               ctx->Extensions.EXT_blend_equation_separate &&
115 
116 			      /* Technically, 2.0 requires the functionality
117 			       * of the EXT version.  Enable 2.0 if either
118 			       * extension is available, and assume that a
119 			       * driver that only exposes the ATI extension
120 			       * will fallback to software when necessary.
121 			       */
122 			      (ctx->Extensions.EXT_stencil_two_side
123 			       || ctx->Extensions.ATI_separate_stencil));
124    const GLboolean ver_2_1 = (ver_2_0 &&
125                               ctx->Const.GLSLVersion >= 120 &&
126                               ctx->Extensions.EXT_pixel_buffer_object &&
127                               ctx->Extensions.EXT_texture_sRGB);
128    const GLboolean ver_3_0 = (ver_2_1 &&
129                               ctx->Const.GLSLVersion >= 130 &&
130                               ctx->Const.MaxSamples >= 4 &&
131                               ctx->Extensions.ARB_color_buffer_float &&
132                               ctx->Extensions.ARB_depth_buffer_float &&
133                               ctx->Extensions.ARB_half_float_pixel &&
134                               ctx->Extensions.ARB_half_float_vertex &&
135                               ctx->Extensions.ARB_map_buffer_range &&
136                               ctx->Extensions.ARB_shader_texture_lod &&
137                               ctx->Extensions.ARB_texture_float &&
138                               ctx->Extensions.ARB_texture_rg &&
139                               ctx->Extensions.ARB_texture_compression_rgtc &&
140                               ctx->Extensions.EXT_draw_buffers2 &&
141                               ctx->Extensions.ARB_framebuffer_object &&
142                               ctx->Extensions.EXT_framebuffer_sRGB &&
143                               ctx->Extensions.EXT_packed_float &&
144                               ctx->Extensions.EXT_texture_array &&
145                               ctx->Extensions.EXT_texture_shared_exponent &&
146                               ctx->Extensions.EXT_transform_feedback &&
147                               ctx->Extensions.NV_conditional_render);
148    const GLboolean ver_3_1 = (ver_3_0 &&
149                               ctx->Const.GLSLVersion >= 140 &&
150                               ctx->Extensions.ARB_copy_buffer &&
151                               ctx->Extensions.ARB_draw_instanced &&
152                               ctx->Extensions.ARB_texture_buffer_object &&
153                               ctx->Extensions.ARB_uniform_buffer_object &&
154                               ctx->Extensions.EXT_texture_snorm &&
155                               ctx->Extensions.NV_primitive_restart &&
156                               ctx->Extensions.NV_texture_rectangle &&
157                               ctx->Const.MaxVertexTextureImageUnits >= 16);
158    const GLboolean ver_3_2 = (ver_3_1 &&
159                               ctx->Const.GLSLVersion >= 150 &&
160                               ctx->Extensions.ARB_depth_clamp &&
161                               ctx->Extensions.ARB_draw_elements_base_vertex &&
162                               ctx->Extensions.ARB_fragment_coord_conventions &&
163                               ctx->Extensions.ARB_geometry_shader4 &&
164                               ctx->Extensions.EXT_provoking_vertex &&
165                               ctx->Extensions.ARB_seamless_cube_map &&
166                               ctx->Extensions.ARB_sync &&
167                               ctx->Extensions.ARB_texture_multisample &&
168                               ctx->Extensions.EXT_vertex_array_bgra);
169    const GLboolean ver_3_3 = (ver_3_2 &&
170                               ctx->Const.GLSLVersion >= 330 &&
171                               ctx->Extensions.ARB_blend_func_extended &&
172                               ctx->Extensions.ARB_explicit_attrib_location &&
173                               ctx->Extensions.ARB_instanced_arrays &&
174                               ctx->Extensions.ARB_occlusion_query2 &&
175                               ctx->Extensions.ARB_shader_bit_encoding &&
176                               ctx->Extensions.ARB_texture_rgb10_a2ui &&
177                               ctx->Extensions.ARB_timer_query &&
178                               ctx->Extensions.ARB_vertex_type_2_10_10_10_rev &&
179                               ctx->Extensions.EXT_texture_swizzle);
180                               /* ARB_sampler_objects is always enabled in mesa */
181 
182    if (ver_3_3) {
183       major = 3;
184       minor = 3;
185    }
186    else if (ver_3_2) {
187       major = 3;
188       minor = 2;
189    }
190    else if (ver_3_1) {
191       major = 3;
192       minor = 1;
193    }
194    else if (ver_3_0) {
195       major = 3;
196       minor = 0;
197    }
198    else if (ver_2_1) {
199       major = 2;
200       minor = 1;
201    }
202    else if (ver_2_0) {
203       major = 2;
204       minor = 0;
205    }
206    else if (ver_1_5) {
207       major = 1;
208       minor = 5;
209    }
210    else if (ver_1_4) {
211       major = 1;
212       minor = 4;
213    }
214    else if (ver_1_3) {
215       major = 1;
216       minor = 3;
217    }
218    else {
219       major = 1;
220       minor = 2;
221    }
222 
223    ctx->Version = major * 10 + minor;
224 
225    override_version(ctx);
226 
227    ctx->VersionString = (char *) malloc(max);
228    if (ctx->VersionString) {
229       _mesa_snprintf(ctx->VersionString, max,
230 		     "%u.%u Mesa " MESA_VERSION_STRING
231 #ifdef MESA_GIT_SHA1
232 		     " (" MESA_GIT_SHA1 ")"
233 #endif
234 		     ,
235 		     ctx->Version / 10, ctx->Version % 10);
236    }
237 }
238 
239 static void
compute_version_es1(struct gl_context * ctx)240 compute_version_es1(struct gl_context *ctx)
241 {
242    static const int max = 100;
243 
244    /* OpenGL ES 1.0 is derived from OpenGL 1.3 */
245    const GLboolean ver_1_0 = (ctx->Extensions.ARB_texture_env_combine &&
246                               ctx->Extensions.ARB_texture_env_dot3);
247    /* OpenGL ES 1.1 is derived from OpenGL 1.5 */
248    const GLboolean ver_1_1 = (ver_1_0 &&
249                               ctx->Extensions.EXT_point_parameters);
250 
251    if (ver_1_1) {
252       ctx->Version = 11;
253    } else if (ver_1_0) {
254       ctx->Version = 10;
255    } else {
256       _mesa_problem(ctx, "Incomplete OpenGL ES 1.0 support.");
257    }
258 
259    ctx->VersionString = (char *) malloc(max);
260    if (ctx->VersionString) {
261       _mesa_snprintf(ctx->VersionString, max,
262 		     "OpenGL ES-CM 1.%d Mesa " MESA_VERSION_STRING
263 #ifdef MESA_GIT_SHA1
264 		     " (" MESA_GIT_SHA1 ")"
265 #endif
266 		     ,
267 		     ctx->Version % 10);
268    }
269 }
270 
271 static void
compute_version_es2(struct gl_context * ctx)272 compute_version_es2(struct gl_context *ctx)
273 {
274    static const int max = 100;
275 
276    /* OpenGL ES 2.0 is derived from OpenGL 2.0 */
277    const GLboolean ver_2_0 = (ctx->Extensions.ARB_texture_cube_map &&
278                               ctx->Extensions.EXT_blend_color &&
279                               ctx->Extensions.EXT_blend_func_separate &&
280                               ctx->Extensions.EXT_blend_minmax &&
281                               ctx->Extensions.ARB_shader_objects &&
282                               ctx->Extensions.ARB_vertex_shader &&
283                               ctx->Extensions.ARB_fragment_shader &&
284                               ctx->Extensions.ARB_texture_non_power_of_two &&
285                               ctx->Extensions.EXT_blend_equation_separate);
286    if (ver_2_0) {
287       ctx->Version = 20;
288    } else {
289       _mesa_problem(ctx, "Incomplete OpenGL ES 2.0 support.");
290    }
291 
292    ctx->VersionString = (char *) malloc(max);
293    if (ctx->VersionString) {
294       _mesa_snprintf(ctx->VersionString, max,
295 		     "OpenGL ES 2.0 Mesa " MESA_VERSION_STRING
296 #ifdef MESA_GIT_SHA1
297 		     " (" MESA_GIT_SHA1 ")"
298 #endif
299 		     );
300    }
301 }
302 
303 /**
304  * Set the context's Version and VersionString fields.
305  * This should only be called once as part of context initialization
306  * or to perform version check for GLX_ARB_create_context_profile.
307  */
308 void
_mesa_compute_version(struct gl_context * ctx)309 _mesa_compute_version(struct gl_context *ctx)
310 {
311    if (ctx->Version)
312       return;
313 
314    switch (ctx->API) {
315    case API_OPENGL:
316    case API_OPENGL_CORE:
317       compute_version(ctx);
318       break;
319    case API_OPENGLES:
320       compute_version_es1(ctx);
321       break;
322    case API_OPENGLES2:
323       compute_version_es2(ctx);
324       break;
325    }
326 
327 }
328