blob: 8ae40d422cb5d384bc97fd6942bba3fbf03350ff [file] [log] [blame]
José Fonseca1cfd89b2011-12-01 21:09:57 +00001/**************************************************************************
2 *
3 * Copyright 2011 Jose Fonseca
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 *
24 **************************************************************************/
25
26
27#include "glproc.hpp"
José Fonsecae91f5bc2014-07-17 20:42:35 +010028#include "os.hpp"
José Fonseca1cfd89b2011-12-01 21:09:57 +000029
30
31#if !defined(_WIN32)
José Fonseca2dc8ebe2011-12-03 11:00:32 +000032#include <unistd.h> // for symlink
Alexander Monakovd6aa74c2013-05-03 21:03:27 +040033#include "dlopen.hpp"
José Fonseca1cfd89b2011-12-01 21:09:57 +000034#endif
35
36
37/*
38 * Handle to the true OpenGL library.
39 */
40#if defined(_WIN32)
José Fonseca3947e362012-04-20 21:04:43 +010041HMODULE _libGlHandle = NULL;
José Fonseca1cfd89b2011-12-01 21:09:57 +000042#else
José Fonseca632a78d2012-04-19 07:18:59 +010043void *_libGlHandle = NULL;
José Fonseca1cfd89b2011-12-01 21:09:57 +000044#endif
45
46
47
48#if defined(_WIN32)
49
50void *
José Fonseca632a78d2012-04-19 07:18:59 +010051_getPublicProcAddress(const char *procName)
José Fonseca1cfd89b2011-12-01 21:09:57 +000052{
José Fonseca632a78d2012-04-19 07:18:59 +010053 if (!_libGlHandle) {
José Fonseca1cfd89b2011-12-01 21:09:57 +000054 char szDll[MAX_PATH] = {0};
55
56 if (!GetSystemDirectoryA(szDll, MAX_PATH)) {
57 return NULL;
58 }
59
José Fonseca1a24faa2014-05-23 11:16:41 +010060 strcat(szDll, "\\opengl32.dll");
José Fonseca1cfd89b2011-12-01 21:09:57 +000061
José Fonseca632a78d2012-04-19 07:18:59 +010062 _libGlHandle = LoadLibraryA(szDll);
63 if (!_libGlHandle) {
José Fonseca1cfd89b2011-12-01 21:09:57 +000064 os::log("apitrace: error: couldn't load %s\n", szDll);
65 return NULL;
66 }
67 }
68
José Fonseca632a78d2012-04-19 07:18:59 +010069 return (void *)GetProcAddress(_libGlHandle, procName);
José Fonseca1cfd89b2011-12-01 21:09:57 +000070}
71
72
73void *
José Fonseca632a78d2012-04-19 07:18:59 +010074_getPrivateProcAddress(const char *procName) {
75 return (void *)_wglGetProcAddress(procName);
José Fonseca1cfd89b2011-12-01 21:09:57 +000076}
77
78
79#elif defined(__APPLE__)
80
81
82/*
83 * Path to the true OpenGL framework
84 */
85static const char *libgl_filename = "/System/Library/Frameworks/OpenGL.framework/OpenGL";
86
87
88/*
89 * Lookup a libGL symbol
90 */
José Fonseca632a78d2012-04-19 07:18:59 +010091void * _libgl_sym(const char *symbol)
José Fonseca1cfd89b2011-12-01 21:09:57 +000092{
93 void *result;
94
José Fonseca632a78d2012-04-19 07:18:59 +010095 if (!_libGlHandle) {
José Fonseca1cfd89b2011-12-01 21:09:57 +000096 /*
97 * Unfortunately we can't just dlopen the true dynamic library because
98 * DYLD_LIBRARY_PATH/DYLD_FRAMEWORK_PATH take precedence, even for
99 * absolute paths. So we create a temporary symlink, and dlopen that
100 * instead.
101 */
102
103 char temp_filename[] = "/tmp/tmp.XXXXXX";
104
105 if (mktemp(temp_filename) != NULL) {
106 if (symlink(libgl_filename, temp_filename) == 0) {
José Fonseca632a78d2012-04-19 07:18:59 +0100107 _libGlHandle = dlopen(temp_filename, RTLD_LOCAL | RTLD_NOW | RTLD_FIRST);
José Fonseca1cfd89b2011-12-01 21:09:57 +0000108 remove(temp_filename);
109 }
110 }
111
José Fonseca632a78d2012-04-19 07:18:59 +0100112 if (!_libGlHandle) {
José Fonseca1cfd89b2011-12-01 21:09:57 +0000113 os::log("apitrace: error: couldn't load %s\n", libgl_filename);
114 os::abort();
115 return NULL;
116 }
117 }
118
José Fonseca632a78d2012-04-19 07:18:59 +0100119 result = dlsym(_libGlHandle, symbol);
José Fonseca1cfd89b2011-12-01 21:09:57 +0000120
José Fonseca39879632012-04-14 22:26:09 +0100121#if 0
122 if (result && result == dlsym(RTLD_SELF, symbol)) {
José Fonseca1cfd89b2011-12-01 21:09:57 +0000123 os::log("apitrace: error: symbol lookup recursion\n");
124 os::abort();
125 return NULL;
126 }
José Fonseca39879632012-04-14 22:26:09 +0100127#endif
José Fonseca1cfd89b2011-12-01 21:09:57 +0000128
129 return result;
130}
131
132
133void *
José Fonseca632a78d2012-04-19 07:18:59 +0100134_getPublicProcAddress(const char *procName)
José Fonseca1cfd89b2011-12-01 21:09:57 +0000135{
José Fonseca632a78d2012-04-19 07:18:59 +0100136 return _libgl_sym(procName);
José Fonseca1cfd89b2011-12-01 21:09:57 +0000137}
138
139void *
José Fonseca632a78d2012-04-19 07:18:59 +0100140_getPrivateProcAddress(const char *procName)
José Fonseca1cfd89b2011-12-01 21:09:57 +0000141{
José Fonseca632a78d2012-04-19 07:18:59 +0100142 return _libgl_sym(procName);
José Fonseca1cfd89b2011-12-01 21:09:57 +0000143}
144
145
146#else
147
148
José Fonseca7700f742013-06-15 11:31:53 +0100149static inline void
150logSymbol(const char *name, void *ptr) {
151 if (0) {
152 if (ptr) {
153 Dl_info info;
154 if (ptr && dladdr(ptr, &info)) {
155 os::log("apitrace: %s -> \"%s\"\n", name, info.dli_fname);
156 }
157 } else {
158 os::log("apitrace: %s -> NULL\n", name);
159 }
160 }
161}
162
163
José Fonseca1cfd89b2011-12-01 21:09:57 +0000164/*
José Fonseca1cfd89b2011-12-01 21:09:57 +0000165 * Lookup a libGL symbol
166 */
José Fonseca632a78d2012-04-19 07:18:59 +0100167void * _libgl_sym(const char *symbol)
José Fonseca1cfd89b2011-12-01 21:09:57 +0000168{
169 void *result;
170
José Fonseca632a78d2012-04-19 07:18:59 +0100171 if (!_libGlHandle) {
José Fonseca1cfd89b2011-12-01 21:09:57 +0000172 /*
173 * The app doesn't directly link against libGL.so, nor does it directly
174 * dlopen it. So we have to load it ourselves.
175 */
176
177 const char * libgl_filename = getenv("TRACE_LIBGL");
178
179 if (!libgl_filename) {
180 /*
181 * Try to use whatever libGL.so the library is linked against.
182 */
183
184 result = dlsym(RTLD_NEXT, symbol);
185 if (result) {
José Fonseca632a78d2012-04-19 07:18:59 +0100186 _libGlHandle = RTLD_NEXT;
José Fonseca1cfd89b2011-12-01 21:09:57 +0000187 return result;
188 }
189
190 libgl_filename = "libGL.so.1";
191 }
192
193 /*
194 * It would have been preferable to use RTLD_LOCAL to ensure that the
195 * application can never access libGL.so symbols directly, but this
196 * won't work, given libGL.so often loads a driver specific SO and
197 * exposes symbols to it.
198 */
199
José Fonseca632a78d2012-04-19 07:18:59 +0100200 _libGlHandle = _dlopen(libgl_filename, RTLD_GLOBAL | RTLD_LAZY);
201 if (!_libGlHandle) {
José Fonseca1cfd89b2011-12-01 21:09:57 +0000202 os::log("apitrace: error: couldn't find libGL.so\n");
203 return NULL;
204 }
205 }
206
José Fonseca0e725472014-05-23 23:24:13 +0100207 result = dlsym(_libGlHandle, symbol);
José Fonseca7700f742013-06-15 11:31:53 +0100208
209 logSymbol(symbol, result);
210
211 return result;
José Fonseca1cfd89b2011-12-01 21:09:57 +0000212}
213
214
215void *
José Fonseca632a78d2012-04-19 07:18:59 +0100216_getPublicProcAddress(const char *procName)
José Fonseca1cfd89b2011-12-01 21:09:57 +0000217{
José Fonseca632a78d2012-04-19 07:18:59 +0100218 return _libgl_sym(procName);
José Fonseca1cfd89b2011-12-01 21:09:57 +0000219}
220
221void *
José Fonseca632a78d2012-04-19 07:18:59 +0100222_getPrivateProcAddress(const char *procName)
José Fonseca1cfd89b2011-12-01 21:09:57 +0000223{
José Fonseca632a78d2012-04-19 07:18:59 +0100224 return (void *)_glXGetProcAddressARB((const GLubyte *)procName);
José Fonseca1cfd89b2011-12-01 21:09:57 +0000225}
226
227
228#endif
229