/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2003 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.
*/

#ifndef OSG_GLEXTENSIONS
#define OSG_GLEXTENSIONS 1

#include <osg/Export>
#include <string>

#if defined(WIN32)
    #define WIN32_LEAN_AND_MEAN
    #ifndef NOMINMAX
        #define NOMINMAX
    #endif // NOMINMAX
    #include <windows.h>
#elif defined(__APPLE__)
    #include <mach-o/dyld.h>
#else
    #include <dlfcn.h>
#endif

namespace osg {



/** Return true if OpenGL "extension" is supported.
  * Note: Must only be called within a valid OpenGL context,
  * undefined behavior may occur otherwise.
*/
extern SG_EXPORT bool isGLExtensionSupported(const char *extension);

/** Return the address of the specified OpenGL function.
  * Return NULL if function not supported by OpenGL library.
  * Note, glGLExtensionFuncPtr is declared inline so that the code
  * is compiled locally to the calling code.  This should get by Windows'
  * dumb implementation of having different GL function ptr's for each
  * library when linked to it. 
*/
inline void* getGLExtensionFuncPtr(const char *funcName)
{
#if defined(WIN32)

    return (void*)wglGetProcAddress(funcName);

#elif defined(__APPLE__)

    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;

#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);

#else // all other unixes

    return dlsym(0, funcName);

#endif
}

/** Set a list of extensions to disable for different OpenGL renderers. This allows
  * OSG applications to work around OpenGL drivers' bugs which are due to problematic extension support.
  * The format of the string is:
  * "GLRendererString : ExtensionName, ExtensionName; GLRenderString2 : ExtensionName;"
  * An example of is : "SUN_XVR1000:GL_EXT_texture_filter_anisotropic"
  * The default setting of GLExtensionDisableString is obtained from the OSG_GL_EXTENSION_DISABLE
  * environmental variable.
*/
extern SG_EXPORT void setGLExtensionDisableString(const std::string& disableString);

/** Get the list of extensions that are disabled for various OpenGL renderers. */
extern SG_EXPORT std::string& getGLExtensionDisableString();



/** Return the address of the specified OpenGL function. If not found then
  * check a second function name, if this fails then return NULL as function is
  * not supported by OpenGL library. This is used for checking something
  * like glActiveTexture (which is in OGL1.3) or glActiveTextureARB.
*/
inline void* getGLExtensionFuncPtr(const char *funcName,const char *fallbackFuncName)
{
    void* ptr = getGLExtensionFuncPtr(funcName);
    if (ptr) return ptr;
    return getGLExtensionFuncPtr(fallbackFuncName);
}

/** Return true if OpenGL "extension" is supported.
  * Note: Must only be called within a valid OpenGL context,
  * undefined behavior may occur otherwise.
*/
extern SG_EXPORT bool isGLUExtensionSupported(const char *extension);


}

#endif
