1 #include "TREGLExtensions.h"
2 #include <TCFoundation/mystring.h>
3 #include <TCFoundation/TCUserDefaults.h>
4 // !!!WARNING!!!
5 // The following is kind of bad form, but I'm going to do it anyway.  I'm
6 // including a header file from a library that is dependent on this library.
7 // This works fine, because I'm not using any classes in the other library,
8 // just #defines, but it is still very strange behavior.
9 #include <LDLib/LDUserDefaultsKeys.h>
10 #include <stdio.h>
11 
12 #ifdef WIN32
13 #if defined(_MSC_VER) && _MSC_VER >= 1400 && defined(_DEBUG)
14 #define new DEBUG_CLIENTBLOCK
15 #endif // _DEBUG
16 #endif // WIN32
17 
18 namespace TREGLExtensionsNS
19 {
20 #ifndef GL_GLEXT_PROTOTYPES
21 	// GL_NV_vertex_array_range
22 	PFNGLVERTEXARRAYRANGENVPROC glVertexArrayRangeNV = NULL;
23 	// GL_EXT_multi_draw_arrays
24 	PFNGLMULTIDRAWELEMENTSEXTPROC glMultiDrawElementsEXT = NULL;
25 	// GL_ARB_vertex_buffer_object
26 	PFNGLBINDBUFFERARBPROC glBindBufferARB = NULL;
27 	PFNGLDELETEBUFFERSARBPROC glDeleteBuffersARB = NULL;
28 	PFNGLGENBUFFERSARBPROC glGenBuffersARB = NULL;
29 	PFNGLISBUFFERARBPROC glIsBufferARB = NULL;
30 	PFNGLBUFFERDATAARBPROC glBufferDataARB = NULL;
31 	PFNGLBUFFERSUBDATAARBPROC glBufferSubDataARB = NULL;
32 	PFNGLGETBUFFERSUBDATAARBPROC glGetBufferSubDataARB = NULL;
33 	PFNGLMAPBUFFERARBPROC glMapBufferARB = NULL;
34 	PFNGLUNMAPBUFFERARBPROC glUnmapBufferARB = NULL;
35 	PFNGLGETBUFFERPARAMETERIVARBPROC glGetBufferParameterivARB = NULL;
36 	PFNGLGETBUFFERPOINTERVARBPROC glGetBufferPointervARB = NULL;
37 	// GL_ARB_occlusion_query
38 	PFNGLGENQUERIESARBPROC glGenQueriesARB = NULL;
39 	PFNGLDELETEQUERIESARBPROC glDeleteQueriesARB = NULL;
40 	PFNGLISQUERYARBPROC glIsQueryARB = NULL;
41 	PFNGLBEGINQUERYARBPROC glBeginQueryARB = NULL;
42 	PFNGLENDQUERYARBPROC glEndQueryARB = NULL;
43 	PFNGLGETQUERYIVARBPROC glGetQueryivARB = NULL;
44 	PFNGLGETQUERYOBJECTIVARBPROC glGetQueryObjectivARB = NULL;
45 	PFNGLGETQUERYOBJECTUIVARBPROC glGetQueryObjectuivARB = NULL;
46 	// GL_EXT_framebuffer_object
47 	PFNGLISRENDERBUFFEREXTPROC glIsRenderbufferEXT = NULL;
48 	PFNGLBINDRENDERBUFFEREXTPROC glBindRenderbufferEXT = NULL;
49 	PFNGLDELETERENDERBUFFERSEXTPROC glDeleteRenderbuffersEXT = NULL;
50 	PFNGLGENRENDERBUFFERSEXTPROC glGenRenderbuffersEXT = NULL;
51 	PFNGLRENDERBUFFERSTORAGEEXTPROC glRenderbufferStorageEXT = NULL;
52 	PFNGLGETRENDERBUFFERPARAMETERIVEXTPROC
53 		glGetRenderbufferParameterivEXT = NULL;
54 	PFNGLISFRAMEBUFFEREXTPROC glIsFramebufferEXT = NULL;
55 	PFNGLBINDFRAMEBUFFEREXTPROC glBindFramebufferEXT = NULL;
56 	PFNGLDELETEFRAMEBUFFERSEXTPROC glDeleteFramebuffersEXT = NULL;
57 	PFNGLGENFRAMEBUFFERSEXTPROC glGenFramebuffersEXT = NULL;
58 	PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC glCheckFramebufferStatusEXT = NULL;
59 	PFNGLFRAMEBUFFERTEXTURE1DEXTPROC glFramebufferTexture1DEXT = NULL;
60 	PFNGLFRAMEBUFFERTEXTURE2DEXTPROC glFramebufferTexture2DEXT = NULL;
61 	PFNGLFRAMEBUFFERTEXTURE3DEXTPROC glFramebufferTexture3DEXT = NULL;
62 	PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC glFramebufferRenderbufferEXT = NULL;
63 	PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC
64 		glGetFramebufferAttachmentParameterivEXT = NULL;
65 	PFNGLGENERATEMIPMAPEXTPROC glGenerateMipmapEXT = NULL;
66 #endif // GL_GLEXT_PROTOTYPES
67 
68 #ifdef WIN32
69 	// WGL_EXT_pixel_format
70 	PFNWGLGETPIXELFORMATATTRIBIVEXTPROC wglGetPixelFormatAttribivARB = NULL;
71 	PFNWGLGETPIXELFORMATATTRIBFVEXTPROC wglGetPixelFormatAttribfvARB = NULL;
72 	PFNWGLCHOOSEPIXELFORMATEXTPROC wglChoosePixelFormatARB = NULL;
73 	// WGL_ARB_extensions_string
74 	PFNWGLGETEXTENSIONSSTRINGARBPROC wglGetExtensionsStringARB = NULL;
75 	// WGL_ARB_pbuffer
76 	PFNWGLCREATEPBUFFERARBPROC wglCreatePbufferARB = NULL;
77 	PFNWGLGETPBUFFERDCARBPROC wglGetPbufferDCARB = NULL;
78 	PFNWGLRELEASEPBUFFERDCARBPROC wglReleasePbufferDCARB = NULL;
79 	PFNWGLDESTROYPBUFFERARBPROC wglDestroyPbufferARB = NULL;
80 	PFNWGLQUERYPBUFFERARBPROC wglQueryPbufferARB = NULL;
81 #endif // WIN32
82 	// WGL_NV_allocate_memory
83 	PFNWGLALLOCATEMEMORYNVPROC wglAllocateMemoryNV = NULL;
84 	PFNWGLFREEMEMORYNVPROC wglFreeMemoryNV = NULL;
85 }
86 
87 // GL_NV_vertex_array_range
88 PFNGLVERTEXARRAYRANGENVPROC TREGLExtensions::sm_glVertexArrayRangeNV = NULL;
89 // GL_EXT_multi_draw_arrays
90 PFNGLMULTIDRAWELEMENTSEXTPROC TREGLExtensions::sm_glMultiDrawElementsEXT = NULL;
91 // GL_ARB_vertex_buffer_object
92 PFNGLBINDBUFFERARBPROC TREGLExtensions::sm_glBindBufferARB = NULL;
93 PFNGLDELETEBUFFERSARBPROC TREGLExtensions::sm_glDeleteBuffersARB = NULL;
94 PFNGLGENBUFFERSARBPROC TREGLExtensions::sm_glGenBuffersARB = NULL;
95 PFNGLISBUFFERARBPROC TREGLExtensions::sm_glIsBufferARB = NULL;
96 PFNGLBUFFERDATAARBPROC TREGLExtensions::sm_glBufferDataARB = NULL;
97 PFNGLBUFFERSUBDATAARBPROC TREGLExtensions::sm_glBufferSubDataARB = NULL;
98 PFNGLGETBUFFERSUBDATAARBPROC TREGLExtensions::sm_glGetBufferSubDataARB = NULL;
99 PFNGLMAPBUFFERARBPROC TREGLExtensions::sm_glMapBufferARB = NULL;
100 PFNGLUNMAPBUFFERARBPROC TREGLExtensions::sm_glUnmapBufferARB = NULL;
101 PFNGLGETBUFFERPARAMETERIVARBPROC TREGLExtensions::sm_glGetBufferParameterivARB =
102 	NULL;
103 PFNGLGETBUFFERPOINTERVARBPROC TREGLExtensions::sm_glGetBufferPointervARB = NULL;
104 // GL_ARB_occlusion_query
105 PFNGLGENQUERIESARBPROC TREGLExtensions::sm_glGenQueriesARB = NULL;
106 PFNGLDELETEQUERIESARBPROC TREGLExtensions::sm_glDeleteQueriesARB = NULL;
107 PFNGLISQUERYARBPROC TREGLExtensions::sm_glIsQueryARB = NULL;
108 PFNGLBEGINQUERYARBPROC TREGLExtensions::sm_glBeginQueryARB = NULL;
109 PFNGLENDQUERYARBPROC TREGLExtensions::sm_glEndQueryARB = NULL;
110 PFNGLGETQUERYIVARBPROC TREGLExtensions::sm_glGetQueryivARB = NULL;
111 PFNGLGETQUERYOBJECTIVARBPROC TREGLExtensions::sm_glGetQueryObjectivARB = NULL;
112 PFNGLGETQUERYOBJECTUIVARBPROC TREGLExtensions::sm_glGetQueryObjectuivARB = NULL;
113 // GL_EXT_framebuffer_object
114 PFNGLISRENDERBUFFEREXTPROC TREGLExtensions::sm_glIsRenderbufferEXT = NULL;
115 PFNGLBINDRENDERBUFFEREXTPROC TREGLExtensions::sm_glBindRenderbufferEXT = NULL;
116 PFNGLDELETERENDERBUFFERSEXTPROC TREGLExtensions::sm_glDeleteRenderbuffersEXT =
117 	NULL;
118 PFNGLGENRENDERBUFFERSEXTPROC TREGLExtensions::sm_glGenRenderbuffersEXT = NULL;
119 PFNGLRENDERBUFFERSTORAGEEXTPROC TREGLExtensions::sm_glRenderbufferStorageEXT =
120 	NULL;
121 PFNGLGETRENDERBUFFERPARAMETERIVEXTPROC
122 	TREGLExtensions::sm_glGetRenderbufferParameterivEXT = NULL;
123 PFNGLISFRAMEBUFFEREXTPROC TREGLExtensions::sm_glIsFramebufferEXT = NULL;
124 PFNGLBINDFRAMEBUFFEREXTPROC TREGLExtensions::sm_glBindFramebufferEXT = NULL;
125 PFNGLDELETEFRAMEBUFFERSEXTPROC TREGLExtensions::sm_glDeleteFramebuffersEXT =
126 	NULL;
127 PFNGLGENFRAMEBUFFERSEXTPROC TREGLExtensions::sm_glGenFramebuffersEXT = NULL;
128 PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC
129 	TREGLExtensions::sm_glCheckFramebufferStatusEXT = NULL;
130 PFNGLFRAMEBUFFERTEXTURE1DEXTPROC TREGLExtensions::sm_glFramebufferTexture1DEXT =
131 	NULL;
132 PFNGLFRAMEBUFFERTEXTURE2DEXTPROC TREGLExtensions::sm_glFramebufferTexture2DEXT =
133 	NULL;
134 PFNGLFRAMEBUFFERTEXTURE3DEXTPROC TREGLExtensions::sm_glFramebufferTexture3DEXT =
135 	NULL;
136 PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC
137 	TREGLExtensions::sm_glFramebufferRenderbufferEXT = NULL;
138 PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC
139 	TREGLExtensions::sm_glGetFramebufferAttachmentParameterivEXT = NULL;
140 PFNGLGENERATEMIPMAPEXTPROC TREGLExtensions::sm_glGenerateMipmapEXT = NULL;
141 
142 
143 StringSet TREGLExtensions::sm_glExtensions;
144 GLfloat TREGLExtensions::sm_maxAnisoLevel = 1.0f;
145 bool TREGLExtensions::sm_rendererIsMesa = false;
146 bool TREGLExtensions::sm_tempDisable = false;
147 std::string TREGLExtensions::sm_version;
148 int TREGLExtensions::sm_versionMaj = -1;
149 int TREGLExtensions::sm_versionMin = -1;
150 
151 TREGLExtensions::TREGLExtensionsCleanup TREGLExtensions::sm_extensionsCleanup;
152 
153 #ifdef WIN32
154 #define GET_EXTENSION(name) wglGetProcAddress(#name)
155 #else
156 #define GET_EXTENSION(name) (name)
157 #endif
158 
~TREGLExtensionsCleanup(void)159 TREGLExtensions::TREGLExtensionsCleanup::~TREGLExtensionsCleanup(void)
160 {
161 	TREGLExtensions::cleanup();
162 }
163 
disableAll(bool disable)164 void TREGLExtensions::disableAll(bool disable)
165 {
166 	sm_tempDisable = disable;
167 }
168 
cleanup(void)169 void TREGLExtensions::cleanup(void)
170 {
171 	sm_glExtensions.clear();
172 }
173 
initExtensions(StringSet & extensions,const char * extensionsString)174 void TREGLExtensions::initExtensions(
175 	StringSet &extensions,
176 	const char *extensionsString)
177 {
178 	int count;
179 	char **components = componentsSeparatedByString(extensionsString, " ",
180 		count);
181 
182 	for (int i = 0; i < count; i++)
183 	{
184 		extensions.insert(components[i]);
185 	}
186 	deleteStringArray(components, count);
187 }
188 
setup(void)189 void TREGLExtensions::setup(void)
190 {
191 	cleanup();
192 	sm_version = (const char *)glGetString(GL_VERSION);
193 	if (sscanf(sm_version.c_str(), "%d.%d", &sm_versionMaj, &sm_versionMin) !=
194 		2)
195 	{
196 		sm_versionMaj = -1;
197 		sm_versionMin = -1;
198 	}
199 	initExtensions(sm_glExtensions, (const char*)glGetString(GL_EXTENSIONS));
200 	// Note that when we load the function pointers, don't want to pay
201 	// attention to any ignore flags in the registry, so all the checks for
202 	// extensions have the force flag set to true.  Otherwise, if the
203 	// program starts with the ignore flag set, and it later gets cleared,
204 	// the function pointers won't be loaded.
205 	if (haveVARExtension(true))
206 	{
207 #ifdef WIN32
208 		// NOTE: I should really change the __APPLE__ path to do their
209 		// equivalent of wglGetProcAddress.  However, since this extension won't
210 		// work anyway without a bunch of glX stuff that I'm not going to do,
211 		// I'm not going to make that change just for this.
212 		sm_glVertexArrayRangeNV = (PFNGLVERTEXARRAYRANGENVPROC)
213 			GET_EXTENSION(glVertexArrayRangeNV);
214 #endif // WIN32
215 	}
216 	const char *renderer = (const char *)glGetString(GL_RENDERER);
217 	if (stringHasCaseInsensitivePrefix(renderer, "Mesa "))
218 	{
219 		sm_rendererIsMesa = true;
220 	}
221 	if (haveMultiDrawArraysExtension(true))
222 	{
223 		sm_glMultiDrawElementsEXT = (PFNGLMULTIDRAWELEMENTSEXTPROC)
224 			GET_EXTENSION(glMultiDrawElementsEXT);
225 	}
226 	if (haveVBOExtension(true))
227 	{
228 		sm_glBindBufferARB = (PFNGLBINDBUFFERARBPROC)
229 			GET_EXTENSION(glBindBufferARB);
230 		sm_glDeleteBuffersARB = (PFNGLDELETEBUFFERSARBPROC)
231 			GET_EXTENSION(glDeleteBuffersARB);
232 		sm_glGenBuffersARB = (PFNGLGENBUFFERSARBPROC)
233 			GET_EXTENSION(glGenBuffersARB);
234 		sm_glIsBufferARB = (PFNGLISBUFFERARBPROC)
235 			GET_EXTENSION(glIsBufferARB);
236 		sm_glBufferDataARB = (PFNGLBUFFERDATAARBPROC)
237 			GET_EXTENSION(glBufferDataARB);
238 		sm_glBufferSubDataARB = (PFNGLBUFFERSUBDATAARBPROC)
239 			GET_EXTENSION(glBufferSubDataARB);
240 		sm_glGetBufferSubDataARB = (PFNGLGETBUFFERSUBDATAARBPROC)
241 			GET_EXTENSION(glGetBufferSubDataARB);
242 		sm_glMapBufferARB = (PFNGLMAPBUFFERARBPROC)
243 			GET_EXTENSION(glMapBufferARB);
244 		sm_glUnmapBufferARB = (PFNGLUNMAPBUFFERARBPROC)
245 			GET_EXTENSION(glUnmapBufferARB);
246 		sm_glGetBufferParameterivARB = (PFNGLGETBUFFERPARAMETERIVARBPROC)
247 			GET_EXTENSION(glGetBufferParameterivARB);
248 		sm_glGetBufferPointervARB = (PFNGLGETBUFFERPOINTERVARBPROC)
249 			GET_EXTENSION(glGetBufferPointervARB);
250 	}
251 	if (haveOcclusionQueryExtension(true))
252 	{
253 		sm_glGenQueriesARB = (PFNGLGENQUERIESARBPROC)
254 			GET_EXTENSION(glGenQueriesARB);
255 		sm_glDeleteQueriesARB = (PFNGLDELETEQUERIESARBPROC)
256 			GET_EXTENSION(glDeleteQueriesARB);
257 		sm_glIsQueryARB = (PFNGLISQUERYARBPROC)
258 			GET_EXTENSION(glIsQueryARB);
259 		sm_glBeginQueryARB = (PFNGLBEGINQUERYARBPROC)
260 			GET_EXTENSION(glBeginQueryARB);
261 		sm_glEndQueryARB = (PFNGLENDQUERYARBPROC)
262 			GET_EXTENSION(glEndQueryARB);
263 		sm_glGetQueryivARB = (PFNGLGETQUERYIVARBPROC)
264 			GET_EXTENSION(glGetQueryivARB);
265 		sm_glGetQueryObjectivARB = (PFNGLGETQUERYOBJECTIVARBPROC)
266 			GET_EXTENSION(glGetQueryObjectivARB);
267 		sm_glGetQueryObjectuivARB = (PFNGLGETQUERYOBJECTUIVARBPROC)
268 			GET_EXTENSION(glGetQueryObjectuivARB);
269 	}
270 	if (haveAnisoExtension(true))
271 	{
272 		glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &sm_maxAnisoLevel);
273 	}
274 	else
275 	{
276 		sm_maxAnisoLevel = 1.0f;
277 	}
278 	if (haveFramebufferObjectExtension(true))
279 	{
280 		sm_glIsRenderbufferEXT = (PFNGLISRENDERBUFFEREXTPROC)
281 			GET_EXTENSION(glIsRenderbufferEXT);
282 		sm_glBindRenderbufferEXT = (PFNGLBINDRENDERBUFFEREXTPROC)
283 			GET_EXTENSION(glBindRenderbufferEXT);
284 		sm_glDeleteRenderbuffersEXT = (PFNGLDELETERENDERBUFFERSEXTPROC)
285 			GET_EXTENSION(glDeleteRenderbuffersEXT);
286 		sm_glGenRenderbuffersEXT = (PFNGLGENRENDERBUFFERSEXTPROC)
287 			GET_EXTENSION(glGenRenderbuffersEXT);
288 		sm_glRenderbufferStorageEXT = (PFNGLRENDERBUFFERSTORAGEEXTPROC)
289 			GET_EXTENSION(glRenderbufferStorageEXT);
290 		sm_glGetRenderbufferParameterivEXT = (PFNGLGETRENDERBUFFERPARAMETERIVEXTPROC)
291 			GET_EXTENSION(glGetRenderbufferParameterivEXT);
292 		sm_glIsFramebufferEXT = (PFNGLISFRAMEBUFFEREXTPROC)
293 			GET_EXTENSION(glIsFramebufferEXT);
294 		sm_glBindFramebufferEXT = (PFNGLBINDFRAMEBUFFEREXTPROC)
295 			GET_EXTENSION(glBindFramebufferEXT);
296 		sm_glDeleteFramebuffersEXT = (PFNGLDELETEFRAMEBUFFERSEXTPROC)
297 			GET_EXTENSION(glDeleteFramebuffersEXT);
298 		sm_glGenFramebuffersEXT = (PFNGLGENFRAMEBUFFERSEXTPROC)
299 			GET_EXTENSION(glGenFramebuffersEXT);
300 		sm_glCheckFramebufferStatusEXT = (PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC)
301 			GET_EXTENSION(glCheckFramebufferStatusEXT);
302 		sm_glFramebufferTexture1DEXT = (PFNGLFRAMEBUFFERTEXTURE1DEXTPROC)
303 			GET_EXTENSION(glFramebufferTexture1DEXT);
304 		sm_glFramebufferTexture2DEXT = (PFNGLFRAMEBUFFERTEXTURE2DEXTPROC)
305 			GET_EXTENSION(glFramebufferTexture2DEXT);
306 		sm_glFramebufferTexture3DEXT = (PFNGLFRAMEBUFFERTEXTURE3DEXTPROC)
307 			GET_EXTENSION(glFramebufferTexture3DEXT);
308 		sm_glFramebufferRenderbufferEXT = (PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC)
309 			GET_EXTENSION(glFramebufferRenderbufferEXT);
310 		sm_glGetFramebufferAttachmentParameterivEXT =
311 			(PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC)
312 			GET_EXTENSION(glGetFramebufferAttachmentParameterivEXT);
313 		sm_glGenerateMipmapEXT = (PFNGLGENERATEMIPMAPEXTPROC)
314 			GET_EXTENSION(glGenerateMipmapEXT);
315 	}
316 #ifndef GL_GLEXT_PROTOTYPES
317 	using namespace TREGLExtensionsNS;
318 	glVertexArrayRangeNV = sm_glVertexArrayRangeNV;
319 	// GL_EXT_multi_draw_arrays
320 	glMultiDrawElementsEXT = sm_glMultiDrawElementsEXT;
321 	// GL_ARB_vertex_buffer_object
322 	glBindBufferARB = sm_glBindBufferARB;
323 	glDeleteBuffersARB = sm_glDeleteBuffersARB;
324 	glGenBuffersARB = sm_glGenBuffersARB;
325 	glIsBufferARB = sm_glIsBufferARB;
326 	glBufferDataARB = sm_glBufferDataARB;
327 	glBufferSubDataARB = sm_glBufferSubDataARB;
328 	glGetBufferSubDataARB = sm_glGetBufferSubDataARB;
329 	glMapBufferARB = sm_glMapBufferARB;
330 	glUnmapBufferARB = sm_glUnmapBufferARB;
331 	glGetBufferParameterivARB = sm_glGetBufferParameterivARB;
332 	glGetBufferPointervARB = sm_glGetBufferPointervARB;
333 	// GL_ARB_occlusion_query
334 	glGenQueriesARB = sm_glGenQueriesARB;
335 	glDeleteQueriesARB = sm_glDeleteQueriesARB;
336 	glIsQueryARB = sm_glIsQueryARB;
337 	glBeginQueryARB = sm_glBeginQueryARB;
338 	glEndQueryARB = sm_glEndQueryARB;
339 	glGetQueryivARB = sm_glGetQueryivARB;
340 	glGetQueryObjectivARB = sm_glGetQueryObjectivARB;
341 	glGetQueryObjectuivARB = sm_glGetQueryObjectuivARB;
342 	// GL_EXT_framebuffer_object
343 	glIsRenderbufferEXT = sm_glIsRenderbufferEXT;
344 	glBindRenderbufferEXT = sm_glBindRenderbufferEXT;
345 	glDeleteRenderbuffersEXT = sm_glDeleteRenderbuffersEXT;
346 	glGenRenderbuffersEXT = sm_glGenRenderbuffersEXT;
347 	glRenderbufferStorageEXT = sm_glRenderbufferStorageEXT;
348 	glGetRenderbufferParameterivEXT = sm_glGetRenderbufferParameterivEXT;
349 	glIsFramebufferEXT = sm_glIsFramebufferEXT;
350 	glBindFramebufferEXT = sm_glBindFramebufferEXT;
351 	glDeleteFramebuffersEXT = sm_glDeleteFramebuffersEXT;
352 	glGenFramebuffersEXT = sm_glGenFramebuffersEXT;
353 	glCheckFramebufferStatusEXT = sm_glCheckFramebufferStatusEXT;
354 	glFramebufferTexture1DEXT = sm_glFramebufferTexture1DEXT;
355 	glFramebufferTexture2DEXT = sm_glFramebufferTexture2DEXT;
356 	glFramebufferTexture3DEXT = sm_glFramebufferTexture3DEXT;
357 	glFramebufferRenderbufferEXT = sm_glFramebufferRenderbufferEXT;
358 	glGetFramebufferAttachmentParameterivEXT =
359 		sm_glGetFramebufferAttachmentParameterivEXT;
360 	glGenerateMipmapEXT = sm_glGenerateMipmapEXT;
361 #endif // GL_GLEXT_PROTOTYPES
362 #ifdef WIN32
363 	using namespace TREGLExtensionsNS;
364 	if (haveVARExtension(true))
365 	{
366 		wglAllocateMemoryNV = (PFNWGLALLOCATEMEMORYNVPROC)
367 			wglGetProcAddress("wglAllocateMemoryNV");
368 		wglFreeMemoryNV = (PFNWGLFREEMEMORYNVPROC)
369 			wglGetProcAddress("wglFreeMemoryNV");
370 	}
371 #endif // WIN32
372 }
373 
haveNvMultisampleFilterHintExtension(bool force)374 bool TREGLExtensions::haveNvMultisampleFilterHintExtension(bool force)
375 {
376 	bool ignore = TCUserDefaults::boolForKey(IGNORE_MS_FILTER_HINT_KEY, false,
377 		false);
378 
379 	return (!ignore || force) &&
380 		checkForExtension("GL_NV_multisample_filter_hint", force);
381 }
382 
haveVARExtension(bool force)383 bool TREGLExtensions::haveVARExtension(bool force)
384 {
385 	bool ignore = TCUserDefaults::boolForKey(IGNORE_VAR_KEY, false, false);
386 
387 	using namespace TREGLExtensionsNS;
388 	return (!ignore || force) && checkForExtension("GL_NV_vertex_array_range",
389 		force);// && wglAllocateMemoryNV != NULL && wglFreeMemoryNV != NULL;
390 }
391 
haveMultiDrawArraysExtension(bool force)392 bool TREGLExtensions::haveMultiDrawArraysExtension(bool force)
393 {
394 	if (sm_rendererIsMesa)
395 	{
396 		// This extension apparently sucks on Mesa.  As near as I can tell, it
397 		// won't work inside a display list.
398 		return false;
399 	}
400 #ifdef __APPLE__
401 	int one = 1;
402 	TCByte binary[] = {1,0,0,0};
403 
404 	if (one != *(int*)binary)
405 	{
406 		// Doesn't work on PPC Mac (at least in Rosetta).  The above checks to
407 		// see if the current architecture is big endian or little endian.  If
408 		// it's big endian (PPC), we'll get here.
409 		return false;
410 	}
411 #endif
412 	bool ignore = TCUserDefaults::boolForKey(IGNORE_MULTI_DRAW_ARRAYS_KEY,
413 		false, false);
414 
415 	return (!ignore || force) && checkForExtension("GL_EXT_multi_draw_arrays",
416 		force);
417 }
418 
haveOcclusionQueryExtension(bool force)419 bool TREGLExtensions::haveOcclusionQueryExtension(bool force)
420 {
421 	bool ignore = TCUserDefaults::boolForKey(IGNORE_OCCLUSION_QUERY_KEY, false,
422 		false);
423 
424 	return (!ignore || force) && checkForExtension("GL_ARB_occlusion_query",
425 		force);
426 }
427 
haveFramebufferObjectExtension(bool force)428 bool TREGLExtensions::haveFramebufferObjectExtension(bool force)
429 {
430 	bool ignore = TCUserDefaults::boolForKey(IGNORE_FRAMEBUFFER_OBJECT_KEY,
431 		false, false);
432 
433 	return (!ignore || force) && checkForExtension("GL_EXT_framebuffer_object",
434 		force);
435 }
436 
haveClampToBorderExtension(bool force)437 bool TREGLExtensions::haveClampToBorderExtension(bool force)
438 {
439 	bool ignore = TCUserDefaults::boolForKey(IGNORE_CLAMP_TO_BORDER, false,
440 		false);
441 
442 	return (!ignore || force) && checkForOGLVersion(1, 3, force);
443 }
444 
haveAnisoExtension(bool force)445 bool TREGLExtensions::haveAnisoExtension(bool force)
446 {
447 	bool ignore = TCUserDefaults::boolForKey(IGNORE_ANISO_KEY, false, false);
448 
449 	return (!ignore || force) &&
450 		checkForExtension("GL_EXT_texture_filter_anisotropic", force);
451 }
452 
haveVBOExtension(bool force)453 bool TREGLExtensions::haveVBOExtension(bool force)
454 {
455 	bool ignore = TCUserDefaults::boolForKey(IGNORE_VBO_KEY, false, false);
456 
457 	return (!ignore || force) &&
458 		checkForExtension("GL_ARB_vertex_buffer_object", force);
459 }
460 
checkForExtension(const StringSet & extensions,const char * extension,bool force)461 bool TREGLExtensions::checkForExtension(
462 	const StringSet &extensions,
463 	const char* extension,
464 	bool force)
465 {
466 	bool ignore = TCUserDefaults::boolForKey(IGNORE_ALL_OGL_EXTENSIONS, false,
467 		false) || sm_tempDisable;
468 
469 	if (!ignore || force)
470 	{
471 		return extensions.find(extension) != extensions.end();
472 	}
473 	return false;
474 }
475 
checkForExtension(const char * extension,bool force)476 bool TREGLExtensions::checkForExtension(const char* extension, bool force)
477 {
478 	return checkForExtension(sm_glExtensions, extension, force);
479 }
480 
checkForOGLVersion(int major,int minor,bool force)481 bool TREGLExtensions::checkForOGLVersion(
482 	int major,
483 	int minor,
484 	bool force /*= false*/)
485 {
486 	bool ignore = TCUserDefaults::boolForKey(IGNORE_ALL_OGL_EXTENSIONS, false,
487 		false) || sm_tempDisable;
488 
489 	if (!ignore || force)
490 	{
491 		return sm_versionMaj > major ||
492 			(sm_versionMaj == major && sm_versionMin >= minor);
493 	}
494 	return false;
495 }
496 
getMaxAnisoLevel(void)497 GLfloat TREGLExtensions::getMaxAnisoLevel(void)
498 {
499 	if (haveAnisoExtension())
500 	{
501 		return sm_maxAnisoLevel;
502 	}
503 	else
504 	{
505 		return 1.0f;
506 	}
507 }
508