/*
								+---------------------------------+
								|								  |
								|	 ***   OpenGL ES 2.0   ***	  |
								|								  |
								|  Copyright  © -tHE SWINe- 2012  |
								|								  |
								|			GLES20.cpp			  |
								|								  |
								+---------------------------------+
*/

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

#include "../NewFix.h"
#include "../CallStack.h"
#define GLES20EMU_CPP
#include "GLES20.h"
#include "../StlUtils.h"

#ifndef __HAVE_EGL
#define __HAVE_EGL
#endif // !__HAVE_EGL
// use EGL by default (only present here to allow manual override)

#ifndef __HAVE_GLES
#pragma message("warning: __HAVE_GLES is not defined, use GLES20Emu instead\n")
#endif // !__HAVE_GLES
// make sure __HAVE_GLES is defined

#if defined(__HAVE_EGL)
#include <EGL/egl.h> // eglGetProcAddress()

/**
 *	@def wglGetProcAddress
 *	@brief windows get proc address lookalike on linux platform
 *	@param[in] x is name of the function to retrieve
 */
#define wglGetProcAddress(x) eglGetProcAddress((x))
#elif defined(_WIN32) || defined(_WIN64)
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <GL/wglext.h> // wglGetProcAddress()
#else // _WIN32 || _WIN64
#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

/**
 *	@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;
}

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);
	if(!p_s_version) {
#if defined(_WIN32) || defined(_WIN64)
		MessageBoxW(0, L"OpenGL extension string is 0!", L"CGLES20ExtensionHandler", MB_OK);
#endif // _WIN32 || _WIN64
		return std::make_pair(-1, -1);
	}

	if(!memcmp(p_s_version, "OpenGL ES", strlen("OpenGL ES") * sizeof(char)))
		p_s_version += strlen("OpenGL ES");
	// some vendors (our loved NVIDIA) start the version string with "OpenGL ES" (e.g. "OpenGL ES 2.0.12345 NVIDIA")

#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)
		MessageBoxW(0, L"OpenGL version string malformed!", L"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

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);
		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*/ {
		const char *p_s_extensions;
		if(!(p_s_extensions = (const char*)glGetString(GL_EXTENSIONS)))
			return false;
		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::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);
		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);
	}
}

#if defined(__HAVE_EGL)

bool CGLES20ExtensionHandler::b_SupportedPlatformExtension(const char *p_s_extension_name)
{
	const char *p_s_extensions = (const char*)eglQueryString(eglGetDisplay(EGL_DEFAULT_DISPLAY), EGL_EXTENSIONS);
	// get EGL 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;
}

#elif 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
#error("GLX 1.2 is needed for glXGetClientString(GLX_EXTENSIONS) to work")
#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();
}

#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

#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

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

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

	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 ===
 */
