/*
								+---------------------------------+
								|								  |
								|	 ***   OpenGL ES 2.0   ***	  |
								|								  |
								|  Copyright  © -tHE SWINe- 2011  |
								|								  |
								|		   GLES20Emu.cpp		  |
								|								  |
								+---------------------------------+
*/

/**
 *	@file gles2/GLES20Emu.cpp
 *	@author -tHE SWINe-
 *	@brief OpenGL ES 2.0 emulation
 */

#include "../NewFix.h"
#include "../CallStack.h"
#include <string.h>
#define GLES20EMU_CPP
#include "GLES20Emu.h"
#include "../StlUtils.h"

#if defined(_WIN32) || defined(_WIN64)
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <GL/wglext.h> // wglGetProcAddress()
#else // _WIN32 || _WIN64
#ifdef __APPLE__
// note that this works even if /usr/X11R6/include is not present on your
// system. in case it is, you can remove this branch and compile / link with:
//		-I /usr/X11R6/include -L/usr/X11R6/lib -lGL -lX11
// otherwise use:
//		-framework GLUT -framework OpenGL

#include <stdlib.h>
#include <string.h>
#include <AvailabilityMacros.h>

#ifdef MAC_OS_X_VERSION_10_3

#include <dlfcn.h>

void *glXGetProcAddress(const void *p_s_name)
{
	static void *p_opengl_dll = 0;
	if(!p_opengl_dll)
		p_opengl_dll = dlopen("/System/Library/Frameworks/OpenGL.framework/Versions/Current/OpenGL", RTLD_LAZY);
	return (p_opengl_dll)? dlsym(p_opengl_dll, (const char*)p_s_name) : 0;
}

#else // MAC_OS_X_VERSION_10_3

#include <mach-o/dyld.h>

void *glXGetProcAddress(const void *p_s_name)
{
	static const struct mach_header *p_opengl_dll = 0;
	if(!p_opengl_dll) {
		p_opengl_dll = NSAddImage("/System/Library/Frameworks/OpenGL.framework/Versions/Current/OpenGL",
			NSADDIMAGE_OPTION_RETURN_ON_ERROR);
	}
	// load the OpenGL library

	const char *_p_s_name = (const char*)p_s_name;
	char *p_s_mangled_name = new(std::nothrow) char[strlen(_p_s_name) + 2];
	if(!p_s_mangled_name)
		return 0;
	*p_s_mangled_name = '_';
	strcpy(p_s_mangled_name + 1, _p_s_name);
	// mangle the function name in accordance with cdecl

	NSSymbol p_symbol = (p_opengl_dll)? NSLookupSymbolInImage(p_opengl_dll, p_s_mangled_name,
		NSLOOKUPSYMBOLINIMAGE_OPTION_BIND | NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR) : 0;
	delete[] p_s_mangled_name;
	return (p_symbol)? NSAddressOfSymbol(p_symbol) : 0;
	// get proc addr
}

#endif // MAC_OS_X_VERSION_10_3

#else // __APPLE__
#include <GL/glx.h>
//#include <GL/glxext.h> // my glxext.h doesn't cope nicely with some unices; gotta get another version

#ifndef GLX_VERSION_1_4

/**
 *	@def glXGetProcAddress
 *	@brief get proc address on linux platform
 *	@param[in] x is name of the function to retrieve
 */
#define glXGetProcAddress(x) (*glXGetProcAddressARB)((const GLubyte*)x)

#endif // !GLX_VERSION_1_4
#endif // __APPLE__

/**
 *	@def wglGetProcAddress
 *	@brief windows get proc address lookalike on linux platform
 *	@param[in] x is name of the function to retrieve
 */
#define wglGetProcAddress(x) (*glXGetProcAddress)((GLubyte*)(x))
#endif // _WIN32 || _WIN64

#ifdef NULL_FUNCTION_POINTERS
#define INIT_FUNC_POINTERS = 0
#else // NULL_FUNCTION_POINTERS
#define INIT_FUNC_POINTERS 
#endif // NULL_FUNCTION_POINTERS

/*
 *								=== CGLES20ExtensionHandler ===
 */

bool CGLES20ExtensionHandler::b_Support_OpenGL(int n_min_major, int n_min_minor)
{
	std::pair<int, int> t_version = t_OpenGL_Version();
	int n_major = t_version.first,
		n_minor = t_version.second;
	if(n_major > n_min_major)
		return true;
	if(n_major == n_min_major && n_minor >= n_min_minor)
		return true;
	return false;
}

int CGLES20ExtensionHandler::n_OpenGL_Version()
{
	std::pair<int, int> t_version = t_OpenGL_Version();
	return t_version.first * 10 + t_version.second;
}

#ifdef __HAVE_GL_AUTOCHECK
#undef glGetString
#undef glGetIntegerv
#endif // __HAVE_GL_AUTOCHECK
// unwrap glGetString and glGetIntegerv, we want to check their errors manually

std::pair<int, int> CGLES20ExtensionHandler::t_OpenGL_Version()
{
	int n_major, n_minor;
	const char *p_s_version;
	p_s_version = (const char*)glGetString(GL_VERSION);
#ifdef __APPLE__
	if(glGetError() == GL_INVALID_ENUM) { // never know if we are in core profile
		//fprintf(stderr, "warning: glGetString(GL_VERSION) yields GL_INVALID_ENUM\n");
		glGetIntegerv(0x821B, &n_major);
		glGetIntegerv(0x821C, &n_minor);
		return std::make_pair(n_major, n_minor);
	} /*else
		fprintf(stderr, "debug: glGetString(GL_VERSION) yields %s\n", p_s_version);*/
#endif // __APPLE__
	if(!p_s_version) {
#if defined(_WIN32) || defined(_WIN64)
		MessageBoxA(0, "OpenGL extension string is 0!", "CGLES20ExtensionHandler", MB_OK);
#endif // _WIN32 || _WIN64
		return std::make_pair(-1, -1);
	}

#if defined(_MSC_VER) && !defined(__MWERKS__) && _MSC_VER >= 1400
	if(sscanf_s(p_s_version, "%d.%d", &n_major, &n_minor) != 2) {
#else //_MSC_VER && !__MWERKS__ && _MSC_VER >= 1400
	if(sscanf(p_s_version, "%d.%d", &n_major, &n_minor) != 2) {
#endif //_MSC_VER && !__MWERKS__ && _MSC_VER >= 1400
#if defined(_WIN32) || defined(_WIN64)
		MessageBoxA(0, "OpenGL version string malformed!", "CGLES20ExtensionHandler", MB_OK);
#endif // _WIN32 || _WIN64
		_ASSERTE(0); // error - OpenGL version string malformed!
		return std::make_pair(-1, -1);
	}

	return std::make_pair(n_major, n_minor);
}

int CGLES20ExtensionHandler::n_OpenGL_Version_Major()
{
	return t_OpenGL_Version().first;
}

int CGLES20ExtensionHandler::n_OpenGL_Version_Minor()
{
	return t_OpenGL_Version().second;
}

static const GLubyte* (GLApi *glGetStringi_ptr)(GLenum name, GLuint index) = 0;
#define GL_NUM_EXTENSIONS 0x821D /**< @brief OpenGL 3.0 enum */
// that's how it's done on new hw

static bool b_SupportedExtension_Fallback(const char *p_s_extension_name)
{
	const char *p_s_extensions;
	if(!(p_s_extensions = (const char*)glGetString(GL_EXTENSIONS)))
		return false;
	int n;
	if((n = glGetError()) != GL_NO_ERROR)
		fprintf(stderr, "warning: glGetString() yields 0x%04x (%s)\n", n, (p_s_extensions)? p_s_extensions : "(null)");
	const char *p_s_search_str = p_s_extensions;
	do {
		if((p_s_search_str = strstr(p_s_search_str, p_s_extension_name))) {
			if(p_s_search_str > p_s_extensions && !isspace(*(p_s_search_str - 1)))
				continue;
			if(strlen(p_s_search_str + strlen(p_s_extension_name)) &&
			   !isspace(*(p_s_search_str + strlen(p_s_extension_name))))
				continue;

			return true;
		}
	} while(p_s_search_str && *(++ p_s_search_str));

	return false;
}

bool CGLES20ExtensionHandler::b_SupportedExtension(const char *p_s_extension_name)
{
	if(glGetStringi_ptr || (glGetStringi_ptr =
	   (const GLubyte*(GLApi*)(GLenum, GLuint))wglGetProcAddress("glGetStringi"))) {
		// try to fetch glGetStringi()

		int n_extension_num;
		glGetIntegerv(GL_NUM_EXTENSIONS, &n_extension_num);
		if(glGetError() != GL_NO_ERROR) // fails on Mac
			return b_SupportedExtension_Fallback(p_s_extension_name);
		for(int i = 0; i < n_extension_num; ++ i) {
			const char *p_s_ext_name = (const char*)glGetStringi_ptr(GL_EXTENSIONS, i);
			if(!p_s_ext_name)
				continue; // ?

			if(!strcmp(p_s_ext_name, p_s_extension_name))
				return true; // ... and there it is!
		}
		// this tends to be slightly faster
	} else
		return b_SupportedExtension_Fallback(p_s_extension_name);

	return false;
}

bool CGLES20ExtensionHandler::Get_ExtensionString(std::string &r_s_extension_list)
{
	if(glGetStringi_ptr || (glGetStringi_ptr =
	   (const GLubyte*(GLApi*)(GLenum, GLuint))wglGetProcAddress("glGetStringi"))) {
		// try to fetch glGetStringi()

		r_s_extension_list.erase();

		int n_extension_num;
		glGetIntegerv(GL_NUM_EXTENSIONS, &n_extension_num);
		if(glGetError() != GL_NO_ERROR) { // fails on Mac
			const char *p_s_extensions = (const char*)glGetString(GL_EXTENSIONS);
			if(!p_s_extensions) {
				r_s_extension_list.erase();
				return false;
			}
			return stl_ut::AssignCStr(r_s_extension_list, p_s_extensions);
		}
		for(int i = 0; i < n_extension_num; ++ i) {
			const char *p_s_ext_name = (const char*)glGetStringi_ptr(GL_EXTENSIONS, i);
			if(!p_s_ext_name)
				continue; // ?
			try {
				if(i)
					r_s_extension_list += " ";
				r_s_extension_list += p_s_ext_name;
			} catch(std::bad_alloc&) {
				return false;
			}
		}
		// new OpenGL 3 extensions scheme to avoid buffer overruns in old software

		return true;
	} else {
		const char *p_s_extensions = (const char*)glGetString(GL_EXTENSIONS);
		if(!p_s_extensions) {
			r_s_extension_list.erase();
			return false;
		}
		return stl_ut::AssignCStr(r_s_extension_list, p_s_extensions);
	}
}

#ifdef __HAVE_GL_AUTOCHECK
#define glGetString(name) glGetString_glachwrap(name, __FILE__, __LINE__)
#define glGetIntegerv(pname,params) do { glGetIntegerv_glachwrap(pname, params); GL_AUTOCHECK_BLOCK("glGetIntegerv", __FILE__, __LINE__); } while(0)
#endif // __HAVE_GL_AUTOCHECK
// redefine to have error handling for the rest of the code

std::string s_extensions_string; // storage for GL_EXTENSIONS string

#ifdef __HAVE_GL_AUTOCHECK
const GLubyte *__gles20emupatch_glGetString(GLenum name, const char *p_s_file, int n_line)
#else // __HAVE_GL_AUTOCHECK
const GLubyte *__gles20emupatch_glGetString(GLenum name)
#endif // __HAVE_GL_AUTOCHECK
{
	const GLubyte *p_s_result;
	if(name == GL_EXTENSIONS) {
		CGLES20ExtensionHandler::Get_ExtensionString(s_extensions_string);
		p_s_result = (const GLubyte*)s_extensions_string.c_str();
	} else
#ifdef __HAVE_GL_AUTOCHECK
		p_s_result = GLAutoCheckStaticFuncName(glGetString)(name, p_s_file, n_line);
#else // __HAVE_GL_AUTOCHECK
		p_s_result = GLAutoCheckStaticFuncName(glGetString)(name);
#endif // __HAVE_GL_AUTOCHECK
	return p_s_result;
}

#if defined(_WIN32) || defined(_WIN64)

bool CGLES20ExtensionHandler::b_SupportedPlatformExtension(const char *p_s_extension_name)
{
#ifndef WGL_WGLEXT_PROTOTYPES
	PFNWGLGETEXTENSIONSSTRINGARBPROC wglGetExtensionsStringARB;
	if(!(wglGetExtensionsStringARB =
	   (PFNWGLGETEXTENSIONSSTRINGARBPROC)wglGetProcAddress("wglGetExtensionsStringARB")))
		return false;
	// get wglGetExtensionsStringARB() if not linked statically
#endif // !WGL_WGLEXT_PROTOTYPES

	const char *p_s_extensions = (const char*)wglGetExtensionsStringARB(wglGetCurrentDC());
	// get WGL extensions string

	const char *p_s_search_str = p_s_extensions;
	do {
		if((p_s_search_str = strstr(p_s_search_str, p_s_extension_name))) {
			if(p_s_search_str > p_s_extensions && !isspace(*(p_s_search_str - 1)))
				continue;
			if(strlen(p_s_search_str + strlen(p_s_extension_name)) &&
			   !isspace(*(p_s_search_str + strlen(p_s_extension_name))))
				continue;

			return true;
		}
	} while(p_s_search_str && strlen(++ p_s_search_str));
	// look for the extension

	return false;
}

#else // _WIN32 || _WIN64

bool CGLES20ExtensionHandler::b_SupportedPlatformExtension(const char *p_s_extension_name)
{
#ifdef GLX_VERSION_1_2
	const char *p_s_extensions;
	p_s_extensions = (const char*)glXGetClientString(glXGetCurrentDisplay(), GLX_EXTENSIONS); // @todo - debug this
	// glXGetClientString() is in GLX 1.1 and later (static linking)
	// glXGetCurrentDisplay() is in GLX 1.2 and later (static linking)
	// GLX_EXTENSIONS is in GLX 1.1
	// get GLX extensions string

	/*p_s_extensions = (const char*)glXQueryExtensionsString(glXGetCurrentDisplay(),
		DefaultScreen(glXGetCurrentDisplay()));*/
	// this could also work

	const char *p_s_search_str = p_s_extensions;
	do {
		if((p_s_search_str = strstr(p_s_search_str, p_s_extension_name))) {
			if(p_s_search_str > p_s_extensions && !isspace(*(p_s_search_str - 1)))
				continue;
			if(strlen(p_s_search_str + strlen(p_s_extension_name)) &&
			   !isspace(*(p_s_search_str + strlen(p_s_extension_name))))
				continue;

			return true;
		}
	} while(p_s_search_str && strlen(++ p_s_search_str));
	// look for the extension

#else // GLX_VERSION_1_2
#ifdef __APPLE__
	// can't expect anything from a Mac
#else // __APPLE__
#error("GLX 1.2 is needed for glXGetClientString(GLX_EXTENSIONS) to work")
#endif // __APPLE__
#endif // GLX_VERSION_1_2

	return false;
}

#endif // _WIN32 || _WIN64

int CGLES20ExtensionHandler::n_GetAllSupportedExtensionsFuncPointers()
{
#ifdef _DEBUG
	GLEH_OpenGL_ES_2_0 = false;
	GLEH_ARB_vertex_array_object = false;
	GLEH_OES_texture_3D = false;
	GLEH_OES_depth24 = false;
	GLEH_OES_depth32 = false;
	GLEH_OES_element_index_uint = false;
	GLEH_OES_mapbuffer = false;
	GLEH_OES_rgb8_rgba8 = false;
	GLEH_OES_stencil1 = false;
	GLEH_OES_stencil4 = false;
	GLEH_OES_stencil8 = false;
	GLEH_OES_depth_texture = false;
	GLEH_OES_packed_depth_stencil = false;
	GLEH_OES_get_program_binary = false;
	GLEH_EXT_texture_format_BGRA8888 = false;
	GLEH_NV_fence = false;
	GLEH_EXT_texture_lod_bias = false;
	GLEH_NV_draw_buffers = false;
	GLEH_NV_fbo_color_attachments = false;
	GLEH_NV_read_buffer = false;

	GLEH_EXT_texture_array = false;
	GLEH_EXT_occlusion_query_boolean = false;
	GLEH_EXT_robustness = false;
	GLEH_NV_read_depth_stencil = false;
	GLEH_NV_texture_compression_s3tc_update = false;
	GLEH_EXT_unpack_subimage = false;
	GLEH_EXT_texture_filter_anisotropic = false;
	GLEH_OES_standard_derivatives = false;
	GLEH_OES_compressed_ETC1_RGB8_texture = false;
	GLEH_OES_texture_float = false;
	GLEH_OES_vertex_half_float = false;
	GLEH_OES_fbo_render_mipmap = false;
	// this is just to check GLEH_ fral presence
#endif //_DEBUG

	return n_GetGLES20FuncPointers() +
		   n_GetARBVertexArrayObjectFuncPointers() +
		   n_GetOESTexture3DFuncPointers() +
		   n_GetOESDepth24FuncPointers() +
		   n_GetOESDepth32FuncPointers() +
		   n_GetOESElementIndexUIntFuncPointers() +
		   n_GetOESMapbufferFuncPointers() +
		   n_GetOESRGB8RGBA8FuncPointers() +
		   n_GetOESStencil1FuncPointers() +
		   n_GetOESStencil4FuncPointers() +
		   n_GetOESStencil8FuncPointers() +
		   n_GetOESDepthTextureFuncPointers() +
		   n_GetOESPackedDepthStencilFuncPointers() +
		   n_GetOESGetProgramBinaryFuncPointers() +
		   n_GetEXTTextureFormatBGRA8888FuncPointers() +
		   n_GetNVFenceFuncPointers() +
		   n_GetEXTTextureLODBiasFuncPointers() +
		   n_GetNVDrawBuffersFuncPointers() +
		   n_GetNVFBOColorAttachmentsFuncPointers() +
		   n_GetNVReadBufferFuncPointers() +
		   n_GetOESFboRenderMipmapFuncPointers() +
		   n_GetOESVertexHalfFloatFuncPointers() +
		   n_GetOESTextureFloatFuncPointers() +
		   n_GetOESCompressedETC1RGB8TextureFuncPointers() +
		   n_GetOESStandardDerivativesFuncPointers() +
		   n_GetEXTTextureFilterAnisotropicFuncPointers() +
		   n_GetEXTUnpackSubimageFuncPointers() +
		   n_GetNVTextureCompressionS3tcUpdateFuncPointers() +
		   n_GetNVReadDepthStencilFuncPointers() +
		   n_GetEXTRobustnessFuncPointers() +
		   n_GetEXTOcclusionQueryBooleanFuncPointers() +
		   n_GetEXTTextureArrayFuncPointers();
}

char *p_s_PreprocessShaderSource(const char *p_s_source, bool b_is_fragment_shader)
{
#ifdef _HAVE_OPENGLES2
	const char *p_s_source_code = p_s_source;
#else // _HAVE_OPENGLES2
	if(!strstr(p_s_source, "precision"))
		fprintf(stderr, "warning: shader source code requires precision specifier in OpenGL ES\n");
	// most of the OpenGL implementations won't warn about that, we have to do it

	std::string s_source2;
	try {
		std::string s_temp_shader_source, s_temp_shader_source2;
		do {
			int n_major, n_minor;
			const char *p_s_glsl_version = (const char*)glGetString(GL_SHADING_LANGUAGE_VERSION);
#if defined(_MSC_VER) && !defined(__MWERKS__) && _MSC_VER >= 1400
			if(!p_s_glsl_version || sscanf_s(p_s_glsl_version, "%d.%d", &n_major, &n_minor) != 2) {
#else //_MSC_VER && !__MWERKS__ && _MSC_VER >= 1400
			if(!p_s_glsl_version || sscanf(p_s_glsl_version, "%d.%d", &n_major, &n_minor) != 2) {
#endif //_MSC_VER && !__MWERKS__ && _MSC_VER >= 1400
				n_major = 0;
				n_minor = 0;
			}
			// try to obtain GLSL version

#ifndef _MAC
			if(CGLES20ExtensionHandler::b_Support_OpenGL(3, 3) && (n_major > 3 || (n_major == 3 && n_minor >= 30))) {
				s_source2 = "#version 330\r\n" // have to specify GLSL version on PC
					"#define texture1D(t,c) texture((t), (c))\r\n"
					"#define texture2D(t,c) texture((t), (c))\r\n"
					"#define texture3D(t,c) texture((t), (c))\r\n"; // deprecated texture functions
#else // !_MAC
			if(CGLES20ExtensionHandler::b_Support_OpenGL(3, 2) && (n_major > 3 || (n_major == 3 && n_minor >= 20))) {
				s_source2 = "#version 320\r\n" // have to specify GLSL version on MAC
					"#define texture1D(t,c) texture((t), (c))\r\n"
					"#define texture2D(t,c) texture((t), (c))\r\n"
					"#define texture3D(t,c) texture((t), (c))\r\n"; // deprecated texture functions
				// note this was changed from 330 to 320 for MAC since their cutting edge OpenGL is 3.2 (Q2 2013)
#endif // !_MAC
			} else if(n_major > 1 || (n_major == 1 && n_minor >= 30))
				s_source2 = "#version 130\r\n"; // this is fallback; some OpenGL 2.1 implementations with recent drivers do support this
			else {
				// no version specifier for very old implementations

				s_temp_shader_source = p_s_source;
				// copy shader source ...

				size_t n_pos = 0;
				while((n_pos = s_temp_shader_source.find("precision", n_pos)) != std::string::npos) {
					size_t b = n_pos, e = s_temp_shader_source.length();
					b += strlen("precision");
					// default precision specification statement

					if(b == e) {
						++ n_pos; // unknown syntax, just continue
						continue;
					}
					while(b < e && isspace(uint8_t(s_temp_shader_source[b])))
						++ b;
					// skip space

					if(b + 4 < e && !memcmp(s_temp_shader_source.data() + b, "lowp", 4 * sizeof(char)))
						b += 4;
					else if(b + 7 < e && !memcmp(s_temp_shader_source.data() + b, "mediump", 7 * sizeof(char)))
						b += 7;
					else if(b + 5 < e && !memcmp(s_temp_shader_source.data() + b, "highp", 5 * sizeof(char)))
						b += 5;
					else {
						++ n_pos; // unknown syntax, just continue
						continue;
					}
					// skip precission qualifier

					if(b == e) {
						++ n_pos; // unknown syntax, just continue
						continue;
					}
					while(b < e && isspace(uint8_t(s_temp_shader_source[b])))
						++ b;
					// skip space

					if(b == e) {
						++ n_pos; // unknown syntax, just continue
						continue;
					}
					while(b < e && isalnum(uint8_t(s_temp_shader_source[b])))
						++ b;
					// skip data type (eg. float, vec4, ...)

					while(b < e && isspace(uint8_t(s_temp_shader_source[b])))
						++ b;
					// skip space

					if(b == e || s_temp_shader_source[b] != ';') {
						++ n_pos; // unknown syntax, just continue
						continue;
					}
					++ b; // skip ';'
					// skip semicolon

					size_t n_begin = n_pos;
					size_t n_end = b;
					_ASSERTE(n_end >= n_begin);
					if(n_end >= n_begin)
						s_temp_shader_source.erase(n_begin, n_end - n_begin);
					// erase the default precission specification
				}
				// this erases any default precision qualifiers there are

				// todo - it would also be nice to erase precision qualifiers from
				// the individual variables (eg. "uniform highp float time;")

				p_s_source = s_temp_shader_source.c_str();
				// just need to get rid of "precision highp float;" lines because these compilers do not understand those
				break;
			}
			// set shading language version

			if(b_is_fragment_shader) {
				// fragment
				s_source2 += "out vec4 _v_gl_frag_color_;\r\n";
				s_source2 += "#define gl_FragColor _v_gl_frag_color_\r\n";
				s_source2 += "#define varying in\r\n";
				s_source2 += "#line 0\r\n"; // fix line numbering ...
			} else {
				// vertex
				s_source2 += "#define attribute in\r\n";
				s_source2 += "#define varying out\r\n";
				s_source2 += "#line 0\r\n"; // fix line numbering ...
			};
			// add directives, if required

			{
				s_temp_shader_source2 = p_s_source;

				size_t n_pos = 0;
				while((n_pos = s_temp_shader_source2.find("version", n_pos)) != std::string::npos) {
					size_t b = n_pos, e = s_temp_shader_source2.length();
					b += strlen("version");
					// version specification statement

					while(n_pos > 0 && isspace(uint8_t(s_temp_shader_source2[n_pos - 1])))
						-- n_pos;
					if(!n_pos || s_temp_shader_source2[n_pos - 1] != '#') {
						n_pos = b; // avoid repeating the search
						continue;
					}
					-- n_pos; // skip '#'
					// look for the hash sign (might be separated by spaces from the version keyword)

					if(b == e || !isspace(uint8_t(s_temp_shader_source2[b]))) {
						n_pos = b; // avoid repeating the search
						continue;
					}
					while(b < e && isspace(uint8_t(s_temp_shader_source2[b])))
						++ b;
					// skip space

					if(b == e) {
						++ n_pos; // unknown syntax, just continue
						continue;
					}
					while(b < e && isalnum(uint8_t(s_temp_shader_source2[b])))
						++ b;
					// skip version specification (currently a number, e.g. "330")

					if(b < e && s_temp_shader_source2[b] != '\r' && s_temp_shader_source2[b] != '\n')
						fprintf(stderr, "warning: version specification does not end in newline\n");
					// should end in newline to avoid preprocessor handling the next source code line
					// (happens often when specifying shaders in strings)

					s_temp_shader_source2.erase(n_pos, b - n_pos);
					// erase from the list
				}

				p_s_source = s_temp_shader_source2.c_str();
			}
			// dispose of additional #version
		} while(0);
		// add some directives for the OpenGL ES shaders to work on OpenGL hardware
		// t_odo - intercept glShaderSource and preprocess the source code in there

		s_source2 += p_s_source;
		// include the main shader source
	} catch(std::bad_alloc&) {
		return 0;
	}
	const char *p_s_source_code = s_source2.c_str();
#endif // _HAVE_OPENGLES2

#if defined(_MSC_VER) && !defined(__MWERKS__) && _MSC_VER >= 1400
	return _strdup(p_s_source_code);
#else // _MSC_VER && !__MWERKS__ && _MSC_VER >= 1400
	return strdup(p_s_source_code);
#endif // _MSC_VER && !__MWERKS__ && _MSC_VER >= 1400
}

#define GL_LINE									0x1B01
#define GL_FILL									0x1B02
extern "C" void ApiEntry glPolygonMode(GLenum n_side, GLenum n_mode);
// hack - use an OpenGL function

void glesemuEnableWireframe()
{
	glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
}

void glesemuDisableWireframe()
{
	glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
}

char *p_s_PreprocessSource_VertexShader(const char *p_s_source)
{
	return p_s_PreprocessShaderSource(p_s_source, false);
}

char *p_s_PreprocessSource_FragmentShader(const char *p_s_source)
{
	return p_s_PreprocessShaderSource(p_s_source, true);
}

void __gles20emupatch_glShaderSource(GLuint shader, GLsizei count, const GLchar** string, const GLint* length)
{
	int n_type;
	GLFuncPtrName(glGetShaderiv)(shader, GL_SHADER_TYPE, &n_type);

	GLint *p_length_list = new(std::nothrow) GLint[count];
	char **p_source_list = new(std::nothrow) char*[count];
	// alloc list for shader sources (ignore alloc errors here)

	if(n_type == GL_VERTEX_SHADER) {
        for(int i = 0; i < count; ++ i) {
            p_source_list[i] = p_s_PreprocessSource_VertexShader(string[i]);
			size_t n_len = strlen(p_source_list[i]);
			_ASSERTE(n_len <= INT_MAX);
            p_length_list[i] = GLint(n_len);
        }
        // preprocess the shaders
    } else if(n_type == GL_FRAGMENT_SHADER) {
        for(int i = 0; i < count; ++ i) {
            p_source_list[i] = p_s_PreprocessSource_FragmentShader(string[i]);
			size_t n_len = strlen(p_source_list[i]);
			_ASSERTE(n_len <= INT_MAX);
            p_length_list[i] = GLint(n_len);
        }
        // preprocess the shaders
	} else {
		for(int i = 0; i < count; ++ i) {
#if defined(_MSC_VER) && !defined(__MWERKS__) && _MSC_VER >= 1400
			p_source_list[i] = _strdup(string[i]);
#else // _MSC_VER && !__MWERKS__ && _MSC_VER >= 1400
			p_source_list[i] = strdup(string[i]);
#endif // _MSC_VER && !__MWERKS__ && _MSC_VER >= 1400
			size_t n_len = (length)? length[i] : strlen(p_source_list[i]);
			_ASSERTE(n_len <= INT_MAX);
			p_length_list[i] = GLint(n_len);
		}
		// this is probably failure, someone didn't call glGenShaders(). let it fail ...
	}

	GLFuncPtrName(glShaderSource)(shader, count, (const char**)p_source_list, p_length_list);
	// call GL

	for(int i = 0; i < count; ++ i)
		delete[] p_source_list[i];
	delete[] p_source_list;
	delete[] p_length_list;
	// cleanup
}

#define CGL4ExtensionHandler CGLES20ExtensionHandler
// fix code generated by GLEH

/*
 *								--- OpenGL ES 2.0 ---
 */

bool GLEH_OpenGL_ES_2_0 = false;

#define __GENERATE_GL_OGL_dynamic_opengles_20_functions

#ifdef __GENERATE_GL_OGL_dynamic_opengles_20_functions

void (GLApi *GLFuncPtrName(glActiveTexture))(GLenum) INIT_FUNC_POINTERS;
void (GLApi *GLFuncPtrName(glAttachShader))(GLuint, GLuint) INIT_FUNC_POINTERS;
void (GLApi *GLFuncPtrName(glBindAttribLocation))(GLuint, GLuint, const GLchar*) INIT_FUNC_POINTERS;
void (GLApi *GLFuncPtrName(glBindBuffer))(GLenum, GLuint) INIT_FUNC_POINTERS;
void (GLApi *GLFuncPtrName(glBindFramebuffer))(GLenum, GLuint) INIT_FUNC_POINTERS;
void (GLApi *GLFuncPtrName(glBindRenderbuffer))(GLenum, GLuint) INIT_FUNC_POINTERS;
void (GLApi *GLFuncPtrName(glBlendColor))(GLclampf, GLclampf, GLclampf, GLclampf) INIT_FUNC_POINTERS;
void (GLApi *GLFuncPtrName(glBlendEquation))(GLenum) INIT_FUNC_POINTERS;
void (GLApi *GLFuncPtrName(glBlendEquationSeparate))(GLenum, GLenum) INIT_FUNC_POINTERS;
void (GLApi *GLFuncPtrName(glBlendFuncSeparate))(GLenum, GLenum, GLenum, GLenum) INIT_FUNC_POINTERS;
void (GLApi *GLFuncPtrName(glBufferData))(GLenum, GLsizeiptr, const void*, GLenum) INIT_FUNC_POINTERS;
void (GLApi *GLFuncPtrName(glBufferSubData))(GLenum, GLintptr, GLsizeiptr, const void*) INIT_FUNC_POINTERS;
GLenum (GLApi *GLFuncPtrName(glCheckFramebufferStatus))(GLenum) INIT_FUNC_POINTERS;
void (GLApi *GLFuncPtrName(glClearDepthf))(GLclampf) INIT_FUNC_POINTERS;
void (GLApi *GLFuncPtrName(glCompileShader))(GLuint) INIT_FUNC_POINTERS;
void (GLApi *GLFuncPtrName(glCompressedTexImage2D))(GLenum, int, GLenum, GLsizei, GLsizei, int, GLsizei, const void*) INIT_FUNC_POINTERS;
void (GLApi *GLFuncPtrName(glCompressedTexSubImage2D))(GLenum, int, int, int, GLsizei, GLsizei, GLenum, GLsizei, const void*) INIT_FUNC_POINTERS;
GLuint (GLApi *GLFuncPtrName(glCreateProgram))() INIT_FUNC_POINTERS;
GLuint (GLApi *GLFuncPtrName(glCreateShader))(GLenum) INIT_FUNC_POINTERS;
void (GLApi *GLFuncPtrName(glDeleteBuffers))(GLsizei, const GLuint*) INIT_FUNC_POINTERS;
void (GLApi *GLFuncPtrName(glDeleteFramebuffers))(GLsizei, const GLuint*) INIT_FUNC_POINTERS;
void (GLApi *GLFuncPtrName(glDeleteProgram))(GLuint) INIT_FUNC_POINTERS;
void (GLApi *GLFuncPtrName(glDeleteRenderbuffers))(GLsizei, const GLuint*) INIT_FUNC_POINTERS;
void (GLApi *GLFuncPtrName(glDeleteShader))(GLuint) INIT_FUNC_POINTERS;
void (GLApi *GLFuncPtrName(glDepthRangef))(GLclampf, GLclampf) INIT_FUNC_POINTERS;
void (GLApi *GLFuncPtrName(glDetachShader))(GLuint, GLuint) INIT_FUNC_POINTERS;
void (GLApi *GLFuncPtrName(glDisableVertexAttribArray))(GLuint) INIT_FUNC_POINTERS;
void (GLApi *GLFuncPtrName(glEnableVertexAttribArray))(GLuint) INIT_FUNC_POINTERS;
void (GLApi *GLFuncPtrName(glFramebufferRenderbuffer))(GLenum, GLenum, GLenum, GLuint) INIT_FUNC_POINTERS;
void (GLApi *GLFuncPtrName(glFramebufferTexture2D))(GLenum, GLenum, GLenum, GLuint, int) INIT_FUNC_POINTERS;
void (GLApi *GLFuncPtrName(glGenBuffers))(GLsizei, GLuint*) INIT_FUNC_POINTERS;
void (GLApi *GLFuncPtrName(glGenerateMipmap))(GLenum) INIT_FUNC_POINTERS;
void (GLApi *GLFuncPtrName(glGenFramebuffers))(GLsizei, GLuint*) INIT_FUNC_POINTERS;
void (GLApi *GLFuncPtrName(glGenRenderbuffers))(GLsizei, GLuint*) INIT_FUNC_POINTERS;
void (GLApi *GLFuncPtrName(glGetActiveAttrib))(GLuint, GLuint, GLsizei, GLsizei*, GLsizei*, GLenum*, GLchar*) INIT_FUNC_POINTERS;
void (GLApi *GLFuncPtrName(glGetActiveUniform))(GLuint, GLuint, GLsizei, GLsizei*, GLsizei*, GLenum*, GLchar*) INIT_FUNC_POINTERS;
void (GLApi *GLFuncPtrName(glGetAttachedShaders))(GLuint, GLsizei, GLsizei*, GLuint*) INIT_FUNC_POINTERS;
int (GLApi *GLFuncPtrName(glGetAttribLocation))(GLuint, const GLchar*) INIT_FUNC_POINTERS;
void (GLApi *GLFuncPtrName(glGetBufferParameteriv))(GLenum, GLenum, int*) INIT_FUNC_POINTERS;
void (GLApi *GLFuncPtrName(glGetFramebufferAttachmentParameteriv))(GLenum, GLenum, GLenum, int*) INIT_FUNC_POINTERS;
void (GLApi *GLFuncPtrName(glGetProgramiv))(GLuint, GLenum, int*) INIT_FUNC_POINTERS;
void (GLApi *GLFuncPtrName(glGetProgramInfoLog))(GLuint, GLsizei, GLsizei*, GLchar*) INIT_FUNC_POINTERS;
void (GLApi *GLFuncPtrName(glGetRenderbufferParameteriv))(GLenum, GLenum, int*) INIT_FUNC_POINTERS;
void (GLApi *GLFuncPtrName(glGetShaderiv))(GLuint, GLenum, int*) INIT_FUNC_POINTERS;
void (GLApi *GLFuncPtrName(glGetShaderInfoLog))(GLuint, GLsizei, GLsizei*, GLchar*) INIT_FUNC_POINTERS;
void (GLApi *GLFuncPtrName(glGetShaderPrecisionFormat))(GLenum, GLenum, int*, int*) INIT_FUNC_POINTERS;
void (GLApi *GLFuncPtrName(glGetShaderSource))(GLuint, GLsizei, GLsizei*, GLchar*) INIT_FUNC_POINTERS;
void (GLApi *GLFuncPtrName(glGetUniformfv))(GLuint, int, float*) INIT_FUNC_POINTERS;
void (GLApi *GLFuncPtrName(glGetUniformiv))(GLuint, int, int*) INIT_FUNC_POINTERS;
int (GLApi *GLFuncPtrName(glGetUniformLocation))(GLuint, const GLchar*) INIT_FUNC_POINTERS;
void (GLApi *GLFuncPtrName(glGetVertexAttribfv))(GLuint, GLenum, float*) INIT_FUNC_POINTERS;
void (GLApi *GLFuncPtrName(glGetVertexAttribiv))(GLuint, GLenum, int*) INIT_FUNC_POINTERS;
void (GLApi *GLFuncPtrName(glGetVertexAttribPointerv))(GLuint, GLenum, void**) INIT_FUNC_POINTERS;
GLboolean (GLApi *GLFuncPtrName(glIsBuffer))(GLuint) INIT_FUNC_POINTERS;
GLboolean (GLApi *GLFuncPtrName(glIsFramebuffer))(GLuint) INIT_FUNC_POINTERS;
GLboolean (GLApi *GLFuncPtrName(glIsProgram))(GLuint) INIT_FUNC_POINTERS;
GLboolean (GLApi *GLFuncPtrName(glIsRenderbuffer))(GLuint) INIT_FUNC_POINTERS;
GLboolean (GLApi *GLFuncPtrName(glIsShader))(GLuint) INIT_FUNC_POINTERS;
void (GLApi *GLFuncPtrName(glLinkProgram))(GLuint) INIT_FUNC_POINTERS;
void (GLApi *GLFuncPtrName(glReleaseShaderCompiler))() INIT_FUNC_POINTERS;
void (GLApi *GLFuncPtrName(glRenderbufferStorage))(GLenum, GLenum, GLsizei, GLsizei) INIT_FUNC_POINTERS;
void (GLApi *GLFuncPtrName(glSampleCoverage))(GLclampf, GLboolean) INIT_FUNC_POINTERS;
void (GLApi *GLFuncPtrName(glShaderBinary))(GLsizei, const GLuint*, GLenum, const void*, GLsizei) INIT_FUNC_POINTERS;
void (GLApi *GLFuncPtrName(glShaderSource))(GLuint, GLsizei, const GLchar**, const int*) INIT_FUNC_POINTERS;
void (GLApi *GLFuncPtrName(glStencilFuncSeparate))(GLenum, GLenum, int, GLuint) INIT_FUNC_POINTERS;
void (GLApi *GLFuncPtrName(glStencilMaskSeparate))(GLenum, GLuint) INIT_FUNC_POINTERS;
void (GLApi *GLFuncPtrName(glStencilOpSeparate))(GLenum, GLenum, GLenum, GLenum) INIT_FUNC_POINTERS;
void (GLApi *GLFuncPtrName(glUniform1f))(int, float) INIT_FUNC_POINTERS;
void (GLApi *GLFuncPtrName(glUniform2f))(int, float, float) INIT_FUNC_POINTERS;
void (GLApi *GLFuncPtrName(glUniform3f))(int, float, float, float) INIT_FUNC_POINTERS;
void (GLApi *GLFuncPtrName(glUniform4f))(int, float, float, float, float) INIT_FUNC_POINTERS;
void (GLApi *GLFuncPtrName(glUniform1i))(int, int) INIT_FUNC_POINTERS;
void (GLApi *GLFuncPtrName(glUniform2i))(int, int, int) INIT_FUNC_POINTERS;
void (GLApi *GLFuncPtrName(glUniform3i))(int, int, int, int) INIT_FUNC_POINTERS;
void (GLApi *GLFuncPtrName(glUniform4i))(int, int, int, int, int) INIT_FUNC_POINTERS;
void (GLApi *GLFuncPtrName(glUniform1fv))(int, GLsizei, const float*) INIT_FUNC_POINTERS;
void (GLApi *GLFuncPtrName(glUniform2fv))(int, GLsizei, const float*) INIT_FUNC_POINTERS;
void (GLApi *GLFuncPtrName(glUniform3fv))(int, GLsizei, const float*) INIT_FUNC_POINTERS;
void (GLApi *GLFuncPtrName(glUniform4fv))(int, GLsizei, const float*) INIT_FUNC_POINTERS;
void (GLApi *GLFuncPtrName(glUniform1iv))(int, GLsizei, const int*) INIT_FUNC_POINTERS;
void (GLApi *GLFuncPtrName(glUniform2iv))(int, GLsizei, const int*) INIT_FUNC_POINTERS;
void (GLApi *GLFuncPtrName(glUniform3iv))(int, GLsizei, const int*) INIT_FUNC_POINTERS;
void (GLApi *GLFuncPtrName(glUniform4iv))(int, GLsizei, const int*) INIT_FUNC_POINTERS;
void (GLApi *GLFuncPtrName(glUniformMatrix2fv))(int, GLsizei, GLboolean, const float*) INIT_FUNC_POINTERS;
void (GLApi *GLFuncPtrName(glUniformMatrix3fv))(int, GLsizei, GLboolean, const float*) INIT_FUNC_POINTERS;
void (GLApi *GLFuncPtrName(glUniformMatrix4fv))(int, GLsizei, GLboolean, const float*) INIT_FUNC_POINTERS;
void (GLApi *GLFuncPtrName(glUseProgram))(GLuint) INIT_FUNC_POINTERS;
void (GLApi *GLFuncPtrName(glValidateProgram))(GLuint) INIT_FUNC_POINTERS;
void (GLApi *GLFuncPtrName(glVertexAttrib1f))(GLuint, float) INIT_FUNC_POINTERS;
void (GLApi *GLFuncPtrName(glVertexAttrib1fv))(GLuint, const float*) INIT_FUNC_POINTERS;
void (GLApi *GLFuncPtrName(glVertexAttrib2f))(GLuint, float, float) INIT_FUNC_POINTERS;
void (GLApi *GLFuncPtrName(glVertexAttrib2fv))(GLuint, const float*) INIT_FUNC_POINTERS;
void (GLApi *GLFuncPtrName(glVertexAttrib3f))(GLuint, float, float, float) INIT_FUNC_POINTERS;
void (GLApi *GLFuncPtrName(glVertexAttrib3fv))(GLuint, const float*) INIT_FUNC_POINTERS;
void (GLApi *GLFuncPtrName(glVertexAttrib4f))(GLuint, float, float, float, float) INIT_FUNC_POINTERS;
void (GLApi *GLFuncPtrName(glVertexAttrib4fv))(GLuint, const float*) INIT_FUNC_POINTERS;
void (GLApi *GLFuncPtrName(glVertexAttribPointer))(GLuint, int, GLenum, GLboolean, GLsizei, const void*) INIT_FUNC_POINTERS;

#endif //__GENERATE_GL_OGL_dynamic_opengles_20_functions

int CGLES20ExtensionHandler::n_GetGLES20FuncPointers()
{
	int n_failed_functions = 0;

#ifdef __GENERATE_GL_OGL_dynamic_opengles_20_functions

	if(!(GLFuncPtrName(glActiveTexture) = (void(GLApi*)(GLenum))wglGetProcAddress("glActiveTexture"))) ++ n_failed_functions;
	if(!(GLFuncPtrName(glAttachShader) = (void(GLApi*)(GLuint, GLuint))wglGetProcAddress("glAttachObjectARB"))) ++ n_failed_functions;
	if(!(GLFuncPtrName(glBindAttribLocation) = (void(GLApi*)(GLuint, GLuint, const GLchar*))wglGetProcAddress("glBindAttribLocation"))) ++ n_failed_functions;
	if(!(GLFuncPtrName(glBindBuffer) = (void(GLApi*)(GLenum, GLuint))wglGetProcAddress("glBindBuffer"))) ++ n_failed_functions;
	if(!(GLFuncPtrName(glBindFramebuffer) = (void(GLApi*)(GLenum, GLuint))wglGetProcAddress("glBindFramebufferEXT"))) ++ n_failed_functions;
	if(!(GLFuncPtrName(glBindRenderbuffer) = (void(GLApi*)(GLenum, GLuint))wglGetProcAddress("glBindRenderbufferEXT"))) ++ n_failed_functions;
	if(!(GLFuncPtrName(glBlendColor) = (void(GLApi*)(GLclampf, GLclampf, GLclampf, GLclampf))wglGetProcAddress("glBlendColor"))) ++ n_failed_functions;
	if(!(GLFuncPtrName(glBlendEquation) = (void(GLApi*)(GLenum))wglGetProcAddress("glBlendEquation"))) ++ n_failed_functions;
	if(!(GLFuncPtrName(glBlendEquationSeparate) = (void(GLApi*)(GLenum, GLenum))wglGetProcAddress("glBlendEquationSeparate"))) ++ n_failed_functions;
	if(!(GLFuncPtrName(glBlendFuncSeparate) = (void(GLApi*)(GLenum, GLenum, GLenum, GLenum))wglGetProcAddress("glBlendFuncSeparate"))) ++ n_failed_functions;
	if(!(GLFuncPtrName(glBufferData) = (void(GLApi*)(GLenum, GLsizeiptr, const void*, GLenum))wglGetProcAddress("glBufferData"))) ++ n_failed_functions;
	if(!(GLFuncPtrName(glBufferSubData) = (void(GLApi*)(GLenum, GLintptr, GLsizeiptr, const void*))wglGetProcAddress("glBufferSubData"))) ++ n_failed_functions;
	if(!(GLFuncPtrName(glCheckFramebufferStatus) = (GLenum(GLApi*)(GLenum))wglGetProcAddress("glCheckFramebufferStatusEXT"))) ++ n_failed_functions;
	if(!(GLFuncPtrName(glClearDepthf) = (void(GLApi*)(GLclampf))wglGetProcAddress("glClearDepthf"))) ++ n_failed_functions;
	if(!(GLFuncPtrName(glCompileShader) = (void(GLApi*)(GLuint))wglGetProcAddress("glCompileShaderARB"))) ++ n_failed_functions;
	if(!(GLFuncPtrName(glCompressedTexImage2D) = (void(GLApi*)(GLenum, int, GLenum, GLsizei, GLsizei, int, GLsizei, const void*))wglGetProcAddress("glCompressedTexImage2D"))) ++ n_failed_functions;
	if(!(GLFuncPtrName(glCompressedTexSubImage2D) = (void(GLApi*)(GLenum, int, int, int, GLsizei, GLsizei, GLenum, GLsizei, const void*))wglGetProcAddress("glCompressedTexSubImage2D"))) ++ n_failed_functions;
	if(!(GLFuncPtrName(glCreateProgram) = (GLuint(GLApi*)())wglGetProcAddress("glCreateProgramObjectARB"))) ++ n_failed_functions;
	if(!(GLFuncPtrName(glCreateShader) = (GLuint(GLApi*)(GLenum))wglGetProcAddress("glCreateShaderObjectARB"))) ++ n_failed_functions;
	if(!(GLFuncPtrName(glDeleteBuffers) = (void(GLApi*)(GLsizei, const GLuint*))wglGetProcAddress("glDeleteBuffers"))) ++ n_failed_functions;
	if(!(GLFuncPtrName(glDeleteFramebuffers) = (void(GLApi*)(GLsizei, const GLuint*))wglGetProcAddress("glDeleteFramebuffersEXT"))) ++ n_failed_functions;
	if(!(GLFuncPtrName(glDeleteProgram) = (void(GLApi*)(GLuint))wglGetProcAddress("glDeleteProgram"))) ++ n_failed_functions;
	if(!(GLFuncPtrName(glDeleteRenderbuffers) = (void(GLApi*)(GLsizei, const GLuint*))wglGetProcAddress("glDeleteRenderbuffersEXT"))) ++ n_failed_functions;
	if(!(GLFuncPtrName(glDeleteShader) = (void(GLApi*)(GLuint))wglGetProcAddress("glDeleteObjectARB"))) ++ n_failed_functions;
	if(!(GLFuncPtrName(glDepthRangef) = (void(GLApi*)(GLclampf, GLclampf))wglGetProcAddress("glDepthRangef"))) ++ n_failed_functions;
	if(!(GLFuncPtrName(glDetachShader) = (void(GLApi*)(GLuint, GLuint))wglGetProcAddress("glDetachObjectARB"))) ++ n_failed_functions;
	if(!(GLFuncPtrName(glDisableVertexAttribArray) = (void(GLApi*)(GLuint))wglGetProcAddress("glDisableVertexAttribArray"))) ++ n_failed_functions;
	if(!(GLFuncPtrName(glEnableVertexAttribArray) = (void(GLApi*)(GLuint))wglGetProcAddress("glEnableVertexAttribArray"))) ++ n_failed_functions;
	if(!(GLFuncPtrName(glFramebufferRenderbuffer) = (void(GLApi*)(GLenum, GLenum, GLenum, GLuint))wglGetProcAddress("glFramebufferRenderbufferEXT"))) ++ n_failed_functions;
	if(!(GLFuncPtrName(glFramebufferTexture2D) = (void(GLApi*)(GLenum, GLenum, GLenum, GLuint, int))wglGetProcAddress("glFramebufferTexture2DEXT"))) ++ n_failed_functions;
	if(!(GLFuncPtrName(glGenBuffers) = (void(GLApi*)(GLsizei, GLuint*))wglGetProcAddress("glGenBuffers"))) ++ n_failed_functions;
	if(!(GLFuncPtrName(glGenerateMipmap) = (void(GLApi*)(GLenum))wglGetProcAddress("glGenerateMipmap"))) ++ n_failed_functions;
	if(!(GLFuncPtrName(glGenFramebuffers) = (void(GLApi*)(GLsizei, GLuint*))wglGetProcAddress("glGenFramebuffersEXT"))) ++ n_failed_functions;
	if(!(GLFuncPtrName(glGenRenderbuffers) = (void(GLApi*)(GLsizei, GLuint*))wglGetProcAddress("glGenRenderbuffersEXT"))) ++ n_failed_functions;
	if(!(GLFuncPtrName(glGetActiveAttrib) = (void(GLApi*)(GLuint, GLuint, GLsizei, GLsizei*, GLsizei*, GLenum*, GLchar*))wglGetProcAddress("glGetActiveAttrib"))) ++ n_failed_functions;
	if(!(GLFuncPtrName(glGetActiveUniform) = (void(GLApi*)(GLuint, GLuint, GLsizei, GLsizei*, GLsizei*, GLenum*, GLchar*))wglGetProcAddress("glGetActiveUniformARB"))) ++ n_failed_functions;
	if(!(GLFuncPtrName(glGetAttachedShaders) = (void(GLApi*)(GLuint, GLsizei, GLsizei*, GLuint*))wglGetProcAddress("glGetAttachedObjectsARB"))) ++ n_failed_functions;
	if(!(GLFuncPtrName(glGetAttribLocation) = (int(GLApi*)(GLuint, const GLchar*))wglGetProcAddress("glGetAttribLocation"))) ++ n_failed_functions;
	if(!(GLFuncPtrName(glGetBufferParameteriv) = (void(GLApi*)(GLenum, GLenum, int*))wglGetProcAddress("glGetBufferParameteriv"))) ++ n_failed_functions;
	if(!(GLFuncPtrName(glGetFramebufferAttachmentParameteriv) = (void(GLApi*)(GLenum, GLenum, GLenum, int*))wglGetProcAddress("glGetFramebufferAttachmentParameterivEXT"))) ++ n_failed_functions;
	if(!(GLFuncPtrName(glGetProgramiv) = (void(GLApi*)(GLuint, GLenum, int*))wglGetProcAddress("glGetObjectParameterivARB"))) ++ n_failed_functions;
	if(!(GLFuncPtrName(glGetProgramInfoLog) = (void(GLApi*)(GLuint, GLsizei, GLsizei*, GLchar*))wglGetProcAddress("glGetInfoLogARB"))) ++ n_failed_functions;
	if(!(GLFuncPtrName(glGetRenderbufferParameteriv) = (void(GLApi*)(GLenum, GLenum, int*))wglGetProcAddress("glGetRenderbufferParameterivEXT"))) ++ n_failed_functions;
	if(!(GLFuncPtrName(glGetShaderiv) = (void(GLApi*)(GLuint, GLenum, int*))wglGetProcAddress("glGetShaderiv"))) ++ n_failed_functions;
	if(!(GLFuncPtrName(glGetShaderInfoLog) = (void(GLApi*)(GLuint, GLsizei, GLsizei*, GLchar*))wglGetProcAddress("glGetShaderInfoLog"))) ++ n_failed_functions;
	if(!(GLFuncPtrName(glGetShaderPrecisionFormat) = (void(GLApi*)(GLenum, GLenum, int*, int*))wglGetProcAddress("glGetShaderPrecisionFormat"))) ++ n_failed_functions;
	if(!(GLFuncPtrName(glGetShaderSource) = (void(GLApi*)(GLuint, GLsizei, GLsizei*, GLchar*))wglGetProcAddress("glGetShaderSourceARB"))) ++ n_failed_functions;
	if(!(GLFuncPtrName(glGetUniformfv) = (void(GLApi*)(GLuint, int, float*))wglGetProcAddress("glGetUniformfvARB"))) ++ n_failed_functions;
	if(!(GLFuncPtrName(glGetUniformiv) = (void(GLApi*)(GLuint, int, int*))wglGetProcAddress("glGetUniformivARB"))) ++ n_failed_functions;
	if(!(GLFuncPtrName(glGetUniformLocation) = (int(GLApi*)(GLuint, const GLchar*))wglGetProcAddress("glGetUniformLocationARB"))) ++ n_failed_functions;
	if(!(GLFuncPtrName(glGetVertexAttribfv) = (void(GLApi*)(GLuint, GLenum, float*))wglGetProcAddress("glGetVertexAttribfv"))) ++ n_failed_functions;
	if(!(GLFuncPtrName(glGetVertexAttribiv) = (void(GLApi*)(GLuint, GLenum, int*))wglGetProcAddress("glGetVertexAttribiv"))) ++ n_failed_functions;
	if(!(GLFuncPtrName(glGetVertexAttribPointerv) = (void(GLApi*)(GLuint, GLenum, void**))wglGetProcAddress("glGetVertexAttribPointerv"))) ++ n_failed_functions;
	if(!(GLFuncPtrName(glIsBuffer) = (GLboolean(GLApi*)(GLuint))wglGetProcAddress("glIsBuffer"))) ++ n_failed_functions;
	if(!(GLFuncPtrName(glIsFramebuffer) = (GLboolean(GLApi*)(GLuint))wglGetProcAddress("glIsFramebufferEXT"))) ++ n_failed_functions;
	if(!(GLFuncPtrName(glIsProgram) = (GLboolean(GLApi*)(GLuint))wglGetProcAddress("glIsProgram"))) ++ n_failed_functions;
	if(!(GLFuncPtrName(glIsRenderbuffer) = (GLboolean(GLApi*)(GLuint))wglGetProcAddress("glIsRenderbufferEXT"))) ++ n_failed_functions;
	if(!(GLFuncPtrName(glIsShader) = (GLboolean(GLApi*)(GLuint))wglGetProcAddress("glIsShader"))) ++ n_failed_functions;
	if(!(GLFuncPtrName(glLinkProgram) = (void(GLApi*)(GLuint))wglGetProcAddress("glLinkProgramARB"))) ++ n_failed_functions;
	if(!(GLFuncPtrName(glReleaseShaderCompiler) = (void(GLApi*)())wglGetProcAddress("glReleaseShaderCompiler"))) ++ n_failed_functions;
	if(!(GLFuncPtrName(glRenderbufferStorage) = (void(GLApi*)(GLenum, GLenum, GLsizei, GLsizei))wglGetProcAddress("glRenderbufferStorageEXT"))) ++ n_failed_functions;
	if(!(GLFuncPtrName(glSampleCoverage) = (void(GLApi*)(GLclampf, GLboolean))wglGetProcAddress("glSampleCoverage"))) ++ n_failed_functions;
	if(!(GLFuncPtrName(glShaderBinary) = (void(GLApi*)(GLsizei, const GLuint*, GLenum, const void*, GLsizei))wglGetProcAddress("glShaderBinary"))) ++ n_failed_functions;
	if(!(GLFuncPtrName(glShaderSource) = (void(GLApi*)(GLuint, GLsizei, const GLchar**, const int*))wglGetProcAddress("glShaderSourceARB"))) ++ n_failed_functions;
	if(!(GLFuncPtrName(glStencilFuncSeparate) = (void(GLApi*)(GLenum, GLenum, int, GLuint))wglGetProcAddress("glStencilFuncSeparate"))) ++ n_failed_functions;
	if(!(GLFuncPtrName(glStencilMaskSeparate) = (void(GLApi*)(GLenum, GLuint))wglGetProcAddress("glStencilMaskSeparate"))) ++ n_failed_functions;
	if(!(GLFuncPtrName(glStencilOpSeparate) = (void(GLApi*)(GLenum, GLenum, GLenum, GLenum))wglGetProcAddress("glStencilOpSeparate"))) ++ n_failed_functions;
	if(!(GLFuncPtrName(glUniform1f) = (void(GLApi*)(int, float))wglGetProcAddress("glUniform1f"))) ++ n_failed_functions;
	if(!(GLFuncPtrName(glUniform2f) = (void(GLApi*)(int, float, float))wglGetProcAddress("glUniform2f"))) ++ n_failed_functions;
	if(!(GLFuncPtrName(glUniform3f) = (void(GLApi*)(int, float, float, float))wglGetProcAddress("glUniform3f"))) ++ n_failed_functions;
	if(!(GLFuncPtrName(glUniform4f) = (void(GLApi*)(int, float, float, float, float))wglGetProcAddress("glUniform4f"))) ++ n_failed_functions;
	if(!(GLFuncPtrName(glUniform1i) = (void(GLApi*)(int, int))wglGetProcAddress("glUniform1i"))) ++ n_failed_functions;
	if(!(GLFuncPtrName(glUniform2i) = (void(GLApi*)(int, int, int))wglGetProcAddress("glUniform2i"))) ++ n_failed_functions;
	if(!(GLFuncPtrName(glUniform3i) = (void(GLApi*)(int, int, int, int))wglGetProcAddress("glUniform3i"))) ++ n_failed_functions;
	if(!(GLFuncPtrName(glUniform4i) = (void(GLApi*)(int, int, int, int, int))wglGetProcAddress("glUniform4i"))) ++ n_failed_functions;
	if(!(GLFuncPtrName(glUniform1fv) = (void(GLApi*)(int, GLsizei, const float*))wglGetProcAddress("glUniform1fv"))) ++ n_failed_functions;
	if(!(GLFuncPtrName(glUniform2fv) = (void(GLApi*)(int, GLsizei, const float*))wglGetProcAddress("glUniform2fv"))) ++ n_failed_functions;
	if(!(GLFuncPtrName(glUniform3fv) = (void(GLApi*)(int, GLsizei, const float*))wglGetProcAddress("glUniform3fv"))) ++ n_failed_functions;
	if(!(GLFuncPtrName(glUniform4fv) = (void(GLApi*)(int, GLsizei, const float*))wglGetProcAddress("glUniform4fv"))) ++ n_failed_functions;
	if(!(GLFuncPtrName(glUniform1iv) = (void(GLApi*)(int, GLsizei, const int*))wglGetProcAddress("glUniform1iv"))) ++ n_failed_functions;
	if(!(GLFuncPtrName(glUniform2iv) = (void(GLApi*)(int, GLsizei, const int*))wglGetProcAddress("glUniform2iv"))) ++ n_failed_functions;
	if(!(GLFuncPtrName(glUniform3iv) = (void(GLApi*)(int, GLsizei, const int*))wglGetProcAddress("glUniform3iv"))) ++ n_failed_functions;
	if(!(GLFuncPtrName(glUniform4iv) = (void(GLApi*)(int, GLsizei, const int*))wglGetProcAddress("glUniform4iv"))) ++ n_failed_functions;
	if(!(GLFuncPtrName(glUniformMatrix2fv) = (void(GLApi*)(int, GLsizei, GLboolean, const float*))wglGetProcAddress("glUniformMatrix2fv"))) ++ n_failed_functions;
	if(!(GLFuncPtrName(glUniformMatrix3fv) = (void(GLApi*)(int, GLsizei, GLboolean, const float*))wglGetProcAddress("glUniformMatrix3fv"))) ++ n_failed_functions;
	if(!(GLFuncPtrName(glUniformMatrix4fv) = (void(GLApi*)(int, GLsizei, GLboolean, const float*))wglGetProcAddress("glUniformMatrix4fv"))) ++ n_failed_functions;
	if(!(GLFuncPtrName(glUseProgram) = (void(GLApi*)(GLuint))wglGetProcAddress("glUseProgramObjectARB"))) ++ n_failed_functions;
	if(!(GLFuncPtrName(glValidateProgram) = (void(GLApi*)(GLuint))wglGetProcAddress("glValidateProgramARB"))) ++ n_failed_functions;
	if(!(GLFuncPtrName(glVertexAttrib1f) = (void(GLApi*)(GLuint, float))wglGetProcAddress("glVertexAttrib1f"))) ++ n_failed_functions;
	if(!(GLFuncPtrName(glVertexAttrib1fv) = (void(GLApi*)(GLuint, const float*))wglGetProcAddress("glVertexAttrib1fv"))) ++ n_failed_functions;
	if(!(GLFuncPtrName(glVertexAttrib2f) = (void(GLApi*)(GLuint, float, float))wglGetProcAddress("glVertexAttrib2f"))) ++ n_failed_functions;
	if(!(GLFuncPtrName(glVertexAttrib2fv) = (void(GLApi*)(GLuint, const float*))wglGetProcAddress("glVertexAttrib2fv"))) ++ n_failed_functions;
	if(!(GLFuncPtrName(glVertexAttrib3f) = (void(GLApi*)(GLuint, float, float, float))wglGetProcAddress("glVertexAttrib3f"))) ++ n_failed_functions;
	if(!(GLFuncPtrName(glVertexAttrib3fv) = (void(GLApi*)(GLuint, const float*))wglGetProcAddress("glVertexAttrib3fv"))) ++ n_failed_functions;
	if(!(GLFuncPtrName(glVertexAttrib4f) = (void(GLApi*)(GLuint, float, float, float, float))wglGetProcAddress("glVertexAttrib4f"))) ++ n_failed_functions;
	if(!(GLFuncPtrName(glVertexAttrib4fv) = (void(GLApi*)(GLuint, const float*))wglGetProcAddress("glVertexAttrib4fv"))) ++ n_failed_functions;
	if(!(GLFuncPtrName(glVertexAttribPointer) = (void(GLApi*)(GLuint, int, GLenum, GLboolean, GLsizei, const void*))wglGetProcAddress("glVertexAttribPointer"))) ++ n_failed_functions;

#endif //__GENERATE_GL_OGL_dynamic_opengles_20_functions

	GLEH_OpenGL_ES_2_0 = !n_failed_functions && b_Support_OpenGL(2, 0);

	return n_failed_functions;
}

/*
 *								--- ~OpenGL ES 2.0 ---
 */

/*
 *								--- GL_ARB_vertex_array_object ---
 */

bool GLEH_ARB_vertex_array_object = false;

#ifdef __GENERATE_GL_ARB_vertex_array_object

void (GLApi *GLFuncPtrName(glBindVertexArray))(GLuint) INIT_FUNC_POINTERS;
void (GLApi *GLFuncPtrName(glDeleteVertexArrays))(GLsizei, const GLuint*) INIT_FUNC_POINTERS;
void (GLApi *GLFuncPtrName(glGenVertexArrays))(GLsizei, GLuint*) INIT_FUNC_POINTERS;
GLboolean (GLApi *GLFuncPtrName(glIsVertexArray))(GLuint) INIT_FUNC_POINTERS;

GLuint __n_gles20emupatch_default_vertex_array = 0; // default vertex array patch

#endif //__GENERATE_GL_ARB_vertex_array_object

int CGL4ExtensionHandler::n_GetARBVertexArrayObjectFuncPointers()
{
	int n_failed_functions = 0;

#ifdef __GENERATE_GL_ARB_vertex_array_object

	if(!(GLFuncPtrName(glBindVertexArray) = (void(GLApi*)(GLuint))wglGetProcAddress("glBindVertexArray"))) ++ n_failed_functions;
	if(!(GLFuncPtrName(glDeleteVertexArrays) = (void(GLApi*)(GLsizei, const GLuint*))wglGetProcAddress("glDeleteVertexArrays"))) ++ n_failed_functions;
	if(!(GLFuncPtrName(glGenVertexArrays) = (void(GLApi*)(GLsizei, GLuint*))wglGetProcAddress("glGenVertexArrays"))) ++ n_failed_functions;
	if(!(GLFuncPtrName(glIsVertexArray) = (GLboolean(GLApi*)(GLuint))wglGetProcAddress("glIsVertexArray"))) ++ n_failed_functions;

#endif //__GENERATE_GL_ARB_vertex_array_object

	GLEH_ARB_vertex_array_object = !n_failed_functions && b_SupportedExtension("GL_ARB_vertex_array_object");

#ifdef __GENERATE_GL_ARB_vertex_array_object

	if(GLEH_ARB_vertex_array_object) {
		glGenVertexArrays(1, &__n_gles20emupatch_default_vertex_array);
		glBindVertexArray(__n_gles20emupatch_default_vertex_array);
		// some OpenGL versions do not allow VAO 0 to be used for actual rendering; this (kind of) fixes it
	}

#endif //__GENERATE_GL_ARB_vertex_array_object

	return n_failed_functions;
}

/*
 *								--- ~GL_ARB_vertex_array_object ---
 */

/*
 *								--- GL_OES_texture_3D ---
 */

bool GLEH_OES_texture_3D = false;

#ifdef __GENERATE_GL_OES_texture_3D

void (GLApi *GLFuncPtrName(glTexImage3DOES))(GLenum, int, GLenum, GLsizei, GLsizei, GLsizei, int, GLenum, GLenum, const void*) INIT_FUNC_POINTERS;
void (GLApi *GLFuncPtrName(glTexSubImage3DOES))(GLenum, int, int, int, int, GLsizei, GLsizei, GLsizei, GLenum, GLenum, const void*) INIT_FUNC_POINTERS;
void (GLApi *GLFuncPtrName(glCopyTexSubImage3DOES))(GLenum, int, int, int, int, int, int, GLsizei, GLsizei) INIT_FUNC_POINTERS;
void (GLApi *GLFuncPtrName(glCompressedTexImage3DOES))(GLenum, int, GLenum, GLsizei, GLsizei, GLsizei, int, GLsizei, const void*) INIT_FUNC_POINTERS;
void (GLApi *GLFuncPtrName(glCompressedTexSubImage3DOES))(GLenum, int, int, int, int, GLsizei, GLsizei, GLsizei, GLenum, GLsizei, const void*) INIT_FUNC_POINTERS;
void (GLApi *GLFuncPtrName(glFramebufferTexture3DOES))(GLenum, GLenum, GLenum, GLuint, int, int) INIT_FUNC_POINTERS;

#endif // __GENERATE_GL_OES_texture_3D

int CGL4ExtensionHandler::n_GetOESTexture3DFuncPointers()
{
	int n_failed_functions = 0;

#ifdef __GENERATE_GL_OES_texture_3D

	if(!(GLFuncPtrName(glTexImage3DOES) = (void(GLApi*)(GLenum, int, GLenum, GLsizei, GLsizei, GLsizei, int, GLenum, GLenum, const void*))wglGetProcAddress("glTexImage3D"))) ++ n_failed_functions;
	if(!(GLFuncPtrName(glTexSubImage3DOES) = (void(GLApi*)(GLenum, int, int, int, int, GLsizei, GLsizei, GLsizei, GLenum, GLenum, const void*))wglGetProcAddress("glTexSubImage3D"))) ++ n_failed_functions;
	if(!(GLFuncPtrName(glCopyTexSubImage3DOES) = (void(GLApi*)(GLenum, int, int, int, int, int, int, GLsizei, GLsizei))wglGetProcAddress("glCopyTexSubImage3D"))) ++ n_failed_functions;
	if(!(GLFuncPtrName(glCompressedTexImage3DOES) = (void(GLApi*)(GLenum, int, GLenum, GLsizei, GLsizei, GLsizei, int, GLsizei, const void*))wglGetProcAddress("glCompressedTexImage3D"))) ++ n_failed_functions;
	if(!(GLFuncPtrName(glCompressedTexSubImage3DOES) = (void(GLApi*)(GLenum, int, int, int, int, GLsizei, GLsizei, GLsizei, GLenum, GLsizei, const void*))wglGetProcAddress("glCompressedTexSubImage3D"))) ++ n_failed_functions;
	if(!(GLFuncPtrName(glFramebufferTexture3DOES) = (void(GLApi*)(GLenum, GLenum, GLenum, GLuint, int, int))wglGetProcAddress("glFramebufferTexture3D"))) ++ n_failed_functions;

#endif // __GENERATE_GL_OES_texture_3D

	GLEH_OES_texture_3D = !n_failed_functions && b_SupportedExtension("GL_OES_texture_3D");

	return n_failed_functions;
}

/*
 *								--- ~GL_OES_texture_3D ---
 */

/*
 *								--- GL_OES_depth24 ---
 */

bool GLEH_OES_depth24 = false;

int CGL4ExtensionHandler::n_GetOESDepth24FuncPointers()
{
	int n_failed_functions = 0;

	// no new functions or procedures here

	GLEH_OES_depth24 = !n_failed_functions && b_SupportedExtension("GL_OES_depth24");

	return n_failed_functions;
}

/*
 *								--- ~GL_OES_depth24 ---
 */

/*
 *								--- GL_OES_depth32 ---
 */

bool GLEH_OES_depth32 = false;

int CGL4ExtensionHandler::n_GetOESDepth32FuncPointers()
{
	int n_failed_functions = 0;

	// no new functions or procedures here

	GLEH_OES_depth32 = !n_failed_functions && b_SupportedExtension("GL_OES_depth32");

	return n_failed_functions;
}

/*
 *								--- ~GL_OES_depth32 ---
 */

/*
 *								--- GL_OES_element_index_uint ---
 */

bool GLEH_OES_element_index_uint = false;

int CGL4ExtensionHandler::n_GetOESElementIndexUIntFuncPointers()
{
	int n_failed_functions = 0;

	// no new functions or procedures here

	GLEH_OES_element_index_uint = !n_failed_functions && b_SupportedExtension("GL_OES_element_index_uint");

	return n_failed_functions;
}

/*
 *								--- ~GL_OES_element_index_uint ---
 */

/*
 *								--- GL_OES_mapbuffer ---
 */

bool GLEH_OES_mapbuffer = false;

#ifdef __GENERATE_GL_OES_mapbuffer

void (GLApi *GLFuncPtrName(glGetBufferPointervOES))(GLenum, GLenum, void**) INIT_FUNC_POINTERS;
void* (GLApi *GLFuncPtrName(glMapBufferOES))(GLenum, GLenum) INIT_FUNC_POINTERS;
GLboolean (GLApi *GLFuncPtrName(glUnmapBufferOES))(GLenum) INIT_FUNC_POINTERS;

#endif // __GENERATE_GL_OES_mapbuffer

int CGL4ExtensionHandler::n_GetOESMapbufferFuncPointers()
{
	int n_failed_functions = 0;

#ifdef __GENERATE_GL_OES_mapbuffer

	if(!(GLFuncPtrName(glGetBufferPointervOES) = (void(GLApi*)(GLenum, GLenum, void**))wglGetProcAddress("glGetBufferPointerv"))) ++ n_failed_functions;
	if(!(GLFuncPtrName(glMapBufferOES) = (void*(GLApi*)(GLenum, GLenum))wglGetProcAddress("glMapBuffer"))) ++ n_failed_functions;
	if(!(GLFuncPtrName(glUnmapBufferOES) = (GLboolean(GLApi*)(GLenum))wglGetProcAddress("glUnmapBuffer"))) ++ n_failed_functions;

#endif // __GENERATE_GL_OES_mapbuffer

	GLEH_OES_mapbuffer = !n_failed_functions && b_SupportedExtension("GL_OES_mapbuffer");

	return n_failed_functions;
}

/*
 *								--- ~GL_OES_mapbuffer ---
 */

/*
 *								--- GL_OES_rgb8_rgba8 ---
 */

bool GLEH_OES_rgb8_rgba8 = false;

int CGL4ExtensionHandler::n_GetOESRGB8RGBA8FuncPointers()
{
	int n_failed_functions = 0;

	// no new functions or procedures here

	GLEH_OES_rgb8_rgba8 = !n_failed_functions && b_SupportedExtension("GL_OES_rgb8_rgba8");

	return n_failed_functions;
}

/*
 *								--- ~GL_OES_rgb8_rgba8 ---
 */

/*
 *								--- GL_OES_stencil1 ---
 */

bool GLEH_OES_stencil1 = false;

int CGL4ExtensionHandler::n_GetOESStencil1FuncPointers()
{
	int n_failed_functions = 0;

	// no new functions or procedures here

	GLEH_OES_stencil1 = !n_failed_functions && b_SupportedExtension("GL_OES_stencil1");

	return n_failed_functions;
}

/*
 *								--- ~GL_OES_stencil1 ---
 */

/*
 *								--- GL_OES_stencil4 ---
 */

bool GLEH_OES_stencil4 = false;

int CGL4ExtensionHandler::n_GetOESStencil4FuncPointers()
{
	int n_failed_functions = 0;

	// no new functions or procedures here

	GLEH_OES_stencil4 = !n_failed_functions && b_SupportedExtension("GL_OES_stencil4");

	return n_failed_functions;
}

/*
 *								--- ~GL_OES_stencil4 ---
 */

/*
 *								--- GL_OES_stencil8 ---
 */

bool GLEH_OES_stencil8 = false;

int CGL4ExtensionHandler::n_GetOESStencil8FuncPointers()
{
	int n_failed_functions = 0;

	// no new functions or procedures here

	GLEH_OES_stencil8 = !n_failed_functions && b_SupportedExtension("GL_OES_stencil8");

	return n_failed_functions;
}

/*
 *								--- ~GL_OES_stencil8 ---
 */

/*
 *								--- GL_OES_depth_texture ---
 */

bool GLEH_OES_depth_texture = false;

int CGL4ExtensionHandler::n_GetOESDepthTextureFuncPointers()
{
	int n_failed_functions = 0;

	// no new functions or procedures here

	GLEH_OES_depth_texture = !n_failed_functions && b_SupportedExtension("GL_OES_depth_texture");

	return n_failed_functions;
}

/*
 *								--- ~GL_OES_depth_texture ---
 */

/*
 *								--- GL_OES_packed_depth_stencil ---
 */

bool GLEH_OES_packed_depth_stencil = false;

int CGL4ExtensionHandler::n_GetOESPackedDepthStencilFuncPointers()
{
	int n_failed_functions = 0;

	// no new functions or procedures here

	GLEH_OES_packed_depth_stencil = !n_failed_functions && b_SupportedExtension("GL_OES_packed_depth_stencil");

	return n_failed_functions;
}

/*
 *								--- ~GL_OES_packed_depth_stencil ---
 */

/*
 *								--- GL_OES_get_program_binary ---
 */

bool GLEH_OES_get_program_binary = false;

#ifdef __GENERATE_GL_OES_get_program_binary

void (GLApi *GLFuncPtrName(glGetProgramBinaryOES))(GLuint, GLsizei, GLsizei*, GLenum*, void*) INIT_FUNC_POINTERS;
void (GLApi *GLFuncPtrName(glProgramBinaryOES))(GLuint, GLenum, const void*, int) INIT_FUNC_POINTERS;

#endif // __GENERATE_GL_OES_get_program_binary

int CGL4ExtensionHandler::n_GetOESGetProgramBinaryFuncPointers()
{
	int n_failed_functions = 0;

#ifdef __GENERATE_GL_OES_get_program_binary

	if(!(GLFuncPtrName(glGetProgramBinaryOES) = (void(GLApi*)(GLuint, GLsizei, GLsizei*, GLenum*, void*))wglGetProcAddress("glGetProgramBinary"))) ++ n_failed_functions;
	if(!(GLFuncPtrName(glProgramBinaryOES) = (void(GLApi*)(GLuint, GLenum, const void*, int))wglGetProcAddress("glProgramBinary"))) ++ n_failed_functions;

#endif // __GENERATE_GL_OES_get_program_binary

	GLEH_OES_get_program_binary = !n_failed_functions && b_SupportedExtension("GL_OES_get_program_binary");

	return n_failed_functions;
}

/*
 *								--- ~GL_OES_get_program_binary ---
 */

/*
 *								--- GL_OES_fbo_render_mipmap ---
 */

bool GLEH_OES_fbo_render_mipmap = false;

int CGL4ExtensionHandler::n_GetOESFboRenderMipmapFuncPointers()
{
	int n_failed_functions = 0;

	// no new functions or procedures here

	GLEH_OES_fbo_render_mipmap = !n_failed_functions && b_SupportedExtension("GL_OES_fbo_render_mipmap");

	return n_failed_functions;
}

/*
 *								--- ~GL_OES_fbo_render_mipmap ---
 */

/*
 *								--- GL_OES_vertex_half_float ---
 */

bool GLEH_OES_vertex_half_float = false;

int CGL4ExtensionHandler::n_GetOESVertexHalfFloatFuncPointers()
{
	int n_failed_functions = 0;

	// no new functions or procedures here

	GLEH_OES_vertex_half_float = !n_failed_functions && b_SupportedExtension("GL_OES_vertex_half_float");

	return n_failed_functions;
}

/*
 *								--- ~GL_OES_vertex_half_float ---
 */

/*
 *								--- GL_OES_texture_float ---
 */

bool GLEH_OES_texture_float = false;

int CGL4ExtensionHandler::n_GetOESTextureFloatFuncPointers()
{
	int n_failed_functions = 0;

	// no new functions or procedures here

	GLEH_OES_texture_float = !n_failed_functions && b_SupportedExtension("GL_OES_texture_float");

	return n_failed_functions;
}

/*
 *								--- ~GL_OES_texture_float ---
 */

/*
 *								--- GL_OES_compressed_ETC1_RGB8_texture ---
 */

bool GLEH_OES_compressed_ETC1_RGB8_texture = false;

int CGL4ExtensionHandler::n_GetOESCompressedETC1RGB8TextureFuncPointers()
{
	int n_failed_functions = 0;

	// no new functions or procedures here

	GLEH_OES_compressed_ETC1_RGB8_texture = !n_failed_functions && b_SupportedExtension("GL_OES_compressed_ETC1_RGB8_texture");

	return n_failed_functions;
}

/*
 *								--- ~GL_OES_compressed_ETC1_RGB8_texture ---
 */

/*
 *								--- GL_OES_standard_derivatives ---
 */

bool GLEH_OES_standard_derivatives = false;

int CGL4ExtensionHandler::n_GetOESStandardDerivativesFuncPointers()
{
	int n_failed_functions = 0;

	// no new functions or procedures here

	GLEH_OES_standard_derivatives = !n_failed_functions && b_SupportedExtension("GL_OES_standard_derivatives");

	return n_failed_functions;
}

/*
 *								--- ~GL_OES_standard_derivatives ---
 */

/*
 *								--- GL_EXT_texture_format_BGRA8888 ---
 */

bool GLEH_EXT_texture_format_BGRA8888 = false;

int CGL4ExtensionHandler::n_GetEXTTextureFormatBGRA8888FuncPointers()
{
	int n_failed_functions = 0;

	// no new functions or procedures here

	GLEH_EXT_texture_format_BGRA8888 = !n_failed_functions && b_SupportedExtension("GL_EXT_texture_format_BGRA8888");

	return n_failed_functions;
}

/*
 *								--- ~GL_EXT_texture_format_BGRA8888 ---
 */

/*
 *								--- GL_NV_fence ---
 */

bool GLEH_NV_fence = false;

#ifdef __GENERATE_GL_NV_fence

void (GLApi *GLFuncPtrName(glGenFencesNV))(GLsizei, GLuint*) INIT_FUNC_POINTERS;
void (GLApi *GLFuncPtrName(glDeleteFencesNV))(GLsizei, const GLuint*) INIT_FUNC_POINTERS;
void (GLApi *GLFuncPtrName(glSetFenceNV))(GLuint, GLenum) INIT_FUNC_POINTERS;
GLboolean (GLApi *GLFuncPtrName(glTestFenceNV))(GLuint) INIT_FUNC_POINTERS;
void (GLApi *GLFuncPtrName(glFinishFenceNV))(GLuint) INIT_FUNC_POINTERS;
GLboolean (GLApi *GLFuncPtrName(glIsFenceNV))(GLuint) INIT_FUNC_POINTERS;
void (GLApi *GLFuncPtrName(glGetFenceivNV))(GLuint, GLenum, int*) INIT_FUNC_POINTERS;

#endif // __GENERATE_GL_NV_fence

int CGL4ExtensionHandler::n_GetNVFenceFuncPointers()
{
	int n_failed_functions = 0;

#ifdef __GENERATE_GL_NV_fence

	if(!(GLFuncPtrName(glGenFencesNV) = (void(GLApi*)(GLsizei, GLuint*))wglGetProcAddress("glGenFencesNV"))) ++ n_failed_functions;
	if(!(GLFuncPtrName(glDeleteFencesNV) = (void(GLApi*)(GLsizei, const GLuint*))wglGetProcAddress("glDeleteFencesNV"))) ++ n_failed_functions;
	if(!(GLFuncPtrName(glSetFenceNV) = (void(GLApi*)(GLuint, GLenum))wglGetProcAddress("glSetFenceNV"))) ++ n_failed_functions;
	if(!(GLFuncPtrName(glTestFenceNV) = (GLboolean(GLApi*)(GLuint))wglGetProcAddress("glTestFenceNV"))) ++ n_failed_functions;
	if(!(GLFuncPtrName(glFinishFenceNV) = (void(GLApi*)(GLuint))wglGetProcAddress("glFinishFenceNV"))) ++ n_failed_functions;
	if(!(GLFuncPtrName(glIsFenceNV) = (GLboolean(GLApi*)(GLuint))wglGetProcAddress("glIsFenceNV"))) ++ n_failed_functions;
	if(!(GLFuncPtrName(glGetFenceivNV) = (void(GLApi*)(GLuint, GLenum, int*))wglGetProcAddress("glGetFenceivNV"))) ++ n_failed_functions;

#endif // __GENERATE_GL_NV_fence

	GLEH_NV_fence = !n_failed_functions && b_SupportedExtension("GL_NV_fence");

	return n_failed_functions;
}

/*
 *								--- ~GL_NV_fence ---
 */

/*
 *								--- GL_EXT_texture_lod_bias ---
 */

bool GLEH_EXT_texture_lod_bias = false;

int CGL4ExtensionHandler::n_GetEXTTextureLODBiasFuncPointers()
{
	int n_failed_functions = 0;

	// no new functions or procedures here

	GLEH_EXT_texture_lod_bias = !n_failed_functions && b_SupportedExtension("GL_EXT_texture_lod_bias");

	return n_failed_functions;
}

/*
 *								--- ~GL_EXT_texture_lod_bias ---
 */

/*
 *								--- GL_NV_draw_buffers ---
 */

bool GLEH_NV_draw_buffers = false;

#ifdef __GENERATE_GL_NV_draw_buffers

void (GLApi *GLFuncPtrName(glDrawBuffersNV))(GLsizei, const GLenum*) INIT_FUNC_POINTERS;

#endif // __GENERATE_GL_NV_draw_buffers

int CGL4ExtensionHandler::n_GetNVDrawBuffersFuncPointers()
{
	int n_failed_functions = 0;

#ifdef __GENERATE_GL_NV_draw_buffers

	if(!(GLFuncPtrName(glDrawBuffersNV) = (void(GLApi*)(GLsizei, const GLenum*))wglGetProcAddress("glDrawBuffers"))) ++ n_failed_functions;

#endif // __GENERATE_GL_NV_draw_buffers

	GLEH_NV_draw_buffers = !n_failed_functions && b_SupportedExtension("GL_NV_draw_buffers");

	return n_failed_functions;
}

/*
 *								--- ~GL_NV_draw_buffers ---
 */

/*
 *								--- GL_NV_fbo_color_attachments ---
 */

bool GLEH_NV_fbo_color_attachments = false;

int CGL4ExtensionHandler::n_GetNVFBOColorAttachmentsFuncPointers()
{
	int n_failed_functions = 0;

	// no new functions or procedures here

	GLEH_NV_fbo_color_attachments = !n_failed_functions && b_SupportedExtension("GL_NV_fbo_color_attachments");

	return n_failed_functions;
}

/*
 *								--- ~GL_NV_fbo_color_attachments ---
 */

/*
 *								--- GL_NV_read_buffer ---
 */

bool GLEH_NV_read_buffer = false;

#ifdef __GENERATE_GL_NV_read_buffer

void (GLApi *GLFuncPtrName(glReadBufferNV))(GLenum) INIT_FUNC_POINTERS;

#endif // __GENERATE_GL_NV_read_buffer

int CGL4ExtensionHandler::n_GetNVReadBufferFuncPointers()
{
	int n_failed_functions = 0;

#ifdef __GENERATE_GL_NV_read_buffer

	if(!(GLFuncPtrName(glReadBufferNV) = (void(GLApi*)(GLenum))wglGetProcAddress("glReadBufferNV"))) ++ n_failed_functions;

#endif // __GENERATE_GL_NV_read_buffer

	GLEH_NV_read_buffer = !n_failed_functions && b_SupportedExtension("GL_NV_read_buffer");

	return n_failed_functions;
}

/*
 *								--- ~GL_NV_read_buffer ---
 */

/*
 *								--- GL_EXT_texture_filter_anisotropic ---
 */

bool GLEH_EXT_texture_filter_anisotropic = false;

int CGL4ExtensionHandler::n_GetEXTTextureFilterAnisotropicFuncPointers()
{
	int n_failed_functions = 0;

	// no new functions or procedures here

	GLEH_EXT_texture_filter_anisotropic = !n_failed_functions && b_SupportedExtension("GL_EXT_texture_filter_anisotropic");

	return n_failed_functions;
}

/*
 *								--- ~GL_EXT_texture_filter_anisotropic ---
 */

/*
 *								--- GL_EXT_unpack_subimage ---
 */

bool GLEH_EXT_unpack_subimage = false;

int CGL4ExtensionHandler::n_GetEXTUnpackSubimageFuncPointers()
{
	int n_failed_functions = 0;

	// no new functions or procedures here

	GLEH_EXT_unpack_subimage = !n_failed_functions && b_SupportedExtension("GL_EXT_unpack_subimage");

	return n_failed_functions;
}

/*
 *								--- ~GL_EXT_unpack_subimage ---
 */

/*
 *								--- GL_NV_texture_compression_s3tc_update ---
 */

bool GLEH_NV_texture_compression_s3tc_update = false;

int CGL4ExtensionHandler::n_GetNVTextureCompressionS3tcUpdateFuncPointers()
{
	int n_failed_functions = 0;

	// no new functions or procedures here

	GLEH_NV_texture_compression_s3tc_update = !n_failed_functions && b_SupportedExtension("GL_NV_texture_compression_s3tc_update");

	return n_failed_functions;
}

/*
 *								--- ~GL_NV_texture_compression_s3tc_update ---
 */

/*
 *								--- GL_NV_read_depth_stencil ---
 */

bool GLEH_NV_read_depth_stencil = false;

int CGL4ExtensionHandler::n_GetNVReadDepthStencilFuncPointers()
{
	int n_failed_functions = 0;

	// no new functions or procedures here

	GLEH_NV_read_depth_stencil = !n_failed_functions && b_SupportedExtension("GL_NV_read_depth_stencil");

	return n_failed_functions;
}

/*
 *								--- ~GL_NV_read_depth_stencil ---
 */

/*
 *								--- GL_EXT_robustness ---
 */

bool GLEH_EXT_robustness = false;

#ifdef __GENERATE_GL_EXT_robustness

GLenum (GLApi *GLFuncPtrName(glGetGraphicsResetStatusEXT))() INIT_FUNC_POINTERS;
void (GLApi *GLFuncPtrName(glReadnPixelsEXT))(int, int, GLsizei, GLsizei, GLenum, GLenum, GLsizei, void*) INIT_FUNC_POINTERS;
void (GLApi *GLFuncPtrName(glGetnUniformfvEXT))(GLuint, int, GLsizei, float*) INIT_FUNC_POINTERS;
void (GLApi *GLFuncPtrName(glGetnUniformivEXT))(GLuint, int, GLsizei, int*) INIT_FUNC_POINTERS;

#endif // __GENERATE_GL_EXT_robustness

int CGL4ExtensionHandler::n_GetEXTRobustnessFuncPointers()
{
	int n_failed_functions = 0;

#ifdef __GENERATE_GL_EXT_robustness

	if(!(GLFuncPtrName(glGetGraphicsResetStatusEXT) = (GLenum(GLApi*)())wglGetProcAddress("glGetGraphicsResetStatusEXT"))) ++ n_failed_functions;
	if(!(GLFuncPtrName(glReadnPixelsEXT) = (void(GLApi*)(int, int, GLsizei, GLsizei, GLenum, GLenum, GLsizei, void*))wglGetProcAddress("glReadnPixelsEXT"))) ++ n_failed_functions;
	if(!(GLFuncPtrName(glGetnUniformfvEXT) = (void(GLApi*)(GLuint, int, GLsizei, float*))wglGetProcAddress("glGetnUniformfvEXT"))) ++ n_failed_functions;
	if(!(GLFuncPtrName(glGetnUniformivEXT) = (void(GLApi*)(GLuint, int, GLsizei, int*))wglGetProcAddress("glGetnUniformivEXT"))) ++ n_failed_functions;

#endif // __GENERATE_GL_EXT_robustness

	GLEH_EXT_robustness = !n_failed_functions && b_SupportedExtension("GL_EXT_robustness");

	return n_failed_functions;
}

/*
 *								--- ~GL_EXT_robustness ---
 */

/*
 *								--- GL_EXT_occlusion_query_boolean ---
 */

bool GLEH_EXT_occlusion_query_boolean = false;

#ifdef __GENERATE_GL_EXT_occlusion_query_boolean

void (GLApi *GLFuncPtrName(glGenQueriesEXT))(GLsizei, GLuint*) INIT_FUNC_POINTERS;
void (GLApi *GLFuncPtrName(glDeleteQueriesEXT))(GLsizei, const GLuint*) INIT_FUNC_POINTERS;
GLboolean (GLApi *GLFuncPtrName(glIsQueryEXT))(GLuint) INIT_FUNC_POINTERS;
void (GLApi *GLFuncPtrName(glBeginQueryEXT))(GLenum, GLuint) INIT_FUNC_POINTERS;
void (GLApi *GLFuncPtrName(glEndQueryEXT))(GLenum) INIT_FUNC_POINTERS;
void (GLApi *GLFuncPtrName(glGetQueryivEXT))(GLenum, GLenum, int*) INIT_FUNC_POINTERS;
void (GLApi *GLFuncPtrName(glGetQueryObjectuivEXT))(GLuint, GLenum, GLuint*) INIT_FUNC_POINTERS;

#endif // __GENERATE_GL_EXT_occlusion_query_boolean

int CGL4ExtensionHandler::n_GetEXTOcclusionQueryBooleanFuncPointers()
{
	int n_failed_functions = 0;

#ifdef __GENERATE_GL_EXT_occlusion_query_boolean

	if(!(GLFuncPtrName(glGenQueriesEXT) = (void(GLApi*)(GLsizei, GLuint*))wglGetProcAddress("glGenQueriesEXT"))) ++ n_failed_functions;
	if(!(GLFuncPtrName(glDeleteQueriesEXT) = (void(GLApi*)(GLsizei, const GLuint*))wglGetProcAddress("glDeleteQueriesEXT"))) ++ n_failed_functions;
	if(!(GLFuncPtrName(glIsQueryEXT) = (GLboolean(GLApi*)(GLuint))wglGetProcAddress("glIsQueryEXT"))) ++ n_failed_functions;
	if(!(GLFuncPtrName(glBeginQueryEXT) = (void(GLApi*)(GLenum, GLuint))wglGetProcAddress("glBeginQueryEXT"))) ++ n_failed_functions;
	if(!(GLFuncPtrName(glEndQueryEXT) = (void(GLApi*)(GLenum))wglGetProcAddress("glEndQueryEXT"))) ++ n_failed_functions;
	if(!(GLFuncPtrName(glGetQueryivEXT) = (void(GLApi*)(GLenum, GLenum, int*))wglGetProcAddress("glGetQueryivEXT"))) ++ n_failed_functions;
	if(!(GLFuncPtrName(glGetQueryObjectuivEXT) = (void(GLApi*)(GLuint, GLenum, GLuint*))wglGetProcAddress("glGetQueryObjectuivEXT"))) ++ n_failed_functions;

#endif // __GENERATE_GL_EXT_occlusion_query_boolean

	GLEH_EXT_occlusion_query_boolean = !n_failed_functions && b_SupportedExtension("GL_EXT_occlusion_query_boolean");

	return n_failed_functions;
}

/*
 *								--- ~GL_EXT_occlusion_query_boolean ---
 */

/*
 *								--- GL_EXT_texture_array ---
 */

bool GLEH_EXT_texture_array = false;

#ifdef __GENERATE_GL_EXT_texture_array

void (GLApi *GLFuncPtrName(glFramebufferTextureLayerEXT))(GLenum, GLenum, GLuint, int, int) INIT_FUNC_POINTERS;

#endif // __GENERATE_GL_EXT_texture_array

int CGL4ExtensionHandler::n_GetEXTTextureArrayFuncPointers()
{
	int n_failed_functions = 0;

#ifdef __GENERATE_GL_EXT_texture_array

	if(!(GLFuncPtrName(glFramebufferTextureLayerEXT) = (void(GLApi*)(GLenum, GLenum, GLuint, int, int))wglGetProcAddress("glFramebufferTextureLayerEXT"))) ++ n_failed_functions;

#endif // __GENERATE_GL_EXT_texture_array

	GLEH_EXT_texture_array = !n_failed_functions && b_SupportedExtension("GL_EXT_texture_array");

	return n_failed_functions;
}

/*
 *								--- ~GL_EXT_texture_array ---
 */

/*
 *								=== ~CGLES20ExtensionHandler ===
 */
