00001
00005 #include "alleggl.h"
00006 #include "allglint.h"
00007 #include <string.h>
00008 #ifdef ALLEGRO_MACOSX
00009 #include <OpenGL/glu.h>
00010 #else
00011 #include <GL/glu.h>
00012 #endif
00013
00014 #include <allegro/internal/aintern.h>
00015
00016
00017
00018 #define AGL_API(type, name, args) AGL_##name##_t name;
00019 typedef struct AGL_EXT {
00020 # include "allegrogl/GLext/gl_ext_api.h"
00021 #ifdef ALLEGRO_WINDOWS
00022 # include "allegrogl/GLext/wgl_ext_api.h"
00023 #elif defined ALLEGRO_UNIX
00024 # include "allegrogl/GLext/glx_ext_api.h"
00025 #endif
00026 } AGL_EXT;
00027 #undef AGL_API
00028
00029
00030
00031 struct allegro_gl_info allegro_gl_info;
00032
00033
00034
00048 AGL_EXTENSION_LIST_GL allegro_gl_extensions_GL;
00049
00050
00051
00057 #ifdef ALLEGRO_UNIX
00058 AGL_EXTENSION_LIST_GLX allegro_gl_extensions_GLX;
00059 #endif
00060
00061
00062
00068 #ifdef ALLEGRO_WINDOWS
00069 AGL_EXTENSION_LIST_WGL allegro_gl_extensions_WGL;
00070 #endif
00071
00072
00073
00074
00075 AGL_EXT *agl_extension_table = NULL;
00076
00077
00078 #ifdef ALLEGROGL_GENERIC_DRIVER
00079 #include "GL/amesa.h"
00080 #endif
00081
00082
00083 #ifdef ALLEGROGL_HAVE_DYNAMIC_LINK
00084 #include <dlfcn.h>
00085
00086
00087 static void* __agl_handle = NULL;
00088
00089 typedef void* (*GLXGETPROCADDRESSARBPROC) (const GLubyte*);
00090 static GLXGETPROCADDRESSARBPROC aglXGetProcAddress;
00091 #else
00092
00093 #ifdef ALLEGROGL_GLXGETPROCADDRESSARB
00094 #define aglXGetProcAddress glXGetProcAddressARB
00095 #else
00096 #define aglXGetProcAddress glXGetProcAddress
00097 #endif
00098 #endif
00099
00100
00101 #ifdef ALLEGRO_MACOSX
00102 #undef TRUE
00103 #undef FALSE
00104 #include <Carbon/Carbon.h>
00105 #undef TRUE
00106 #undef FALSE
00107 #define TRUE -1
00108 #define FALSE 0
00109
00110 static CFBundleRef opengl_bundle_ref;
00111 #endif
00112
00113
00114
00115
00116 #define AGL_API(type, name, args) AGL_##name##_t __agl##name = NULL;
00117 # include "allegrogl/GLext/gl_ext_api.h"
00118 #undef AGL_API
00119 #ifdef ALLEGRO_WINDOWS
00120 #define AGL_API(type, name, args) AGL_##name##_t __awgl##name = NULL;
00121 # include "allegrogl/GLext/wgl_ext_api.h"
00122 #undef AGL_API
00123 #elif defined ALLEGRO_UNIX
00124 #define AGL_API(type, name, args) AGL_##name##_t __aglX##name = NULL;
00125 # include "allegrogl/GLext/glx_ext_api.h"
00126 #undef AGL_API
00127 #endif
00128
00129
00130
00131
00132 AGL_EXT* __allegro_gl_create_extensions() {
00133
00134 AGL_EXT *ret = malloc(sizeof(AGL_EXT));
00135
00136 if (!ret) {
00137 return NULL;
00138 }
00139
00140 memset(ret, 0, sizeof(AGL_EXT));
00141
00142 return ret;
00143 }
00144
00145
00146
00147
00148
00149
00150 void __allegro_gl_load_extensions(AGL_EXT *ext) {
00151
00152 #ifdef ALLEGRO_MACOSX
00153 CFStringRef function;
00154 #endif
00155
00156 if (!ext) {
00157 return;
00158 }
00159 #ifdef ALLEGRO_UNIX
00160 if (!aglXGetProcAddress) {
00161 return;
00162 }
00163 #endif
00164
00165 # ifdef ALLEGRO_WINDOWS
00166 # define AGL_API(type, name, args) \
00167 ext->name = (AGL_##name##_t)wglGetProcAddress("gl" #name); \
00168 if (ext->name) { AGL_LOG(2,"gl" #name " successfully loaded\n"); }
00169 # include "allegrogl/GLext/gl_ext_api.h"
00170 # undef AGL_API
00171 # define AGL_API(type, name, args) \
00172 ext->name = (AGL_##name##_t)wglGetProcAddress("wgl" #name); \
00173 if (ext->name) { AGL_LOG(2,"wgl" #name " successfully loaded\n"); }
00174 # include "allegrogl/GLext/wgl_ext_api.h"
00175 # undef AGL_API
00176 # elif defined ALLEGRO_UNIX
00177 # define AGL_API(type, name, args) \
00178 ext->name = (AGL_##name##_t)aglXGetProcAddress((const GLubyte*)"gl" #name); \
00179 if (ext->name) { AGL_LOG(2,"gl" #name " successfully loaded\n"); }
00180 # include "allegrogl/GLext/gl_ext_api.h"
00181 # undef AGL_API
00182 # define AGL_API(type, name, args) \
00183 ext->name = (AGL_##name##_t)aglXGetProcAddress((const GLubyte*)"glX" #name); \
00184 if (ext->name) { AGL_LOG(2,"glX" #name " successfully loaded\n"); }
00185 # include "allegrogl/GLext/glx_ext_api.h"
00186 # undef AGL_API
00187 # elif defined ALLEGRO_MACOSX
00188 # define AGL_API(type, name, args) \
00189 function = CFStringCreateWithCString(kCFAllocatorDefault, "gl" #name, \
00190 kCFStringEncodingASCII); \
00191 if (function) { \
00192 ext->name = (AGL_##name##_t)CFBundleGetFunctionPointerForName( \
00193 opengl_bundle_ref, function); \
00194 CFRelease(function); \
00195 } \
00196 if (ext->name) { AGL_LOG(2,"gl" #name " successfully loaded\n"); }
00197 # include "allegrogl/GLext/gl_ext_api.h"
00198 # undef AGL_API
00199 # endif
00200 }
00201
00202
00203
00204
00205
00206
00207 void __allegro_gl_set_extensions(AGL_EXT *ext) {
00208
00209 if (!ext) {
00210 return;
00211 }
00212
00213 #define AGL_API(type, name, args) __agl##name = ext->name;
00214 # include "allegrogl/GLext/gl_ext_api.h"
00215 #undef AGL_API
00216 #ifdef ALLEGRO_WINDOWS
00217 #define AGL_API(type, name, args) __awgl##name = ext->name;
00218 # include "allegrogl/GLext/wgl_ext_api.h"
00219 #undef AGL_API
00220 #elif defined ALLEGRO_UNIX
00221 #define AGL_API(type, name, args) __aglX##name = ext->name;
00222 # include "allegrogl/GLext/glx_ext_api.h"
00223 #undef AGL_API
00224 #endif
00225 }
00226
00227
00228
00229
00230 void __allegro_gl_destroy_extensions(AGL_EXT *ext) {
00231
00232 if (ext) {
00233 if (ext == agl_extension_table) {
00234 agl_extension_table = NULL;
00235 }
00236 free(ext);
00237 }
00238 }
00239
00240
00241
00242
00243
00244
00245
00246 int __allegro_gl_look_for_an_extension(AL_CONST char *name,
00247 AL_CONST GLubyte * extensions)
00248 {
00249 AL_CONST GLubyte *start;
00250 GLubyte *where, *terminator;
00251
00252
00253 where = (GLubyte *) strchr(name, ' ');
00254 if (where || *name == '\0')
00255 return FALSE;
00256
00257
00258
00259 start = extensions;
00260 for (;;) {
00261 where = (GLubyte *) strstr((AL_CONST char *) start, name);
00262 if (!where)
00263 break;
00264 terminator = where + strlen(name);
00265 if (where == start || *(where - 1) == ' ')
00266 if (*terminator == ' ' || *terminator == '\0')
00267 return TRUE;
00268 start = terminator;
00269 }
00270 return FALSE;
00271 }
00272
00273
00274
00275 #ifdef ALLEGRO_WINDOWS
00276 static AGL_GetExtensionsStringARB_t __wglGetExtensionsStringARB = NULL;
00277 static HDC __hdc = NULL;
00278 #elif defined ALLEGRO_UNIX
00279 #include <xalleg.h>
00280 #endif
00281
00282
00283
00299 int allegro_gl_is_extension_supported(AL_CONST char *extension)
00300 {
00301 int ret;
00302
00303 if (!__allegro_gl_valid_context)
00304 return FALSE;
00305
00306 if (!glGetString(GL_EXTENSIONS))
00307 return FALSE;
00308
00309 ret = __allegro_gl_look_for_an_extension(extension,
00310 glGetString(GL_EXTENSIONS));
00311
00312 #ifdef ALLEGRO_WINDOWS
00313 if (!ret && strncmp(extension, "WGL", 3) == 0) {
00314 if (!__wglGetExtensionsStringARB || __hdc != __allegro_gl_hdc) {
00315 __wglGetExtensionsStringARB = (AGL_GetExtensionsStringARB_t)
00316 wglGetProcAddress("wglGetExtensionsStringARB");
00317 __hdc = __allegro_gl_hdc;
00318 }
00319 if (__wglGetExtensionsStringARB) {
00320 ret = __allegro_gl_look_for_an_extension(extension,
00321 __wglGetExtensionsStringARB(__allegro_gl_hdc));
00322 }
00323 }
00324 #elif defined ALLEGRO_UNIX
00325 if (!ret && strncmp(extension, "GLX", 3) == 0) {
00326 ret = __allegro_gl_look_for_an_extension(extension,
00327 (const GLubyte*)glXQueryExtensionsString(_xwin.display,
00328 _xwin.screen));
00329 }
00330 #endif
00331
00332 return ret;
00333 }
00334
00335
00336
00337
00363 void *allegro_gl_get_proc_address(AL_CONST char *name)
00364 {
00365 void *symbol = NULL;
00366 #ifdef ALLEGRO_MACOSX
00367 CFStringRef function;
00368 #endif
00369
00370 if (!__allegro_gl_valid_context)
00371 return NULL;
00372
00373 #ifdef ALLEGROGL_GENERIC_DRIVER
00374
00375
00376
00377 symbol = AMesaGetProcAddress(name);
00378
00379 #elif defined ALLEGRO_WINDOWS
00380
00381
00382
00383
00384
00385 symbol = wglGetProcAddress(name);
00386 #elif defined ALLEGROGL_UNIX
00387 if (aglXGetProcAddress) {
00388
00389
00390
00391
00392 symbol = aglXGetProcAddress(name);
00393 }
00394 #elif defined ALLEGROGL_HAVE_DYNAMIC_LINK
00395 else {
00396
00397
00398
00399 if (__agl_handle) {
00400 symbol = dlsym(__agl_handle, name);
00401 }
00402 }
00403 #elif defined ALLEGRO_MACOSX
00404 function = CFStringCreateWithCString(kCFAllocatorDefault, name,
00405 kCFStringEncodingASCII);
00406 if (function) {
00407 symbol = CFBundleGetFunctionPointerForName(opengl_bundle_ref, function);
00408 CFRelease(function);
00409 }
00410 #else
00411
00412
00413
00414
00415 #endif
00416
00417 if (!symbol) {
00418
00419 #if defined ALLEGROGL_HAVE_DYNAMIC_LINK
00420 if (!aglXGetProcAddress) {
00421 TRACE("** Warning ** get_proc_address: libdl::dlsym: %s\n",
00422 dlerror());
00423 }
00424 #endif
00425
00426 TRACE("** Warning ** get_proc_address : Unable to load symbol %s\n",
00427 name);
00428 }
00429 else {
00430 TRACE("* Note * get_proc_address : Symbol %s successfully loaded\n",
00431 name);
00432 }
00433 return symbol;
00434 }
00435
00436
00437
00438
00439
00440 static void __fill_in_info_struct(const GLubyte *rendereru,
00441 struct allegro_gl_info *info) {
00442 const char *renderer = (const char*)rendereru;
00443
00444
00445 if (strstr(renderer, "3Dfx/Voodoo")) {
00446 info->is_voodoo = 1;
00447 }
00448 else if (strstr(renderer, "Matrox G200")) {
00449 info->is_matrox_g200 = 1;
00450 }
00451 else if (strstr(renderer, "RagePRO")) {
00452 info->is_ati_rage_pro = 1;
00453 }
00454 else if (strstr(renderer, "RADEON 7000")) {
00455 info->is_ati_radeon_7000 = 1;
00456 }
00457 else if (strstr(renderer, "Mesa DRI R200")) {
00458 info->is_ati_r200_chip = 1;
00459 }
00460
00461 if ((strncmp(renderer, "3Dfx/Voodoo3 ", 13) == 0)
00462 || (strncmp(renderer, "3Dfx/Voodoo2 ", 13) == 0)
00463 || (strncmp(renderer, "3Dfx/Voodoo ", 12) == 0)) {
00464 info->is_voodoo3_and_under = 1;
00465 }
00466
00467
00468 info->version = allegro_gl_opengl_version();
00469
00470 return;
00471 }
00472
00473
00474
00475
00476
00477
00478
00479 void __allegro_gl_manage_extensions(void)
00480 {
00481 AL_CONST GLubyte *buf;
00482 int i;
00483
00484 #ifdef ALLEGRO_MACOSX
00485 CFURLRef bundle_url;
00486 #endif
00487
00488
00489 #if LOGLEVEL >= 1
00490 AGL_LOG(1, "OpenGL Extensions:\n");
00491 __allegro_gl_print_extensions((AL_CONST char*)
00492 glGetString(GL_EXTENSIONS));
00493 #endif
00494
00495
00496 buf = gluGetString(GLU_VERSION);
00497 TRACE("GLU Version : %s\n\n", buf);
00498
00499 #ifdef ALLEGROGL_HAVE_DYNAMIC_LINK
00500
00501 __agl_handle = dlopen("libGL.so", RTLD_LAZY);
00502 if (__agl_handle) {
00503 aglXGetProcAddress = (GLXGETPROCADDRESSARBPROC) dlsym(__agl_handle,
00504 "glXGetProcAddressARB");
00505 if (!aglXGetProcAddress) {
00506 aglXGetProcAddress = (GLXGETPROCADDRESSARBPROC) dlsym(__agl_handle,
00507 "glXGetProcAddress");
00508 }
00509 }
00510 else {
00511 TRACE("** Warning ** Failed to dlopen libGL.so : %s\n", dlerror());
00512 }
00513 TRACE("glXGetProcAddress Extension: %s\n",
00514 aglXGetProcAddress ? "Supported" : "Unsupported");
00515 #elif defined ALLEGRO_UNIX
00516 #ifdef ALLEGROGL_GLXGETPROCADDRESSARB
00517 TRACE("glXGetProcAddressARB Extension: supported\n");
00518 #else
00519 TRACE("glXGetProcAddress Extension: supported\n");
00520 #endif
00521 #endif
00522
00523 #ifdef ALLEGRO_MACOSX
00524 bundle_url = CFURLCreateWithFileSystemPath(kCFAllocatorDefault,
00525 CFSTR("/System/Library/Frameworks/OpenGL.framework"),
00526 kCFURLPOSIXPathStyle, true);
00527 opengl_bundle_ref = CFBundleCreate(kCFAllocatorDefault, bundle_url);
00528 CFRelease(bundle_url);
00529 #endif
00530
00531 __fill_in_info_struct(glGetString(GL_RENDERER), &allegro_gl_info);
00532
00533
00534 agl_extension_table = __allegro_gl_create_extensions();
00535 __allegro_gl_load_extensions(agl_extension_table);
00536 __allegro_gl_set_extensions(agl_extension_table);
00537
00538 for (i = 0; i < 5; i++) {
00539 __allegro_gl_texture_read_format[i] = -1;
00540 __allegro_gl_texture_components[i] = GL_RGB;
00541 }
00542 __allegro_gl_texture_read_format[3] = GL_UNSIGNED_BYTE;
00543 __allegro_gl_texture_read_format[4] = GL_UNSIGNED_BYTE;
00544 __allegro_gl_texture_components[4] = GL_RGBA;
00545
00546
00547
00548 # define AGL_EXT(name, ver) { \
00549 allegro_gl_extensions_GL.name = \
00550 allegro_gl_is_extension_supported("GL_" #name) \
00551 || (allegro_gl_info.version >= ver && ver > 0); \
00552 }
00553 # include "allegrogl/GLext/gl_ext_list.h"
00554 # undef AGL_EXT
00555
00556 #ifdef ALLEGRO_UNIX
00557 # define AGL_EXT(name, ver) { \
00558 allegro_gl_extensions_GLX.name = \
00559 allegro_gl_is_extension_supported("GLX_" #name) \
00560 || (allegro_gl_info.version >= ver && ver > 0); \
00561 }
00562 # include "allegrogl/GLext/glx_ext_list.h"
00563 # undef AGL_EXT
00564 #elif defined ALLEGRO_WINDOWS
00565 # define AGL_EXT(name, ver) { \
00566 allegro_gl_extensions_WGL.name = \
00567 allegro_gl_is_extension_supported("WGL_" #name) \
00568 || (allegro_gl_info.version >= ver && ver > 0); \
00569 }
00570 # include "allegrogl/GLext/wgl_ext_list.h"
00571 # undef AGL_EXT
00572 #endif
00573
00574
00575 if (allegro_gl_extensions_GL.ARB_multitexture) {
00576 glGetIntegerv(GL_MAX_TEXTURE_UNITS,
00577 (GLint*)&allegro_gl_info.num_texture_units);
00578 }
00579 else {
00580 allegro_gl_info.num_texture_units = 1;
00581 }
00582
00583
00584 glGetIntegerv(GL_MAX_TEXTURE_SIZE,
00585 (GLint*)&allegro_gl_info.max_texture_size);
00586
00587
00588
00589
00590 allegro_gl_extensions_GL.EXT_packed_pixels &= !allegro_gl_info.is_voodoo;
00591
00592
00593 if (allegro_gl_extensions_GL.EXT_packed_pixels) {
00594
00595 AGL_LOG(1, "Packed Pixels formats available\n");
00596
00597
00598
00599 __allegro_gl_texture_read_format[0] = GL_UNSIGNED_BYTE_3_3_2;
00600 __allegro_gl_texture_read_format[1] = GL_UNSIGNED_SHORT_5_5_5_1;
00601 __allegro_gl_texture_read_format[2] = GL_UNSIGNED_SHORT_5_6_5;
00602 }
00603
00604
00605
00606
00607
00608
00609 { const char *vendor = (const char*)glGetString(GL_VENDOR);
00610 if (strstr(vendor, "NVIDIA Corporation")) {
00611 if (!allegro_gl_extensions_GL.NV_fragment_program2
00612 || !allegro_gl_extensions_GL.NV_vertex_program3) {
00613 allegro_gl_extensions_GL.ARB_texture_non_power_of_two = 0;
00614 }
00615 }
00616 else if (strstr(vendor, "ATI Technologies")) {
00617 if (!strstr((const char*)glGetString(GL_EXTENSIONS),
00618 "GL_ARB_texture_non_power_of_two")
00619 && allegro_gl_info.version >= 2.0f) {
00620 allegro_gl_extensions_GL.ARB_texture_non_power_of_two = 0;
00621 }
00622 }
00623 }
00624
00625 TRACE("\n");
00626 }
00627
00628
00629
00630
00631
00632
00633
00634
00635 void __allegro_gl_print_extensions(AL_CONST char * extension)
00636 {
00637 char buf[80];
00638 char* start;
00639
00640 while (*extension != '\0') {
00641 start = buf;
00642 strncpy(buf, extension, 80);
00643 while ((*start != ' ') && (*start != '\0')) {
00644 extension++;
00645 start++;
00646 }
00647 *start = '\0';
00648 extension ++;
00649 TRACE("\t%s\n", buf);
00650 }
00651 TRACE("\n");
00652 }
00653
00654
00655
00656 void __allegro_gl_unmanage_extensions() {
00657 __allegro_gl_destroy_extensions(agl_extension_table);
00658 #ifdef ALLEGRO_MACOSX
00659 CFRelease(opengl_bundle_ref);
00660 #endif
00661 #ifdef ALLEGROGL_HAVE_DYNAMIC_LINK
00662 if (__agl_handle) {
00663 dlclose(__agl_handle);
00664 __agl_handle = NULL;
00665 }
00666 #endif
00667 }
00668