glext.c

Go to the documentation of this file.
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 /* GL extension Structure. Holds the extension pointers for a single context */
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 /* Current driver info */
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 /* Current context */
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 /* Handle for dynamic library libGL.so */
00087 static void* __agl_handle = NULL;
00088 /* Pointer to glXGetProcAddressARB */
00089 typedef void* (*GLXGETPROCADDRESSARBPROC) (const GLubyte*);
00090 static GLXGETPROCADDRESSARBPROC aglXGetProcAddress;
00091 #else
00092 /* Tries static linking */
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 /* Define the GL API pointers */
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 /* Create the extension table */
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 /* Load the extension addresses into the table.
00148  * Should only be done on context creation.
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 /* Set the GL API pointers to the current table 
00205  * Should only be called on context switches.
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 /* Destroys the extension table */
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 /* __allegro_gl_look_for_an_extension:
00243  * This function has been written by Mark J. Kilgard in one of his
00244  * tutorials about OpenGL extensions
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     /* Extension names should not have spaces. */
00253     where = (GLubyte *) strchr(name, ' ');
00254     if (where || *name == '\0')
00255         return FALSE;
00256     /* It takes a bit of care to be fool-proof about parsing the
00257      * OpenGL extensions string. Don't be fooled by sub-strings, etc.
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 /* int allegro_gl_is_extension_supported(AL_CONST char *extension) */
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 /* void * allegro_gl_get_proc_address(AL_CONST char *name) */
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     /* AMesa provides a function to get a proc address. It does
00375      * not emulate dynamic linking of course...
00376      */
00377     symbol = AMesaGetProcAddress(name);
00378 
00379 #elif defined ALLEGRO_WINDOWS
00380     /* For once Windows is the easiest platform to use :)
00381      * It provides a standardized way to get a function address
00382      * But of course there is a drawback : the symbol is only valid
00383      * under the current context :P
00384      */
00385     symbol = wglGetProcAddress(name);
00386 #elif defined ALLEGROGL_UNIX
00387     if (aglXGetProcAddress) {
00388         /* This is definitely the *good* way on Unix to get a GL proc
00389          * address. Unfortunately glXGetProcAddress is an extension
00390          * and may not be available on all platforms
00391          */
00392         symbol = aglXGetProcAddress(name);
00393     }
00394 #elif defined ALLEGROGL_HAVE_DYNAMIC_LINK
00395     else {
00396         /* Hack if glXGetProcAddress is not available :
00397          * we try to find the symbol into libGL.so
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     /* DOS does not support dynamic linking. If the function is not
00412      * available at build-time then it will not be available at run-time
00413      * Therefore we do not need to look for it...
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 /* Fills in the AllegroGL info struct for blacklisting video cards.
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     /* Some cards are "special"... */
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     /* Read OpenGL properties */    
00468     info->version = allegro_gl_opengl_version();
00469 
00470     return;
00471 }
00472 
00473 
00474 
00475 /* __allegro_gl_manage_extensions:
00476  * This functions fills the __allegro_gl_extensions structure and displays
00477  * on the log file which extensions are available
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     /* Print out OpenGL extensions */
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     /* Print out GLU version */
00496     buf = gluGetString(GLU_VERSION);
00497     TRACE("GLU Version : %s\n\n", buf);
00498 
00499 #ifdef ALLEGROGL_HAVE_DYNAMIC_LINK
00500     /* Get glXGetProcAddress entry */
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     /* Load extensions */
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     /* Get extension info for the rest of the lib */
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     /* Get number of texture units */
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     /* Get max texture size */
00584     glGetIntegerv(GL_MAX_TEXTURE_SIZE,
00585                   (GLint*)&allegro_gl_info.max_texture_size);
00586 
00587     /* Note: Voodoo (even V5) don't seem to correctly support
00588      * packed pixel formats. Disabling them for those cards.
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         /* XXX On NV cards, we want to use BGRA instead of RGBA for speed */
00598         /* Fills the __allegro_gl_texture_format array */
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     /* NVidia and ATI cards expose OpenGL 2.0 but often don't accelerate
00605      * non-power-of-2 textures. This check is how you verify that NP2
00606      * textures are hardware accelerated or not.
00607      * We should clobber the NPOT support if it's not accelerated.
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 /* __allegro_gl_print_extensions:
00631  * Given a string containing extensions (i.e. a NULL terminated string where
00632  * each extension are separated by a space and which names do not contain any
00633  * space)
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 

Generated on Mon Apr 3 18:20:13 2006 for AllegroGL by  doxygen 1.4.6