www.pudn.com > simple_fragment_program2.zip > glh_extensions.h


// Comments: 
// 
//   The trick with GLH_EXT_SINGLE_FILE is that you need to have it defined in 
// exactly one cpp file because it piggy-backs the function implementations in 
// the header.  You don't want multiple implementations defined or the linker 
// gets mad, but one file must have the implementations in it or the linker 
// gets mad for different reasons. 
//  
//   The goal was to avoid having this helper require a separate cpp file.  One 
// thing you could do is just have a glh_extensions.cpp that did 
//  
// #define GLH_EXT_SINGLE_FILE 
// #include  
// 
// and make it the only file that ever defines GLH_EXT_SINGLE_FILE. 
 
#ifndef GLH_EXTENSIONS 
#define GLH_EXTENSIONS 
 
#include  
#include  
#include  
 
#if defined(WIN32) 
# include  
#endif 
 
#ifdef MACOS 
#include  
#else 
#include  
#endif 
 
#ifdef WIN32 
# include  
#endif 
 
#define CHECK_MEMORY(ptr) \ 
    if (NULL == ptr) { \ 
        printf("Error allocating memory in file %s, line %d\n", __FILE__, __LINE__); \ 
        exit(-1); \ 
    } 
 
#ifdef GLH_EXT_SINGLE_FILE 
#  define GLH_EXTENSIONS_SINGLE_FILE  // have to do this because glh_genext.h unsets GLH_EXT_SINGLE_FILE 
#endif 
 
#if (defined(WIN32) || defined(UNIX)) 
#include "glh_genext.h" 
#elif defined(MACOS) 
#include  
#else 
#include  
#endif 
 
#ifdef __cplusplus 
extern "C" { 
#endif 
 
#ifdef GLH_EXTENSIONS_SINGLE_FILE 
static char *unsupportedExts = NULL; 
static char *sysExts = NULL; 
#ifndef GL_SHADER_CONSISTENT_NV 
#define GL_SHADER_CONSISTENT_NV           0x86DD 
#endif 
#ifndef GL_TEXTURE_SHADER_NV 
#define GL_TEXTURE_SHADER_NV              0x86DE 
#endif 
#ifndef GL_SHADER_OPERATION_NV 
#define GL_SHADER_OPERATION_NV            0x86DF 
#endif 
 
static int ExtensionExists(const char* extName, const char* sysExts) 
{ 
    char *padExtName = (char*)malloc(strlen(extName) + 2); 
    strcat(strcpy(padExtName, extName), " "); 
 
    if (0 == strcmp(extName, "GL_VERSION_1_2")) { 
        const char *version = (const char*)glGetString(GL_VERSION); 
        if (strstr(version, "1.0") == version || strstr(version, "1.1") == version) { 
            return GL_FALSE; 
        } else { 
            return GL_TRUE; 
        } 
    } 
    if (0 == strcmp(extName, "GL_VERSION_1_3")) { 
        const char *version = (const char*)glGetString(GL_VERSION); 
        if (strstr(version, "1.0") == version || 
            strstr(version, "1.1") == version || 
            strstr(version, "1.2") == version) { 
            return GL_FALSE; 
        } else { 
            return GL_TRUE; 
        } 
    } 
    if (0 == strcmp(extName, "GL_VERSION_1_4")) { 
        const char *version = (const char*)glGetString(GL_VERSION); 
        if (strstr(version, "1.0") == version || 
            strstr(version, "1.1") == version || 
            strstr(version, "1.2") == version ||  
            strstr(version, "1.3") == version) { 
            return GL_FALSE; 
        } else { 
            return GL_TRUE; 
        } 
    } 
    if (0 == strcmp(extName, "GL_VERSION_1_5")) { 
        const char *version = (const char*)glGetString(GL_VERSION); 
        if (strstr(version, "1.0") == version || 
            strstr(version, "1.1") == version || 
            strstr(version, "1.2") == version ||  
            strstr(version, "1.3") == version ||  
            strstr(version, "1.4") == version) { 
            return GL_FALSE; 
        } else { 
            return GL_TRUE; 
        } 
    } 
    if (strstr(sysExts, padExtName)) { 
        free(padExtName); 
        return GL_TRUE; 
    } else { 
        free(padExtName); 
        return GL_FALSE; 
    } 
} 
 
static const char* EatWhiteSpace(const char *str) 
{ 
    for (; *str && (' ' == *str || '\t' == *str || '\n' == *str); str++); 
    return str; 
} 
 
static const char* EatNonWhiteSpace(const char *str) 
{ 
    for (; *str && (' ' != *str && '\t' != *str && '\n' != *str); str++); 
    return str; 
} 
 
int glh_init_extensions(const char *origReqExts) 
{ 
    // Length of requested extensions string 
    size_t reqExtsLen; 
    char *reqExts; 
    // Ptr for individual extensions within reqExts 
    char *reqExt; 
    int success = GL_TRUE; 
    // build space-padded extension string 
    if (NULL == sysExts) { 
        const char *extensions = (const char*)glGetString(GL_EXTENSIONS); 
        size_t sysExtsLen = strlen(extensions); 
        const char *winsys_extensions = "";      
        size_t winsysExtsLen = 0; 
#if defined(WIN32) 
        { 
            PFNWGLGETEXTENSIONSSTRINGARBPROC wglGetExtensionsStringARB = 0; 
            wglGetExtensionsStringARB = (PFNWGLGETEXTENSIONSSTRINGARBPROC)wglGetProcAddress("wglGetExtensionsStringARB"); 
            if(wglGetExtensionsStringARB) 
            { 
                winsys_extensions = wglGetExtensionsStringARB(wglGetCurrentDC()); 
                winsysExtsLen = strlen(winsys_extensions); 
            } 
        } 
#elif defined(UNIX) 
        { 
 
          winsys_extensions = glXQueryExtensionsString (glXGetCurrentDisplay(),DefaultScreen(glXGetCurrentDisplay())) ; 
          winsysExtsLen = strlen (winsys_extensions); 
        } 
#endif 
        // Add 2 bytes, one for padding space, one for terminating NULL 
        sysExts = (char*)malloc(sysExtsLen + winsysExtsLen + 3); 
        CHECK_MEMORY(sysExts); 
        strcpy(sysExts, extensions); 
        sysExts[sysExtsLen] = ' '; 
        sysExts[sysExtsLen + 1] = 0; 
        strcat(sysExts, winsys_extensions); 
        sysExts[sysExtsLen + 1 + winsysExtsLen] = ' '; 
        sysExts[sysExtsLen + 1 + winsysExtsLen + 1] = 0; 
    } 
 
    if (NULL == origReqExts) 
        return GL_TRUE; 
    reqExts = strdup(origReqExts); 
    reqExtsLen = strlen(reqExts); 
    if (NULL == unsupportedExts) { 
        unsupportedExts = (char*)malloc(reqExtsLen + 2); 
    } else if (reqExtsLen > strlen(unsupportedExts)) { 
        unsupportedExts = (char*)realloc(unsupportedExts, reqExtsLen + 2); 
    } 
    CHECK_MEMORY(unsupportedExts); 
    *unsupportedExts = 0; 
 
    // Parse requested extension list 
    for (reqExt = reqExts; 
        (reqExt = (char*)EatWhiteSpace(reqExt)) && *reqExt; 
        reqExt = (char*)EatNonWhiteSpace(reqExt)) 
    { 
        char *extEnd = (char*)EatNonWhiteSpace(reqExt); 
        char saveChar = *extEnd; 
        *extEnd = (char)0; 
 
#if (defined(WIN32) || defined(UNIX)) 
        if (!ExtensionExists(reqExt, sysExts) || !glh_init_extension(reqExt)) { 
#elif defined(MACOS) 
        if (!ExtensionExists(reqExt, sysExts)) {    // don't try to get function pointers if on MacOS 
#endif 
            // add reqExt to end of unsupportedExts 
            strcat(unsupportedExts, reqExt); 
            strcat(unsupportedExts, " "); 
            success = GL_FALSE; 
        } 
        *extEnd = saveChar; 
    } 
    free(reqExts); 
    return success; 
} 
 
const char* glh_get_unsupported_extensions() 
{ 
    return (const char*)unsupportedExts; 
} 
 
void glh_shutdown_extensions() 
{ 
    if (unsupportedExts) 
    { 
        free(unsupportedExts); 
        unsupportedExts = NULL; 
    } 
    if (sysExts) 
    { 
        free(sysExts); 
        sysExts = NULL; 
    } 
} 
 
int glh_extension_supported(const char *extension) 
{ 
    static const GLubyte *extensions = NULL; 
    const GLubyte *start; 
    GLubyte *where, *terminator; 
     
    // Extension names should not have spaces. 
    where = (GLubyte *) strchr(extension, ' '); 
    if (where || *extension == '\0') 
      return 0; 
     
    if (!extensions) 
      extensions = glGetString(GL_EXTENSIONS); 
 
    // It takes a bit of care to be fool-proof about parsing the 
    // OpenGL extensions string.  Don't be fooled by sub-strings, 
    // etc. 
    start = extensions; 
    for (;;)  
    { 
        where = (GLubyte *) strstr((const char *) start, extension); 
        if (!where) 
            break; 
        terminator = where + strlen(extension); 
        if (where == start || *(where - 1) == ' ')  
        { 
            if (*terminator == ' ' || *terminator == '\0')  
            { 
                return 1; 
            } 
        } 
        start = terminator; 
    } 
    return 0; 
} 
 
#else 
int glh_init_extensions(const char *origReqExts); 
const char* glh_get_unsupported_extensions(); 
void glh_shutdown_extensions(); 
int glh_extension_supported(const char *extension); 
#endif /* GLH_EXT_SINGLE_FILE */ 
 
#ifdef __cplusplus 
} 
#endif 
 
#endif /* GLH_EXTENSIONS */