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

Revision 10721, 13.7 kB (checked in by robert, 5 years ago)

Added dlsymb settting for QNX

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