#ifndef __INC_QG_OPENGL_BASE_H__
#define __INC_QG_OPENGL_BASE_H__

#ifdef _MSC_VER
#pragma once
#endif

//
struct qbRdhCaps;

//
struct qbOpenGLBase
{
	static void QglInitializeExtensions(const char* extstr);
	static bool QglTestExtensions();

	K_FORCEINLINE static bool QglSupportASTC() { return qgl_support_astc; }
	K_FORCEINLINE static bool QglSupportATITC() { return false; }
	K_FORCEINLINE static bool QglSupportBGRA8888() { return true; }
	K_FORCEINLINE static bool QglSupportColorBufferHalfFloat() { return true; }
	K_FORCEINLINE static bool QglSupportCopyImage() { return qgl_support_copy_image; }
	K_FORCEINLINE static bool QglSupportDebugContext() { return false; }
	K_FORCEINLINE static bool QglSupportDepthStencilAttachment() { return true; }
	K_FORCEINLINE static bool QglSupportDepthTexture() { return true; }
	K_FORCEINLINE static bool QglSupportDXT() { return true; }
	K_FORCEINLINE static bool QglSupportGenerateMipmap() { return false; }
	K_FORCEINLINE static bool QglSupportHalfFloat() { return true; }
	K_FORCEINLINE static bool QglSupportMapBuffer() { return true; }
	K_FORCEINLINE static bool QglSupportMultiOffScreen() { return true; }
	K_FORCEINLINE static bool QglSupportMultisampledTexture() { return true; }
	K_FORCEINLINE static bool QglSupportOcclusion() { return true; }
	K_FORCEINLINE static bool QglSupportPackedDepthStencil() { return true; }
	K_FORCEINLINE static bool QglSupportPolygonMode() { return true; }
	K_FORCEINLINE static bool QglSupportPVRTC() { return false; }
	K_FORCEINLINE static bool QglSupportRGBA8() { return true; }
	K_FORCEINLINE static bool QglSupportSeparateAlphaBlend() { return true; }
	K_FORCEINLINE static bool QglSupportSRGB() { return true; }
	K_FORCEINLINE static bool QglSupportTexture3D() { return true; }
	K_FORCEINLINE static bool QglSupportTextureBaseLevel() { return true; }
	K_FORCEINLINE static bool QglSupportTextureCompare() { return true; }
	K_FORCEINLINE static bool QglSupportTextureFloat() { return true; }
	K_FORCEINLINE static bool QglSupportTextureHalfFloat() { return true; }
	K_FORCEINLINE static bool QglSupportTextureLODBias() { return true; }
	K_FORCEINLINE static bool QglSupportTextureNPOT() { return true; }
	K_FORCEINLINE static bool QglSupportTextureParameter() { return true; }
	K_FORCEINLINE static bool QglSupportTextureMaxLevel() { return true; }
	K_FORCEINLINE static bool QglSupportTextureVolume() { return false; }

	K_FORCEINLINE static GLint QglGetMaxTextureImageUnits() { return qgl_max_texture_image_units; }
	K_FORCEINLINE static GLint QglGetMaxCombinedTextureImageUnits() { return qgl_max_combined_texture_image_units; }
	K_FORCEINLINE static GLint QglGetMaxOffScreenCount() { return 1; }
	K_FORCEINLINE static GLint QglGetTextureDimension() { return qgl_texture_dimension; }
	K_FORCEINLINE static GLint QglGetShaderVersion() { return qgl_shader_version; }
	K_FORCEINLINE static GLint QglGetVersion() { return qgl_version; }
	K_FORCEINLINE static GLenum QglGetDepthFormat() { return GL_DEPTH_COMPONENT16; }

	// 기본
	K_FORCEINLINE static void QglPolygonMode(GLenum face, GLenum mode) {}
	K_FORCEINLINE static void QglClearBufferfv(GLenum type, GLint idnex, const GLfloat* value) {}
	K_FORCEINLINE static void QglClearBufferfi(GLenum type, GLint idnex, GLfloat depth, GLint stencil) {}
	K_FORCEINLINE static void QglClearBufferiv(GLenum type, GLint idnex, const GLint* value) {}
	K_FORCEINLINE static void QglClearDepth(GLdouble depth) {}
	K_FORCEINLINE static void QglDepthRange(GLdouble near, GLdouble far) {}

	// 텍스쳐
	K_FORCEINLINE static void QglActiveTexture(GLenum texture) {}
	K_FORCEINLINE static void QglCompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void* data) {}
	K_FORCEINLINE static void QglGenerateMipmap(GLenum target) {}

	// 블렌드
	K_FORCEINLINE static void QglBlendEquation(GLenum mode) {}
	K_FORCEINLINE static void QglBlendEquationi(GLuint index, GLenum mode) {}
	K_FORCEINLINE static void QglBlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha) {}
	K_FORCEINLINE static void QglBlendEquationSeparatei(GLuint index, GLenum modeRGB, GLenum modeAlpha) {}
	K_FORCEINLINE static void QglBlendFunc(GLenum src, GLenum dst) {}
	K_FORCEINLINE static void QglBlendFunci(GLuint index, GLenum src, GLenum dst) {}
	K_FORCEINLINE static void QglBlendFuncSeparate(GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha) {}
	K_FORCEINLINE static void QglBlendFuncSeparatei(GLuint index, GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha) {}
	K_FORCEINLINE static void QglColorMaski(GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a) {}
	K_FORCEINLINE static void QglEnableIndexed(GLenum target, GLuint index) {}
	K_FORCEINLINE static void QglDisableIndexed(GLenum target, GLuint index) {}

	// 레이아웃	
	K_FORCEINLINE static void QglEnableVertexArray(GLuint index) {}
	K_FORCEINLINE static void QglDisableVertexArray(GLuint index) {}
	K_FORCEINLINE static void QglVertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* pointer) {}

	// FBO
	K_FORCEINLINE static void QglGenFramebuffers(GLsizei n, GLuint* framebuffers) {}
	K_FORCEINLINE static void QglBindFramebuffer(GLenum target, GLuint framebuffer) {}
	K_FORCEINLINE static void QglDeleteFramebuffers(GLsizei n, const GLuint* framebuffers) {}
	K_FORCEINLINE static GLenum QglCheckFramebufferStatus(GLenum target) { return 0; }
	K_FORCEINLINE static void QglFramebufferTexture1D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) {}
	K_FORCEINLINE static void QglFramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) {}
	K_FORCEINLINE static void QglFramebufferTexture3D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset) {}
	K_FORCEINLINE static void QglGenRenderbuffers(GLsizei n, GLuint* renderbuffers) {}
	K_FORCEINLINE static void QglBindRenderbuffer(GLenum target, GLuint renderbuffer) {}
	K_FORCEINLINE static void QglDeleteRenderbuffers(GLsizei n, const GLuint* renderbuffers) {}
	K_FORCEINLINE static void QglRenderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height) {}
	K_FORCEINLINE static void QglFramebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer) {}
	K_FORCEINLINE static void QglGetRenderbufferParameteriv(GLenum target, GLenum pname, GLint* params) {}
	K_FORCEINLINE static void QglGetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, GLenum pname, GLint* params) {}

	// 프로그램과 세이더
	K_FORCEINLINE static GLuint QglCreateProgram(void) { return 0; }
	K_FORCEINLINE static void QglDeleteProgram(GLuint object) {}
	K_FORCEINLINE static void QglAttachShader(GLuint program, GLuint shader) {}
	K_FORCEINLINE static void QglDetachShader(GLuint program, GLuint shader) {}
	K_FORCEINLINE static void QglGetAttachedShaders(GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders) {}
	K_FORCEINLINE static void QglGetProgramiv(GLuint program, GLenum type, GLint* param) {}
	K_FORCEINLINE static void QglGetProgramInfoLog(GLuint program, GLsizei maxLength, GLsizei* length, GLchar* infoLog) {}
	K_FORCEINLINE static void QglGetActiveAttrib(GLuint program, GLuint index, GLsizei maxlength, GLsizei* length, GLint* size, GLenum* type, GLchar* name) {}
	K_FORCEINLINE static void QglGetActiveUniform(GLuint program, GLuint index, GLsizei maxlength, GLsizei* length, GLint* size, GLenum* type, GLchar* name) {}
	K_FORCEINLINE static GLint QglGetAttribLocation(GLuint program, const GLchar *name) { return -1; }
	K_FORCEINLINE static GLint QglGetUniformLocation(GLuint program, const GLchar* name) { return -1; }

	K_FORCEINLINE static GLuint QglCreateShader(GLenum shaderType) { return 0; }
	K_FORCEINLINE static void QglShaderSource(GLuint shader, GLsizei numOfStrings, const char** strings, const GLint* lengths) {}
	K_FORCEINLINE static void QglCompileShader(GLuint shader) {}
	K_FORCEINLINE static void QglLinkProgram(GLuint program) {}
	K_FORCEINLINE static void QglUseProgram(GLuint prog) {}
	K_FORCEINLINE static void QglDeleteShader(GLuint shader) {}
	K_FORCEINLINE static void QglGetShaderiv(GLuint shader, GLenum type, GLint* param) {}
	K_FORCEINLINE static void QglGetShaderInfoLog(GLuint shader, GLsizei maxLength, GLsizei* length, GLchar* infoLog) {}

	K_FORCEINLINE static void QglUniform1fv(GLint loc, GLsizei count, const GLfloat* v) {}
	K_FORCEINLINE static void QglUniform2fv(GLint loc, GLsizei count, const GLfloat* v) {}
	K_FORCEINLINE static void QglUniform3fv(GLint loc, GLsizei count, const GLfloat* v) {}
	K_FORCEINLINE static void QglUniform4fv(GLint loc, GLsizei count, const GLfloat* v) {}
	K_FORCEINLINE static void QglUniform1iv(GLint loc, GLsizei count, const GLint* v) {}
	K_FORCEINLINE static void QglUniform2iv(GLint loc, GLsizei count, const GLint* v) {}
	K_FORCEINLINE static void QglUniform3iv(GLint loc, GLsizei count, const GLint* v) {}
	K_FORCEINLINE static void QglUniform4iv(GLint loc, GLsizei count, const GLint* v) {}
	K_FORCEINLINE static void QglUniformMatrix2fv(GLint loc, GLsizei count, GLboolean transpose, const GLfloat* v) {}
	K_FORCEINLINE static void QglUniformMatrix3fv(GLint loc, GLsizei count, GLboolean transpose, const GLfloat* v) {}
	K_FORCEINLINE static void QglUniformMatrix4fv(GLint loc, GLsizei count, GLboolean transpose, const GLfloat* v) {}

	// 버퍼
	K_FORCEINLINE static void QglGenBuffers(GLsizei n, GLuint* buffers) {}
	K_FORCEINLINE static void QglBindBuffer(GLenum target, GLuint buffer) {}
	K_FORCEINLINE static void QglDeleteBuffers(GLsizei n, const GLuint* buffers) {}
	K_FORCEINLINE static void QglBufferData(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage) {}
	K_FORCEINLINE static void QglBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data) {}
	K_FORCEINLINE static void QglGetBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, GLvoid* data) {}
	K_FORCEINLINE static void* QglMapBuffer(GLenum target, GLenum access) { return NULL; }
	K_FORCEINLINE static GLboolean QglUnmapBuffer(GLenum target) { return GL_FALSE; }
	K_FORCEINLINE static GLboolean QglIsBuffer(GLuint buffer) { return GL_FALSE; }
	K_FORCEINLINE static void QglDrawBuffers(GLsizei n, const GLenum* bufs) {}
	K_FORCEINLINE static void QglProvokingVertex(GLenum mode) {}

	// 포인트
	K_FORCEINLINE static void QglPointParameterf(GLint loc, GLfloat f) {}
	K_FORCEINLINE static void QglPointParameterfv(GLint loc, const GLfloat* v) {}

	// 스텐실
	K_FORCEINLINE static void QglStencilFuncSeparate(GLenum frontfunc, GLenum backfunc, GLint ref, GLuint mask) {}
	K_FORCEINLINE static void QglStencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenum zpass) {}

	// 오클루전
	K_FORCEINLINE static void QglGenQueries(GLsizei n, GLuint* ids) {}
	K_FORCEINLINE static void QglDeleteQueries(GLsizei n, const GLuint* ids) {}
	K_FORCEINLINE static GLboolean QglIsQuery(GLuint id) { return GL_FALSE; }
	K_FORCEINLINE static void QglBeginQuery(GLenum target, GLuint id) {}
	K_FORCEINLINE static void QglEndQuery(GLenum target) {}
	K_FORCEINLINE static void QglGetQueryiv(GLenum target, GLenum pname, GLint* params) {}
	K_FORCEINLINE static void QglGetQueryObjectuiv(GLuint id, GLenum pname, GLuint* params) {}

	// 기타
	K_FORCEINLINE static void QglSwapInterval(kpointer display, int interval) {}
	K_FORCEINLINE static bool QglSwapBuffers(kpointer display, kpointer surface) { return true; }

	// 유틸
	K_FORCEINLINE static void QglGetIntegerv(GLenum pname, GLint* v, GLint defv)
	{
		*v = defv;
		glGetIntegerv(pname, v);
	}

	static GLenum QglGetError(const char** str = NULL, bool display = true);

protected:
	static GLint qgl_max_texture_image_units;
	static GLint qgl_max_combined_texture_image_units;
	static GLint qgl_texture_dimension;
	static GLint qgl_shader_version;
	static GLint qgl_version;
	static bool qgl_support_astc;
	static bool qgl_support_copy_image;
};

//
#define QGGL_INVALID_ENUM					(GLenum)K_INVALID_VALUE
#define QGGL_INVALID_UINT					(GLuint)K_INVALID_VALUE

// 기타 OPENGL에서 쓰는 값들 (ES2에 없는 것들)
#ifndef GL_POLYGON_OFFSET_LINE
#define GL_POLYGON_OFFSET_LINE				0x2A02
#endif
#ifndef GL_POLYGON_OFFSET_POINT
#define GL_POLYGON_OFFSET_POINT				0x2A01
#endif
#ifndef GL_FIRST_VERTEX_CONVENTION
#define GL_FIRST_VERTEX_CONVENTION			0x8E4D
#endif
#ifndef GL_COLOR
#define GL_COLOR							0x1800
#endif
#ifndef GL_DEPTH
#define GL_DEPTH							0x1801
#endif
#ifndef GL_STENCIL
#define GL_STENCIL							0x1802
#endif
#ifndef GL_DEPTH_STENCIL
#define GL_DEPTH_STENCIL					0x84F9
#endif

#endif // !__INC_QG_OPENGL_BASE_H__
