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

Revision 13041, 14.4 kB (checked in by robert, 2 years ago)

Ran script to remove trailing spaces and tabs

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