1 #include "baselayer.h"
2 #include "compat.h"
3 #include "glad/glad.h"
4 #include "glbuild.h"
5 
6 #if defined USE_OPENGL
7 
8 #ifdef RENDERTYPESDL
9 # include "sdlayer.h"
10 #endif
11 
12 GLenum BuildGLError;
BuildGLErrorCheck(void)13 void BuildGLErrorCheck(void)
14 {
15     volatile GLenum err;
16     while (err = glGetError(), err != GL_NO_ERROR)
17     {
18         BuildGLError = err; // set a watchpoint/breakpoint here
19     }
20 }
21 
22 #if defined DYNAMIC_GL
23 
24 #if !defined RENDERTYPESDL && defined _WIN32
25 bwglCreateContextProcPtr bwglCreateContext;
26 bwglDeleteContextProcPtr bwglDeleteContext;
27 bwglGetProcAddressProcPtr bwglGetProcAddress;
28 bwglMakeCurrentProcPtr bwglMakeCurrent;
29 
30 bwglChoosePixelFormatProcPtr bwglChoosePixelFormat;
31 bwglDescribePixelFormatProcPtr bwglDescribePixelFormat;
32 bwglGetPixelFormatProcPtr bwglGetPixelFormat;
33 bwglSetPixelFormatProcPtr bwglSetPixelFormat;
34 #endif
35 
36 #endif
37 
38 #if defined DYNAMIC_GLU
39 
40 // GLU
41 bgluTessBeginContourProcPtr bgluTessBeginContour;
42 bgluTessBeginPolygonProcPtr bgluTessBeginPolygon;
43 bgluTessCallbackProcPtr bgluTessCallback;
44 bgluTessEndContourProcPtr bgluTessEndContour;
45 bgluTessEndPolygonProcPtr bgluTessEndPolygon;
46 bgluTessNormalProcPtr bgluTessNormal;
47 bgluTessPropertyProcPtr bgluTessProperty;
48 bgluTessVertexProcPtr bgluTessVertex;
49 bgluNewTessProcPtr bgluNewTess;
50 bgluDeleteTessProcPtr bgluDeleteTess;
51 
52 bgluPerspectiveProcPtr bgluPerspective;
53 
54 bgluErrorStringProcPtr bgluErrorString;
55 
56 bgluProjectProcPtr bgluProject;
57 bgluUnProjectProcPtr bgluUnProject;
58 
59 bgluLookAtProcPtr bgluLookAt;
60 
61 #endif
62 
63 #if defined DYNAMIC_GL || defined DYNAMIC_GLEXT || defined DYNAMIC_GLU
64 # if !defined _WIN32
65 #  include <dlfcn.h>
66 # endif
67 #endif
68 
69 #if defined DYNAMIC_GL || defined DYNAMIC_GLEXT
70 
71 #if !defined RENDERTYPESDL && defined _WIN32
72 static HMODULE hGLDLL;
73 
74 char *gldriver = NULL;
75 
getproc_(const char * s,int32_t * err,int32_t fatal,int32_t extension)76 static void *getproc_(const char *s, int32_t *err, int32_t fatal, int32_t extension)
77 {
78     void *t;
79 #if defined RENDERTYPESDL
80     UNREFERENCED_PARAMETER(extension);
81     t = (void *)SDL_GL_GetProcAddress(s);
82 #elif defined _WIN32
83     if (extension) t = (void *)bwglGetProcAddress(s);
84     else t = (void *)GetProcAddress(hGLDLL,s);
85 #else
86 #error Need a dynamic loader for this platform...
87 #endif
88     if (!t && fatal)
89     {
90         initprintf("Failed to find %s in %s\n", s, gldriver);
91         *err = 1;
92     }
93     return t;
94 }
95 #define GETPROC(s)        getproc_(s,&err,1,0)
96 
loadwgl(const char * driver)97 int32_t loadwgl(const char *driver)
98 {
99     int32_t err=0;
100 
101     if (hGLDLL) return 0;
102 
103     if (!driver)
104     {
105         driver = "opengl32.dll";
106     }
107 
108     hGLDLL = LoadLibrary(driver);
109     if (!hGLDLL)
110     {
111         initprintf("Failed loading \"%s\"\n", driver);
112         return -1;
113     }
114 
115     gldriver = Xstrdup(driver);
116 
117     bwglCreateContext = (bwglCreateContextProcPtr) GETPROC("wglCreateContext");
118     bwglDeleteContext = (bwglDeleteContextProcPtr) GETPROC("wglDeleteContext");
119     bwglGetProcAddress = (bwglGetProcAddressProcPtr) GETPROC("wglGetProcAddress");
120     bwglMakeCurrent = (bwglMakeCurrentProcPtr) GETPROC("wglMakeCurrent");
121 
122     bwglChoosePixelFormat = (bwglChoosePixelFormatProcPtr) GETPROC("wglChoosePixelFormat");
123     bwglDescribePixelFormat = (bwglDescribePixelFormatProcPtr) GETPROC("wglDescribePixelFormat");
124     bwglGetPixelFormat = (bwglGetPixelFormatProcPtr) GETPROC("wglGetPixelFormat");
125     bwglSetPixelFormat = (bwglSetPixelFormatProcPtr) GETPROC("wglSetPixelFormat");
126 
127     if (err) unloadwgl();
128     return err;
129 }
unloadwgl(void)130 int32_t unloadwgl(void)
131 {
132     if (!hGLDLL) return 0;
133 
134     DO_FREE_AND_NULL(gldriver);
135 
136     FreeLibrary(hGLDLL);
137     hGLDLL = NULL;
138 
139     bwglCreateContext = (bwglCreateContextProcPtr) NULL;
140     bwglDeleteContext = (bwglDeleteContextProcPtr) NULL;
141     bwglGetProcAddress = (bwglGetProcAddressProcPtr) NULL;
142     bwglMakeCurrent = (bwglMakeCurrentProcPtr) NULL;
143 
144     bwglChoosePixelFormat = (bwglChoosePixelFormatProcPtr) NULL;
145     bwglDescribePixelFormat = (bwglDescribePixelFormatProcPtr) NULL;
146     bwglGetPixelFormat = (bwglGetPixelFormatProcPtr) NULL;
147     bwglSetPixelFormat = (bwglSetPixelFormatProcPtr) NULL;
148     return 0;
149 }
150 #endif
151 
152 #endif
153 
154 #if defined DYNAMIC_GLU
155 #if defined _WIN32
156 static HMODULE hGLUDLL;
157 #else
158 static void *gluhandle = NULL;
159 #endif
160 
161 char *glulibrary = NULL;
162 
glugetproc_(const char * s,int32_t * err,int32_t fatal)163 static void *glugetproc_(const char *s, int32_t *err, int32_t fatal)
164 {
165     void *t;
166 #if defined _WIN32
167     t = (void *)GetProcAddress(hGLUDLL,s);
168 #else
169     t = (void *)dlsym(gluhandle,s);
170 #endif
171     if (!t && fatal)
172     {
173         initprintf("Failed to find %s in %s\n", s, glulibrary);
174         *err = 1;
175     }
176     return t;
177 }
178 #define GLUGETPROC(s)        glugetproc_(s,&err,1)
179 #define GLUGETPROCSOFT(s)    glugetproc_(s,&err,0)
180 #endif
181 
loadglulibrary(const char * driver)182 int32_t loadglulibrary(const char *driver)
183 {
184 #if defined DYNAMIC_GLU
185     int32_t err=0;
186 
187 #if defined _WIN32
188     if (hGLUDLL) return 0;
189 #endif
190 
191     if (!driver)
192     {
193 #ifdef _WIN32
194         driver = "glu32.dll";
195 #elif defined __APPLE__
196         driver = "/System/Library/Frameworks/OpenGL.framework/OpenGL"; // FIXME: like I know anything about Apple.  Hah.
197 #elif defined __OpenBSD__
198         driver = "libGLU.so";
199 #else
200         driver = "libGLU.so.1";
201 #endif
202     }
203 
204 #if defined _WIN32
205     hGLUDLL = LoadLibrary(driver);
206     if (!hGLUDLL)
207 #else
208     gluhandle = dlopen(driver, RTLD_NOW|RTLD_GLOBAL);
209     if (!gluhandle)
210 #endif
211     {
212         initprintf("Failed loading \"%s\"\n",driver);
213         return -1;
214     }
215 
216     glulibrary = Xstrdup(driver);
217 
218     bgluTessBeginContour = (bgluTessBeginContourProcPtr) GLUGETPROC("gluTessBeginContour");
219     bgluTessBeginPolygon = (bgluTessBeginPolygonProcPtr) GLUGETPROC("gluTessBeginPolygon");
220     bgluTessCallback = (bgluTessCallbackProcPtr) GLUGETPROC("gluTessCallback");
221     bgluTessEndContour = (bgluTessEndContourProcPtr) GLUGETPROC("gluTessEndContour");
222     bgluTessEndPolygon = (bgluTessEndPolygonProcPtr) GLUGETPROC("gluTessEndPolygon");
223     bgluTessNormal = (bgluTessNormalProcPtr) GLUGETPROC("gluTessNormal");
224     bgluTessProperty = (bgluTessPropertyProcPtr) GLUGETPROC("gluTessProperty");
225     bgluTessVertex = (bgluTessVertexProcPtr) GLUGETPROC("gluTessVertex");
226     bgluNewTess = (bgluNewTessProcPtr) GLUGETPROC("gluNewTess");
227     bgluDeleteTess = (bgluDeleteTessProcPtr) GLUGETPROC("gluDeleteTess");
228 
229     bgluPerspective = (bgluPerspectiveProcPtr) GLUGETPROC("gluPerspective");
230 
231     bgluErrorString = (bgluErrorStringProcPtr) GLUGETPROC("gluErrorString");
232 
233     bgluProject = (bgluProjectProcPtr) GLUGETPROC("gluProject");
234     bgluUnProject = (bgluUnProjectProcPtr) GLUGETPROC("gluUnProject");
235 
236     bgluLookAt = (bgluLookAtProcPtr) GLUGETPROC("gluLookAt");
237 
238     if (err) unloadglulibrary();
239     return err;
240 #else
241     UNREFERENCED_PARAMETER(driver);
242     return 0;
243 #endif
244 }
245 
unloadglulibrary(void)246 int32_t unloadglulibrary(void)
247 {
248 #if defined DYNAMIC_GLU
249 #if defined _WIN32
250     if (!hGLUDLL) return 0;
251 #endif
252 
253     DO_FREE_AND_NULL(glulibrary);
254 
255 #if defined _WIN32
256     FreeLibrary(hGLUDLL);
257     hGLUDLL = NULL;
258 #else
259     if (gluhandle) dlclose(gluhandle);
260     gluhandle = NULL;
261 #endif
262 
263     bgluTessBeginContour = (bgluTessBeginContourProcPtr) NULL;
264     bgluTessBeginPolygon = (bgluTessBeginPolygonProcPtr) NULL;
265     bgluTessCallback = (bgluTessCallbackProcPtr) NULL;
266     bgluTessEndContour = (bgluTessEndContourProcPtr) NULL;
267     bgluTessEndPolygon = (bgluTessEndPolygonProcPtr) NULL;
268     bgluTessNormal = (bgluTessNormalProcPtr) NULL;
269     bgluTessProperty = (bgluTessPropertyProcPtr) NULL;
270     bgluTessVertex = (bgluTessVertexProcPtr) NULL;
271     bgluNewTess = (bgluNewTessProcPtr) NULL;
272     bgluDeleteTess = (bgluDeleteTessProcPtr) NULL;
273 
274     bgluPerspective = (bgluPerspectiveProcPtr) NULL;
275 
276     bgluErrorString = (bgluErrorStringProcPtr) NULL;
277 
278     bgluProject = (bgluProjectProcPtr) NULL;
279     bgluUnProject = (bgluUnProjectProcPtr) NULL;
280 
281     bgluLookAt = (bgluLookAtProcPtr)NULL;
282 #endif
283 
284     return 0;
285 }
286 
287 
288 //////// glGenTextures/glDeleteTextures debugging ////////
289 # if defined DEBUGGINGAIDS && defined DEBUG_TEXTURE_NAMES
290 static uint8_t *texnameused;  // bitmap
291 static uint32_t *texnamefromwhere;  // hash of __FILE__
292 static uint32_t texnameallocsize;
293 
294 // djb3 algorithm
texdbg_getcode(const char * s)295 static inline uint32_t texdbg_getcode(const char *s)
296 {
297     uint32_t h = 5381;
298     int32_t ch;
299 
300     while ((ch = *s++) != '\0')
301         h = ((h << 5) + h) ^ ch;
302 
303     return h;
304 }
305 
texdbg_realloc(uint32_t maxtexname)306 static void texdbg_realloc(uint32_t maxtexname)
307 {
308     uint32_t newsize = texnameallocsize ? texnameallocsize : 64;
309 
310     if (maxtexname < texnameallocsize)
311         return;
312 
313     while (maxtexname >= newsize)
314         newsize <<= 1;
315 //    initprintf("texdebug: new size %u\n", newsize);
316 
317     texnameused = Xrealloc(texnameused, newsize>>3);
318     texnamefromwhere = Xrealloc(texnamefromwhere, newsize*sizeof(uint32_t));
319 
320     Bmemset(texnameused + (texnameallocsize>>3), 0, (newsize-texnameallocsize)>>3);
321     Bmemset(texnamefromwhere + texnameallocsize, 0, (newsize-texnameallocsize)*sizeof(uint32_t));
322 
323     texnameallocsize = newsize;
324 }
325 
326 #undef bglGenTextures
texdbg_bglGenTextures(GLsizei n,GLuint * textures,const char * srcfn)327 void texdbg_bglGenTextures(GLsizei n, GLuint *textures, const char *srcfn)
328 {
329     int32_t i;
330     uint32_t hash = srcfn ? texdbg_getcode(srcfn) : 0;
331 
332     for (i=0; i<n; i++)
333         if (textures[i] < texnameallocsize && (texnameused[textures[i]>>3]&pow2char[textures[i]&7]))
334             initprintf("texdebug %x Gen: overwriting used tex name %u from %x\n", hash, textures[i], texnamefromwhere[textures[i]]);
335 
336     bglGenTextures(n, textures);
337 
338     {
339         GLuint maxtexname = 0;
340 
341         for (i=0; i<n; i++)
342             maxtexname = max(maxtexname, textures[i]);
343 
344         texdbg_realloc(maxtexname);
345 
346         for (i=0; i<n; i++)
347         {
348             texnameused[textures[i]>>3] |= pow2char[textures[i]&7];
349             texnamefromwhere[textures[i]] = hash;
350         }
351     }
352 }
353 
354 #undef bglDeleteTextures
texdbg_bglDeleteTextures(GLsizei n,const GLuint * textures,const char * srcfn)355 void texdbg_bglDeleteTextures(GLsizei n, const GLuint *textures, const char *srcfn)
356 {
357     int32_t i;
358     uint32_t hash = srcfn ? texdbg_getcode(srcfn) : 0;
359 
360     for (i=0; i<n; i++)
361         if (textures[i] < texnameallocsize)
362         {
363             if ((texnameused[textures[i]>>3]&pow2char[textures[i]&7])==0)
364                 initprintf("texdebug %x Del: deleting unused tex name %u\n", hash, textures[i]);
365             else if ((texnameused[textures[i]>>3]&pow2char[textures[i]&7]) &&
366                          texnamefromwhere[textures[i]] != hash)
367                 initprintf("texdebug %x Del: deleting foreign tex name %u from %x\n", hash,
368                            textures[i], texnamefromwhere[textures[i]]);
369         }
370 
371     bglDeleteTextures(n, textures);
372 
373     if (texnameallocsize)
374         for (i=0; i<n; i++)
375         {
376             texnameused[textures[i]>>3] &= ~pow2char[textures[i]&7];
377             texnamefromwhere[textures[i]] = 0;
378         }
379 }
380 # endif  // defined DEBUGGINGAIDS
381 
382 #endif
383