Hi Paul,

The changes look sensible.  The use of WINAPI in the typedef broke the build
so I replaced this with APIENTRY, fingers crossed this will work fine.
W.r.t GLES it doesn't get the glGetStringi function, only the glGetString
method so I presume the old pathway will be fine...

Ack, I've just done a second review of the changes I was about to check in
and don't think that just testing for GL version will be OK as GLES version
number will eventually go to 3 so would end your new code path and if
glGetStringi method isn't found it'll fail.  I'll refactor the code so that
it just does the check against the glGetStringi pointer and the version...
More news in a minute...

Robert.

On Mon, Feb 8, 2010 at 9:42 PM, Paul Martz <[email protected]> wrote:

> Hi Robert -- Here's a fix for querying the extension string under GL3.
>
> Summary: GL3 deprecates "glGetString(GL_EXTENSIONS)". In GL3, individual
> extension strings are queried by looping over GL_NUM_EXTENSIONS and calling
> "glGetStringi(GL_EXTENSIONS,<index>)".
>
> The fix is basically as follows:
>  if( GL3 )
>    Query indexed extension strings.
>  else
>    Query the old way.
>
> The "else" branch is re-indented but otherwise shouldn't contain any
> changes.
>
> Please give this an eye for how it should work on GL ES. Perhaps the simple
> check of OpenGL version is inadequate.
>
> Thanks,
> --
> Paul Martz
> Skew Matrix Software LLC
> _http://www.skew-matrix.com_ <http://www.skew-matrix.com/>
> +1 303 859 9466
>
>
> /* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
>  *
>  * This library is open source and may be redistributed and/or modified
> under
>  * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
>  * (at your option) any later version.  The full license is in LICENSE file
>  * included with this distribution, and on the openscenegraph.org website.
>  *
>  * This library is distributed in the hope that it will be useful,
>  * but WITHOUT ANY WARRANTY; without even the implied warranty of
>  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>  * OpenSceneGraph Public License for more details.
> */
> #include <osg/GLExtensions>
> #include <osg/GL>
> #include <osg/GLU>
> #include <osg/Notify>
> #include <osg/Math>
> #include <osg/buffered_value>
>
> #include <stdlib.h>
> #include <string.h>
> #include <stdio.h>
> #include <float.h>
>
> #include <string>
> #include <vector>
> #include <set>
>
> #if defined(WIN32)
> #include <windows.h>
> #endif
>
>
> typedef std::set<std::string>  ExtensionSet;
> static osg::buffered_object<ExtensionSet> s_glExtensionSetList;
> static osg::buffered_object<std::string> s_glRendererList;
> static osg::buffered_value<int> s_glInitializedList;
>
> static osg::buffered_object<ExtensionSet> s_gluExtensionSetList;
> static osg::buffered_object<std::string> s_gluRendererList;
> static osg::buffered_value<int> s_gluInitializedList;
>
> float osg::getGLVersionNumber()
> {
>    // needs to be extended to do proper things with subversions like 1.5.1,
> etc.
>    char *versionstring   = (char*) glGetString( GL_VERSION );
>    if (!versionstring) return 0.0;
>
>    std::string vs( versionstring );
>    return( asciiToFloat( vs.substr( 0, vs.find( " " ) ).c_str() ) );
> }
>
> bool osg::isExtensionInExtensionString(const char *extension, const char
> *extensionString)
> {
>    const char *startOfWord = extensionString;
>    const char *endOfWord;
>    while ((endOfWord = strchr(startOfWord,' ')) != 0)
>    {
>        if (strncmp(extension, startOfWord, endOfWord - startOfWord) == 0)
>            return true;
>        startOfWord = endOfWord+1;
>    }
>    if (*startOfWord && strcmp(extension, startOfWord) == 0)
>        return true;
>
>   return false;
> }
>
> bool osg::isGLExtensionSupported(unsigned int contextID, const char
> *extension)
> {
>    return osg::isGLExtensionOrVersionSupported(contextID, extension,
> FLT_MAX);
> }
>
> bool osg::isGLExtensionOrVersionSupported(unsigned int contextID, const
> char *extension, float requiredGLVersion)
> {
>    ExtensionSet& extensionSet = s_glExtensionSetList[contextID];
>    std::string& rendererString = s_glRendererList[contextID];
>
>    // first check to see if GL version number of recent enough.
>    bool result = requiredGLVersion <= osg::getGLVersionNumber();
>
>    if (!result)
>    {
>        // if not already set up, initialize all the per graphic context
> values.
>        if (!s_glInitializedList[contextID])
>        {
>            s_glInitializedList[contextID] = 1;
>
>            // set up the renderer
>            const GLubyte* renderer = glGetString(GL_RENDERER);
>            rendererString = renderer ? (const char*)renderer : "";
>
>            // get the extension list from OpenGL.
>            if( osg::getGLVersionNumber() >= 3.0 )
>            {
>                // OpenGL 3.0 adds the concept of indexed strings and
>                // deprecates calls to glGetString( GL_EXTENSIONS ), which
>                // will now generate GL_INVALID_ENUM.
>
>                // Get extensions using new indexed string interface.
>
>                typedef const GLubyte * WINAPI PFNGLGETSTRINGIPROC( GLenum,
> GLuint );
>                PFNGLGETSTRINGIPROC* glGetStringi = 0;
>                setGLExtensionFuncPtr( glGetStringi, "glGetStringi");
>
>                if( glGetStringi != NULL )
>                {
>    #  ifndef GL_NUM_EXTENSIONS
>    #    define GL_NUM_EXTENSIONS 0x821D
>    #  endif
>                    GLint numExt;
>                    glGetIntegerv( GL_NUM_EXTENSIONS, &numExt );
>                    int idx;
>                    for( idx=0; idx<numExt; idx++ )
>                    {
>                        extensionSet.insert( std::string( (char*)(
> glGetStringi( GL_EXTENSIONS, idx ) ) ) );
>                    }
>                }
>                else
>                {
>                    osg::notify( osg::WARN ) <<
> "isGLExtensionOrVersionSupported: Can't obtain glGetStringi function
> pointer." << std::endl;
>                }
>            }
>            else
>            {
>                // Get extensions using GL1/2 interface.
>
>                const char* extensions = (const
> char*)glGetString(GL_EXTENSIONS);
>                if (extensions==NULL) return false;
>
>                // insert the ' ' delimiated extensions words into the
> extensionSet.
>                const char *startOfWord = extensions;
>                const char *endOfWord;
>                while ((endOfWord = strchr(startOfWord,' '))!=NULL)
>                {
>                    extensionSet.insert(std::string(startOfWord,endOfWord));
>                    startOfWord = endOfWord+1;
>                }
>                if (*startOfWord!=0)
> extensionSet.insert(std::string(startOfWord));
>            }
>
>    #if defined(WIN32) && (defined(OSG_GL1_AVAILABLE) ||
> defined(OSG_GL2_AVAILABLE) || defined(OSG_GL3_AVAILABLE))
>
>            // add WGL extensions to the list
>
>            typedef const char* WINAPI WGLGETEXTENSIONSSTRINGARB(HDC);
>            WGLGETEXTENSIONSSTRINGARB* wglGetExtensionsStringARB = 0;
>            setGLExtensionFuncPtr(wglGetExtensionsStringARB,
> "wglGetExtensionsStringARB");
>
>            typedef const char* WINAPI WGLGETEXTENSIONSSTRINGEXT();
>            WGLGETEXTENSIONSSTRINGEXT* wglGetExtensionsStringEXT = 0;
>            setGLExtensionFuncPtr(wglGetExtensionsStringEXT,
> "wglGetExtensionsStringEXT");
>
>            const char* wglextensions = 0;
>
>            if (wglGetExtensionsStringARB)
>            {
>                HDC dc = wglGetCurrentDC();
>                wglextensions = wglGetExtensionsStringARB(dc);
>            }
>            else if (wglGetExtensionsStringEXT)
>            {
>                wglextensions = wglGetExtensionsStringEXT();
>            }
>
>            if (wglextensions)
>            {
>                const char* startOfWord = wglextensions;
>                const char* endOfWord;
>                while ((endOfWord = strchr(startOfWord, ' ')))
>                {
>                    extensionSet.insert(std::string(startOfWord,
> endOfWord));
>                    startOfWord = endOfWord+1;
>                }
>                if (*startOfWord != 0)
> extensionSet.insert(std::string(startOfWord));
>            }
>
>    #endif
>
>            osg::notify(INFO)<<"OpenGL extensions supported by installed
> OpenGL drivers are:"<<std::endl;
>            for(ExtensionSet::iterator itr=extensionSet.begin();
>                itr!=extensionSet.end();
>                ++itr)
>            {
>                osg::notify(INFO)<<"    "<<*itr<<std::endl;
>            }
>
>        }
>
>        // true if extension found in extensionSet.
>        result = extensionSet.find(extension)!=extensionSet.end();
>    }
>
>    // now see if extension is in the extension disabled list
>    bool extensionDisabled = false;
>    if (result)
>    {
>
>        const std::string& disableString = getGLExtensionDisableString();
>        if (!disableString.empty())
>        {
>
>            std::string::size_type pos=0;
>            while ( pos!=std::string::npos &&
> (pos=disableString.find(extension,pos))!=std::string::npos )
>            {
>                std::string::size_type previousColon =
> disableString.find_last_of(':',pos);
>                std::string::size_type previousSemiColon =
> disableString.find_last_of(';',pos);
>
>                std::string renderer = "";
>                if (previousColon!=std::string::npos)
>                {
>                    if (previousSemiColon==std::string::npos) renderer =
> disableString.substr(0,previousColon);
>                    else if (previousSemiColon<previousColon) renderer =
> disableString.substr(previousSemiColon+1,previousColon-previousSemiColon-1);
>                }
>
>                if (!renderer.empty())
>                {
>
>                    // remove leading spaces if they exist.
>                    std::string::size_type leadingSpaces =
> renderer.find_first_not_of(' ');
>                    if (leadingSpaces==std::string::npos) renderer = ""; //
> nothing but spaces
>                    else if (leadingSpaces!=0)
> renderer.erase(0,leadingSpaces);
>
>                    // remove trailing spaces if they exist.
>                    std::string::size_type trailingSpaces =
> renderer.find_last_not_of(' ');
>                    if (trailingSpaces!=std::string::npos)
> renderer.erase(trailingSpaces+1,std::string::npos);
>
>                }
>
>                if (renderer.empty())
>                {
>                    extensionDisabled = true;
>                    break;
>                }
>
>                if (rendererString.find(renderer)!=std::string::npos)
>                {
>                    extensionDisabled = true;
>                    break;
>
>                }
>
>                // move the position in the disable string along so that the
> same extension is found multiple times
>                ++pos;
>            }
>
>        }
>    }
>
>    if (result)
>    {
>        if (!extensionDisabled) osg::notify(INFO)<<"OpenGL extension
> '"<<extension<<"' is supported."<<std::endl;
>        else osg::notify(INFO)<<"OpenGL extension '"<<extension<<"' is
> supported by OpenGL\ndriver but has been disabled by
> osg::getGLExtensionDisableString()."<<std::endl;
>    }
>    else osg::notify(INFO)<<"OpenGL extension '"<<extension<<"' is not
> supported."<<std::endl;
>
>
>    return result && !extensionDisabled;
> }
>
> void osg::setGLExtensionDisableString(const std::string& disableString)
> {
>    getGLExtensionDisableString() = disableString;
> }
>
> std::string& osg::getGLExtensionDisableString()
> {
>    static const char* envVar = getenv("OSG_GL_EXTENSION_DISABLE");
>    static std::string s_GLExtensionDisableString(envVar?envVar:"Nothing
> defined");
>
>    return s_GLExtensionDisableString;
> }
>
> #ifdef OSG_GLU_AVAILABLE
>    bool osg::isGLUExtensionSupported(unsigned int contextID, const char
> *extension)
>    {
>        ExtensionSet& extensionSet = s_gluExtensionSetList[contextID];
>        std::string& rendererString = s_gluRendererList[contextID];
>
>        // if not already set up, initialize all the per graphic context
> values.
>        if (!s_gluInitializedList[contextID])
>        {
>            s_gluInitializedList[contextID] = 1;
>
>            // set up the renderer
>            const GLubyte* renderer = glGetString(GL_RENDERER);
>            rendererString = renderer ? (const char*)renderer : "";
>
>            // get the extension list from OpenGL.
>            const char* extensions = (const
> char*)gluGetString(GLU_EXTENSIONS);
>            if (extensions==NULL) return false;
>
>            // insert the ' ' delimiated extensions words into the
> extensionSet.
>            const char *startOfWord = extensions;
>            const char *endOfWord;
>            while ((endOfWord = strchr(startOfWord,' '))!=NULL)
>            {
>                extensionSet.insert(std::string(startOfWord,endOfWord));
>                startOfWord = endOfWord+1;
>            }
>            if (*startOfWord!=0)
> extensionSet.insert(std::string(startOfWord));
>
>            osg::notify(INFO)<<"OpenGL extensions supported by installed
> OpenGL drivers are:"<<std::endl;
>            for(ExtensionSet::iterator itr=extensionSet.begin();
>                itr!=extensionSet.end();
>                ++itr)
>            {
>                osg::notify(INFO)<<"    "<<*itr<<std::endl;
>            }
>
>        }
>
>        // true if extension found in extensionSet.
>        bool result = extensionSet.find(extension)!=extensionSet.end();
>
>        if (result) osg::notify(INFO)<<"OpenGL utility library extension
> '"<<extension<<"' is supported."<<std::endl;
>        else osg::notify(INFO)<<"OpenGL utility library extension
> '"<<extension<<"' is not supported."<<std::endl;
>
>        return result;
>    }
> #else
>    bool osg::isGLUExtensionSupported(unsigned int, const char *)
>    {
>        return false;
>    }
> #endif
>
>
>
> #if defined(WIN32)
>    #define WIN32_LEAN_AND_MEAN
>    #ifndef NOMINMAX
>        #define NOMINMAX
>    #endif // NOMINMAX
>    #include <windows.h>
> #elif defined(__APPLE__)
>    // The NS*Symbol* stuff found in <mach-o/dyld.h> is deprecated.
>    // Since 10.3 (Panther) OS X has provided the dlopen/dlsym/dlclose
>    // family of functions under <dlfcn.h>. Since 10.4 (Tiger), Apple
> claimed
>    // the dlfcn family was significantly faster than the NS*Symbol* family.
>    // Since 'deprecated' needs to be taken very seriously with the
>    // coming of 10.5 (Leopard), it makes sense to use the dlfcn family when
> possible.
>    #include <AvailabilityMacros.h>
>    #if !defined(MAC_OS_X_VERSION_10_3) || (MAC_OS_X_VERSION_MIN_REQUIRED <
> MAC_OS_X_VERSION_10_3)
>        #define USE_APPLE_LEGACY_NSSYMBOL
>        #include <mach-o/dyld.h>
>    #else
>        #include <dlfcn.h>
>    #endif
> #else
>    #include <dlfcn.h>
> #endif
>
> void* osg::getGLExtensionFuncPtr(const char *funcName)
> {
>    //
> osg::notify(osg::NOTICE)<<"osg::getGLExtensionFuncPtr("<<funcName<<")"<<std::endl;
>
> #if defined(WIN32)
>
>    #if defined(OSG_GLES2_AVAILABLE)
>        static HMODULE hmodule = GetModuleHandle("libGLESv2.dll");
>        return convertPointerType<void*, PROC>(GetProcAddress(hmodule,
> funcName));
>    #elif defined(OSG_GLES1_AVAILABLE)
>        static HMODULE hmodule = GetModuleHandle("libgles_cm.dll");
>        return convertPointerType<void*, PROC>(GetProcAddress(hmodule,
> funcName));
>    #else
>        return convertPointerType<void*, PROC>(wglGetProcAddress(funcName));
>    #endif
>
> #elif defined(__APPLE__)
>
>    #if defined(USE_APPLE_LEGACY_NSSYMBOL)
>        std::string temp( "_" );
>        temp += funcName;    // Mac OS X prepends an underscore on function
> names
>        if ( NSIsSymbolNameDefined( temp.c_str() ) )
>        {
>            NSSymbol symbol = NSLookupAndBindSymbol( temp.c_str() );
>            return NSAddressOfSymbol( symbol );
>        } else
>            return NULL;
>    #else
>        // I am uncertain of the correct and ideal usage of dlsym here.
>        // On the surface, it would seem that the FreeBSD implementation
>        // would be the ideal one to copy, but ELF and Mach-o are different
>        // and Apple's man page says the following about using RTLD_DEFAULT:
>        // "This can be a costly search and should be avoided."
>        // The documentation mentions nothing about passing in 0 so I must
>        // assume the behavior is undefined.
>        // So I could try copying the Sun method which I think all this
>        // actually originated from.
>
>        // return dlsym( RTLD_DEFAULT, funcName );
>        static void *handle = dlopen((const char *)0L, RTLD_LAZY);
>        return dlsym(handle, funcName);
>    #endif
>
> #elif defined (__sun)
>
>     static void *handle = dlopen((const char *)0L, RTLD_LAZY);
>     return dlsym(handle, funcName);
>
> #elif defined (__sgi)
>
>     static void *handle = dlopen((const char *)0L, RTLD_LAZY);
>     return dlsym(handle, funcName);
>
> #elif defined (__FreeBSD__)
>
>    return dlsym( RTLD_DEFAULT, funcName );
>
> #elif defined (__linux__)
>
>    typedef void (*__GLXextFuncPtr)(void);
>    typedef __GLXextFuncPtr (*GetProcAddressARBProc)(const char*);
>
>    #if !defined(OSG_GLES1_AVAILABLE) && !defined(OSG_GLES2_AVAILABLE)
>    static GetProcAddressARBProc s_glXGetProcAddressARB =
> convertPointerType<GetProcAddressARBProc, void*>(dlsym(0,
> "glXGetProcAddressARB"));
>    if (s_glXGetProcAddressARB)
>    {
>        return convertPointerType<void*,
> __GLXextFuncPtr>((s_glXGetProcAddressARB)(funcName));
>    }
>    #endif
>
>    return dlsym(0, funcName);
>
> #elif defined (__QNX__)
>
>    return dlsym(RTLD_DEFAULT, funcName);
>
> #else // all other unixes
>
>    return dlsym(0, funcName);
>
> #endif
> }
>
> _______________________________________________
> osg-submissions mailing list
> [email protected]
>
> http://lists.openscenegraph.org/listinfo.cgi/osg-submissions-openscenegraph.org
>
>
_______________________________________________
osg-submissions mailing list
[email protected]
http://lists.openscenegraph.org/listinfo.cgi/osg-submissions-openscenegraph.org

Reply via email to