5fe944d02fdec3bc506f0a3cfb23ca0f209f23b4
[libgliar] / src / gliar.c
1 /*
2 libgliar - a library that can fake the OpenGL context info returned by
3 the glGet OpenGL calls
4
5 Copyright (C) 2013 Canonical Ltd
6
7 This program is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.    See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program.        If not, see <http://www.gnu.org/licenses/>.
19
20 Author: Eleni Maria Stea <elene.mst@gmail.com>
21 */
22
23 #include <stdio.h>
24 #include <string.h>
25 #include <stdlib.h>
26 #include <ctype.h>
27 #include <unistd.h>
28 #include <dlfcn.h>
29 #include <pwd.h>
30 #include <GL/gl.h>
31 #include "cfg.h"
32
33 #ifndef GL_NUM_SHADING_LANGUAGE_VERSIONS
34 #define GL_NUM_SHADING_LANGUAGE_VERSIONS        0x82E9
35 #endif
36
37 static int init_valid_extensions(void);
38
39 static int done_init;
40
41 static const GLubyte* (*gl_get_string)(GLenum);
42 static const GLubyte* (*gl_get_stringi)(GLenum, GLuint);
43 static const void* (*gl_get_integerv)(GLenum, GLint*);
44
45 /*static const void* (*gl_get_booleanv)(GLenum, GLboolean*);
46 static const void* (*gl_get_doublev)(GLenum, GLdouble*);
47 static const void* (*gl_get_floatv)(GLenum, GLfloat*);
48 static const void* (*gl_get_integer64v)(GLenum, GLint64*);
49
50 static const void* (*gl_get_booleani_v)(GLenum, GLuint, GLboolean*);
51 static const void* (*gl_get_doublei_v)(GLenum, GLuint, GLdouble*);
52 static const void* (*gl_get_floati_v)(GLenum, GLuint, GLfloat*);
53 static const void* (*gl_get_integeri_v)(GLenum, GLuint, GLint*);
54 static const void* (*gl_get_integer64i_v)(GLenum, GLuint, GLint64*);*/
55
56 static struct cfgopt *cfglist;
57
58
59 static int init(void)
60 {
61         if(done_init) {
62                 return 0;
63         }
64
65         gl_get_string = dlsym(RTLD_NEXT, "glGetString");
66         gl_get_stringi = dlsym(RTLD_NEXT, "glGetStringi");
67         gl_get_integerv = dlsym(RTLD_NEXT, "glGetIntegerv");
68
69         /*gl_get_booleanv = dlsym(RTLD_NEXT, "glGetBooleanv");
70         gl_get_doublev = dlsym(RTLD_NEXT, "glGetDoublev");
71         gl_get_floatv = dlsym(RTLD_NEXT, "glGetFloatv");
72         gl_get_integer64v = dlsym(RTLD_NEXT, "glGetInteger64v");
73
74         gl_get_booleani_v = dlsym(RTLD_NEXT, "glGetBooleani_v");
75         gl_get_doublei_v = dlsym(RTLD_NEXT, "glGetDoublei_v");
76         gl_get_floati_v = dlsym(RTLD_NEXT, "glGetFloati_v");
77         gl_get_integeri_v = dlsym(RTLD_NEXT, "glGetIntegeri_v");
78         gl_get_integer64i_v = dlsym(RTLD_NEXT, "glGetInteger64i_v");*/
79
80         if(init_valid_extensions() == -1) {
81                 fprintf(stderr, "GLIAR: failed to initialize the valid extension list, might end up with unavailable extensions!\n");
82         }
83
84         if(!(cfglist = gliar_load_cfg("gliar.conf"))) {
85                 struct passwd *pw;
86                 char *homedir, *path;
87
88                 if((pw = getpwuid(getuid()))) {
89                         homedir = pw->pw_dir;
90                 } else {
91                         homedir = getenv("HOME");
92                 }
93
94                 if(homedir) {
95                         path = alloca(strlen(homedir) + strlen(".gliar.conf") + 2);
96                         sprintf(path, "%s/.gliar.conf", homedir);
97
98                         cfglist = gliar_load_cfg(path);
99                 }
100         }
101
102         done_init = 1;
103         return 0;
104 }
105
106 static int init_valid_extensions(void)
107 {
108         int i, num_ext, prev_space = 0;
109         const char *gl_ext_str;
110         char *ext_str, *tok, *ptr, **ext_table;
111
112         /* initialize the list of valid extensions */
113         if(!(gl_ext_str = (const char*)gl_get_string(GL_EXTENSIONS))) {
114                 return -1;
115         }
116
117         if(!(ext_str = malloc(strlen(gl_ext_str) + 1))) {
118                 return -1;
119         }
120         strcpy(ext_str, gl_ext_str);
121
122         /* count the extensions */
123         num_ext = 0;
124         ptr = ext_str;
125         while(*ptr) {
126                 if(isspace(*ptr) && prev_space == 0) {
127                         prev_space = 1;
128                         num_ext++;
129                 } else {
130                         prev_space = 0;
131                 }
132                 ptr++;
133         }
134
135         /* allocate extension table */
136         if(!(ext_table = malloc(num_ext * sizeof *ext_table))) {
137                 free(ext_str);
138                 return -1;
139         }
140
141         /* setup the ext_table slots to point to the start of each substring (extension) */
142         for(i=0; i<num_ext; i++) {
143                 if(!(tok = strtok(i == 0 ? ext_str : 0, " \t\v\n\r"))) {
144                         fprintf(stderr, "DEBUG: strtok returned 0 at token %d\n", i);
145                         num_ext = i;
146                 }
147                 ext_table[i] = tok;
148         }
149
150         gliar_value_set("extensions", ext_table, num_ext);
151
152         free(ext_table);
153         free(ext_str);
154         return 0;
155 }
156
157 const GLubyte *glGetString(GLenum name)
158 {
159         const char *key;
160         const struct cfgopt *option;
161
162         init();
163
164         switch(name) {
165         case GL_VENDOR:
166                 key = "vendor";
167                 break;
168
169         case GL_VERSION:
170                 key = "version";
171                 break;
172
173         case GL_EXTENSIONS:
174                 key = "extensions";
175                 break;
176
177         case GL_RENDERER:
178                 key = "renderer";
179                 break;
180
181         case GL_SHADING_LANGUAGE_VERSION:
182                 key = "sl version";
183                 break;
184
185         default:
186                 key = 0;
187         }
188
189         if(key && (option = gliar_find_opt(cfglist, key))) {
190                 return (const GLubyte*)option->conc_vals;
191         }
192
193         return gl_get_string(name);
194 }
195
196 const GLubyte *glGetStringi(GLenum name, GLuint index)
197 {
198         char *key;
199         const struct cfgopt *option;
200
201         init();
202
203         switch(name) {
204         case GL_EXTENSIONS:
205                 key = "extensions";
206                 break;
207
208         case GL_SHADING_LANGUAGE_VERSION:
209                 key = "sl version";
210                 break;
211
212         default:
213                 key = 0;
214         }
215
216         if(key && (option = gliar_find_opt(cfglist, key))) {
217                 return (const GLubyte*)option->str_val[index];
218         }
219
220         return gl_get_stringi(name, index);
221 }
222
223 void glGetIntegerv(GLenum name, GLint *val)
224 {
225         char *key;
226         const struct cfgopt *option;
227
228         init();
229
230         switch(name) {
231         case GL_NUM_EXTENSIONS:
232                 if(1) {
233                         key = "extensions";
234                 } else {
235         case GL_NUM_SHADING_LANGUAGE_VERSIONS:
236                         key = "sl version";
237                 }
238                 if(key && (option = gliar_find_opt(cfglist, key))) {
239                         *val = option->str_count;
240                         return;
241                 }
242                 break;
243
244         case GL_MAX_TEXTURE_UNITS:
245                 key = "max texture units";
246                 break;
247
248         case GL_MAX_TEXTURE_SIZE:
249                 key = "max texture size";
250                 break;
251
252         default:
253                 key = 0;
254         }
255
256         if(key && (option = gliar_find_opt(cfglist, key)) && option->type == GLIAR_NUMBER) {
257                 *val = option->num_val;
258                 return;
259         }
260
261         gl_get_integerv(name, val);
262 }