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

Revision 11126, 15.9 kB (checked in by robert, 5 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."

From Robert Osfield, added #if !defined(OSG_GLES1_AVAILABLE) && !defined(OSG_GLES2_AVAILABLE) to new block to prevent it
being compiled under GLES where no glGetStringi exists.

  • 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 !defined(OSG_GLES1_AVAILABLE) && !defined(OSG_GLES2_AVAILABLE)
95            if( osg::getGLVersionNumber() >= 3.0 )
96            {
97                // OpenGL 3.0 adds the concept of indexed strings and
98                // deprecates calls to glGetString( GL_EXTENSIONS ), which
99                // will now generate GL_INVALID_ENUM.
100
101                // Get extensions using new indexed string interface.
102
103                typedef const GLubyte * APIENTRY PFNGLGETSTRINGIPROC( GLenum, GLuint );
104                PFNGLGETSTRINGIPROC* glGetStringi = 0;
105                setGLExtensionFuncPtr( glGetStringi, "glGetStringi");
106
107                if( glGetStringi != NULL )
108                {
109                    #  ifndef GL_NUM_EXTENSIONS
110                    #    define GL_NUM_EXTENSIONS 0x821D
111                    #  endif
112                    GLint numExt;
113                    glGetIntegerv( GL_NUM_EXTENSIONS, &numExt );
114                    int idx;
115                    for( idx=0; idx<numExt; idx++ )
116                    {
117                        extensionSet.insert( std::string( (char*)( glGetStringi( GL_EXTENSIONS, idx ) ) ) );
118                    }
119                }
120                else
121                {
122                    osg::notify( osg::WARN ) << "isGLExtensionOrVersionSupported: Can't obtain glGetStringi function pointer." << std::endl;
123                }
124            }
125            else
126            #endif
127            {
128                // Get extensions using GL1/2 interface.
129
130                const char* extensions = (const char*)glGetString(GL_EXTENSIONS);
131                if (extensions==NULL) return false;
132
133                // insert the ' ' delimiated extensions words into the extensionSet.
134                const char *startOfWord = extensions;
135                const char *endOfWord;
136                while ((endOfWord = strchr(startOfWord,' '))!=NULL)
137                {
138                    extensionSet.insert(std::string(startOfWord,endOfWord));
139                    startOfWord = endOfWord+1;
140                }
141                if (*startOfWord!=0) extensionSet.insert(std::string(startOfWord));
142            }
143
144    #if defined(WIN32) && (defined(OSG_GL1_AVAILABLE) || defined(OSG_GL2_AVAILABLE) || defined(OSG_GL3_AVAILABLE))
145
146            // add WGL extensions to the list
147
148            typedef const char* WINAPI WGLGETEXTENSIONSSTRINGARB(HDC);
149            WGLGETEXTENSIONSSTRINGARB* wglGetExtensionsStringARB = 0;
150            setGLExtensionFuncPtr(wglGetExtensionsStringARB, "wglGetExtensionsStringARB");
151
152            typedef const char* WINAPI WGLGETEXTENSIONSSTRINGEXT();
153            WGLGETEXTENSIONSSTRINGEXT* wglGetExtensionsStringEXT = 0;
154            setGLExtensionFuncPtr(wglGetExtensionsStringEXT, "wglGetExtensionsStringEXT");
155
156            const char* wglextensions = 0;
157
158            if (wglGetExtensionsStringARB)
159            {
160                HDC dc = wglGetCurrentDC();
161                wglextensions = wglGetExtensionsStringARB(dc);
162            }
163            else if (wglGetExtensionsStringEXT)
164            {
165                wglextensions = wglGetExtensionsStringEXT();
166            }
167
168            if (wglextensions)
169            {   
170                const char* startOfWord = wglextensions;
171                const char* endOfWord;
172                while ((endOfWord = strchr(startOfWord, ' ')))
173                {
174                    extensionSet.insert(std::string(startOfWord, endOfWord));
175                    startOfWord = endOfWord+1;
176                }
177                if (*startOfWord != 0) extensionSet.insert(std::string(startOfWord));
178            }
179
180    #endif
181
182            OSG_NOTIFY(INFO)<<"OpenGL extensions supported by installed OpenGL drivers are:"<<std::endl;
183            for(ExtensionSet::iterator itr=extensionSet.begin();
184                itr!=extensionSet.end();
185                ++itr)
186            {
187                OSG_NOTIFY(INFO)<<"    "<<*itr<<std::endl;
188            }
189
190        }
191
192        // true if extension found in extensionSet.
193        result = extensionSet.find(extension)!=extensionSet.end();
194    }
195   
196    // now see if extension is in the extension disabled list
197    bool extensionDisabled = false;
198    if (result)
199    {
200
201        const std::string& disableString = getGLExtensionDisableString();
202        if (!disableString.empty())
203        {
204                   
205            std::string::size_type pos=0;
206            while ( pos!=std::string::npos && (pos=disableString.find(extension,pos))!=std::string::npos )
207            {
208                std::string::size_type previousColon = disableString.find_last_of(':',pos);
209                std::string::size_type previousSemiColon = disableString.find_last_of(';',pos);
210               
211                std::string renderer = "";
212                if (previousColon!=std::string::npos)
213                {
214                    if (previousSemiColon==std::string::npos) renderer = disableString.substr(0,previousColon);
215                    else if (previousSemiColon<previousColon) renderer = disableString.substr(previousSemiColon+1,previousColon-previousSemiColon-1);
216                }
217
218                if (!renderer.empty())
219                {
220               
221                    // remove leading spaces if they exist.
222                    std::string::size_type leadingSpaces = renderer.find_first_not_of(' ');
223                    if (leadingSpaces==std::string::npos) renderer = ""; // nothing but spaces
224                    else if (leadingSpaces!=0) renderer.erase(0,leadingSpaces);
225
226                    // remove trailing spaces if they exist.
227                    std::string::size_type trailingSpaces = renderer.find_last_not_of(' ');
228                    if (trailingSpaces!=std::string::npos) renderer.erase(trailingSpaces+1,std::string::npos);
229
230                }
231                           
232                if (renderer.empty())
233                {
234                    extensionDisabled = true;
235                    break;
236                }
237               
238                if (rendererString.find(renderer)!=std::string::npos)
239                {
240                    extensionDisabled = true;
241                    break;
242                   
243                }
244               
245                // move the position in the disable string along so that the same extension is found multiple times
246                ++pos;
247            }
248
249        }
250    }
251
252    if (result)
253    {
254        if (!extensionDisabled)
255        {
256            OSG_NOTIFY(INFO)<<"OpenGL extension '"<<extension<<"' is supported."<<std::endl;
257        }
258        else
259        {
260            OSG_NOTIFY(INFO)<<"OpenGL extension '"<<extension<<"' is supported by OpenGL\ndriver but has been disabled by osg::getGLExtensionDisableString()."<<std::endl;
261        }
262    }
263    else
264    {
265        OSG_NOTIFY(INFO)<<"OpenGL extension '"<<extension<<"' is not supported."<<std::endl;
266    }
267
268
269    return result && !extensionDisabled;
270}
271
272void osg::setGLExtensionDisableString(const std::string& disableString)
273{
274    getGLExtensionDisableString() = disableString;
275}
276
277std::string& osg::getGLExtensionDisableString()
278{
279    static const char* envVar = getenv("OSG_GL_EXTENSION_DISABLE");
280    static std::string s_GLExtensionDisableString(envVar?envVar:"Nothing defined");
281
282    return s_GLExtensionDisableString;
283}
284
285#ifdef OSG_GLU_AVAILABLE
286    bool osg::isGLUExtensionSupported(unsigned int contextID, const char *extension)
287    {
288        ExtensionSet& extensionSet = s_gluExtensionSetList[contextID];
289        std::string& rendererString = s_gluRendererList[contextID];
290
291        // if not already set up, initialize all the per graphic context values.
292        if (!s_gluInitializedList[contextID])
293        {
294            s_gluInitializedList[contextID] = 1;
295
296            // set up the renderer
297            const GLubyte* renderer = glGetString(GL_RENDERER);
298            rendererString = renderer ? (const char*)renderer : "";
299
300            // get the extension list from OpenGL.
301            const char* extensions = (const char*)gluGetString(GLU_EXTENSIONS);
302            if (extensions==NULL) return false;
303
304            // insert the ' ' delimiated extensions words into the extensionSet.
305            const char *startOfWord = extensions;
306            const char *endOfWord;
307            while ((endOfWord = strchr(startOfWord,' '))!=NULL)
308            {
309                extensionSet.insert(std::string(startOfWord,endOfWord));
310                startOfWord = endOfWord+1;
311            }
312            if (*startOfWord!=0) extensionSet.insert(std::string(startOfWord));
313
314            OSG_NOTIFY(INFO)<<"OpenGL extensions supported by installed OpenGL drivers are:"<<std::endl;
315            for(ExtensionSet::iterator itr=extensionSet.begin();
316                itr!=extensionSet.end();
317                ++itr)
318            {
319                OSG_NOTIFY(INFO)<<"    "<<*itr<<std::endl;
320            }
321
322        }
323
324        // true if extension found in extensionSet.
325        bool result = extensionSet.find(extension)!=extensionSet.end();
326
327        if (result)
328        {
329            OSG_NOTIFY(INFO)<<"OpenGL utility library extension '"<<extension<<"' is supported."<<std::endl;
330        }
331        else
332        {
333            OSG_NOTIFY(INFO)<<"OpenGL utility library extension '"<<extension<<"' is not supported."<<std::endl;
334        }
335
336        return result;
337    }
338#else
339    bool osg::isGLUExtensionSupported(unsigned int, const char *)
340    {
341        return false;
342    }
343#endif
344
345
346
347#if defined(WIN32)
348    #define WIN32_LEAN_AND_MEAN
349    #ifndef NOMINMAX
350        #define NOMINMAX
351    #endif // NOMINMAX
352    #include <windows.h>
353#elif defined(__APPLE__)
354    // The NS*Symbol* stuff found in <mach-o/dyld.h> is deprecated.
355    // Since 10.3 (Panther) OS X has provided the dlopen/dlsym/dlclose
356    // family of functions under <dlfcn.h>. Since 10.4 (Tiger), Apple claimed
357    // the dlfcn family was significantly faster than the NS*Symbol* family.
358    // Since 'deprecated' needs to be taken very seriously with the
359    // coming of 10.5 (Leopard), it makes sense to use the dlfcn family when possible.
360    #include <AvailabilityMacros.h>
361    #if !defined(MAC_OS_X_VERSION_10_3) || (MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_3)
362        #define USE_APPLE_LEGACY_NSSYMBOL
363        #include <mach-o/dyld.h>
364    #else
365        #include <dlfcn.h>
366    #endif
367#else
368    #include <dlfcn.h>
369#endif
370
371void* osg::getGLExtensionFuncPtr(const char *funcName)
372{
373    // OSG_NOTIFY(osg::NOTICE)<<"osg::getGLExtensionFuncPtr("<<funcName<<")"<<std::endl;
374   
375#if defined(WIN32)
376
377    #if defined(OSG_GLES2_AVAILABLE)
378        static HMODULE hmodule = GetModuleHandle("libGLESv2.dll");
379        return convertPointerType<void*, PROC>(GetProcAddress(hmodule, funcName));
380    #elif defined(OSG_GLES1_AVAILABLE)
381        static HMODULE hmodule = GetModuleHandle("libgles_cm.dll");
382        return convertPointerType<void*, PROC>(GetProcAddress(hmodule, funcName));
383    #else
384        return convertPointerType<void*, PROC>(wglGetProcAddress(funcName));
385    #endif
386
387#elif defined(__APPLE__)
388
389    #if defined(USE_APPLE_LEGACY_NSSYMBOL)
390        std::string temp( "_" );
391        temp += funcName;    // Mac OS X prepends an underscore on function names
392        if ( NSIsSymbolNameDefined( temp.c_str() ) )
393        {
394            NSSymbol symbol = NSLookupAndBindSymbol( temp.c_str() );
395            return NSAddressOfSymbol( symbol );
396        } else
397            return NULL;
398    #else
399        // I am uncertain of the correct and ideal usage of dlsym here.
400        // On the surface, it would seem that the FreeBSD implementation
401        // would be the ideal one to copy, but ELF and Mach-o are different
402        // and Apple's man page says the following about using RTLD_DEFAULT:
403        // "This can be a costly search and should be avoided."
404        // The documentation mentions nothing about passing in 0 so I must
405        // assume the behavior is undefined.
406        // So I could try copying the Sun method which I think all this
407        // actually originated from.
408
409        // return dlsym( RTLD_DEFAULT, funcName );
410        static void *handle = dlopen((const char *)0L, RTLD_LAZY);
411        return dlsym(handle, funcName);
412    #endif
413
414#elif defined (__sun)
415
416     static void *handle = dlopen((const char *)0L, RTLD_LAZY);
417     return dlsym(handle, funcName);
418   
419#elif defined (__sgi)
420
421     static void *handle = dlopen((const char *)0L, RTLD_LAZY);
422     return dlsym(handle, funcName);
423
424#elif defined (__FreeBSD__)
425
426    return dlsym( RTLD_DEFAULT, funcName );
427
428#elif defined (__linux__)
429
430    typedef void (*__GLXextFuncPtr)(void);
431    typedef __GLXextFuncPtr (*GetProcAddressARBProc)(const char*);
432   
433    #if !defined(OSG_GLES1_AVAILABLE) && !defined(OSG_GLES2_AVAILABLE)
434    static GetProcAddressARBProc s_glXGetProcAddressARB = convertPointerType<GetProcAddressARBProc, void*>(dlsym(0, "glXGetProcAddressARB"));
435    if (s_glXGetProcAddressARB)
436    {
437        return convertPointerType<void*, __GLXextFuncPtr>((s_glXGetProcAddressARB)(funcName));
438    }
439    #endif
440
441    return dlsym(0, funcName);
442
443#elif defined (__QNX__)
444
445    return dlsym(RTLD_DEFAULT, funcName);
446
447#else // all other unixes
448
449    return dlsym(0, funcName);
450
451#endif
452}
Note: See TracBrowser for help on using the browser.