Index: trunk/src/lib/gl.cc
===================================================================
--- trunk/src/lib/gl.cc	(revision 245)
+++ trunk/src/lib/gl.cc	(revision 311)
@@ -6,4 +6,5 @@
 
 #include "nv/common.hh"
+#include "nv/range.hh"
 #include "nv/lib/gl.hh"
 
@@ -33,4 +34,5 @@
 #include <nv/lib/detail/wgl_functions.inc>
 #endif
+#include <nv/lib/detail/gl_ext/gl_ext_all_functions.inc>
 #undef NV_GL_FUN_REN
 #undef NV_GL_FUN_EXT
@@ -38,25 +40,64 @@
 
 static nv::library gl_library;
+static nv::gl_extensions gl_loaded_extensions = nv::gl_extensions(0);
+extern "C" void* (NV_GL_APIENTRY *gl_ext_loader) ( const char* ) = nullptr;
 static bool gl_library_loaded = false;
 static bool wgl_library_loaded = false;
 
-bool nv::load_gl_library( const char* path )
-{
-	if ( gl_library_loaded ) return true;
+static const char *gl_extension_names[] = {
+	"UNKNOWN",
+#define NV_GL_EXTENSION( count, id, name ) "GL_EXT_"#id,
+#include <nv/lib/detail/gl_ext/gl_ext_info.inc>
+#undef NV_GL_EXTENSION
+};
+
+static const char *gl_extension_ids[] = {
+	"UNKNOWN",
+#define NV_GL_EXTENSION( count, id, name ) #id,
+#include <nv/lib/detail/gl_ext/gl_ext_info.inc>
+#undef NV_GL_EXTENSION
+};
+
+
+static void* load_gl_ext_symbol_impl( const char* name, nv::log_level fail_level = nv::LOG_DEBUG )
+{
+	void* result = gl_ext_loader( name );
+	NV_LOG( ( result ? nv::LOG_DEBUG : fail_level ), "load_gl_ext_symbol : " << name << ( result ? " succeded." : "failed." ) );
+	return result;
+}
+
+static void* load_gl_ext_symbol( const char* name, bool iterate, const char* ext )
+{
+	void * result        = nullptr;
+	result = load_gl_ext_symbol_impl( ext ? ( std::string(name) + ext ).c_str() : name );
+	if ( result ) return result;
+	if ( iterate )
+	{
+		result = gl_ext_loader( (std::string(name) + "ARB").c_str() );
+		if ( result ) return result;
+		result = gl_ext_loader( (std::string(name) + "EXT").c_str() );
+		if ( result ) return result;
+	}
+	return result;
+}
+
+bool nv::load_gl_library( const char* path, bool force_reload )
+{
+	if ( gl_library_loaded && !force_reload ) return true;
 #if defined( NV_SDL_GL )
 #		define NV_GL_LOAD( symbol ) *(void **) (&symbol) = SDL_GL_GetProcAddress(#symbol);
 #		define NV_GL_LOAD_EXT( symbol ) *(void **) (&symbol) = SDL_GL_GetProcAddress(#symbol);
+	*(void **) (&gl_ext_loader) = SDL_GL_GetProcAddress;
 #else
 	if ( !gl_library.is_open() ) gl_library.open( path );
 
-	void * (NV_GL_APIENTRY *ext_loader) (const char* proc) = nullptr;
 #	if NV_PLATFORM == NV_WINDOWS 
 #		define NV_GL_LOAD( symbol ) *(void **) (&symbol) = gl_library.get(#symbol);
-		*(void **) (&ext_loader) = gl_library.get("wglGetProcAddress");
-#		define NV_GL_LOAD_EXT( symbol ) *(void **) (&symbol) = ext_loader(#symbol);
+		*(void **) (&gl_ext_loader) = gl_library.get("wglGetProcAddress");
+#		define NV_GL_LOAD_EXT( symbol ) *(void **) (&symbol) = gl_ext_loader(#symbol);
 #	elif (NV_PLATFORM == NV_LINUX || NV_PLATFORM == NV_APPLE)
 #		define NV_GL_LOAD( symbol ) *(void **) (&symbol) = gl_library.get(#symbol);
-		*(void **) (&ext_loader) = gl_library.get("glXGetProcAddress");
-#		define NV_GL_LOAD_EXT( symbol ) *(void **) (&symbol) = ext_loader(#symbol);
+		*(void **) (&gl_ext_loader) = gl_library.get("glXGetProcAddress");
+#		define NV_GL_LOAD_EXT( symbol ) *(void **) (&symbol) = gl_ext_loader(#symbol);
 #	else
 #		define NV_GL_LOAD( symbol ) *(void **) (&symbol) = gl_library.get(#symbol);
@@ -77,7 +118,7 @@
 }
 
-bool nv::load_wgl_library( const char* path /*= NV_GL_PATH */ )
-{
-	if ( wgl_library_loaded ) return true;
+bool nv::load_wgl_library( const char* path /*= NV_GL_PATH */, bool force_reload )
+{
+	if ( wgl_library_loaded && !force_reload ) return true;
 #if NV_PLATFORM == NV_WINDOWS 
 #if defined( NV_SDL_GL )
@@ -85,11 +126,11 @@
 #		define NV_GL_LOAD_EXT( symbol ) *(void **) (&symbol) = SDL_GL_GetProcAddress(#symbol);
 #	    define NV_GL_LOAD_REN( fname, rname )  *(void **) (&rname) = SDL_GL_GetProcAddress(#fname);
+	(void **) (&gl_ext_loader) = SDL_GL_GetProcAddress;
 #else // 
 	if ( !gl_library.is_open() ) gl_library.open( path );
 
-	void * (NV_GL_APIENTRY *ext_loader) (const char* proc) = nullptr;
-	*(void **) (&ext_loader) = gl_library.get("wglGetProcAddress");
+	*(void **) (&gl_ext_loader) = gl_library.get("wglGetProcAddress");
 #define NV_GL_LOAD( symbol ) *(void **) (&symbol) = gl_library.get(#symbol);
-#define NV_GL_LOAD_EXT( symbol ) *(void **) (&symbol) = ext_loader(#symbol);
+#define NV_GL_LOAD_EXT( symbol ) *(void **) (&symbol) = gl_ext_loader(#symbol);
 #define NV_GL_LOAD_REN( fname, rname ) *(void **) (&rname) = gl_library.get(#fname);
 #endif 
@@ -186,2 +227,84 @@
 }
 
+const char* nv::get_gl_extension_name( gl_extensions extension )
+{
+	uint32 value = uint32( extension );
+	uint32 index = 0; 
+	while ( value >>= 1 ) index++;
+	return NV_SAFE_ARRAY(gl_extension_names, index+1, gl_extension_names[0] );
+}
+
+
+bool nv::load_gl_extension( gl_extensions extension )
+{
+	const char* name = get_gl_extension_name( extension );
+	// TODO: first check for support using gl mechanisms 
+	//       see SDL 2.0 SDL_video.c
+	if ( !gl_library.is_open() ) 
+	{
+		NV_LOG( nv::LOG_ERROR, "load_gl_extension used, while gl_library was closed!" );
+		return false;
+	}
+
+	if ( gl_ext_loader == nullptr )
+	{
+		NV_LOG( nv::LOG_ERROR, "load_gl_extension used, while gl_ext_loader was undefined!" );
+		return false;
+	}
+	NV_LOG( nv::LOG_DEBUG, "load_gl_extension - loading extension - \"" << name << "\"..." );
+
+	uint32 count      = 0; 
+	uint32 fail_count = 0;
+
+#	define NV_GL_FUN_EXT( rtype, symbol, fparams ) \
+	*(void **) (&symbol) = load_gl_ext_symbol(#symbol, true, nullptr); \
+	count++; if ( !symbol ) fail_count++;
+
+	switch ( extension )
+	{
+	case GL_EXT_FRAMEBUFFER_BLIT : {
+#include <nv/lib/detail/gl_ext/gl_ext_framebuffer_blit_functions.inc>
+	} break;
+	case GL_EXT_FRAMEBUFFER_OBJECT : {
+#include <nv/lib/detail/gl_ext/gl_ext_framebuffer_object_functions.inc>
+	} break;
+	default : {
+		NV_LOG( nv::LOG_ERROR, "load_gl_extension - unknown extension \"" << name << "\"!" );
+		return nullptr;
+	}
+	}
+#	undef NV_GL_FUN_EXT
+
+	if ( fail_count == 0 )
+	{
+		NV_LOG( nv::LOG_NOTICE, "load_gl_extension - extension \"" << name << "\" loaded (" << count << " symbols)" );
+		return false;
+	}
+	NV_LOG( nv::LOG_NOTICE, "load_gl_extension - failed to load extension \"" << name << "\" (" << count << "/" << fail_count << " symbols loaded)" );
+	return true;
+}
+
+nv::gl_extensions nv::load_gl_extensions( uint32 extensions )
+{
+	gl_extensions result = gl_extensions(0);
+	for ( auto ext : nv::bits( gl_extensions(extensions) ) )
+	{
+		if ( load_gl_extension(ext) ) result = gl_extensions( result | ext );
+	}
+	return result;
+}
+
+bool nv::is_gl_extension_loaded( gl_extensions extensions )
+{
+	return ( gl_loaded_extensions & extensions ) != 0;
+}
+
+bool nv::are_gl_extensions_loaded( uint32 extensions )
+{
+	for ( auto ext : nv::bits( gl_extensions(extensions) ) )
+	{
+		if ( !is_gl_extension_loaded(ext) ) return false;
+	}
+	return true;
+}
+
