52
52
#else
53
53
#include <dlfcn.h>
54
54
#include <stdlib.h>
55
- #define WINAPI
56
55
#endif
57
56
#define NO_SHORTCUTS
58
57
#include "gl_funcs.h"
59
58
60
59
#if WINDOWS
61
60
#define GetOpenGLModuleHandle (flags ) ktxFindOpenGL()
62
- #define LoadProcAddr GetProcAddress
63
- HMODULE ktxOpenGLModuleHandle ;
61
+ static HMODULE ktxOpenGLModuleHandle ;
62
+ static PFNGLGETPROCADDRESS pfnWglGetProcAddress ;
63
+
64
+ PFNVOIDFUNCTION
65
+ defaultGLGetProcAddress (const char * proc )
66
+ {
67
+ PFNVOIDFUNCTION pfnGLProc = NULL ;
68
+
69
+ if (pfnWglGetProcAddress )
70
+ pfnGLProc = pfnWglGetProcAddress (proc );
71
+ if (!pfnGLProc ) {
72
+ pfnGLProc = (PFNVOIDFUNCTION )GetProcAddress (ktxOpenGLModuleHandle ,
73
+ proc );
74
+ }
75
+ return pfnGLProc ;
76
+ }
64
77
#elif MACOS || UNIX || IOS
65
78
// Using NULL returns a handle that can be used to search the process that
66
79
// loaded us and any other libraries it has loaded. That's all we need to
67
80
// search as the app is responsible for creating the GL context so it must
68
81
// be there.
69
82
#define GetOpenGLModuleHandle (flags ) dlopen(NULL, flags)
70
- #define LoadProcAddr dlsym
71
- #define LIBRARY_NAME NULL
72
- void * ktxOpenGLModuleHandle ;
83
+ static void * ktxOpenGLModuleHandle ;
84
+
85
+ PFNVOIDFUNCTION
86
+ defaultGLGetProcAddress (const char * proc )
87
+ {
88
+ return dlsym (ktxOpenGLModuleHandle , proc );
89
+ }
73
90
#elif WEB
74
91
extern void * emscripten_GetProcAddress (const char * name_ );
75
92
#define GetOpenGLModuleHandle (flag ) (void*)0x0000ffff // Value doesn't matter.
76
- #define LoadProcAddr (lib , proc ) emscripten_GetProcAddress(proc)
77
- #define LIBRARY_NAME "unused"
78
93
void * ktxOpenGLModuleHandle ;
94
+
95
+ #define defaultGLGetProcAddress ((PFNGLGETPROCADDRESS)emscripten_GetProcAddress)
79
96
#else
80
97
#error "Don\'t know how to load symbols on this OS."
81
98
#endif
82
99
83
- typedef void (WINAPI * PFNVOIDFUNCTION )(void );
84
- typedef PFNVOIDFUNCTION * (WINAPI * PFNWGLGETPROCADDRESS ) (const char * proc );
85
- static PFNWGLGETPROCADDRESS wglGetProcAddressPtr ;
100
+ static bool openGLLoaded = false;
86
101
static const char * noloadmsg = "Could not load OpenGL command: %s!\n" ;
87
102
88
103
/* Define pointers for functions libktx is using. */
89
104
struct glFuncPtrs gl ;
90
105
91
- #if defined(__GNUC__ )
92
- // This strange casting is because dlsym returns a void* thus is not
93
- // compatible with ISO C which forbids conversion of object pointers
94
- // to function pointers. The cast masks the conversion from the
95
- // compiler thus no warning even though -pedantic is set. Since the
96
- // platform supports dlsym, conversion to function pointers must
97
- // work, despite the mandated ISO C warning.
98
106
#define GL_FUNCTION (type , func , required ) \
99
- if ( wglGetProcAddressPtr ) \
100
- *(void **)(&gl.func) = wglGetProcAddressPtr(#func); \
101
- if ( !gl.func ) \
102
- *(void **)(&gl.func) = LoadProcAddr(ktxOpenGLModuleHandle, #func); \
103
- if ( !gl.func && required ) { \
104
- fprintf(stderr, noloadmsg, #func); \
105
- return KTX_NOT_FOUND; \
106
- }
107
- #else
108
- #define GL_FUNCTION (type , func , required ) \
109
- if ( wglGetProcAddressPtr ) \
110
- gl.func = (type)wglGetProcAddressPtr(#func); \
111
- if ( !gl.func) \
112
- gl.func = (type)LoadProcAddr(ktxOpenGLModuleHandle, #func); \
107
+ gl.func = (type)pfnGLGetProcAddress(#func); \
113
108
if ( !gl.func && required) { \
114
109
fprintf(stderr, noloadmsg, #func); \
115
110
return KTX_NOT_FOUND; \
116
111
}
117
- #endif
118
112
119
113
#if WINDOWS
120
114
static HMODULE
@@ -130,7 +124,7 @@ ktxFindOpenGL() {
130
124
& module
131
125
);
132
126
if (found ) {
133
- if (LoadProcAddr (module , "glGetError" ) != NULL )
127
+ if (GetProcAddress (module , "glGetError" ) != NULL )
134
128
return module ;
135
129
}
136
130
// Not statically linked. See what dll the process has loaded.
@@ -154,22 +148,23 @@ ktxFindOpenGL() {
154
148
);
155
149
if (found ) {
156
150
// Need wglGetProcAddr for non-OpenGL-2 functions.
157
- wglGetProcAddressPtr =
158
- (PFNWGLGETPROCADDRESS ) LoadProcAddr (module ,
159
- "wglGetProcAddress" );
160
- if (wglGetProcAddressPtr != NULL )
151
+ pfnWglGetProcAddress =
152
+ (PFNGLGETPROCADDRESS ) GetProcAddress (module ,
153
+ "wglGetProcAddress" );
154
+ if (pfnWglGetProcAddress != NULL )
161
155
return module ;
162
156
}
163
- return module ; // Keep the compiler happy!
157
+ return 0 ;
164
158
}
165
159
#endif
166
160
167
161
ktx_error_code_e
168
162
ktxLoadOpenGLLibrary (void )
169
163
{
170
- if (ktxOpenGLModuleHandle )
164
+ if (openGLLoaded )
171
165
return KTX_SUCCESS ;
172
166
167
+ // Look for OpenGL module and set up default GetProcAddress.
173
168
ktxOpenGLModuleHandle = GetOpenGLModuleHandle (RTLD_LAZY );
174
169
if (ktxOpenGLModuleHandle == NULL ) {
175
170
fprintf (stderr , "OpenGL lib not linked or loaded by application.\n" );
@@ -184,9 +179,48 @@ ktxLoadOpenGLLibrary(void)
184
179
return KTX_LIBRARY_NOT_LINKED ; // So release version doesn't crash.
185
180
#endif
186
181
}
182
+ return KTX_SUCCESS ;
183
+ }
184
+
185
+ /**
186
+ * @~English
187
+ * @brief Load pointers for the GL functions used by ktxTexture_GLUpload.
188
+ *
189
+ * Should be called by an application before its first call to
190
+ * ktxTexture\_GLUpload, passing a pointer to the GLGetProcAddress function
191
+ * provided by whatever OpenGL framework it is using. For backward
192
+ * compatibility, ktxTexture\_GLUpload calls this with a NULL pointer causing an
193
+ * attempt to load the pointers from the program module using
194
+ * @c dlsym (GNU/Linux, macOS), @c wglGetProcAddr and @c GetProcAddr (Windows)
195
+ * or @c emscripten_GetProcAddress (Web). This works with the vast majority of
196
+ * OpenGL implementations but issues have been seen on Fedora systems
197
+ * particularly with NVIDIA hardware. For full robustness, applications should
198
+ * call this function.
199
+ *
200
+ * @param [in] pfnGLGetProcAddress pointer to function for retrieving pointers
201
+ * to GL functions. If NULL, retrieval is
202
+ * attempted using system dependent generic
203
+ * functions.
204
+ */
205
+ KTX_API ktx_error_code_e KTX_APIENTRY
206
+ ktxLoadOpenGL (PFNGLGETPROCADDRESS pfnGLGetProcAddress )
207
+ {
208
+ if (openGLLoaded )
209
+ return KTX_SUCCESS ;
210
+
211
+ if (!pfnGLGetProcAddress ) {
212
+ ktx_error_code_e result = ktxLoadOpenGLLibrary ();
213
+ if (result != KTX_SUCCESS ) {
214
+ return result ;
215
+ }
216
+ pfnGLGetProcAddress = defaultGLGetProcAddress ;
217
+ }
218
+
219
+ // Load function pointers
187
220
188
221
#include "gl_funclist.inl"
189
222
223
+ openGLLoaded = true;
190
224
return KTX_SUCCESS ;
191
225
}
192
226
0 commit comments