root/OpenSceneGraph/trunk/src/osg/GLExtensions.cpp @ 11125

Revision 11125, 15.8 kB (checked in by robert, 4 years ago)

From Paul Martz, "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."

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
2 *
3 * This library is open source and may be redistributed and/or modified under 
4 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
5 * (at your option) any later version.  The full license is in LICENSE file
6 * included with this distribution, and on the openscenegraph.org website.
7 *
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 * OpenSceneGraph Public License for more details.
12*/
13#include <osg/GLExtensions>
14#include <osg/GL>
15#include <osg/GLU>
16#include <osg/Notify>
17#include <osg/Math>
18#include <osg/buffered_value>
19
20#include <stdlib.h>
21#include <string.h>
22#include <stdio.h>
23#include <float.h>
24
25#include <string>
26#include <vector>
27#include <set>
28
29#if defined(WIN32)
30#include <windows.h>
31#endif
32
33
34typedef std::set<std::string>  ExtensionSet;
35static osg::buffered_object<ExtensionSet> s_glExtensionSetList;
36static osg::buffered_object<std::string> s_glRendererList;
37static osg::buffered_value<int> s_glInitializedList;
38
39static osg::buffered_object<ExtensionSet> s_gluExtensionSetList;
40static osg::buffered_object<std::string> s_gluRendererList;
41static osg::buffered_value<int> s_gluInitializedList;
42
43float osg::getGLVersionNumber()
44{
45    // needs to be extended to do proper things with subversions like 1.5.1, etc.
46    char *versionstring   = (char*) glGetString( GL_VERSION );
47    if (!versionstring) return 0.0;
48
49    std::string vs( versionstring );
50    return( asciiToFloat( vs.substr( 0, vs.find( " " ) ).c_str() ) );
51}
52
53bool osg::isExtensionInExtensionString(const char *extension, const char *extensionString)
54{
55    const char *startOfWord = extensionString;
56    const char *endOfWord;
57    while ((endOfWord = strchr(startOfWord,' ')) != 0)
58    {
59        if (strncmp(extension, startOfWord, endOfWord - startOfWord) == 0)
60            return true;
61        startOfWord = endOfWord+1;
62    }
63    if (*startOfWord && strcmp(extension, startOfWord) == 0)
64        return true;
65   
66   return false;
67}
68
69bool osg::isGLExtensionSupported(unsigned int contextID, const char *extension)
70{
71    return osg::isGLExtensionOrVersionSupported(contextID, extension, FLT_MAX);
72}
73
74bool osg::isGLExtensionOrVersionSupported(unsigned int contextID, const char *extension, float requiredGLVersion)
75{
76    ExtensionSet& extensionSet = s_glExtensionSetList[contextID];
77    std::string& rendererString = s_glRendererList[contextID];
78
79    // first check to see if GL version number of recent enough.
80    bool result = requiredGLVersion <= osg::getGLVersionNumber();
81   
82    if (!result)
83    {   
84        // if not already set up, initialize all the per graphic context values.
85        if (!s_glInitializedList[contextID])
86        {
87            s_glInitializedList[contextID] = 1;
88
89            // set up the renderer
90            const GLubyte* renderer = glGetString(GL_RENDERER);
91            rendererString = renderer ? (const char*)renderer : "";
92
93            // get the extension list from OpenGL.
94            if( osg::getGLVersionNumber() >= 3.0 )
95            {
96                // OpenGL 3.0 adds the concept of indexed strings and
97                // deprecates calls to glGetString( GL_EXTENSIONS ), which
98                // will now generate GL_INVALID_ENUM.
99
100                // Get extensions using new indexed string interface.
101
102                typedef const GLubyte * APIENTRY PFNGLGETSTRINGIPROC( GLenum, GLuint );
103                PFNGLGETSTRINGIPROC* glGetStringi = 0;
104                setGLExtensionFuncPtr( glGetStringi, "glGetStringi");
105
106                if( glGetStringi != NULL )
107                {
108    #  ifndef GL_NUM_EXTENSIONS
109    #    define GL_NUM_EXTENSIONS 0x821D
110    #  endif
111                    GLint numExt;
112                    glGetIntegerv( GL_NUM_EXTENSIONS, &numExt );
113                    int idx;
114                    for( idx=0; idx<numExt; idx++ )
115                    {
116                        extensionSet.insert( std::string( (char*)( glGetStringi( GL_EXTENSIONS, idx ) ) ) );
117                    }
118                }
119                else
120                {
121                    osg::notify( osg::WARN ) << "isGLExtensionOrVersionSupported: Can't obtain glGetStringi function pointer." << std::endl;
122                }
123            }
124            else
125            {
126                // Get extensions using GL1/2 interface.
127
128                const char* extensions = (const char*)glGetString(GL_EXTENSIONS);
129                if (extensions==NULL) return false;
130
131                // insert the ' ' delimiated extensions words into the extensionSet.
132                const char *startOfWord = extensions;
133                const char *endOfWord;
134                while ((endOfWord = strchr(startOfWord,' '))!=NULL)
135                {
136                    extensionSet.insert(std::string(startOfWord,endOfWord));
137                    startOfWord = endOfWord+1;
138                }
139                if (*startOfWord!=0) extensionSet.insert(std::string(startOfWord));
140            }
141
142    #if defined(WIN32) && (defined(OSG_GL1_AVAILABLE) || defined(OSG_GL2_AVAILABLE) || defined(OSG_GL3_AVAILABLE))
143
144            // add WGL extensions to the list
145
146            typedef const char* WINAPI WGLGETEXTENSIONSSTRINGARB(HDC);
147            WGLGETEXTENSIONSSTRINGARB* wglGetExtensionsStringARB = 0;
148            setGLExtensionFuncPtr(wglGetExtensionsStringARB, "wglGetExtensionsStringARB");
149
150            typedef const char* WINAPI WGLGETEXTENSIONSSTRINGEXT();
151            WGLGETEXTENSIONSSTRINGEXT* wglGetExtensionsStringEXT = 0;
152            setGLExtensionFuncPtr(wglGetExtensionsStringEXT, "wglGetExtensionsStringEXT");
153
154            const char* wglextensions = 0;
155
156            if (wglGetExtensionsStringARB)
157            {
158                HDC dc = wglGetCurrentDC();
159                wglextensions = wglGetExtensionsStringARB(dc);
160            }
161            else if (wglGetExtensionsStringEXT)
162            {
163                wglextensions = wglGetExtensionsStringEXT();
164            }
165
166            if (wglextensions)
167            {   
168                const char* startOfWord = wglextensions;
169                const char* endOfWord;
170                while ((endOfWord = strchr(startOfWord, ' ')))
171                {
172                    extensionSet.insert(std::string(startOfWord, endOfWord));
173                    startOfWord = endOfWord+1;
174                }
175                if (*startOfWord != 0) extensionSet.insert(std::string(startOfWord));
176            }
177
178    #endif
179
180            OSG_NOTIFY(INFO)<<"OpenGL extensions supported by installed OpenGL drivers are:"<<std::endl;
181            for(ExtensionSet::iterator itr=extensionSet.begin();
182                itr!=extensionSet.end();
183                ++itr)
184            {
185                OSG_NOTIFY(INFO)<<"    "<<*itr<<std::endl;
186            }
187
188        }
189
190        // true if extension found in extensionSet.
191        result = extensionSet.find(extension)!=extensionSet.end();
192    }
193   
194    // now see if extension is in the extension disabled list
195    bool extensionDisabled = false;
196    if (result)
197    {
198
199        const std::string& disableString = getGLExtensionDisableString();
200        if (!disableString.empty())
201        {
202                   
203            std::string::size_type pos=0;
204            while ( pos!=std::string::npos && (pos=disableString.find(extension,pos))!=std::string::npos )
205            {
206                std::string::size_type previousColon = disableString.find_last_of(':',pos);
207                std::string::size_type previousSemiColon = disableString.find_last_of(';',pos);
208               
209                std::string renderer = "";
210                if (previousColon!=std::string::npos)
211                {
212                    if (previousSemiColon==std::string::npos) renderer = disableString.substr(0,previousColon);
213                    else if (previousSemiColon<previousColon) renderer = disableString.substr(previousSemiColon+1,previousColon-previousSemiColon-1);
214                }
215
216                if (!renderer.empty())
217                {
218               
219                    // remove leading spaces if they exist.
220                    std::string::size_type leadingSpaces = renderer.find_first_not_of(' ');
221                    if (leadingSpaces==std::string::npos) renderer = ""; // nothing but spaces
222                    else if (leadingSpaces!=0) renderer.erase(0,leadingSpaces);
223
224                    // remove trailing spaces if they exist.
225                    std::string::size_type trailingSpaces = renderer.find_last_not_of(' ');
226                    if (trailingSpaces!=std::string::npos) renderer.erase(trailingSpaces+1,std::string::npos);
227
228                }
229                           
230                if (renderer.empty())
231                {
232                    extensionDisabled = true;
233                    break;
234                }
235               
236                if (rendererString.find(renderer)!=std::string::npos)
237                {
238                    extensionDisabled = true;
239                    break;
240                   
241                }
242               
243                // move the position in the disable string along so that the same extension is found multiple times
244                ++pos;
245            }
246
247        }
248    }
249
250    if (result)
251    {
252        if (!extensionDisabled)
253        {
254            OSG_NOTIFY(INFO)<<"OpenGL extension '"<<extension<<"' is supported."<<std::endl;
255        }
256        else
257        {
258            OSG_NOTIFY(INFO)<<"OpenGL extension '"<<extension<<"' is supported by OpenGL\ndriver but has been disabled by osg::getGLExtensionDisableString()."<<std::endl;
259        }
260    }
261    else
262    {
263        OSG_NOTIFY(INFO)<<"OpenGL extension '"<<extension<<"' is not supported."<<std::endl;
264    }
265
266
267    return result && !extensionDisabled;
268}
269
270void osg::setGLExtensionDisableString(const std::string& disableString)
271{
272    getGLExtensionDisableString() = disableString;
273}
274
275std::string& osg::getGLExtensionDisableString()
276{
277    static const char* envVar = getenv("OSG_GL_EXTENSION_DISABLE");
278    static std::string s_GLExtensionDisableString(envVar?envVar:"Nothing defined");
279
280    return s_GLExtensionDisableString;
281}
282
283#ifdef OSG_GLU_AVAILABLE
284    bool osg::isGLUExtensionSupported(unsigned int contextID, const char *extension)
285    {
286        ExtensionSet& extensionSet = s_gluExtensionSetList[contextID];
287        std::string& rendererString = s_gluRendererList[contextID];
288
289        // if not already set up, initialize all the per graphic context values.
290        if (!s_gluInitializedList[contextID])
291        {
292            s_gluInitializedList[contextID] = 1;
293
294            // set up the renderer
295            const GLubyte* renderer = glGetString(GL_RENDERER);
296            rendererString = renderer ? (const char*)renderer : "";
297
298            // get the extension list from OpenGL.
299            const char* extensions = (const char*)gluGetString(GLU_EXTENSIONS);
300            if (extensions==NULL) return false;
301
302            // insert the ' ' delimiated extensions words into the extensionSet.
303            const char *startOfWord = extensions;
304            const char *endOfWord;
305            while ((endOfWord = strchr(startOfWord,' '))!=NULL)
306            {
307                extensionSet.insert(std::string(startOfWord,endOfWord));
308                startOfWord = endOfWord+1;
309            }
310            if (*startOfWord!=0) extensionSet.insert(std::string(startOfWord));
311
312            OSG_NOTIFY(INFO)<<"OpenGL extensions supported by installed OpenGL drivers are:"<<std::endl;
313            for(ExtensionSet::iterator itr=extensionSet.begin();
314                itr!=extensionSet.end();
315                ++itr)
316            {
317                OSG_NOTIFY(INFO)<<"    "<<*itr<<std::endl;
318            }
319
320        }
321
322        // true if extension found in extensionSet.
323        bool result = extensionSet.find(extension)!=extensionSet.end();
324
325        if (result)
326        {
327            OSG_NOTIFY(INFO)<<"OpenGL utility library extension '"<<extension<<"' is supported."<<std::endl;
328        }
329        else
330        {
331            OSG_NOTIFY(INFO)<<"OpenGL utility library extension '"<<extension<<"' is not supported."<<std::endl;
332        }
333
334        return result;
335    }
336#else
337    bool osg::isGLUExtensionSupported(unsigned int, const char *)
338    {
339        return false;
340    }
341#endif
342
343
344
345#if defined(WIN32)
346    #define WIN32_LEAN_AND_MEAN
347    #ifndef NOMINMAX
348        #define NOMINMAX
349    #endif // NOMINMAX
350    #include <windows.h>
351#elif defined(__APPLE__)
352    // The NS*Symbol* stuff found in <mach-o/dyld.h> is deprecated.
353    // Since 10.3 (Panther) OS X has provided the dlopen/dlsym/dlclose
354    // family of functions under <dlfcn.h>. Since 10.4 (Tiger), Apple claimed
355    // the dlfcn family was significantly faster than the NS*Symbol* family.
356    // Since 'deprecated' needs to be taken very seriously with the
357    // coming of 10.5 (Leopard), it makes sense to use the dlfcn family when possible.
358    #include <AvailabilityMacros.h>
359    #if !defined(MAC_OS_X_VERSION_10_3) || (MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_3)
360        #define USE_APPLE_LEGACY_NSSYMBOL
361        #include <mach-o/dyld.h>
362    #else
363        #include <dlfcn.h>
364    #endif
365#else
366    #include <dlfcn.h>
367#endif
368
369void* osg::getGLExtensionFuncPtr(const char *funcName)
370{
371    // OSG_NOTIFY(osg::NOTICE)<<"osg::getGLExtensionFuncPtr("<<funcName<<")"<<std::endl;
372   
373#if defined(WIN32)
374
375    #if defined(OSG_GLES2_AVAILABLE)
376        static HMODULE hmodule = GetModuleHandle("libGLESv2.dll");
377        return convertPointerType<void*, PROC>(GetProcAddress(hmodule, funcName));
378    #elif defined(OSG_GLES1_AVAILABLE)
379        static HMODULE hmodule = GetModuleHandle("libgles_cm.dll");
380        return convertPointerType<void*, PROC>(GetProcAddress(hmodule, funcName));
381    #else
382        return convertPointerType<void*, PROC>(wglGetProcAddress(funcName));
383    #endif
384
385#elif defined(__APPLE__)
386
387    #if defined(USE_APPLE_LEGACY_NSSYMBOL)
388        std::string temp( "_" );
389        temp += funcName;    // Mac OS X prepends an underscore on function names
390        if ( NSIsSymbolNameDefined( temp.c_str() ) )
391        {
392            NSSymbol symbol = NSLookupAndBindSymbol( temp.c_str() );
393            return NSAddressOfSymbol( symbol );
394        } else
395            return NULL;
396    #else
397        // I am uncertain of the correct and ideal usage of dlsym here.
398        // On the surface, it would seem that the FreeBSD implementation
399        // would be the ideal one to copy, but ELF and Mach-o are different
400        // and Apple's man page says the following about using RTLD_DEFAULT:
401        // "This can be a costly search and should be avoided."
402        // The documentation mentions nothing about passing in 0 so I must
403        // assume the behavior is undefined.
404        // So I could try copying the Sun method which I think all this
405        // actually originated from.
406
407        // return dlsym( RTLD_DEFAULT, funcName );
408        static void *handle = dlopen((const char *)0L, RTLD_LAZY);
409        return dlsym(handle, funcName);
410    #endif
411
412#elif defined (__sun)
413
414     static void *handle = dlopen((const char *)0L, RTLD_LAZY);
415     return dlsym(handle, funcName);
416   
417#elif defined (__sgi)
418
419     static void *handle = dlopen((const char *)0L, RTLD_LAZY);
420     return dlsym(handle, funcName);
421
422#elif defined (__FreeBSD__)
423
424    return dlsym( RTLD_DEFAULT, funcName );
425
426#elif defined (__linux__)
427
428    typedef void (*__GLXextFuncPtr)(void);
429    typedef __GLXextFuncPtr (*GetProcAddressARBProc)(const char*);
430   
431    #if !defined(OSG_GLES1_AVAILABLE) && !defined(OSG_GLES2_AVAILABLE)
432    static GetProcAddressARBProc s_glXGetProcAddressARB = convertPointerType<GetProcAddressARBProc, void*>(dlsym(0, "glXGetProcAddressARB"));
433    if (s_glXGetProcAddressARB)
434    {
435        return convertPointerType<void*, __GLXextFuncPtr>((s_glXGetProcAddressARB)(funcName));
436    }
437    #endif
438
439    return dlsym(0, funcName);
440
441#elif defined (__QNX__)
442
443    return dlsym(RTLD_DEFAULT, funcName);
444
445#else // all other unixes
446
447    return dlsym(0, funcName);
448
449#endif
450}
Note: See TracBrowser for help on using the browser.