Main Page | Modules | File List | Globals | Related Pages

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("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("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                 glXQueryExtensionsString(_xwin.display, _xwin.screen));
00328     }
00329 #endif
00330 
00331     return ret;
00332 }
00333 
00334 
00335 
00336 /* void * allegro_gl_get_proc_address(AL_CONST char *name) */
00362 void *allegro_gl_get_proc_address(AL_CONST char *name)
00363 {
00364     void *symbol = NULL;
00365 #ifdef ALLEGRO_MACOSX
00366     CFStringRef function;
00367 #endif
00368 
00369     if (!__allegro_gl_valid_context)
00370         return NULL;
00371 
00372 #ifdef ALLEGROGL_GENERIC_DRIVER
00373     /* AMesa provides a function to get a proc address. It does
00374      * not emulate dynamic linking of course...
00375      */
00376     symbol = AMesaGetProcAddress(name);
00377 
00378 #elif defined ALLEGRO_WINDOWS
00379     /* For once Windows is the easiest platform to use :)
00380      * It provides a standardized way to get a function address
00381      * But of course there is a drawback : the symbol is only valid
00382      * under the current context :P
00383      */
00384     symbol = wglGetProcAddress(name);
00385 #elif defined ALLEGROGL_UNIX
00386     if (aglXGetProcAddress) {
00387         /* This is definitely the *good* way on Unix to get a GL proc
00388          * address. Unfortunately glXGetProcAddress is an extension
00389          * and may not be available on all platforms
00390          */
00391         symbol = aglXGetProcAddress(name);
00392     }
00393 #elif defined ALLEGROGL_HAVE_DYNAMIC_LINK
00394     else {
00395         /* Hack if glXGetProcAddress is not available :
00396          * we try to find the symbol into libGL.so
00397          */
00398         if (__agl_handle) {
00399             symbol = dlsym(__agl_handle, name);
00400         }
00401     }
00402 #elif defined ALLEGRO_MACOSX
00403     function = CFStringCreateWithCString(kCFAllocatorDefault, name,
00404                                          kCFStringEncodingASCII);
00405     if (function) {
00406         symbol = CFBundleGetFunctionPointerForName(opengl_bundle_ref, function);
00407         CFRelease(function);
00408     }
00409 #else
00410     /* DOS does not support dynamic linking. If the function is not
00411      * available at build-time then it will not be available at run-time
00412      * Therefore we do not need to look for it...
00413      */
00414 #endif
00415 
00416     if (!symbol) {
00417 
00418 #if defined ALLEGROGL_HAVE_DYNAMIC_LINK
00419         if (!aglXGetProcAddress) {
00420             TRACE("** Warning ** get_proc_address: libdl::dlsym: %s\n",
00421                   dlerror());
00422         }
00423 #endif
00424         
00425         TRACE("** Warning ** get_proc_address : Unable to load symbol %s\n",
00426               name);
00427     }
00428     else {
00429         TRACE("* Note * get_proc_address : Symbol %s successfully loaded\n",
00430               name);
00431     }
00432     return symbol;
00433 }
00434 
00435 
00436 
00437 /* Fills in the AllegroGL info struct for blacklisting video cards.
00438  */
00439 void __fill_in_info_struct(const char *renderer, struct allegro_gl_info *info) {
00440     
00441     /* Some cards are "special"... */
00442     if (strstr(renderer, "3Dfx/Voodoo")) {
00443         info->is_voodoo = 1;
00444     }
00445     else if (strstr(renderer, "Matrox G200")) {
00446         info->is_matrox_g200 = 1;
00447     }
00448     else if (strstr(renderer, "RagePRO")) {
00449         info->is_ati_rage_pro = 1;
00450     }
00451     else if (strstr(renderer, "RADEON 7000")) {
00452         info->is_ati_radeon_7000 = 1;
00453     }
00454     else if (strstr(renderer, "Mesa DRI R200")) {
00455         info->is_ati_r200_chip = 1;
00456     }
00457 
00458     if ((strncmp(renderer, "3Dfx/Voodoo3 ", 13) == 0)
00459      || (strncmp(renderer, "3Dfx/Voodoo2 ", 13) == 0) 
00460      || (strncmp(renderer, "3Dfx/Voodoo ", 12) == 0)) {
00461         info->is_voodoo3_and_under = 1;
00462     }
00463 
00464     /* Read OpenGL properties */    
00465     info->version = allegro_gl_opengl_version();
00466 
00467     return;
00468 }
00469 
00470 
00471 
00472 /* __allegro_gl_manage_extensions:
00473  * This functions fills the __allegro_gl_extensions structure and displays
00474  * on the log file which extensions are available
00475  */
00476 void __allegro_gl_manage_extensions(void)
00477 {
00478     AL_CONST GLubyte *buf;
00479     int i;
00480 
00481 #ifdef ALLEGRO_MACOSX
00482     CFURLRef bundle_url;
00483 #endif
00484 
00485     /* Print out OpenGL extensions */
00486 #if LOGLEVEL >= 1
00487     AGL_LOG(1, "OpenGL Extensions:\n");
00488              __allegro_gl_print_extensions((AL_CONST char*)
00489             glGetString(GL_EXTENSIONS));
00490 #endif
00491     
00492     /* Print out GLU version */
00493     buf = gluGetString(GLU_VERSION);
00494     TRACE("GLU Version : %s\n\n", buf);
00495 
00496 #ifdef ALLEGROGL_HAVE_DYNAMIC_LINK
00497     /* Get glXGetProcAddress entry */
00498     __agl_handle = dlopen("libGL.so", RTLD_LAZY);
00499     if (__agl_handle) {
00500         aglXGetProcAddress = (GLXGETPROCADDRESSARBPROC) dlsym(__agl_handle,
00501                                                         "glXGetProcAddressARB");
00502         if (!aglXGetProcAddress) {
00503             aglXGetProcAddress = (GLXGETPROCADDRESSARBPROC) dlsym(__agl_handle,
00504                                                            "glXGetProcAddress");
00505         }
00506     }
00507     else {
00508         TRACE("** Warning ** Failed to dlopen libGL.so : %s\n", dlerror());
00509     }
00510     TRACE("glXGetProcAddress Extension: %s\n",
00511                            aglXGetProcAddress ? "Supported" : "Unsupported");
00512 #elif defined ALLEGRO_UNIX
00513 #ifdef ALLEGROGL_GLXGETPROCADDRESSARB
00514     TRACE("glXGetProcAddressARB Extension: supported\n");
00515 #else
00516     TRACE("glXGetProcAddress Extension: supported\n");
00517 #endif
00518 #endif
00519     
00520 #ifdef ALLEGRO_MACOSX
00521     bundle_url = CFURLCreateWithFileSystemPath(kCFAllocatorDefault,
00522                          CFSTR("/System/Library/Frameworks/OpenGL.framework"),
00523                          kCFURLPOSIXPathStyle, true);
00524     opengl_bundle_ref = CFBundleCreate(kCFAllocatorDefault, bundle_url);
00525     CFRelease(bundle_url);
00526 #endif
00527 
00528     __fill_in_info_struct(glGetString(GL_RENDERER), &allegro_gl_info);
00529 
00530     /* Load extensions */
00531     agl_extension_table = __allegro_gl_create_extensions();
00532     __allegro_gl_load_extensions(agl_extension_table);
00533     __allegro_gl_set_extensions(agl_extension_table);
00534     
00535     for (i = 0; i < 5; i++) {
00536         __allegro_gl_texture_read_format[i] = -1;
00537         __allegro_gl_texture_components[i] = GL_RGB;
00538     }
00539     __allegro_gl_texture_read_format[3] = GL_UNSIGNED_BYTE;
00540     __allegro_gl_texture_read_format[4] = GL_UNSIGNED_BYTE;
00541     __allegro_gl_texture_components[4] = GL_RGBA;
00542 
00543     
00544     /* Get extension info for the rest of the lib */
00545 #    define AGL_EXT(name, ver) {                               \
00546         allegro_gl_extensions_GL.name =                        \
00547               allegro_gl_is_extension_supported("GL_" #name)   \
00548           || (allegro_gl_info.version >= ver && ver > 0);      \
00549     }
00550 #   include "allegrogl/GLext/gl_ext_list.h"
00551 #   undef AGL_EXT
00552 
00553 #ifdef ALLEGRO_UNIX
00554 #    define AGL_EXT(name, ver) {                               \
00555         allegro_gl_extensions_GLX.name =                       \
00556               allegro_gl_is_extension_supported("GLX_" #name)  \
00557           || (allegro_gl_info.version >= ver && ver > 0);      \
00558     }
00559 #   include "allegrogl/GLext/glx_ext_list.h"
00560 #   undef AGL_EXT
00561 #elif defined ALLEGRO_WINDOWS
00562 #    define AGL_EXT(name, ver) {                               \
00563         allegro_gl_extensions_WGL.name =                       \
00564               allegro_gl_is_extension_supported("WGL_" #name)  \
00565           || (allegro_gl_info.version >= ver && ver > 0);      \
00566     }
00567 #   include "allegrogl/GLext/wgl_ext_list.h"
00568 #   undef AGL_EXT
00569 #endif
00570     
00571     /* Get number of texture units */
00572     if (allegro_gl_extensions_GL.ARB_multitexture) {
00573         glGetIntegerv(GL_MAX_TEXTURE_UNITS,
00574                       (GLint*)&allegro_gl_info.num_texture_units);
00575     }
00576     else {
00577         allegro_gl_info.num_texture_units = 1;
00578     }
00579 
00580     /* Get max texture size */
00581     glGetIntegerv(GL_MAX_TEXTURE_SIZE,
00582                   (GLint*)&allegro_gl_info.max_texture_size);
00583 
00584     /* Note: Voodoo (even V5) don't seem to correctly support
00585      * packed pixel formats. Disabling them for those cards.
00586      */
00587     allegro_gl_extensions_GL.EXT_packed_pixels &= !allegro_gl_info.is_voodoo;
00588 
00589     
00590     if (allegro_gl_extensions_GL.EXT_packed_pixels) {
00591 
00592         AGL_LOG(1, "Packed Pixels formats available\n");
00593 
00594         /* XXX On NV cards, we want to use BGRA instead of RGBA for speed */
00595         /* Fills the __allegro_gl_texture_format array */
00596         __allegro_gl_texture_read_format[0] = GL_UNSIGNED_BYTE_3_3_2;
00597         __allegro_gl_texture_read_format[1] = GL_UNSIGNED_SHORT_5_5_5_1;
00598         __allegro_gl_texture_read_format[2] = GL_UNSIGNED_SHORT_5_6_5;
00599     }
00600 
00601     TRACE("\n");
00602 }
00603 
00604 
00605 
00606 /* __allegro_gl_print_extensions:
00607  * Given a string containing extensions (i.e. a NULL terminated string where
00608  * each extension are separated by a space and which names do not contain any
00609  * space)
00610  */
00611 void __allegro_gl_print_extensions(AL_CONST char * extension)
00612 {
00613         char buf[80];
00614         char* start;
00615 
00616         while (*extension != '\0') {
00617                 start = buf;
00618                 strncpy(buf, extension, 80);
00619                 while ((*start != ' ') && (*start != '\0')) {
00620                         extension++;
00621                         start++;
00622                 }
00623                 *start = '\0';
00624                 extension ++;
00625                 TRACE("\t%s\n", buf);
00626         }
00627         TRACE("\n");
00628 }
00629 
00630 
00631 
00632 void __allegro_gl_unmanage_extensions() {
00633     __allegro_gl_destroy_extensions(agl_extension_table);
00634 #ifdef ALLEGRO_MACOSX
00635     CFRelease(opengl_bundle_ref);
00636 #endif
00637 #ifdef ALLEGROGL_HAVE_DYNAMIC_LINK
00638     dlclose(__agl_handle);
00639 #endif
00640 }
00641 

Generated on Wed Jun 30 23:59:52 2004 for AllegroGL by doxygen 1.3.5