#pragma once
#include <glcorearb.h>
#include <glext.h>

typedef struct __GLsync *GLsync;
int OpenGL_shader(GLuint prog, GLenum type, const GLchar* source);

#define OPENGL_FUNC_LIST_NOBIND \
	GLN(GLenum,	glGetError		(void)); \
	GLN(void,	glGenTextures	(GLsizei n, GLuint* textures)); \
	GLN(void,	glBindTexture	(GLenum target, GLuint texture)); \
	GLN(void,	glTexImage2D	(GLenum target, GLint level, GLint iformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid* data));\
	GLN(void,	glGetTexLevelParameteriv	(GLenum target, GLint level, GLenum parameter, GLint* value)); \
	GLN(void,	glTexParameteri	(GLenum target, GLenum parameter, GLint value)); \
	GLN(void,	glTexParameterf	(GLenum target, GLenum parameter, GLfloat value)); \
	GLN(void,	glDeleteTextures(GLsizei n, const GLuint* textures)); \
	GLN(void,	glViewport		(GLint x, GLint y, GLsizei w, GLsizei h)); \
	GLN(void,	glClear			(GLbitfield buffers)); \
	GLN(void,	glDrawArrays	(GLenum mode, GLint first, GLsizei count)); \
	GLN(void,	glFlush			(void)); \
	GLN(void,	glFinish		(void)); \
	GLN(void,	glClearColor	(GLclampf r, GLclampf g, GLclampf b, GLclampf a)); \
	GLN(void,	glDepthFunc		(GLenum func)); \
	GLN(void,	glFrontFace		(GLenum winding)); \
	GLN(void,	glCullFace		(GLenum face)); \
	GLN(void,	glEnable		(GLenum prop)); \
	GLN(void,	glDisable		(GLenum prop)); \
	GLN(void,	glTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels)); \
	GLN(void,	glDrawElements	(GLenum mode, GLsizei count, GLenum type, const GLvoid* offset)); \
	GLN(void,	glBlendFunc		(GLenum sfactor, GLenum dfactor)); \
	GLN(void,	glGetTexImage	(GLenum target, GLint level, GLenum format, GLenum type, GLvoid* image)); \
	GLN(void,	glCopyTexSubImage2D(GLenum target, GLint level, GLint xoff, GLint yoff, GLint x, GLint y, GLint width, GLint height)); \
	GLN(void,	glGetIntegerv	(GLenum pname, GLint* params)); \
	GLN(void,	glScissor		(GLint x, GLint y, GLsizei w, GLsizei h)); \
	GLN(void,	glColorMask		(GLboolean r, GLboolean g, GLboolean b, GLboolean a)); \
	GLN(void,	glDepthMask		(GLboolean d)); \
	GLN(void,	glClearDepth	(GLclampd d)); \

#define OPENGL_FUNC_LIST \
	GL(glDebugMessageCallback,		PFNGLDEBUGMESSAGECALLBACKPROC); \
	GL(glDrawElementsInstanced,		PFNGLDRAWELEMENTSINSTANCEDPROC); \
	GL(glDrawArraysInstanced,		PFNGLDRAWARRAYSINSTANCEDPROC); \
	GL(glGenFramebuffers,			PFNGLGENFRAMEBUFFERSPROC); \
	GL(glBindFramebuffer,			PFNGLBINDFRAMEBUFFERPROC); \
	GL(glDeleteFramebuffers,		PFNGLDELETEFRAMEBUFFERSPROC); \
	GL(glGenRenderbuffers,			PFNGLGENRENDERBUFFERSPROC); \
	GL(glBindRenderbuffer,			PFNGLBINDRENDERBUFFERPROC); \
	GL(glDeleteRenderbuffers,		PFNGLDELETERENDERBUFFERSPROC); \
	GL(glRenderbufferStorage,		PFNGLRENDERBUFFERSTORAGEPROC); \
	GL(glRenderbufferStorageMultisample,	PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC); \
	GL(glFramebufferRenderbuffer,	PFNGLFRAMEBUFFERRENDERBUFFERPROC); \
	GL(glFramebufferTexture2D,		PFNGLFRAMEBUFFERTEXTURE2DPROC); \
	GL(glDrawBuffers,				PFNGLDRAWBUFFERSPROC); \
	GL(glCheckFramebufferStatus,	PFNGLCHECKFRAMEBUFFERSTATUSPROC); \
	GL(glGenVertexArrays,			PFNGLGENVERTEXARRAYSPROC); \
	GL(glBindVertexArray,			PFNGLBINDVERTEXARRAYPROC); \
	GL(glDeleteVertexArrays,		PFNGLDELETEVERTEXARRAYSPROC); \
	GL(glGenBuffers,				PFNGLGENBUFFERSPROC); \
	GL(glBindBuffer,				PFNGLBINDBUFFERPROC); \
	GL(glDeleteBuffers,				PFNGLDELETEBUFFERSPROC); \
	GL(glBufferData,				PFNGLBUFFERDATAPROC); \
	GL(glVertexAttribPointer,		PFNGLVERTEXATTRIBPOINTERPROC); \
	GL(glVertexAttribIPointer,		PFNGLVERTEXATTRIBIPOINTERPROC); \
	GL(glEnableVertexAttribArray,	PFNGLENABLEVERTEXATTRIBARRAYPROC); \
	GL(glCreateShader,				PFNGLCREATESHADERPROC); \
	GL(glDeleteShader,				PFNGLDELETESHADERPROC); \
	GL(glShaderSource,				PFNGLSHADERSOURCEPROC); \
	GL(glCompileShader,				PFNGLCOMPILESHADERPROC); \
	GL(glGetShaderiv,				PFNGLGETSHADERIVPROC); \
	GL(glGetShaderInfoLog,			PFNGLGETSHADERINFOLOGPROC); \
	GL(glGetProgramInfoLog,			PFNGLGETPROGRAMINFOLOGPROC); \
	GL(glAttachShader,				PFNGLATTACHSHADERPROC); \
	GL(glCreateProgram,				PFNGLCREATEPROGRAMPROC); \
	GL(glLinkProgram,				PFNGLLINKPROGRAMPROC); \
	GL(glDeleteProgram,				PFNGLDELETEPROGRAMPROC); \
	GL(glUseProgram,				PFNGLUSEPROGRAMPROC); \
	GL(glBlitFramebuffer,			PFNGLBLITFRAMEBUFFERPROC); \
	GL(glGetUniformLocation,		PFNGLGETUNIFORMLOCATIONPROC); \
	GL(glUniformMatrix4fv,			PFNGLUNIFORMMATRIX4FVPROC); \
	GL(glUniform1f,					PFNGLUNIFORM1FPROC); \
	GL(glUniform1ui,				PFNGLUNIFORM1UIPROC); \
	GL(glUniform1i,					PFNGLUNIFORM1IPROC); \
	GL(glUniform2i,					PFNGLUNIFORM2IPROC); \
	GL(glUniform2uiv,				PFNGLUNIFORM2UIVPROC); \
	GL(glUniform2f,					PFNGLUNIFORM2FPROC); \
	GL(glUniform2fv,				PFNGLUNIFORM2FVPROC); \
	GL(glUniform3f,					PFNGLUNIFORM3FPROC); \
	GL(glUniform3iv,				PFNGLUNIFORM3IVPROC); \
	GL(glUniform3fv,				PFNGLUNIFORM3FVPROC); \
	GL(glUniform4f,					PFNGLUNIFORM4FPROC); \
	GL(glUniform4fv,				PFNGLUNIFORM4FVPROC); \
	GL(glUniform4iv,				PFNGLUNIFORM4IVPROC); \
	GL(glUniform4ui,				PFNGLUNIFORM4UIPROC); \
	GL(glUniform4uiv,				PFNGLUNIFORM4UIVPROC); \
	GL(glMultiDrawArrays,			PFNGLMULTIDRAWARRAYSPROC); \
	GL(glMapBuffer,					PFNGLMAPBUFFERPROC); \
	GL(glMapBufferRange,			PFNGLMAPBUFFERRANGEPROC); \
	GL(glUnmapBuffer,				PFNGLUNMAPBUFFERPROC); \
	GL(glGetTextureHandleARB,				PFNGLGETTEXTUREHANDLEARBPROC); \
	GL(glMakeTextureHandleResidentARB,		PFNGLMAKETEXTUREHANDLERESIDENTARBPROC); \
	GL(glMakeTextureHandleNonResidentARB,	PFNGLMAKETEXTUREHANDLENONRESIDENTARBPROC); \
	GL(glShaderStorageBlockBinding,	PFNGLSHADERSTORAGEBLOCKBINDINGPROC); \
	GL(glBindBufferBase,			PFNGLBINDBUFFERBASEPROC); \
	GL(glGetProgramResourceIndex,	PFNGLGETPROGRAMRESOURCEINDEXPROC); \
	GL(glTexImage2DMultisample,		PFNGLTEXIMAGE2DMULTISAMPLEPROC); \
	GL(glGenerateMipmap,			PFNGLGENERATEMIPMAPPROC); \
	GL(glCompressedTexImage2D,		PFNGLCOMPRESSEDTEXIMAGE2DPROC); \
	GL(glBlendFuncSeparate,			PFNGLBLENDFUNCSEPARATEPROC); \
	GL(glCopyImageSubData,			PFNGLCOPYIMAGESUBDATAPROC); \
	GL(glActiveTexture,				PFNGLACTIVETEXTUREPROC); \
	GL(glTexStorage2D,				PFNGLTEXSTORAGE2DPROC); \
	GL(glTexStorage2DMultisample,	PFNGLTEXSTORAGE2DMULTISAMPLEPROC); \
	GL(glFenceSync,					PFNGLFENCESYNCPROC); \
	GL(glWaitSync,					PFNGLWAITSYNCPROC); \
	GL(glDeleteSync,				PFNGLDELETESYNCPROC); \

#ifndef GL
#define GL(func, type) extern type func;
OPENGL_FUNC_LIST
#undef GL
#endif

#ifndef GLN
#define GLN(ret, sig) __declspec(dllimport) ret __stdcall sig;
OPENGL_FUNC_LIST_NOBIND
#undef GLN
#endif