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