]> git.cworth.org Git - glenv/blob - glwrap.c
Share common code for numeric glGet functions
[glenv] / glwrap.c
1 /* Copyright © 2013, Intel Corporation
2  *
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:
9  *
10  * The above copyright notice and this permission notice shall be included in
11  * all copies or substantial portions of the Software.
12  *
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
19  * THE SOFTWARE.
20  */
21
22 #define GL_GLEXT_PROTOTYPES
23 #include <GL/gl.h>
24
25 #include <glaze.h>
26
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30
31 typedef GLubyte * (get_string_type_t) (GLenum);
32
33 static char *glenv_gl_extensions;
34 static char **glenv_gl_extensions_array;
35 static unsigned int glenv_num_gl_extensions;
36
37 static char *
38 xstrdup (const char *str)
39 {
40         char *ret;
41
42         ret = strdup (str);
43         if (ret == NULL) {
44                 fprintf (stderr, "Out of memory.\n");
45                 exit (1);
46         }
47
48         return ret;
49 }
50
51 static int
52 extension_list_count (const char *list)
53 {
54         int count = 0;
55
56         if (list == NULL)
57                 return 0;
58
59         while (list && *list) {
60                 /* Skip consecutive spaces before and between extensions */
61                 while (*list == ' ')
62                         list++;
63                 if (*list)
64                         count++;
65                 /* Skip to next space */
66                 list = strchr (list, ' ');
67         }
68
69         return count;
70 }
71
72 static void
73 extension_list_append (char **list, const char *extension)
74 {
75         char *new_list;
76
77         /* Nothing to do if extension is empty. */
78         if (extension == NULL || strlen (extension) == 0)
79                 return;
80
81         /* If initial list is empty, just copy extension */
82         if (*list == NULL) {
83                 *list = xstrdup (extension);
84                 return;
85         }
86
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");
91                 exit (1);
92         }
93
94         strcpy (new_list, *list);
95         strcat (new_list, " ");
96         strcat (new_list, extension);
97
98         free (*list);
99         *list = new_list;
100 }
101
102 static int
103 extension_list_contains (const char *list, const char *extension)
104 {
105         const char *match;
106         int length = strlen (extension);
107
108         while (1) {
109                 match = strstr (list, extension);
110                 if (match == NULL)
111                         return 0;
112                 if (match[length] == ' ' || match[length] == '\0')
113                         return 1;
114                 list = match + length;
115         }
116
117         return 0;
118 }
119
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.
123  *
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.
127  */
128 void glenv_first_gl_call (void);
129
130 void
131 glenv_first_gl_call (void)
132 {
133         get_string_type_t *get_string = glaze_lookup ("glGetString");
134         char *orig_extensions;
135         const char *extension;
136
137         orig_extensions = xstrdup ((char *) get_string (GL_EXTENSIONS));
138
139         if (getenv ("GLENV_GL_EXTENSIONS"))
140         {
141                 glenv_gl_extensions = getenv ("GLENV_GL_EXTENSIONS");
142         }
143         else if (getenv ("GLENV_GL_EXTENSIONS_BLACKLIST"))
144         {
145                 const char *blacklist = getenv ("GLENV_GL_EXTENSIONS_BLACKLIST");
146
147                 for (extension = strtok (orig_extensions, " ");
148                      extension;
149                      extension = strtok (NULL, " "))
150                 {
151                         if (! extension_list_contains (blacklist, extension))
152                                 extension_list_append (&glenv_gl_extensions, extension);
153                 }
154         }
155         else if (getenv ("GLENV_GL_EXTENSIONS_WHITELIST"))
156         {
157                 const char *whitelist = getenv ("GLENV_GL_EXTENSIONS_WHITELIST");
158
159                 for (extension = strtok (orig_extensions, " ");
160                      extension;
161                      extension = strtok (NULL, " "))
162                 {
163                         if (extension_list_contains (whitelist, extension))
164                                 extension_list_append (&glenv_gl_extensions, extension);
165                 }
166         }
167
168         free (orig_extensions);
169
170         if (glenv_gl_extensions) {
171                 int i;
172                 char *extensions_copy;
173
174                 glenv_num_gl_extensions = extension_list_count (glenv_gl_extensions);
175
176                 glenv_gl_extensions_array = malloc (sizeof (char *) * glenv_num_gl_extensions);
177
178                 extensions_copy = xstrdup (glenv_gl_extensions);
179
180                 for (i = 0, extension = strtok (extensions_copy, " ");
181                      extension;
182                      i++, extension = strtok (NULL, " "))
183                 {
184                         glenv_gl_extensions_array[i] = xstrdup (extension);
185                 }
186
187                 free (extensions_copy);
188         }
189
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
194          * options. */
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));
201
202                 exit (0);
203         }
204 }
205
206 static int
207 glenv_major_version (void)
208 {
209         const char *version = getenv ("GLENV_GL_VERSION");
210         if (version == NULL)
211                 return 0;
212
213         return atoi (version);
214 }
215
216 static int
217 glenv_minor_version (void)
218 {
219         const char *version = getenv ("GLENV_GL_VERSION");
220         const char *decimal;
221
222         if (version == NULL)
223                 return 0;
224
225         decimal = strchr (version, '.');
226
227         if (decimal == NULL)
228                 return 0;
229
230         return atoi (decimal + 1);
231 }
232
233 /* Read the user-specified glenv value for 'name'.
234  *
235  * Returns true if a value is available and is written to 'value'.
236  */
237 static int
238 glenv_get_integer (GLenum name, int *value)
239 {
240         switch (name) {
241         case GL_NUM_EXTENSIONS:
242                 if (glenv_gl_extensions) {
243                         *value = glenv_num_gl_extensions;
244                         return 1;
245                 }
246                 break;
247         case GL_MAJOR_VERSION:
248                 if (getenv ("GLENV_GL_VERSION")) {
249                         *value = glenv_major_version();
250                         return 1;
251                 }
252                 break;
253         case GL_MINOR_VERSION:
254                 if (getenv ("GLENV_GL_VERSION")) {
255                         *value = glenv_minor_version();
256                         return 1;
257                 }
258                 break;
259         }
260
261         return 0;
262 }
263
264 void
265 glGetDoublev (GLenum pname, GLdouble *params)
266 {
267         int value;
268
269         if (glenv_get_integer (pname, &value))
270                 *params = value;
271         else
272                 GLAZE_DEFER (glGetDoublev, pname, params);
273 }
274
275 void
276 glGetFloatv (GLenum pname, GLfloat *params)
277 {
278         int value;
279
280         if (glenv_get_integer (pname, &value))
281                 *params = value;
282         else
283                 GLAZE_DEFER (glGetFloatv, pname, params);
284 }
285
286 void
287 glGetIntegerv (GLenum pname, GLint *params)
288 {
289         int value;
290
291         if (glenv_get_integer (pname, &value))
292                 *params = value;
293         else
294                 GLAZE_DEFER (glGetIntegerv, pname, params);
295 }
296
297 void
298 glGetInteger64v (GLenum pname, GLint64 * params)
299 {
300         int value;
301
302         if (glenv_get_integer (pname, &value))
303                 *params = value;
304         else
305                 GLAZE_DEFER (glGetInteger64v, pname, params);
306 }
307
308 const GLubyte *
309 glGetString (GLenum name)
310 {
311         const GLubyte *ret;
312
313         switch (name) {
314         case GL_VENDOR:
315                 ret = (GLubyte *) getenv ("GLENV_GL_VENDOR");
316                 if (ret)
317                         return ret;
318                 break;
319         case GL_RENDERER:
320                 ret = (GLubyte *) getenv ("GLENV_GL_RENDERER");
321                 if (ret)
322                         return ret;
323                 break;
324         case GL_VERSION:
325                 ret = (GLubyte *) getenv ("GLENV_GL_VERSION");
326                 if (ret)
327                         return ret;
328                 break;
329         case GL_SHADING_LANGUAGE_VERSION:
330                 ret = (GLubyte *) getenv ("GLENV_GL_SHADING_LANGUAGE_VERSION");
331                 if (ret)
332                         return ret;
333                 break;
334         case GL_EXTENSIONS:
335                 if (glenv_gl_extensions)
336                         return (GLubyte *) glenv_gl_extensions;
337                 break;
338         }
339
340         GLAZE_DEFER_WITH_RETURN (ret, glGetString, name);
341
342         return ret;
343 }
344
345 const GLubyte *
346 glGetStringi (GLenum name, GLuint index)
347 {
348         const GLubyte *ret;
349
350         switch (name) {
351         case GL_EXTENSIONS:
352                 if (glenv_gl_extensions) {
353                         if (index < glenv_num_gl_extensions) {
354                                 return (GLubyte *) glenv_gl_extensions_array[index];
355                         } else {
356                                 /* Force index to an value that will
357                                  * guarantee an INVALID_VALUE value
358                                  * from the underlying glGetStringi.
359                                  */
360                                 index = (GLuint) -1;
361                         }
362                 }
363                 break;
364         case GL_SHADING_LANGUAGE_VERSION:
365                 if (index == 0) {
366                         ret = (GLubyte *) getenv ("GLENV_GL_SHADING_LANGUAGE_VERSION");
367                         if (ret)
368                                 return ret;
369                 }
370                 break;
371         }
372
373         GLAZE_DEFER_WITH_RETURN (ret, glGetStringi, name, index);
374
375         return ret;
376 }