1 /* Copyright © 2013, Intel Corporation
3 * Permission is hereby granted, free of charge, to any person obtaining a copy
4 * of this software and associated documentation files (the "Software"), to deal
5 * in the Software without restriction, including without limitation the rights
6 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 * copies of the Software, and to permit persons to whom the Software is
8 * furnished to do so, subject to the following conditions:
10 * The above copyright notice and this permission notice shall be included in
11 * all copies or substantial portions of the Software.
13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 #define GL_GLEXT_PROTOTYPES
31 typedef GLubyte * (get_string_type_t) (GLenum);
33 static char *glenv_gl_extensions;
34 static char **glenv_gl_extensions_array;
35 static unsigned int glenv_num_gl_extensions;
38 xstrdup (const char *str)
44 fprintf (stderr, "Out of memory.\n");
52 extension_list_count (const char *list)
59 while (list && *list) {
60 /* Skip consecutive spaces before and between extensions */
65 /* Skip to next space */
66 list = strchr (list, ' ');
73 extension_list_append (char **list, const char *extension)
77 /* Nothing to do if extension is empty. */
78 if (extension == NULL || strlen (extension) == 0)
81 /* If initial list is empty, just copy extension */
83 *list = xstrdup (extension);
87 /* Append one space, then extension onto current list. */
88 new_list = malloc (strlen (*list) + 1 + strlen (extension) + 1);
89 if (new_list == NULL) {
90 fprintf (stderr, "Out of memory.\n");
94 strcpy (new_list, *list);
95 strcat (new_list, " ");
96 strcat (new_list, extension);
103 extension_list_contains (const char *list, const char *extension)
106 int length = strlen (extension);
109 match = strstr (list, extension);
112 if (match[length] == ' ' || match[length] == '\0')
114 list = match + length;
120 /* When the first GL call is made, (that is, after the OpenGL context
121 * has been initialized with glX or some other system), then we can
122 * finally implement the "glenv --query" option if it was specified.
124 * Similarly, at this point, we can read the original extensions
125 * string from the OpenGL environment and modify it according to the
126 * blacklist or whitelist that the user may have specified.
128 void glenv_first_gl_call (void);
131 glenv_first_gl_call (void)
133 get_string_type_t *get_string = glaze_lookup ("glGetString");
134 char *orig_extensions;
135 const char *extension;
137 orig_extensions = xstrdup ((char *) get_string (GL_EXTENSIONS));
139 if (getenv ("GLENV_GL_EXTENSIONS"))
141 glenv_gl_extensions = getenv ("GLENV_GL_EXTENSIONS");
143 else if (getenv ("GLENV_GL_EXTENSIONS_BLACKLIST"))
145 const char *blacklist = getenv ("GLENV_GL_EXTENSIONS_BLACKLIST");
147 for (extension = strtok (orig_extensions, " ");
149 extension = strtok (NULL, " "))
151 if (! extension_list_contains (blacklist, extension))
152 extension_list_append (&glenv_gl_extensions, extension);
155 else if (getenv ("GLENV_GL_EXTENSIONS_WHITELIST"))
157 const char *whitelist = getenv ("GLENV_GL_EXTENSIONS_WHITELIST");
159 for (extension = strtok (orig_extensions, " ");
161 extension = strtok (NULL, " "))
163 if (extension_list_contains (whitelist, extension))
164 extension_list_append (&glenv_gl_extensions, extension);
168 free (orig_extensions);
170 if (glenv_gl_extensions) {
172 char *extensions_copy;
174 glenv_num_gl_extensions = extension_list_count (glenv_gl_extensions);
176 glenv_gl_extensions_array = malloc (sizeof (char *) * glenv_num_gl_extensions);
178 extensions_copy = xstrdup (glenv_gl_extensions);
180 for (i = 0, extension = strtok (extensions_copy, " ");
182 i++, extension = strtok (NULL, " "))
184 glenv_gl_extensions_array[i] = xstrdup (extension);
187 free (extensions_copy);
190 /* We deliberately call glGetString directly here rather than
191 * use the get_string function pointer to the underlying
192 * glGetString function. That's because we want --query to
193 * reflect any modifications the user made with other
195 if (getenv ("GLENV_QUERY")) {
196 printf ("--vendor=\"%s\"\n", glGetString (GL_VENDOR));
197 printf ("--renderer=\"%s\"\n", glGetString (GL_RENDERER));
198 printf ("--version=\"%s\"\n", glGetString (GL_VERSION));
199 printf ("--shading-language-version=\"%s\"\n", glGetString (GL_SHADING_LANGUAGE_VERSION));
200 printf ("--extensions=\"%s\"\n", glGetString (GL_EXTENSIONS));
207 glenv_major_version (void)
209 const char *version = getenv ("GLENV_GL_VERSION");
213 return atoi (version);
217 glenv_minor_version (void)
219 const char *version = getenv ("GLENV_GL_VERSION");
225 decimal = strchr (version, '.');
230 return atoi (decimal + 1);
234 glGetDoublev (GLenum pname, GLdouble *params)
237 case GL_NUM_EXTENSIONS:
238 if (glenv_gl_extensions) {
239 *params = glenv_num_gl_extensions;
243 case GL_MAJOR_VERSION:
244 if (getenv ("GLENV_GL_VERSION")) {
245 *params = glenv_major_version();
249 case GL_MINOR_VERSION:
250 if (getenv ("GLENV_GL_VERSION")) {
251 *params = glenv_minor_version();
257 GLAZE_DEFER (glGetDoublev, pname, params);
261 glGetFloatv (GLenum pname, GLfloat *params)
264 case GL_NUM_EXTENSIONS:
265 if (glenv_gl_extensions) {
266 *params = glenv_num_gl_extensions;
270 case GL_MAJOR_VERSION:
271 if (getenv ("GLENV_GL_VERSION")) {
272 *params = glenv_major_version();
276 case GL_MINOR_VERSION:
277 if (getenv ("GLENV_GL_VERSION")) {
278 *params = glenv_minor_version();
284 GLAZE_DEFER (glGetFloatv, pname, params);
288 glGetIntegerv (GLenum pname, GLint *params)
291 case GL_NUM_EXTENSIONS:
292 if (glenv_gl_extensions) {
293 *params = glenv_num_gl_extensions;
297 case GL_MAJOR_VERSION:
298 if (getenv ("GLENV_GL_VERSION")) {
299 *params = glenv_major_version();
303 case GL_MINOR_VERSION:
304 if (getenv ("GLENV_GL_VERSION")) {
305 *params = glenv_minor_version();
311 GLAZE_DEFER (glGetIntegerv, pname, params);
315 glGetInteger64v (GLenum pname, GLint64 * params)
318 case GL_NUM_EXTENSIONS:
319 if (glenv_gl_extensions) {
320 *params = glenv_num_gl_extensions;
324 case GL_MAJOR_VERSION:
325 if (getenv ("GLENV_GL_VERSION")) {
326 *params = glenv_major_version();
330 case GL_MINOR_VERSION:
331 if (getenv ("GLENV_GL_VERSION")) {
332 *params = glenv_minor_version();
338 GLAZE_DEFER (glGetInteger64v, pname, params);
342 glGetString (GLenum name)
348 ret = (GLubyte *) getenv ("GLENV_GL_VENDOR");
353 ret = (GLubyte *) getenv ("GLENV_GL_RENDERER");
358 ret = (GLubyte *) getenv ("GLENV_GL_VERSION");
362 case GL_SHADING_LANGUAGE_VERSION:
363 ret = (GLubyte *) getenv ("GLENV_GL_SHADING_LANGUAGE_VERSION");
368 if (glenv_gl_extensions)
369 return (GLubyte *) glenv_gl_extensions;
373 GLAZE_DEFER_WITH_RETURN (ret, glGetString, name);
379 glGetStringi (GLenum name, GLuint index)
385 if (glenv_gl_extensions) {
386 if (index < glenv_num_gl_extensions) {
387 return (GLubyte *) glenv_gl_extensions_array[index];
389 /* Force index to an value that will
390 * guarantee an INVALID_VALUE value
391 * from the underlying glGetStringi.
397 case GL_SHADING_LANGUAGE_VERSION:
399 ret = (GLubyte *) getenv ("GLENV_GL_SHADING_LANGUAGE_VERSION");
406 GLAZE_DEFER_WITH_RETURN (ret, glGetStringi, name, index);