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
32 void **wrapper_handles;
33 int num_wrapper_handles;
35 #define STRNCMP_LITERAL(str, literal) strncmp (str, literal, sizeof (literal) - 1)
38 open_libgl_handle (void)
40 const char *libgl_path;
45 libgl_path = getenv ("GLAZE_LIBGL");
47 if (libgl_path == NULL) {
50 libgl_path = getenv ("GLAZE_LIBGL_32_AUTO");
51 #elif GLAZE_BITS == 64
52 libgl_path = getenv ("GLAZE_LIBGL_64_AUTO");
55 if (libgl_path == NULL || strlen (libgl_path) == 0) {
57 "Error: Failed to detect OpenGL library.\n"
58 "Please set GLAZE_LIBGL to path of real libGL.so\n");
62 setenv ("GLAZE_LIBGL", libgl_path, 1);
66 libgl_handle = dlopen (libgl_path, RTLD_LAZY | RTLD_GLOBAL);
67 if (libgl_handle == NULL) {
68 fprintf (stderr, "glaze_init: Error: Failed to dlopen %s: %s\n",
69 libgl_path, dlerror());
74 /* Count the number of types 'chr' appears in 'str' */
76 count_chars (const char *str, char chr)
95 open_wrapper_handles (void)
98 char *path_copy, *wrapper, *save;
104 path = getenv ("GLAZE_WRAPPER");
106 fprintf (stderr, "GLAZE_WRAPPER unset. Please set to path of Glaze-using wrapper library.\n");
110 num_wrapper_handles = count_chars (path, ':') + 1;
112 wrapper_handles = malloc (num_wrapper_handles * sizeof (void*));
113 if (wrapper_handles == NULL) {
114 fprintf (stderr, "Out of memory\n");
118 /* Clear dlerror state. */
121 path_copy = strdup (path);
122 if (path_copy == NULL) {
123 fprintf (stderr, "Out of memory\n");
127 for (i = 0, wrapper = strtok_r (path_copy, ":", &save);
128 i < num_wrapper_handles;
129 i++, wrapper = strtok_r (NULL, ":", &save))
131 wrapper_handles[i] = dlopen (wrapper, RTLD_LAZY);
132 if (wrapper_handles[i] == NULL) {
133 const char *error = dlerror();
134 fprintf (stderr, "Error: Failed to dlopen %s: %s\n",
144 glaze_init (void) __attribute__((constructor));
149 open_libgl_handle ();
150 open_wrapper_handles ();
154 call_first_gl_call_callbacks (void)
156 char *callbacks = getenv ("GLAZE_FIRST_GL_CALL_CALLBACK");
157 char *name, *names, *save;
158 void (*callback) (void);
161 if (callbacks == NULL)
164 names = strdup (callbacks);
166 fprintf (stderr, "Out of memory\n");
170 for (name = strtok_r (names, ":", &save);
172 name = strtok_r (NULL, ":", &save))
174 for (i = 0; i < num_wrapper_handles; i++) {
175 callback = dlsym (wrapper_handles[i], name);
181 fprintf (stderr, "Error: Failed to find function %s "
182 "in any GLAZE_WRAPPER library.\n", name);
191 find_symbol_in_glaze_wrappers (const char *name)
196 for (i = 0; i < num_wrapper_handles; i++) {
197 symbol = dlsym (wrapper_handles[i], name);
206 resolve (const char *name)
208 static int before_first_gl_call = 1;
211 if (before_first_gl_call &&
212 STRNCMP_LITERAL (name, "gl") == 0 &&
213 STRNCMP_LITERAL (name, "glX") != 0)
215 call_first_gl_call_callbacks ();
217 before_first_gl_call = 0;
220 /* The wrappers get first choice on all symbols. */
221 symbol = find_symbol_in_glaze_wrappers (name);
225 return dlsym (libgl_handle, name);
229 (*glXGetProcAddress (const unsigned char *name))(void);
232 (*glXGetProcAddress (const unsigned char *name))(void)
234 static int first_call = 1;
235 static typeof (&glXGetProcAddress) wrapper_glXGetProcAddress;
236 static typeof (&glXGetProcAddress) libgl_glXGetProcAddress;
239 /* On the first call, check if the wrapper provides an
240 * implementation of this function. */
242 wrapper_glXGetProcAddress =
243 find_symbol_in_glaze_wrappers ("glXGetProcAddress");
244 libgl_glXGetProcAddress = dlsym (libgl_handle,
245 "glXGetProcAddress");
249 /* If the wrapper implements glXGetProcAddress itself, then it
250 * had better know best what to do. Just let it. */
251 if (wrapper_glXGetProcAddress)
252 return wrapper_glXGetProcAddress (name);
254 /* Otherwise, we need to resolve the name.
256 * The wrappers get first choice on all symbols. */
257 symbol = find_symbol_in_glaze_wrappers ((char *) name);
261 /* The wrapper doesn't care, so defer to the underlying
262 * glXGetProcAddress */
263 return libgl_glXGetProcAddress (name);
268 (*glXGetProcAddressARB (const unsigned char *name))(void);
271 (*glXGetProcAddressARB (const unsigned char *name))(void)
273 static int first_call = 1;
274 static typeof (&glXGetProcAddressARB) wrapper_glXGetProcAddressARB;
275 static typeof (&glXGetProcAddressARB) libgl_glXGetProcAddressARB;
278 /* On the first call, check if the wrapper provides an
279 * implementation of this function. */
281 wrapper_glXGetProcAddressARB =
282 find_symbol_in_glaze_wrappers ("glXGetProcAddressARB");
283 libgl_glXGetProcAddressARB = dlsym (libgl_handle,
284 "glXGetProcAddressARB");
288 /* If the wrapper implements glXGetProcAddressARB itself, then
289 * it had better know best what to do. Just let it. */
290 if (wrapper_glXGetProcAddressARB)
291 return wrapper_glXGetProcAddressARB (name);
293 /* Otherwise, we need to resolve the name.
295 * The wrappers get first choice on all symbols. */
296 symbol = find_symbol_in_glaze_wrappers ((char *) name);
300 /* The wrapper doesn't care, so defer to the underlying
301 * glXGetProcAddressARB */
302 return libgl_glXGetProcAddressARB (name);
306 #define GLAZE_API(name) \
307 void * name() __attribute__((ifunc(#name "_resolver"))); \
309 name ## _resolver (void) { return resolve (#name); }
311 #include "specs/gl.def"
312 #include "specs/glx.def"