AllegroGL: glext.c Source File

AllegroGL 0.4.4

- Main Page
- Related Pages
- Modules
- Files

- File List
- Globals

glext.c
Go to the documentation of this file.
1 /* This code is (C) AllegroGL contributors, and double licensed under
2 * the GPL and zlib licenses. See gpl.txt or zlib.txt for details.
3 */
8 #include "alleggl.h"
9 #include "allglint.h"
10 #include <string.h>
11 #ifdef ALLEGRO_MACOSX
12 #include <OpenGL/glu.h>
13 #else
14 #include <GL/glu.h>
15 #endif
16
17 #include <allegro/internal/aintern.h>
18
19
20 /* GL extension Structure. Holds the extension pointers for a single context */
21 #define AGL_API(type, name, args) AGL_##name##_t name;
22 typedef struct AGL_EXT {
23 # include "allegrogl/GLext/gl_ext_api.h"
24 #ifdef ALLEGRO_WINDOWS
25 # include "allegrogl/GLext/wgl_ext_api.h"
26 #elif defined ALLEGRO_UNIX
27 # include "allegrogl/GLext/glx_ext_api.h"
28 #endif
29 } AGL_EXT;
30 #undef AGL_API
31
32 #define PREFIX_I "agl-ext INFO: "
33 #define PREFIX_W "agl-ext WARNING: "
34 #define PREFIX_E "agl-ext ERROR: "
35
36
37 /* Current driver info */
38 struct allegro_gl_info allegro_gl_info;
39
40
41
55 struct AGL_EXTENSION_LIST_GL allegro_gl_extensions_GL;
56
57
58
64 #ifdef ALLEGRO_UNIX
65 struct AGL_EXTENSION_LIST_GLX allegro_gl_extensions_GLX;
66 #endif
67
68
69
75 #ifdef ALLEGRO_WINDOWS
76 struct AGL_EXTENSION_LIST_WGL allegro_gl_extensions_WGL;
77 #endif
78
79
80
81 /* Current context */
82 AGL_EXT *agl_extension_table = NULL;
83
84
85 #ifdef ALLEGROGL_GENERIC_DRIVER
86 #include "GL/amesa.h"
87 #endif
88
89
90 #ifdef ALLEGROGL_HAVE_DYNAMIC_LINK
91 #include <dlfcn.h>
92
93 /* Handle for dynamic library libGL.so */
94 static void* __agl_handle = NULL;
95 /* Pointer to glXGetProcAddressARB */
96 typedef void* (*GLXGETPROCADDRESSARBPROC) (const GLubyte*);
97 static GLXGETPROCADDRESSARBPROC aglXGetProcAddress;
98 #else
99 /* Tries static linking */
100 #ifdef ALLEGROGL_GLXGETPROCADDRESSARB
101 #define aglXGetProcAddress glXGetProcAddressARB
102 #else
103 #define aglXGetProcAddress glXGetProcAddress
104 #endif
105 #endif
106
107
108 #ifdef ALLEGRO_MACOSX
109 #undef TRUE
110 #undef FALSE
111 #include <Carbon/Carbon.h>
112 #undef TRUE
113 #undef FALSE
114 #define TRUE -1
115 #define FALSE 0
116
117 static CFBundleRef opengl_bundle_ref;
118 #endif
119
120
121
122 /* Define the GL API pointers */
123 #define AGL_API(type, name, args) AGL_##name##_t __agl##name = NULL;
124 # include "allegrogl/GLext/gl_ext_api.h"
125 #undef AGL_API
126 #ifdef ALLEGRO_WINDOWS
127 #define AGL_API(type, name, args) AGL_##name##_t __awgl##name = NULL;
128 # include "allegrogl/GLext/wgl_ext_api.h"
129 #undef AGL_API
130 #elif defined ALLEGRO_UNIX
131 #define AGL_API(type, name, args) AGL_##name##_t __aglX##name = NULL;
132 # include "allegrogl/GLext/glx_ext_api.h"
133 #undef AGL_API
134 #endif
135
136
137
138 /* Create the extension table */
139 AGL_EXT* __allegro_gl_create_extensions() {
140
141 AGL_EXT *ret = malloc(sizeof(AGL_EXT));
142
143 if (!ret) {
144 return NULL;
145 }
146
147 memset(ret, 0, sizeof(AGL_EXT));
148
149 return ret;
150 }
151
152
153
154 /* Load the extension addresses into the table.
155 * Should only be done on context creation.
156 */
157 void __allegro_gl_load_extensions(AGL_EXT *ext) {
158
159 #ifdef ALLEGRO_MACOSX
160 CFStringRef function;
161 #endif
162
163 if (!ext) {
164 return;
165 }
166 #ifdef ALLEGRO_UNIX
167 if (!aglXGetProcAddress) {
168 return;
169 }
170 #endif
171
172 # ifdef ALLEGRO_WINDOWS
173 # define AGL_API(type, name, args) \
174 ext->name = (AGL_##name##_t)wglGetProcAddress("gl" #name); \
175 if (ext->name) { AGL_LOG(2,"gl" #name " successfully loaded\n"); }
176 # include "allegrogl/GLext/gl_ext_api.h"
177 # undef AGL_API
178 # define AGL_API(type, name, args) \
179 ext->name = (AGL_##name##_t)wglGetProcAddress("wgl" #name); \
180 if (ext->name) { AGL_LOG(2,"wgl" #name " successfully loaded\n"); }
181 # include "allegrogl/GLext/wgl_ext_api.h"
182 # undef AGL_API
183 # elif defined ALLEGRO_UNIX
184 # define AGL_API(type, name, args) \
185 ext->name = (AGL_##name##_t)aglXGetProcAddress((const GLubyte*)"gl" #name); \
186 if (ext->name) { AGL_LOG(2,"gl" #name " successfully loaded\n"); }
187 # include "allegrogl/GLext/gl_ext_api.h"
188 # undef AGL_API
189 # define AGL_API(type, name, args) \
190 ext->name = (AGL_##name##_t)aglXGetProcAddress((const GLubyte*)"glX" #name); \
191 if (ext->name) { AGL_LOG(2,"glX" #name " successfully loaded\n"); }
192 # include "allegrogl/GLext/glx_ext_api.h"
193 # undef AGL_API
194 # elif defined ALLEGRO_MACOSX
195 # define AGL_API(type, name, args) \
196 function = CFStringCreateWithCString(kCFAllocatorDefault, "gl" #name, \
197 kCFStringEncodingASCII); \
198 if (function) { \
199 ext->name = (AGL_##name##_t)CFBundleGetFunctionPointerForName( \
200 opengl_bundle_ref, function); \
201 CFRelease(function); \
202 } \
203 if (ext->name) { AGL_LOG(2,"gl" #name " successfully loaded\n"); }
204 # include "allegrogl/GLext/gl_ext_api.h"
205 # undef AGL_API
206 # endif
207 }
208
209
210
211 /* Set the GL API pointers to the current table
212 * Should only be called on context switches.
213 */
214 void __allegro_gl_set_extensions(AGL_EXT *ext) {
215
216 if (!ext) {
217 return;
218 }
219
220 #define AGL_API(type, name, args) __agl##name = ext->name;
221 # include "allegrogl/GLext/gl_ext_api.h"
222 #undef AGL_API
223 #ifdef ALLEGRO_WINDOWS
224 #define AGL_API(type, name, args) __awgl##name = ext->name;
225 # include "allegrogl/GLext/wgl_ext_api.h"
226 #undef AGL_API
227 #elif defined ALLEGRO_UNIX
228 #define AGL_API(type, name, args) __aglX##name = ext->name;
229 # include "allegrogl/GLext/glx_ext_api.h"
230 #undef AGL_API
231 #endif
232 }
233
234
235
236 /* Destroys the extension table */
237 void __allegro_gl_destroy_extensions(AGL_EXT *ext) {
238
239 if (ext) {
240 if (ext == agl_extension_table) {
241 agl_extension_table = NULL;
242 }
243 free(ext);
244 }
245 }
246
247
248
249 /* __allegro_gl_look_for_an_extension:
250 * This function has been written by Mark J. Kilgard in one of his
251 * tutorials about OpenGL extensions
252 */
253 int __allegro_gl_look_for_an_extension(AL_CONST char *name,
254 AL_CONST GLubyte * extensions)
255 {
256 AL_CONST GLubyte *start;
257 GLubyte *where, *terminator;
258
259 /* Extension names should not have spaces. */
260 where = (GLubyte *) strchr(name, ' ');
261 if (where || *name == '\0')
262 return FALSE;
263 /* It takes a bit of care to be fool-proof about parsing the
264 * OpenGL extensions string. Don't be fooled by sub-strings, etc.
265 */
266 start = extensions;
267 for (;;) {
268 where = (GLubyte *) strstr((AL_CONST char *) start, name);
269 if (!where)
270 break;
271 terminator = where + strlen(name);
272 if (where == start || *(where - 1) == ' ')
273 if (*terminator == ' ' || *terminator == '\0')
274 return TRUE;
275 start = terminator;
276 }
277 return FALSE;
278 }
279
280
281
282 #ifdef ALLEGRO_WINDOWS
283 static AGL_GetExtensionsStringARB_t __wglGetExtensionsStringARB = NULL;
284 static HDC __hdc = NULL;
285 #elif defined ALLEGRO_UNIX
286 #include <xalleg.h>
287 #endif
288
289
290 /* int allegro_gl_is_extension_supported(AL_CONST char *extension) */
306 int allegro_gl_is_extension_supported(AL_CONST char *extension)
307 {
308 int ret;
309
310 if (!__allegro_gl_valid_context)
311 return FALSE;
312
313 if (!glGetString(GL_EXTENSIONS))
314 return FALSE;
315
316 ret = __allegro_gl_look_for_an_extension(extension,
317 glGetString(GL_EXTENSIONS));
318
319 #ifdef ALLEGRO_WINDOWS
320 if (!ret && strncmp(extension, "WGL", 3) == 0) {
321 if (!__wglGetExtensionsStringARB || __hdc != __allegro_gl_hdc) {
322 __wglGetExtensionsStringARB = (AGL_GetExtensionsStringARB_t)
323 wglGetProcAddress("wglGetExtensionsStringARB");
324 __hdc = __allegro_gl_hdc;
325 }
326 if (__wglGetExtensionsStringARB) {
327 ret = __allegro_gl_look_for_an_extension(extension,
328 (AL_CONST GLubyte*)__wglGetExtensionsStringARB(__allegro_gl_hdc));
329 }
330 }
331 #elif defined ALLEGRO_UNIX
332 if (!ret && strncmp(extension, "GLX", 3) == 0) {
333 XLOCK();
334 ret = __allegro_gl_look_for_an_extension(extension,
335 (const GLubyte*)glXQueryExtensionsString(_xwin.display,
336 _xwin.screen));
337 XUNLOCK();
338 }
339 #endif
340
341 return ret;
342 }
343
344
345
346 /* void * allegro_gl_get_proc_address(AL_CONST char *name) */
372 void *allegro_gl_get_proc_address(AL_CONST char *name)
373 {
374 void *symbol = NULL;
375 #ifdef ALLEGRO_MACOSX
376 CFStringRef function;
377 #endif
378
379 if (!__allegro_gl_valid_context)
380 return NULL;
381
382 #ifdef ALLEGROGL_GENERIC_DRIVER
383 /* AMesa provides a function to get a proc address. It does
384 * not emulate dynamic linking of course...
385 */
386 symbol = AMesaGetProcAddress(name);
387
388 #elif defined ALLEGRO_WINDOWS
389 /* For once Windows is the easiest platform to use :)
390 * It provides a standardized way to get a function address
391 * But of course there is a drawback : the symbol is only valid
392 * under the current context :P
393 */
394 symbol = wglGetProcAddress(name);
395 #elif defined ALLEGRO_UNIX
396 if (aglXGetProcAddress) {
397 /* This is definitely the *good* way on Unix to get a GL proc
398 * address. Unfortunately glXGetProcAddress is an extension
399 * and may not be available on all platforms
400 */
401 symbol = aglXGetProcAddress((const GLubyte*)name);
402 }
403 #elif defined ALLEGROGL_HAVE_DYNAMIC_LINK
404 else {
405 /* Hack if glXGetProcAddress is not available :
406 * we try to find the symbol into libGL.so
407 */
408 if (__agl_handle) {
409 symbol = dlsym(__agl_handle, name);
410 }
411 }
412 #elif defined ALLEGRO_MACOSX
413 function = CFStringCreateWithCString(kCFAllocatorDefault, name,
414 kCFStringEncodingASCII);
415 if (function) {
416 symbol = CFBundleGetFunctionPointerForName(opengl_bundle_ref, function);
417 CFRelease(function);
418 }
419 #else
420 /* DOS does not support dynamic linking. If the function is not
421 * available at build-time then it will not be available at run-time
422 * Therefore we do not need to look for it...
423 */
424 #endif
425
426 if (!symbol) {
427
428 #if defined ALLEGROGL_HAVE_DYNAMIC_LINK
429 if (!aglXGetProcAddress) {
430 TRACE(PREFIX_W "get_proc_address: libdl::dlsym: %s\n",
431 dlerror());
432 }
433 #endif
434
435 TRACE(PREFIX_W "get_proc_address : Unable to load symbol %s\n",
436 name);
437 }
438 else {
439 TRACE(PREFIX_I "get_proc_address : Symbol %s successfully loaded\n",
440 name);
441 }
442 return symbol;
443 }
444
445
446
447 /* Fills in the AllegroGL info struct for blacklisting video cards.
448 */
449 static void __fill_in_info_struct(const GLubyte *rendereru,
450 struct allegro_gl_info *info) {
451 const char *renderer = (const char*)rendereru;
452
453 /* Some cards are "special"... */
454 if (strstr(renderer, "3Dfx/Voodoo")) {
455 info->is_voodoo = 1;
456 }
457 else if (strstr(renderer, "Matrox G200")) {
458 info->is_matrox_g200 = 1;
459 }
460 else if (strstr(renderer, "RagePRO")) {
461 info->is_ati_rage_pro = 1;
462 }
463 else if (strstr(renderer, "RADEON 7000")) {
464 info->is_ati_radeon_7000 = 1;
465 }
466 else if (strstr(renderer, "Mesa DRI R200")) {
467 info->is_ati_r200_chip = 1;
468 }
469
470 if ((strncmp(renderer, "3Dfx/Voodoo3 ", 13) == 0)
471 || (strncmp(renderer, "3Dfx/Voodoo2 ", 13) == 0)
472 || (strncmp(renderer, "3Dfx/Voodoo ", 12) == 0)) {
473 info->is_voodoo3_and_under = 1;
474 }
475
476 /* Read OpenGL properties */
477 info->version = allegro_gl_opengl_version();
478
479 return;
480 }
481
482
483
484 /* __allegro_gl_manage_extensions:
485 * This functions fills the __allegro_gl_extensions structure and displays
486 * on the log file which extensions are available
487 */
488 void __allegro_gl_manage_extensions(void)
489 {
490 AL_CONST GLubyte *buf;
491 int i;
492
493 #ifdef ALLEGRO_MACOSX
494 CFURLRef bundle_url;
495 #endif
496
497 /* Print out OpenGL extensions */
498 #if LOGLEVEL >= 1
499 AGL_LOG(1, "OpenGL Extensions:\n");
500 __allegro_gl_print_extensions((AL_CONST char*)
501 glGetString(GL_EXTENSIONS));
502 #endif
503
504 /* Print out GLU version */
505 buf = gluGetString(GLU_VERSION);
506 TRACE(PREFIX_I "GLU Version : %s\n", buf);
507
508 #ifdef ALLEGROGL_HAVE_DYNAMIC_LINK
509 /* Get glXGetProcAddress entry */
510 __agl_handle = dlopen("libGL.so", RTLD_LAZY);
511 if (__agl_handle) {
512 aglXGetProcAddress = (GLXGETPROCADDRESSARBPROC) dlsym(__agl_handle,
513 "glXGetProcAddressARB");
514 if (!aglXGetProcAddress) {
515 aglXGetProcAddress = (GLXGETPROCADDRESSARBPROC) dlsym(__agl_handle,
516 "glXGetProcAddress");
517 }
518 }
519 else {
520 TRACE(PREFIX_W "Failed to dlopen libGL.so : %s\n", dlerror());
521 }
522 TRACE(PREFIX_I "glXGetProcAddress Extension: %s\n",
523 aglXGetProcAddress ? "Supported" : "Unsupported");
524 #elif defined ALLEGRO_UNIX
525 #ifdef ALLEGROGL_GLXGETPROCADDRESSARB
526 TRACE(PREFIX_I "glXGetProcAddressARB Extension: supported\n");
527 #else
528 TRACE(PREFIX_I "glXGetProcAddress Extension: supported\n");
529 #endif
530 #endif
531
532 #ifdef ALLEGRO_MACOSX
533 bundle_url = CFURLCreateWithFileSystemPath(kCFAllocatorDefault,
534 CFSTR("/System/Library/Frameworks/OpenGL.framework"),
535 kCFURLPOSIXPathStyle, true);
536 opengl_bundle_ref = CFBundleCreate(kCFAllocatorDefault, bundle_url);
537 CFRelease(bundle_url);
538 #endif
539
540 __fill_in_info_struct(glGetString(GL_RENDERER), &allegro_gl_info);
541
542 /* Load extensions */
543 agl_extension_table = __allegro_gl_create_extensions();
544 __allegro_gl_load_extensions(agl_extension_table);
545 __allegro_gl_set_extensions(agl_extension_table);
546
547 for (i = 0; i < 5; i++) {
548 __allegro_gl_texture_read_format[i] = -1;
549 __allegro_gl_texture_components[i] = GL_RGB;
550 }
551 __allegro_gl_texture_read_format[3] = GL_UNSIGNED_BYTE;
552 __allegro_gl_texture_read_format[4] = GL_UNSIGNED_BYTE;
553 __allegro_gl_texture_components[4] = GL_RGBA;
554
555
556 /* Get extension info for the rest of the lib */
557 # define AGL_EXT(name, ver) { \
558 allegro_gl_extensions_GL.name = \
559 allegro_gl_is_extension_supported("GL_" #name) \
560 || (allegro_gl_info.version >= ver && ver > 0); \
561 }
562 # include "allegrogl/GLext/gl_ext_list.h"
563 # undef AGL_EXT
564
565 #ifdef ALLEGRO_UNIX
566 # define AGL_EXT(name, ver) { \
567 allegro_gl_extensions_GLX.name = \
568 allegro_gl_is_extension_supported("GLX_" #name) \
569 || (allegro_gl_info.version >= ver && ver > 0); \
570 }
571 # include "allegrogl/GLext/glx_ext_list.h"
572 # undef AGL_EXT
573 #elif defined ALLEGRO_WINDOWS
574 # define AGL_EXT(name, ver) { \
575 allegro_gl_extensions_WGL.name = \
576 allegro_gl_is_extension_supported("WGL_" #name) \
577 || (allegro_gl_info.version >= ver && ver > 0); \
578 }
579 # include "allegrogl/GLext/wgl_ext_list.h"
580 # undef AGL_EXT
581 #endif
582
583 /* Get number of texture units */
584 if (allegro_gl_extensions_GL.ARB_multitexture) {
585 glGetIntegerv(GL_MAX_TEXTURE_UNITS,
586 (GLint*)&allegro_gl_info.num_texture_units);
587 }
588 else {
589 allegro_gl_info.num_texture_units = 1;
590 }
591
592 /* Get max texture size */
593 glGetIntegerv(GL_MAX_TEXTURE_SIZE,
594 (GLint*)&allegro_gl_info.max_texture_size);
595
596 /* Note: Voodoo (even V5) don't seem to correctly support
597 * packed pixel formats. Disabling them for those cards.
598 */
599 allegro_gl_extensions_GL.EXT_packed_pixels &= !allegro_gl_info.is_voodoo;
600
601
602 if (allegro_gl_extensions_GL.EXT_packed_pixels) {
603
604 AGL_LOG(1, "Packed Pixels formats available\n");
605
606 /* XXX On NV cards, we want to use BGRA instead of RGBA for speed */
607 /* Fills the __allegro_gl_texture_format array */
608 __allegro_gl_texture_read_format[0] = GL_UNSIGNED_BYTE_3_3_2;
609 __allegro_gl_texture_read_format[1] = GL_UNSIGNED_SHORT_5_5_5_1;
610 __allegro_gl_texture_read_format[2] = GL_UNSIGNED_SHORT_5_6_5;
611 }
612
613 /* NVidia and ATI cards expose OpenGL 2.0 but often don't accelerate
614 * non-power-of-2 textures. This check is how you verify that NP2
615 * textures are hardware accelerated or not.
616 * We should clobber the NPOT support if it's not accelerated.
617 */
618 { const char *vendor = (const char*)glGetString(GL_VENDOR);
619 if (strstr(vendor, "NVIDIA Corporation")) {
620 if (!allegro_gl_extensions_GL.NV_fragment_program2
621 || !allegro_gl_extensions_GL.NV_vertex_program3) {
622 allegro_gl_extensions_GL.ARB_texture_non_power_of_two = 0;
623 }
624 }
625 else if (strstr(vendor, "ATI Technologies")) {
626 if (!strstr((const char*)glGetString(GL_EXTENSIONS),
627 "GL_ARB_texture_non_power_of_two")
628 && allegro_gl_info.version >= 2.0f) {
629 allegro_gl_extensions_GL.ARB_texture_non_power_of_two = 0;
630 }
631 }
632 }
633 }
634
635
636
637 /* __allegro_gl_print_extensions:
638 * Given a string containing extensions (i.e. a NULL terminated string where
639 * each extension are separated by a space and which names do not contain any
640 * space)
641 */
642 void __allegro_gl_print_extensions(AL_CONST char * extension)
643 {
644 char buf[80];
645 char* start;
646
647 while (*extension != '\0') {
648 start = buf;
649 strncpy(buf, extension, 80);
650 while ((*start != ' ') && (*start != '\0')) {
651 extension++;
652 start++;
653 }
654 *start = '\0';
655 extension ++;
656 TRACE(PREFIX_I "%s\n", buf);
657 }
658 }
659
660
661
662 void __allegro_gl_unmanage_extensions() {
663 __allegro_gl_destroy_extensions(agl_extension_table);
664 #ifdef ALLEGRO_MACOSX
665 CFRelease(opengl_bundle_ref);
666 #endif
667 #ifdef ALLEGROGL_HAVE_DYNAMIC_LINK
668 if (__agl_handle) {
669 dlclose(__agl_handle);
670 __agl_handle = NULL;
671 }
672 #endif
673 }
674
allegro_gl_opengl_version
float allegro_gl_opengl_version(void)
Returns the OpenGL version number of the client (the computer the program is running on)...
Definition: alleggl.c:971
allegro_gl_get_proc_address
void * allegro_gl_get_proc_address(AL_CONST char *name)
Helper to get the address of an OpenGL symbol.
Definition: glext.c:372
allegro_gl_extensions_GL
struct AGL_EXTENSION_LIST_GL allegro_gl_extensions_GL
List of OpenGL extensions supported by AllegroGL.
Definition: glext.c:55
agl_extension_table
AGL_EXT * agl_extension_table
List of GLX extensions supported by AllegroGL.
Definition: glext.c:82
allegro_gl_is_extension_supported
int allegro_gl_is_extension_supported(AL_CONST char *extension)
This function is an helper to determine whether an OpenGL extension is available or not...
Definition: glext.c:306
alleggl.h
Main header file for AllegroGL.