/*
								+--------------------------------+
								|                                |
								| ***   OpenGL 2.0 shaders   *** |
								|                                |
								|  Copyright © -tHE SWINe- 2006  |
								|                                |
								|          Shader2.inl           |
								|                                |
								+--------------------------------+
*/

#pragma once
#ifndef __GL_SHADER2_INLINES_INCLUDED
#define __GL_SHADER2_INLINES_INCLUDED

/**
 *	@file gl2/Shader2.inl
 *	@date 2006
 *	@author -tHE SWINe-
 *	@brief OpenGL 2.0 shaders
 *
 *	@date 2006-10-09
 *
 *	passed code revision
 *
 *	removed most of ÜberLame stuff (todo - write new shader manager and generic
 *	encapsulation class)
 *	integers, containing just true or false were changed to bool
 *	fixed minor flaws in shader binding
 *	renamed to Shader2.cpp and Shader2.h respectively to avoid confusion with similar old source
 *
 *	@date 2006-11-10
 *
 *	passed code revision
 *
 *	created inline versions of Bind, Release and SetParam* functions so the encapsulation class,
 *	aware of shader api could use them (virtual functions themselves call them so there is no
 *	code written twice); note inlines are in Shader2.inl, there is too much of them to put them
 *	here
 *
 *	@date 2007-05-10
 *
 *	passed code revision
 *
 *	code to notify current GL state of shader deletion was added to GL_Free functions
 *	destructors don't invoke GL_Free in case shader isn't compiled
 *	void GL_Free(CGLState *p_state) was renamed to void Delete(void)
 *
 *	@date 2007-08-10
 *
 *	changed CGLShader::p_s_Uniform_Name(int n_index, int &r_n_content_type) const
 *	to CGLShader::p_s_Uniform_Name(int n_index, int &r_n_content_type, int &r_n_size) const
 *	so it's possible to determine size of array uniforms
 *
 *	replaced all __inline to inline for g++ compatibility
 *
 *	added CGL_ARB_program::_SetLocalParam4fv_VP(), CGL_ARB_program::_SetLocalParam4fv_FP(),
 *	CGL_ARB_program::_SetEnvParam4fv_VP() and CGL_ARB_program::_SetEnvParam4fv_FP() functions
 *	to overcome branching in CGL_ARB_program::_SetParam4fv()
 *
 *	added GL_EXT_gpu_shader4 uniform types and OpenGL 2.1 non-square matrix uniform types
 *
 *	renamed shader_param_* describing parameter data type to uniform_* as well as changed
 *	enum values so parameter type and size can be masked out of it
 *
 *	added count parameter to Uniform*v() so it's now possible to upload array uniforms
 *
 *	preparing for GL_EXT_geometry_shader
 *
 *	@date 2007-09-22
 *
 *	fixed minor bug which needlessly reallocated name string in CGL_Core_shader::p_s_Uniform_Name
 *	and CGL_ARB_shader::p_s_Uniform_Name
 *
 *	@date 2007-11-10
 *
 *	improved linux compatibility
 *
 *	rather crude change to all fast shader set parameter functions, state guard pointer
 *	was removed and parameters were rearranged so they come in the same order on stack
 *	like needed for gl functions
 *
 *	@date 2007-11-12
 *
 *	reformat (added line breaks where lines were longer than 100 characters)
 *
 *	@date 2007-11-26
 *
 *	added notice that the new NVidia drivers (163.71) slightly changed behavior of
 *	glGetProgramiv with GL_ACTIVE_UNIFORMS, as well as glGetActiveUniform so the reserved
 *	(builtin) OpenGL variables are returned as well, among other shader parameres.
 *
 *	@date 2008-03-04
 *
 *	added OpenGL 2.1 non-square matrix uniform functions and EXT_gpu_shader4 unsigned
 *	integer uniform functions
 *
 *	@date 2008-03-11
 *
 *	added geometry shaders to CGL_Core_shader, note it's not debugged functionality since
 *	i'm short on hardware to debug it on. new functions are CGL_Core_shader constructor
 *	taking three parameters (vertex, geometry and fragment shader source),
 *	CGL_Core_shader::SetGeometry_InputType, CGL_Core_shader::SetGeometry_OutputType,
 *	CGL_Core_shader::n_Geometry_MaxOutputVertices,
 *	CGL_Core_shader::n_Geometry_MaxOutputComponents, CGL_Core_shader::SetGeometry_VerticesOut
 *	and CGL_Core_shader::b_Supported with three parameters (vs, gs, fs)
 *
 *	@date 2008-03-13
 *
 *	fixed faulty assertion in Shader.cpp on line 1275 (1271 before adding this line)
 *
 *	@date 2008-08-08
 *
 *	added \#ifdef for windows 64
 *
 *	@date 2008-08-19
 *
 *	added \#include for OpenGL20.h and OpenGLState.h
 *
 *	@date 2009-05-04
 *
 *	fixed mixed windows / linux line endings
 *
 *	@date 2009-10-20
 *
 *	fixed some warnings when compiling under VC 2005, implemented "Security
 *	Enhancements in the CRT" for VC 2008. compare against MyProjects_2009-10-19_
 *
 *	@date 2012-06-19
 *
 *	Moved multiple inclusion guard before file documentation comment.
 *
 */

/*
 *								=== CGL_ARB_program ===
 */

inline bool CGL_ARB_program::_SetParam4fv(int n_param_type,
	int n_location, const float *p_value) const
{
	__FuncGuard("CGL_ARB_program::_SetParam4fv");

	if(n_param_type == shader_param_Parameter_Env_VP) {
		if(m_p_s_vertex_shader)
			glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, n_location, p_value);
		else
			return false; // bad shader type
	} else if(n_param_type == shader_param_Parameter_Env_FP) {
		if(m_p_s_fragment_shader)
			glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, n_location, p_value);
		else
			return false; // bad shader type
	} else if(n_param_type == shader_param_Parameter_Local_VP) {
		if(m_p_s_vertex_shader)
			glProgramLocalParameter4fvARB(GL_VERTEX_PROGRAM_ARB, n_location, p_value);
		else
			return false; // bad shader type
	} else if(n_param_type == shader_param_Parameter_Local_FP) {
		if(m_p_s_vertex_shader)
			glProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, n_location, p_value);
		else
			return false; // bad shader type
	} else
		return false; // bad param type
	return true;
}

inline void CGL_ARB_program::_SetLocalParam4fv_VP(int n_location, const float *p_value) const
{
	__FuncGuard("CGL_ARB_program::_SetLocalParam4fv_VP");

	glProgramLocalParameter4fvARB(GL_VERTEX_PROGRAM_ARB, n_location, p_value);
}

inline void CGL_ARB_program::_SetLocalParam4fv_FP(int n_location, const float *p_value) const
{
	__FuncGuard("CGL_ARB_program::_SetLocalParam4fv_FP");

	glProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, n_location, p_value);
}

inline void CGL_ARB_program::_SetEnvParam4fv_VP(int n_location, const float *p_value) const
{
	__FuncGuard("CGL_ARB_program::_SetEnvParam4fv_VP");

	glProgramEnvParameter4fvARB(GL_VERTEX_PROGRAM_ARB, n_location, p_value);
}

inline void CGL_ARB_program::_SetEnvParam4fv_FP(int n_location, const float *p_value) const
{
	__FuncGuard("CGL_ARB_program::_SetEnvParam4fv_FP");

	glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, n_location, p_value);
}

inline void CGL_ARB_program::_Bind(CGLState *p_state) const
{
	__FuncGuard("CGL_ARB_program::_Bind");

	if(m_n_vs_object) {
		p_state->EnableVertexProgram();
		p_state->BindVertexProgram(m_n_vs_object);
	} else
		p_state->DisableVertexProgram();
	if(m_n_fs_object) {
		p_state->EnableFragmentProgram();
		p_state->BindFragmentProgram(m_n_fs_object);
	} else
		p_state->DisableFragmentProgram();
}

inline void CGL_ARB_program::_Release(CGLState *p_state) const
{
	__FuncGuard("CGL_ARB_program::_Release");

	p_state->DisableVertexProgram();
	p_state->DisableFragmentProgram();
}

/*
 *								=== ~CGL_ARB_program ===
 */

/*
 *								=== CGL_ARB_shader ===
 */

inline void CGL_ARB_shader::_SetParam1fv(int n_location, int n_count, const float *p_value) const
{
	__FuncGuard("CGL_ARB_shader::_SetParam1fv");

	glUniform1fvARB(n_location, n_count, p_value);
}

inline void CGL_ARB_shader::_SetParam2fv(int n_location, int n_count, const float *p_value) const
{
	__FuncGuard("CGL_ARB_shader::_SetParam2fv");

	glUniform2fvARB(n_location, n_count, p_value);
}

inline void CGL_ARB_shader::_SetParam3fv(int n_location, int n_count, const float *p_value) const
{
	__FuncGuard("CGL_ARB_shader::_SetParam3fv");

	glUniform3fvARB(n_location, n_count, p_value);
}

inline void CGL_ARB_shader::_SetParam4fv(int n_location, int n_count, const float *p_value) const
{
	__FuncGuard("CGL_ARB_shader::_SetParam4fv");

	glUniform4fvARB(n_location, n_count, p_value);
}

inline void CGL_ARB_shader::_SetParam1i(int n_location, int n_value) const
{
	__FuncGuard("CGL_ARB_shader::_SetParam1i");

	glUniform1iARB(n_location, n_value);
}

inline void CGL_ARB_shader::_SetParam1iv(int n_location, int n_count, const int *p_value) const
{
	__FuncGuard("CGL_ARB_shader::_SetParam1iv");

	glUniform1ivARB(n_location, n_count, p_value);
}

inline void CGL_ARB_shader::_SetParam2iv(int n_location, int n_count, const int *p_value) const
{
	__FuncGuard("CGL_ARB_shader::_SetParam2iv");

	glUniform2ivARB(n_location, n_count, p_value);
}

inline void CGL_ARB_shader::_SetParam3iv(int n_location, int n_count, const int *p_value) const
{
	__FuncGuard("CGL_ARB_shader::_SetParam3iv");

	glUniform3ivARB(n_location, n_count, p_value);
}

inline void CGL_ARB_shader::_SetParam4iv(int n_location, int n_count, const int *p_value) const
{
	__FuncGuard("CGL_ARB_shader::_SetParam4iv");

	glUniform4ivARB(n_location, n_count, p_value);
}

inline void CGL_ARB_shader::_SetParamMatrix2fv(int n_location,
	int n_count, bool b_transpose, const float *p_value) const
{
	__FuncGuard("CGL_ARB_shader::_SetParamMatrix2fv");

	glUniformMatrix2fvARB(n_location, n_count, b_transpose, p_value);
}

inline void CGL_ARB_shader::_SetParamMatrix3fv(int n_location,
	int n_count, bool b_transpose, const float *p_value) const
{
	__FuncGuard("CGL_ARB_shader::_SetParamMatrix3fv");

	glUniformMatrix3fvARB(n_location, n_count, b_transpose, p_value);
}

inline void CGL_ARB_shader::_SetParamMatrix4fv(int n_location,
	int n_count, bool b_transpose, const float *p_value) const
{
	__FuncGuard("CGL_ARB_shader::_SetParamMatrix4fv");

	glUniformMatrix4fvARB(n_location, n_count, b_transpose, p_value);
}

inline void CGL_ARB_shader::_Bind(CGLState *p_state) const
{
	__FuncGuard("CGL_ARB_shader::_Bind");

	p_state->BindProgramObject(m_n_program_object);
}

inline void CGL_ARB_shader::_Release(CGLState *p_state) const
{
	__FuncGuard("CGL_ARB_shader::_Release");

	p_state->BindProgramObject(0);
}

/*
 *								=== ~CGL_ARB_shader ===
 */

/*
 *								=== CGL_Core_shader ===
 */

inline void CGL_Core_shader::_SetParam1fv(int n_location, int n_count, const float *p_value) const
{
	__FuncGuard("CGL_Core_shader::_SetParam1fv");

	glUniform1fv(n_location, n_count, p_value);
}

inline void CGL_Core_shader::_SetParam2fv(int n_location, int n_count, const float *p_value) const
{
	__FuncGuard("CGL_Core_shader::_SetParam2fv");

	glUniform2fv(n_location, n_count, p_value);
}

inline void CGL_Core_shader::_SetParam3fv(int n_location, int n_count, const float *p_value) const
{
	__FuncGuard("CGL_Core_shader::_SetParam3fv");

	glUniform3fv(n_location, n_count, p_value);
}

inline void CGL_Core_shader::_SetParam4fv(int n_location, int n_count, const float *p_value) const
{
	__FuncGuard("CGL_Core_shader::_SetParam4fv");

	glUniform4fv(n_location, n_count, p_value);
}

inline void CGL_Core_shader::_SetParam1i(int n_location, int n_value) const
{
	__FuncGuard("CGL_Core_shader::_SetParam1i");

	glUniform1i(n_location, n_value);
}

inline void CGL_Core_shader::_SetParam1iv(int n_location, int n_count, const int *p_value) const
{
	__FuncGuard("CGL_Core_shader::_SetParam1iv");

	glUniform1iv(n_location, n_count, p_value);
}

inline void CGL_Core_shader::_SetParam2iv(int n_location, int n_count, const int *p_value) const
{
	__FuncGuard("CGL_Core_shader::_SetParam2iv");

	glUniform2iv(n_location, n_count, p_value);
}

inline void CGL_Core_shader::_SetParam3iv(int n_location, int n_count, const int *p_value) const
{
	__FuncGuard("CGL_Core_shader::_SetParam3iv");

	glUniform3iv(n_location, n_count, p_value);
}

inline void CGL_Core_shader::_SetParam4iv(int n_location, int n_count, const int *p_value) const
{
	__FuncGuard("CGL_Core_shader::_SetParam4iv");

	glUniform4iv(n_location, n_count, p_value);
}

inline void CGL_Core_shader::_SetParamMatrix2fv(int n_location,
	int n_count, bool b_transpose, const float *p_value) const
{
	__FuncGuard("CGL_Core_shader::_SetParamMatrix2fv");

	glUniformMatrix2fv(n_location, n_count, b_transpose, p_value);
}

inline void CGL_Core_shader::_SetParamMatrix3fv(int n_location,
	int n_count, bool b_transpose, const float *p_value) const
{
	__FuncGuard("CGL_Core_shader::_SetParamMatrix3fv");

	glUniformMatrix3fv(n_location, n_count, b_transpose, p_value);
}

inline void CGL_Core_shader::_SetParamMatrix4fv(int n_location,
	int n_count, bool b_transpose, const float *p_value) const
{
	__FuncGuard("CGL_Core_shader::_SetParamMatrix4fv");

	glUniformMatrix4fv(n_location, n_count, b_transpose, p_value);
}

inline void CGL_Core_shader::_Bind(CGLState *p_state) const
{
	__FuncGuard("CGL_Core_shader::_Bind");

	p_state->BindProgramObject_GL2(m_n_program_object);
}

inline void CGL_Core_shader::_Release(CGLState *p_state) const
{
	__FuncGuard("CGL_Core_shader::_Release");

	p_state->BindProgramObject_GL2(0);
}

inline void CGL_Core_shader::_SetParamMatrix2x3fv(int n_location,
	int n_count, bool b_transpose, const float *p_value) const
{
	__FuncGuard("CGL_Core_shader::_SetParamMatrix2x3fv");

	glUniformMatrix2x3fv(n_location, n_count, b_transpose, p_value);
}

inline void CGL_Core_shader::_SetParamMatrix3x2fv(int n_location,
	int n_count, bool b_transpose, const float *p_value) const
{
	__FuncGuard("CGL_Core_shader::_SetParamMatrix3x2fv");

	glUniformMatrix3x2fv(n_location, n_count, b_transpose, p_value);
}

inline void CGL_Core_shader::_SetParamMatrix2x4fv(int n_location,
	int n_count, bool b_transpose, const float *p_value) const
{
	__FuncGuard("CGL_Core_shader::_SetParamMatrix2x4fv");

	glUniformMatrix2x4fv(n_location, n_count, b_transpose, p_value);
}

inline void CGL_Core_shader::_SetParamMatrix4x2fv(int n_location,
	int n_count, bool b_transpose, const float *p_value) const
{
	__FuncGuard("CGL_Core_shader::_SetParamMatrix4x2fv");

	glUniformMatrix4x2fv(n_location, n_count, b_transpose, p_value);
}

inline void CGL_Core_shader::_SetParamMatrix3x4fv(int n_location,
	int n_count, bool b_transpose, const float *p_value) const
{
	__FuncGuard("CGL_Core_shader::_SetParamMatrix3x4fv");

	glUniformMatrix3x4fv(n_location, n_count, b_transpose, p_value);
}

inline void CGL_Core_shader::_SetParamMatrix4x3fv(int n_location,
	int n_count, bool b_transpose, const float *p_value) const
{
	__FuncGuard("CGL_Core_shader::_SetParamMatrix4x3fv");

	glUniformMatrix4x3fv(n_location, n_count, b_transpose, p_value);
}

inline void CGL_Core_shader::_SetParam1uiv(int n_location,
	int n_count, const unsigned int *p_value) const
{
	__FuncGuard("CGL_Core_shader::_SetParam1uiv");

	glUniform1uivEXT(n_location, n_count, p_value);
}

inline void CGL_Core_shader::_SetParam2uiv(int n_location,
	int n_count, const unsigned int *p_value) const
{
	__FuncGuard("CGL_Core_shader::_SetParam2uiv");

	glUniform2uivEXT(n_location, n_count, p_value);
}

inline void CGL_Core_shader::_SetParam3uiv(int n_location,
	int n_count, const unsigned int *p_value) const
{
	__FuncGuard("CGL_Core_shader::_SetParam3uiv");

	glUniform3uivEXT(n_location, n_count, p_value);
}

inline void CGL_Core_shader::_SetParam4uiv(int n_location,
	int n_count, const unsigned int *p_value) const
{
	__FuncGuard("CGL_Core_shader::_SetParam4uiv");

	glUniform4uivEXT(n_location, n_count, p_value);
}

/*
 *								=== ~CGL_Core_shader ===
 */

#endif // !__GL_SHADER2_INLINES_INCLUDED
