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

#pragma once
#ifndef __GL_SHADER2_INCLUDED
#define __GL_SHADER2_INCLUDED

/**
 *	@file gl2/Shader2.h
 *	@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.
 *
 */

#include "OpenGL20.h"
#include "OpenGLState.h"

// shader parameter types
enum {
	shader_param_Uniform, // ARB_*_shader unifrom
	shader_param_Parameter_Env_VP, // ARB_*_program env param, set trough vertex program
	shader_param_Parameter_Env_FP, // ARB_*_program env param, set trough fragment program
	shader_param_Parameter_Local_VP, // ARB_vertex_program local param
	shader_param_Parameter_Local_FP // ARB_fragment_program local param
};

// uniform data types
enum {
	uniform_Unknown = -1,

	uniform_TypeMask =  0x000ff, // type (like sampler types)
	uniform_ClassMask = 0x00f00, // class (float vector / matrix / sampler / etc)
	uniform_SizeShift = 12, // size in scalar elements

	uniform_class_FloatVec = 1 << 8,
	uniform_class_IntVec = 2 << 8,
	uniform_class_BoolVec = 3 << 8,
	uniform_class_UnsignedIntVec = 4 << 8,
	uniform_class_Matrix = 5 << 8,
	uniform_class_NonSquareMatrix = 6 << 8,
	uniform_class_Sampler = 7 << 8,
	// shader param classes

	uniform_Float = uniform_class_FloatVec | (1 << uniform_SizeShift),
	uniform_Float2 = uniform_class_FloatVec | (2 << uniform_SizeShift),
	uniform_Float3 = uniform_class_FloatVec | (3 << uniform_SizeShift),
	uniform_Float4 = uniform_class_FloatVec | (4 << uniform_SizeShift),
	parameter_Float4 = uniform_Float4, // for sake of consistent naming
	uniform_Int = uniform_class_IntVec | (1 << uniform_SizeShift),
	uniform_Int2 = uniform_class_IntVec | (2 << uniform_SizeShift),
	uniform_Int3 = uniform_class_IntVec | (3 << uniform_SizeShift),
	uniform_Int4 = uniform_class_IntVec | (4 << uniform_SizeShift),
	uniform_Bool = uniform_class_BoolVec | (1 << uniform_SizeShift),
	uniform_Bool2 = uniform_class_BoolVec | (2 << uniform_SizeShift),
	uniform_Bool3 = uniform_class_BoolVec | (3 << uniform_SizeShift),
	uniform_Bool4 = uniform_class_BoolVec | (4 << uniform_SizeShift),
	uniform_Matrix2 = uniform_class_Matrix | (4 << uniform_SizeShift),
	uniform_Matrix3 = uniform_class_Matrix | (9 << uniform_SizeShift),
	uniform_Matrix4 = uniform_class_Matrix | (16 << uniform_SizeShift),
	uniform_Sampler1D = uniform_class_Sampler | (1 << uniform_SizeShift),
	uniform_Sampler2D,
	uniform_Sampler3D,
	uniform_SamplerCube,
	uniform_Sampler1D_Shadow,
	uniform_Sampler2D_Shadow,
	uniform_Sampler2D_Rect,
	uniform_Sampler2D_Rect_Shadow,
	// ARB_vertex_shader

	uniform_Matrix2x3 = uniform_class_NonSquareMatrix | (6 << uniform_SizeShift) | 0,
	uniform_Matrix2x4 = uniform_class_NonSquareMatrix | (8 << uniform_SizeShift) | 1,
	uniform_Matrix3x2 = uniform_class_NonSquareMatrix | (6 << uniform_SizeShift) | 2,
	uniform_Matrix3x4 = uniform_class_NonSquareMatrix | (12 << uniform_SizeShift) | 3,
	uniform_Matrix4x2 = uniform_class_NonSquareMatrix | (8 << uniform_SizeShift) | 4,
	uniform_Matrix4x3 = uniform_class_NonSquareMatrix | (12 << uniform_SizeShift) | 5,
	// OpenGL 2.1

	uniform_Unsigned_Int = uniform_class_UnsignedIntVec | (1 << uniform_SizeShift),
	uniform_Unsigned_Int2 = uniform_class_UnsignedIntVec | (2 << uniform_SizeShift),
	uniform_Unsigned_Int3 = uniform_class_UnsignedIntVec | (3 << uniform_SizeShift),
	uniform_Unsigned_Int4 = uniform_class_UnsignedIntVec | (4 << uniform_SizeShift),
	uniform_Sampler1D_Array = uniform_Sampler2D_Rect_Shadow + 1,
	uniform_Sampler2D_Array,
	uniform_SamplerBuffer,
	uniform_Sampler1D_Array_Shadow,
	uniform_Sampler2D_Array_Shadow,
	uniform_SamplerCube_Shadow,
	uniform_Sampler_Int_1D,
	uniform_Sampler_Int_2D,
	uniform_Sampler_Int_3D,
	uniform_Sampler_Int_Cube,
	uniform_Sampler_Int_2D_Rect,
	uniform_Sampler_Int_1D_Array,
	uniform_Sampler_Int_2D_Array,
	uniform_Sampler_Int_Buffer,
	uniform_Sampler_Unsigned_Int_1D,
	uniform_Sampler_Unsigned_Int_2D,
	uniform_Sampler_Unsigned_Int_3D,
	uniform_Sampler_Unsigned_Int_Cube,
	uniform_Sampler_Unsigned_Int_2D_Rect,
	uniform_Sampler_Unsigned_Int_1D_Array,
	uniform_Sampler_Unsigned_Int_2D_Array,
	uniform_Sampler_Unsigned_Int_Buffer
	// EXT_gpu_shader4
};

/*
 *	class CShaderParamTypeConverter
 *		- OpenGL returns shader parameter data types as set of constants
 *		- for better convenience, those contains are translated to simple enum
 *		  with successive values so determining the group parameter data type
 *		  belongs to no longer requires switch(), two cmp will do
 */
class CShaderParamTypeConverter {
protected:
	static const struct TTableElem {
		int n_enum_value; // not linear anymore
		GLenum n_gl_value;
	} m_p_type_table[];

public:
	/*
	 *	static int CShaderParamTypeConverter::n_EnumValue(GLenum n_gl_value)
	 *		- translate OpenGL parameter type value to enum value
	 *		  (reason to do that is faster parameter type tests as enum values
	 *		  are successive integers)
	 *		- in case unknown parameter type is passed, returns uniform_Unknown
	 */
	static int n_EnumValue(GLenum n_gl_value);

	/*
	 *	static GLenum CShaderParamTypeConverter::n_OpenGLValue(int n_enum_value)
	 *		- translate enum value n_enum_value to OpenGL parameter
	 *		- returns 0 (equal to GL_NONE) on uniform_Unknown / bad enum value
	 */
	static GLenum n_OpenGLValue(int n_enum_value);
};

// shader api types
enum {
	shader_api_ARB_program,
	shader_api_ARB_shader,
	shader_api_Core_shader // OpenGL20
};

/*
 *	class CGLProgram
 *		- most common class for OpenGL vertex / fragment shader / program
 */
class CGLProgram {
protected:
	const char *m_p_s_vertex_shader;
	const char *m_p_s_fragment_shader;

public:
	CGLProgram(const char *p_s_vertex_shader, const char *p_s_fragment_shader)
		:m_p_s_vertex_shader(p_s_vertex_shader),
		m_p_s_fragment_shader(p_s_fragment_shader)
	{ }

	virtual ~CGLProgram() {}

	virtual bool Compile(CGLState *p_state, char *&p_s_info_log) = 0;
	virtual bool SetParam4fv(CGLState *p_state, int n_param_type, int n_location,
		const float *p_value, int n_count = 1) const = 0;
	virtual void Bind(CGLState *p_state) const = 0;
	virtual void Release(CGLState *p_state) const = 0;
	virtual void Delete() = 0;
	virtual int n_Api() const = 0;
};

/*
 *	class CGLShader : public CGLProgram
 *		- class for OpenGL vertex / fragment shader
 */
class CGLShader : public CGLProgram {
public:
	CGLShader(const char *p_s_vertex_shader, const char *p_s_fragment_shader)
		:CGLProgram(p_s_vertex_shader, p_s_fragment_shader)
	{ }

	virtual ~CGLShader() {}

	virtual bool BindAttribLocation(int n_location, const char *p_s_attrib_name) = 0;
	virtual bool Link(char *&p_s_info_log) = 0;
	virtual int n_Uniform_Num() const = 0;
	virtual char *p_s_Uniform_Name(int n_index, int &r_n_content_type, int &r_n_size) const = 0;
	virtual int n_GetUniformLocation(const char *p_s_uniform_name) const = 0;
	virtual bool SetParam1fv(CGLState *p_state, int n_param_type,
		int n_location, const float *p_value, int n_count = 1) = 0;
	virtual bool SetParam2fv(CGLState *p_state, int n_param_type,
		int n_location, const float *p_value, int n_count = 1) = 0;
	virtual bool SetParam3fv(CGLState *p_state, int n_param_type,
		int n_location, const float *p_value, int n_count = 1) = 0;
	virtual bool SetParam1i(CGLState *p_state, int n_location, int n_value) = 0;
	virtual bool SetParam1iv(CGLState *p_state, int n_location,
		const int *p_value, int n_count = 1) = 0;
	virtual bool SetParam2iv(CGLState *p_state, int n_location,
		const int *p_value, int n_count = 1) = 0;
	virtual bool SetParam3iv(CGLState *p_state, int n_location,
		const int *p_value, int n_count = 1) = 0;
	virtual bool SetParam4iv(CGLState *p_state, int n_location,
		const int *p_value, int n_count = 1) = 0;
	virtual bool SetParamMatrix2fv(CGLState *p_state, int n_location,
		bool b_transpose, const float *p_value, int n_count = 1) = 0;
	virtual bool SetParamMatrix3fv(CGLState *p_state, int n_location,
		bool b_transpose, const float *p_value, int n_count = 1) = 0;
	virtual bool SetParamMatrix4fv(CGLState *p_state, int n_location,
		bool b_transpose, const float *p_value, int n_count = 1) = 0;
};

/*
 *	class CGL_ARB_program : public CGLProgram
 *		- class, encapsulating GL_ARB_vertex_program and GL_ARB_fragment_program extensions
 *		- note low-level language doesn't have vertex attrib binding neither uniform locations
 *		  (both are hard-coded in vertex / fragment program source)
 */
class CGL_ARB_program : public CGLProgram {
protected:
	bool m_b_compiled;
	bool m_b_linked;

	unsigned int m_n_vs_object;
	unsigned int m_n_fs_object;

public:
	/*
	 *	CGL_ARB_program::CGL_ARB_program(const char *p_s_vertex_shader,
	 *		const char *p_s_fragment_shader)
	 *		- default constructor
	 *		- p_s_vertex_shader and p_s_fragment_shader are strings, containing shader source
	 *		  codes, one of them can be 0
	 *		- note pointers are copied only, they must not be freed until this object is deleted
	 */
	CGL_ARB_program(const char *p_s_vertex_shader, const char *p_s_fragment_shader);

	/*
	 *	CGL_ARB_program::~CGL_ARB_program()
	 *		- default destructor
	 */
	virtual ~CGL_ARB_program();

	/*
	 *	static bool CGL_ARB_program::b_Supported(bool b_vertex_pipeline = true,
	 *		bool b_fragment_pipeline = true)
	 *		- b_vertex_pipeline and b_fragment_pipeline selects required functionality
	 *		- returns true in case all necessary OpenGL extensions are supported,
	 *		  otherwise returns false
	 */
	static bool b_Supported(bool b_vertex_pipeline = true, bool b_fragment_pipeline = true);

	/*
	 *	bool CGL_ARB_program::Compile(CGLState *p_state, char *&r_p_s_info_log)
	 *		- compile program and return info-log, which has to be freed
	 *		- if you re-compile program, it call Delete() first
	 *		- returns true on success, (still can return log with warnings) false on failure
	 */
	virtual bool Compile(CGLState *p_state, char *&r_p_s_info_log);

	/*
	 *	bool CGL_ARB_program::SetParam4fv(CGLState *p_state, int n_param_type,
	 *		int n_location, const float *p_value, int n_count = 1) const
	 *		- set float vec4 shader parameter
	 *		- p_value is pointer to 4 floats, data will be read from
	 *		- n_location is index of destination register
	 *		- n_count is number of parameters to set
	 *		- n_param_type must be one of shader_param_Parameter_Env_VP,
	 *		  shader_param_Parameter_Env_FP, shader_param_Parameter_Local_VP
	 *		  or shader_param_Parameter_Local_FP
	 */
	virtual bool SetParam4fv(CGLState *p_state, int n_param_type,
		int n_location, const float *p_value, int n_count = 1) const;

	/*
	 *	void CGL_ARB_program::Bind(CGLState *p_state) const
	 *		- binds shader
	 */
	virtual void Bind(CGLState *p_state) const;

	/*
	 *	void CGL_ARB_program::Release(CGLState *p_state) const
	 *		- un-binds shader
	 *		- used for safe switching between shaders with different api-s
	 */
	virtual void Release(CGLState *p_state) const;

	/*
	 *	void CGL_ARB_program::Delete()
	 *		- free open-gl resources
	 *		- if program is about to be used again, it must be re-compiled,
	 *		  re-bound vertex attribs, re-linked and re-queried for unifroms
	 */
	virtual void Delete();

	/*
	 *	int CGL_ARB_program::n_Api() const
	 *		- return which api is used (shader_api_ARB_program)
	 */
	virtual int n_Api() const;

	inline void _Bind(CGLState *p_state) const;
	inline void _Release(CGLState *p_state) const;

	// the following functions doesn't do any parameter checking, assumes shader is bound
	inline bool _SetParam4fv(int n_param_type, int n_location, const float *p_value) const;
	// determines parameter type by n_param_type

	inline void _SetLocalParam4fv_VP(int n_location, const float *p_value) const;
	inline void _SetLocalParam4fv_FP(int n_location, const float *p_value) const;
	inline void _SetEnvParam4fv_VP(int n_location, const float *p_value) const;
	inline void _SetEnvParam4fv_FP(int n_location, const float *p_value) const;
	// parameter type by function name
};

/*
 *	class CGL_ARB_shader : public CGLShader
 *		- class, encapsulating GL_ARB_vertex_shader and GL_ARB_fragment_shader extensions
 */
class CGL_ARB_shader : public CGLShader {
protected:
	bool m_b_compiled;
	bool m_b_linked;

	GLhandleARB m_n_program_object;
	GLhandleARB m_n_vs_object;
	GLhandleARB m_n_fs_object;

public:
	/*
	 *	CGL_ARB_shader::CGL_ARB_shader(const char *p_s_vertex_shader,
	 *		const char *p_s_fragment_shader)
	 *		- default constructor
	 *		- p_s_vertex_shader and p_s_fragment_shader are strings, containing shader source
	 *		  codes, one of them can be 0
	 *		- note pointers are copied only, they must not be freed until this object is deleted
	 */
	CGL_ARB_shader(const char *p_s_vertex_shader, const char *p_s_fragment_shader);

	/*
	 *	CGL_ARB_shader::~CGL_ARB_shader()
	 *		- default destructor
	 */
	virtual ~CGL_ARB_shader();

	/*
	 *	static bool CGL_ARB_shader::b_Supported(bool b_vertex_pipeline = true,
	 *		bool b_fragment_pipeline = true)
	 *		- b_vertex_pipeline and b_fragment_pipeline selects required functionality
	 *		- returns true in case all necessary OpenGL extensions are supported,
	 *		  otherwise returns false
	 */
	static bool b_Supported(bool b_vertex_pipeline = true, bool b_fragment_pipeline = true);

	/*
	 *	virutal bool CGL_ARB_shader::Compile(CGLState *p_state, char *&r_p_s_info_log)
	 *		- compile program and return info-log, which has to be freed
	 *		- if you re-compile program, it call Delete() first
	 *		- returns true on success (can still return warnings), false on failure
	 */
	virtual bool Compile(CGLState *p_state, char *&r_p_s_info_log);

	/*
	 *	virutal bool CGL_ARB_shader::BindAttribLocation(int n_location,
	 *		const char *p_s_attrib_name)
	 *		- bind vertex attrib location
	 *		- can be called only if program was successfully compiled and not linked
	 *		- returns true on success, false on failure
	 */
	virtual bool BindAttribLocation(int n_location, const char *p_s_attrib_name);

	/*
	 *	virutal bool CGL_ARB_shader::Link(char *&r_p_s_info_log)
	 *		- link program, return info-log which has to be freed
	 *		- can be called only if program was successfully compiled and not linked
	 *		- returns true on success (can still return warnings), false on failure
	 */
	virtual bool Link(char *&r_p_s_info_log);

	/*
	 *	virtual int CGL_ARB_shader::n_Uniform_Num() const
	 *		- return number of uniform variables or -1 on failure
	 *		- note this may also include OpenGL builtin uniforms such as
	 *		  gl_ModelViewProjectionMatrixTranspose
	 */
	virtual int n_Uniform_Num() const;

	/*
	 *	virtual char *CGL_ARB_shader::p_s_Uniform_Name(int n_index,
	 *		int &r_n_content_type, int &r_n_size) const
	 *		- return name of uniform variable with index n_index or 0 on failure
	 *		- r_n_content_type is set to variable content type (one of uniform_Float,
	 *		  uniform_Float2, ...)
	 *		- r_n_size is set to size of the uniform variable (1 for scalars, 1 or more
	 *		  than 1 for arrays)
	 */
	virtual char *p_s_Uniform_Name(int n_index, int &r_n_content_type, int &r_n_size) const;

	/*
	 *	virtual int CGL_ARB_shader::n_GetUniformLocation(const char *p_s_uniform_name) const
	 *		- returns uniform location by uniform name
	 *		- note this fails on OpenGL builtin uniforms such as
	 *		  gl_ModelViewProjectionMatrixTranspose
	 *		- returns -1 on failure
	 */
	virtual int n_GetUniformLocation(const char *p_s_uniform_name) const;

	/*
	 *	virtual bool CGL_ARB_shader::SetParam1fv(CGLState *p_state, int n_param_type,
	 *		int n_location, const float *p_value, int n_count = 1)
	 *		- set float uniform to value of first element in p_value array
	 *		- n_param_type is safe-check only, it should be shader_param_Uniform
	 *		- n_location is destination register index
	 *		- n_count is number of parameters to set
	 *		- returns true on success, false on failure
	 */
	virtual bool SetParam1fv(CGLState *p_state, int n_param_type, int n_location,
		const float *p_value, int n_count = 1);

	/*
	 *	virtual bool CGL_ARB_shader::SetParam2fv(CGLState *p_state, int n_param_type,
	 *		int n_location, const float *p_value, int n_count = 1)
	 *		- set float vec2 uniform to value of first two elements in p_value array
	 *		- n_param_type is safe-check only, it should be shader_param_Uniform
	 *		- n_location is destination register index
	 *		- n_count is number of parameters to set
	 *		- returns true on success, false on failure
	 */
	virtual bool SetParam2fv(CGLState *p_state, int n_param_type, int n_location,
		const float *p_value, int n_count = 1);

	/*
	 *	virtual bool CGL_ARB_shader::SetParam3fv(CGLState *p_state, int n_param_type,
	 *		int n_location, const float *p_value, int n_count = 1)
	 *		- set float vec3 uniform to value of first three elements in p_value array
	 *		- n_param_type is safe-check only, it should be shader_param_Uniform
	 *		- n_location is destination register index
	 *		- n_count is number of parameters to set
	 *		- returns true on success, false on failure
	 */
	virtual bool SetParam3fv(CGLState *p_state, int n_param_type, int n_location,
		const float *p_value, int n_count = 1);

	/*
	 *	virtual bool CGL_ARB_shader::SetParam4fv(CGLState *p_state, int n_param_type,
	 *		int n_location, const float *p_value, int n_count = 1) const
	 *		- set float vec4 uniform to value of first four elements in p_value array
	 *		- n_param_type is safe-check only, it should be shader_param_Uniform
	 *		- n_location is destination register index
	 *		- n_count is number of parameters to set
	 *		- returns true on success, false on failure
	 */
	virtual bool SetParam4fv(CGLState *p_state, int n_param_type, int n_location,
		const float *p_value, int n_count = 1) const;

	/*
	 *	virtual bool CGL_ARB_shader::SetParam1i(CGLState *p_state, int n_location,
	 *		int n_value, int n_count = 1)
	 *		- set integer uniform (sampler) to n_value
	 *		- n_location is destination register index
	 *		- returns true on success, false on failure
	 */
	virtual bool SetParam1i(CGLState *p_state, int n_location, int n_value);

	/*
	 *	virtual bool CGL_ARB_shader::SetParam1iv(CGLState *p_state, int n_location,
	 *		const int *p_value, int n_count = 1)
	 *		- set integer uniform to n_value of first two elements in p_value
	 *		- n_location is destination register index
	 *		- n_count is number of parameters to set
	 *		- returns true on success, false on failure
	 */
	virtual bool SetParam1iv(CGLState *p_state, int n_location,
		const int *p_value, int n_count = 1);

	/*
	 *	virtual bool CGL_ARB_shader::SetParam2iv(CGLState *p_state, int n_location,
	 *		const int *p_value, int n_count = 1)
	 *		- set integer vec2 uniform to n_value of first two elements in p_value
	 *		- n_location is destination register index
	 *		- n_count is number of parameters to set
	 *		- returns true on success, false on failure
	 */
	virtual bool SetParam2iv(CGLState *p_state, int n_location,
		const int *p_value, int n_count = 1);

	/*
	 *	virtual bool CGL_ARB_shader::SetParam3iv(CGLState *p_state, int n_location,
	 *		const int *p_value, int n_count = 1)
	 *		- set integer vec3 uniform to n_value of first three elements in p_value
	 *		- n_location is destination register index
	 *		- n_count is number of parameters to set
	 *		- returns true on success, false on failure
	 */
	virtual bool SetParam3iv(CGLState *p_state, int n_location,
		const int *p_value, int n_count = 1);

	/*
	 *	virtual bool CGL_ARB_shader::SetParam4iv(CGLState *p_state, int n_location,
	 *		const int *p_value, int n_count = 1)
	 *		- set integer vec4 uniform to n_value of first four elements in p_value
	 *		- n_location is destination register index
	 *		- n_count is number of parameters to set
	 *		- returns true on success, false on failure
	 */
	virtual bool SetParam4iv(CGLState *p_state, int n_location,
		const int *p_value, int n_count = 1);

	/*
	 *	virtual bool CGL_ARB_shader::SetParamMatrix2fv(CGLState *p_state, int n_location,
	 *		bool b_transpose, const float *p_value, int n_count = 1)
	 *		- set 2x2 float matrix uniform to 2x2 matrix form p_value
	 *		- n_location is destination register index
	 *		- n_count is number of parameters to set
	 *		- returns true on success, false on failure
	 */
	virtual bool SetParamMatrix2fv(CGLState *p_state, int n_location,
		bool b_transpose, const float *p_value, int n_count = 1);

	/*
	 *	virtual bool CGL_ARB_shader::SetParamMatrix3fv(CGLState *p_state, int n_location,
	 *		bool b_transpose, const float *p_value, int n_count = 1)
	 *		- set 3x3 float matrix uniform to 3x3 matrix form p_value
	 *		- n_location is destination register index
	 *		- n_count is number of parameters to set
	 *		- returns true on success, false on failure
	 */
	virtual bool SetParamMatrix3fv(CGLState *p_state, int n_location,
		bool b_transpose, const float *p_value, int n_count = 1);

	/*
	 *	virtual bool CGL_ARB_shader::SetParamMatrix4fv(CGLState *p_state, int n_location,
	 *		bool b_transpose, const float *p_value, int n_count = 1)
	 *		- set 4x4 float matrix uniform to 4x4 matrix form p_value
	 *		- n_location is destination register index
	 *		- n_count is number of parameters to set
	 *		- returns true on success, false on failure
	 */
	virtual bool SetParamMatrix4fv(CGLState *p_state, int n_location,
		bool b_transpose, const float *p_value, int n_count = 1);

	/*
	 *	virtual void CGL_ARB_shader::Bind(CGLState *p_state) const
	 *		- binds shader
	 */
	virtual void Bind(CGLState *p_state) const;

	/*
	 *	virtual void CGL_ARB_shader::Release(CGLState *p_state) const
	 *		- un-binds shader
	 *		- used for safe switching between shaders with different api-s
	 */
	virtual void Release(CGLState *p_state) const;

	/*
	 *	virtual void CGL_ARB_shader::Delete()
	 *		- free open-gl resources
	 *		- if program is about to be used again, it must be re-compiled,
	 *		  re-bound vertex attribs, re-linked and re-queried for unifroms
	 */
	virtual void Delete();

	/*
	 *	virtual int CGL_ARB_shader::n_Api() const
	 *		- return which api is used (shader_api_ARB_shader)
	 */
	virtual int n_Api() const;

	inline void _Bind(CGLState *p_state) const;
	inline void _Release(CGLState *p_state) const;

	// the following functions  doesn't do any parameter checking, assumes shader is bound
	inline void _SetParam1fv(int n_location, int n_count, const float *p_value) const;
	inline void _SetParam2fv(int n_location, int n_count, const float *p_value) const;
	inline void _SetParam3fv(int n_location, int n_count, const float *p_value) const;
	inline void _SetParam4fv(int n_location, int n_count, const float *p_value) const;
	inline void _SetParam1i(int n_location, int n_value) const;
	inline void _SetParam1iv(int n_location, int n_count, const int *p_value) const;
	inline void _SetParam2iv(int n_location, int n_count, const int *p_value) const;
	inline void _SetParam3iv(int n_location, int n_count, const int *p_value) const;
	inline void _SetParam4iv(int n_location, int n_count, const int *p_value) const;
	inline void _SetParamMatrix2fv(int n_location,
		int n_count, bool b_transpose, const float *p_value) const;
	inline void _SetParamMatrix3fv(int n_location,
		int n_count, bool b_transpose, const float *p_value) const;
	inline void _SetParamMatrix4fv(int n_location,
		int n_count, bool b_transpose, const float *p_value) const;
};

/*
 *	class CGL_Core_shader : public CGLShader
 *		- class, encapsulating OpenGL 2.0 high-level vertex and fragment shaders
 */
class CGL_Core_shader : public CGLShader {
protected:
	const char *m_p_s_geometry_shader;

	bool m_b_compiled;
	bool m_b_linked;

	unsigned int m_n_program_object;
	unsigned int m_n_vs_object;
	unsigned int m_n_gs_object;
	unsigned int m_n_fs_object;

public:
	/*
	 *	CGL_Core_shader::CGL_Core_shader(const char *p_s_vertex_shader,
	 *		const char *p_s_fragment_shader)
	 *		- default constructor
	 *		- p_s_vertex_shader and p_s_fragment_shader are strings, containing shader source
	 *		  codes, one of them can be 0
	 *		- note pointers are copied only, they must not be freed until this object is deleted
	 */
	CGL_Core_shader(const char *p_s_vertex_shader, const char *p_s_fragment_shader);

	/*
	 *	CGL_Core_shader::CGL_Core_shader(const char *p_s_vertex_shader,
	 *		const char *p_s_geometry_shader, const char *p_s_fragment_shader)
	 *		- default constructor
	 *		- p_s_vertex_shader, p_s_geometry_shader and p_s_fragment_shader are strings,
	 *		  containing shader source codes, at least one of them must not be 0
	 *		- note pointers are copied only, they must not be freed until this object is deleted
	 */
	CGL_Core_shader(const char *p_s_vertex_shader,
		const char *p_s_geometry_shader, const char *p_s_fragment_shader);

	/*
	 *	CGL_Core_shader::~CGL_Core_shader()
	 *		- default destructor
	 */
	virtual ~CGL_Core_shader();

	/*
	 *	static bool CGL_Core_shader::b_Supported(bool b_vertex_pipeline = true,
	 *		bool b_fragment_pipeline = true)
	 *		- b_vertex_pipeline and b_fragment_pipeline selects required functionality
	 *		- returns true in case all necessary OpenGL extensions are supported,
	 *		  otherwise returns false
	 */
	static bool b_Supported(bool b_vertex_pipeline = true, bool b_fragment_pipeline = true);

	/*
	 *	static bool CGL_Core_shader::b_Supported(bool b_vertex_pipeline,
	 *		bool b_geometry_pipeline, bool b_fragment_pipeline)
	 *		- b_vertex_pipeline, b_geometry_pipeline and b_fragment_pipeline selects
	 *		  required functionality
	 *		- returns true in case all necessary OpenGL extensions are supported,
	 *		  otherwise returns false
	 */
	static bool b_Supported(bool b_vertex_pipeline,
		bool b_geometry_pipeline, bool b_fragment_pipeline);

	/*
	 *	virtual bool CGL_Core_shader::Compile(CGLState *p_state, char *&r_p_s_info_log)
	 *		- compile program and return info-log, which has to be freed
	 *		- if you re-compile program, it call Delete() first
	 *		- returns true on success (can still return warnings), false on failure
	 */
	virtual bool Compile(CGLState *p_state, char *&r_p_s_info_log);

	/*
	 *	virtual bool CGL_Core_shader::BindAttribLocation(int n_location,
	 *		const char *p_s_attrib_name)
	 *		- bind vertex attrib location
	 *		- can be called only if program was successfully compiled and not linked
	 *		- returns true on success, false on failure
	 */
	virtual bool BindAttribLocation(int n_location, const char *p_s_attrib_name);

	/*
	 *	bool CGL_Core_shader::SetGeometry_InputType(GLenum n_input_type = GL_TRIANGLES)
	 *		- sets geometry shader input type (one of GL_POINTS, GL_LINES,
	 *		  GL_LINES_ADJACENCY_EXT, GL_TRIANGLES or GL_TRIANGLES_ADJACENCY_EXT,
	 *		  default is GL_TRIANGLES)
	 *		- note the shader must be compiled, but not linked and there
	 *		  must be geometry shader
	 *		- returns true on success, false on failure
	 */
	bool SetGeometry_InputType(GLenum n_input_type = GL_TRIANGLES);

	/*
	 *	bool CGL_Core_shader::SetGeometry_OutputType(GLenum n_output_type = GL_TRIANGLE_STRIP)
	 *		- sets geometry shader output type (one of GL_POINTS,
	 *		  GL_LINE_STRIP or GL_TRIANGLE_STRIP, default is GL_TRIANGLE_STRIP)
	 *		- note the shader must be compiled, but not linked and there
	 *		  must be geometry shader
	 *		- returns true on success, false on failure
	 */
	bool SetGeometry_OutputType(GLenum n_output_type = GL_TRIANGLE_STRIP);

	/*
	 *	static int CGL_Core_shader::n_Geometry_MaxOutputVertices()
	 *		- returns maximal number of vertices emitted by geometry shader in a single
	 *		  invocation (ie. maximal value of SetGeometry_VerticesOut argument)
	 */
	static int n_Geometry_MaxOutputVertices();

	/*
	 *	static int CGL_Core_shader::n_Geometry_MaxOutputComponents()
	 *		- returns maximal number of all vertex components produced
	 *		  by geometry shader in a single invocation
	 */
	static int n_Geometry_MaxOutputComponents();

	/*
	 *	bool CGL_Core_shader::SetGeometry_VerticesOut(int n_max_vertex_num)
	 *		- sets maximal number of vertices emitted by geometry shader in a single invocation
	 *		  (default 0). note this must be set, otherwise linking shader is going to fail.
	 *		- maximal value of n_max_vertex_num is constrained by n_Geometry_MaxOutputVertices()
	 *		  and indirectly by n_Geometry_MaxOutputComponents()
	 *		- note the shader must be compiled, but not linked and there
	 *		  must be geometry shader
	 *		- returns true on success, false on failure
	 */
	bool SetGeometry_VerticesOut(int n_max_vertex_num);

	/*
	 *	virtual bool CGL_Core_shader::Link(char *&r_p_s_info_log)
	 *		- link program, return info-log which has to be freed
	 *		- can be called only if program was successfully compiled and not linked
	 *		- returns true on success (can still return warnings), false on failure
	 */
	virtual bool Link(char *&r_p_s_info_log);

	/*
	 *	virtual int CGL_Core_shader::n_Uniform_Num() const
	 *		- return number of uniform variables or -1 on failure
	 *		- note this may also include OpenGL builtin uniforms such as
	 *		  gl_ModelViewProjectionMatrixTranspose
	 */
	virtual int n_Uniform_Num() const;

	/*
	 *	virtual char *CGL_Core_shader::p_s_Uniform_Name(int n_index,
	 *		int &r_n_content_type, int &r_n_size) const
	 *		- return name of uniform variable with index n_index or 0 on failure
	 *		- r_n_content_type is set to variable content type (one of uniform_Float,
	 *		  uniform_Float2, ...)
	 *		- r_n_size is set to size of the uniform variable (1 for scalars, 1 or more
	 *		  than 1 for arrays)
	 */
	virtual char *p_s_Uniform_Name(int n_index, int &r_n_content_type, int &r_n_size) const;

	/*
	 *	virtual int CGL_Core_shader::n_GetUniformLocation(const char *p_s_uniform_name) const
	 *		- returns uniform location by uniform name
	 *		- note this fails on OpenGL builtin uniforms such as
	 *		  gl_ModelViewProjectionMatrixTranspose
	 *		- returns -1 on failure
	 */
	virtual int n_GetUniformLocation(const char *p_s_uniform_name) const;

	/*
	 *	virtual bool CGL_Core_shader::SetParam1fv(CGLState *p_state, int n_param_type,
	 *		int n_location, const float *p_value, int n_count = 1)
	 *		- set float uniform to value of first element in p_value array
	 *		- n_param_type is safe-check only, it should be shader_param_Uniform
	 *		- n_location is destination register index
	 *		- n_count is number of parameters to set
	 *		- returns true on success, false on failure
	 */
	virtual bool SetParam1fv(CGLState *p_state, int n_param_type, int n_location,
		const float *p_value, int n_count = 1);

	/*
	 *	virtual bool CGL_Core_shader::SetParam2fv(CGLState *p_state, int n_param_type,
	 *		int n_location, const float *p_value, int n_count = 1)
	 *		- set float vec2 uniform to value of first two elements in p_value array
	 *		- n_param_type is safe-check only, it should be shader_param_Uniform
	 *		- n_location is destination register index
	 *		- n_count is number of parameters to set
	 *		- returns true on success, false on failure
	 */
	virtual bool SetParam2fv(CGLState *p_state, int n_param_type, int n_location,
		const float *p_value, int n_count = 1);

	/*
	 *	virtual bool CGL_Core_shader::SetParam3fv(CGLState *p_state, int n_param_type,
	 *		int n_location, const float *p_value, int n_count = 1)
	 *		- set float vec3 uniform to value of first three element in p_value array
	 *		- n_param_type is safe-check only, it should be shader_param_Uniform
	 *		- n_location is destination register index
	 *		- n_count is number of parameters to set
	 *		- returns true on success, false on failure
	 */
	virtual bool SetParam3fv(CGLState *p_state, int n_param_type, int n_location,
		const float *p_value, int n_count = 1);

	/*
	 *	virtual bool CGL_Core_shader::SetParam4fv(CGLState *p_state, int n_param_type,
	 *		int n_location, const float *p_value, int n_count = 1) const
	 *		- set float vec4 uniform to value of first three element in p_value array
	 *		- n_param_type is safe-check only, it should be shader_param_Uniform
	 *		- n_location is destination register index
	 *		- n_count is number of parameters to set
	 *		- returns true on success, false on failure
	 */
	virtual bool SetParam4fv(CGLState *p_state, int n_param_type, int n_location,
		const float *p_value, int n_count = 1) const;

	/*
	 *	virtual bool CGL_Core_shader::SetParam1i(CGLState *p_state, int n_location, int n_value)
	 *		- set integer uniform (sampler) to n_value
	 *		- n_location is destination register index
	 *		- returns true on success, false on failure
	 */
	virtual bool SetParam1i(CGLState *p_state, int n_location, int n_value);

	/*
	 *	virtual bool CGL_Core_shader::SetParam1iv(CGLState *p_state, int n_location,
	 *		const int *p_value, int n_count = 1)
	 *		- set integer uniform to n_value of first two elements in p_value
	 *		- n_location is destination register index
	 *		- n_count is number of parameters to set
	 *		- returns true on success, false on failure
	 */
	virtual bool SetParam1iv(CGLState *p_state, int n_location,
		const int *p_value, int n_count = 1);

	/*
	 *	virtual bool CGL_Core_shader::SetParam2iv(CGLState *p_state, int n_location,
	 *		const int *p_value, int n_count = 1)
	 *		- set integer vec2 uniform to n_value of first two elements in p_value
	 *		- n_location is destination register index
	 *		- n_count is number of parameters to set
	 *		- returns true on success, false on failure
	 */
	virtual bool SetParam2iv(CGLState *p_state, int n_location,
		const int *p_value, int n_count = 1);

	/*
	 *	virtual bool CGL_Core_shader::SetParam3iv(CGLState *p_state, int n_location,
	 *		const int *p_value, int n_count = 1)
	 *		- set integer vec3 uniform to n_value of first three elements in p_value
	 *		- n_location is destination register index
	 *		- n_count is number of parameters to set
	 *		- returns true on success, false on failure
	 */
	virtual bool SetParam3iv(CGLState *p_state, int n_location,
		const int *p_value, int n_count = 1);

	/*
	 *	virtual bool CGL_Core_shader::SetParam4iv(CGLState *p_state, int n_location,
	 *		const int *p_value, int n_count = 1)
	 *		- set integer vec4 uniform to n_value of first four elements in p_value
	 *		- n_location is destination register index
	 *		- n_count is number of parameters to set
	 *		- returns true on success, false on failure
	 */
	virtual bool SetParam4iv(CGLState *p_state, int n_location,
		const int *p_value, int n_count = 1);

	/*
	 *	virtual bool CGL_Core_shader::SetParam1uiv(CGLState *p_state, int n_location,
	 *		const unsigned int *p_value, int n_count = 1)
	 *		- set unsigned integer uniform to n_value of first two elements in p_value
	 *		- n_location is destination register index
	 *		- n_count is number of parameters to set
	 *		- returns true on success, false on failure
	 */
	virtual bool SetParam1uiv(CGLState *p_state, int n_location,
		const unsigned int *p_value, int n_count = 1);

	/*
	 *	virtual bool CGL_Core_shader::SetParam2uiv(CGLState *p_state, int n_location,
	 *		const unsigned int *p_value, int n_count = 1)
	 *		- set unsigned integer vec2 uniform to n_value of first two elements in p_value
	 *		- n_location is destination register index
	 *		- n_count is number of parameters to set
	 *		- returns true on success, false on failure
	 */
	virtual bool SetParam2uiv(CGLState *p_state, int n_location,
		const unsigned int *p_value, int n_count = 1);

	/*
	 *	virtual bool CGL_Core_shader::SetParam3uiv(CGLState *p_state, int n_location,
	 *		const unsigned int *p_value, int n_count = 1)
	 *		- set unsigned integer vec3 uniform to n_value of first three elements in p_value
	 *		- n_location is destination register index
	 *		- n_count is number of parameters to set
	 *		- returns true on success, false on failure
	 */
	virtual bool SetParam3uiv(CGLState *p_state, int n_location,
		const unsigned int *p_value, int n_count = 1);

	/*
	 *	virtual bool CGL_Core_shader::SetParam4uiv(CGLState *p_state, int n_location,
	 *		const unsigned int *p_value, int n_count = 1)
	 *		- set unsigned integer vec4 uniform to n_value of first four elements in p_value
	 *		- n_location is destination register index
	 *		- n_count is number of parameters to set
	 *		- returns true on success, false on failure
	 */
	virtual bool SetParam4uiv(CGLState *p_state, int n_location,
		const unsigned int *p_value, int n_count = 1);

	/*
	 *	virtual bool CGL_Core_shader::SetParamMatrix2fv(CGLState *p_state, int n_location,
	 *		bool b_transpose, const float *p_value, int n_count = 1)
	 *		- set 2x2 float matrix uniform to 2x2 matrix form p_value
	 *		- n_location is destination register index
	 *		- n_count is number of parameters to set
	 *		- returns true on success, false on failure
	 */
	virtual bool SetParamMatrix2fv(CGLState *p_state, int n_location,
		bool b_transpose, const float *p_value, int n_count = 1);

	/*
	 *	virtual bool CGL_Core_shader::SetParamMatrix3fv(CGLState *p_state, int n_location,
	 *		bool b_transpose, const float *p_value, int n_count = 1)
	 *		- set 3x3 float matrix uniform to 3x3 matrix form p_value
	 *		- n_location is destination register index
	 *		- n_count is number of parameters to set
	 *		- returns true on success, false on failure
	 */
	virtual bool SetParamMatrix3fv(CGLState *p_state, int n_location,
		bool b_transpose, const float *p_value, int n_count = 1);

	/*
	 *	virtual bool CGL_Core_shader::SetParamMatrix4fv(CGLState *p_state, int n_location,
	 *		bool b_transpose, const float *p_value, int n_count = 1)
	 *		- set 4x4 float matrix uniform to 4x4 matrix form p_value
	 *		- n_location is destination register index
	 *		- n_count is number of parameters to set
	 *		- returns true on success, false on failure
	 */
	virtual bool SetParamMatrix4fv(CGLState *p_state, int n_location,
		bool b_transpose, const float *p_value, int n_count = 1);

	/*
	 *	virtual bool CGL_Core_shader::SetParamMatrix2x4fv(CGLState *p_state, int n_location,
	 *		bool b_transpose, const float *p_value, int n_count = 1)
	 *		- set 2x4 float matrix uniform to 2x4 matrix form p_value
	 *		- note this is OpenGL 2.1 function
	 *		- n_location is destination register index
	 *		- n_count is number of parameters to set
	 *		- returns true on success, false on failure
	 */
	virtual bool SetParamMatrix2x4fv(CGLState *p_state, int n_location,
		bool b_transpose, const float *p_value, int n_count = 1);

	/*
	 *	virtual bool CGL_Core_shader::SetParamMatrix4x2fv(CGLState *p_state, int n_location,
	 *		bool b_transpose, const float *p_value, int n_count = 1)
	 *		- set 4x2 float matrix uniform to 4x2 matrix form p_value
	 *		- note this is OpenGL 2.1 function
	 *		- n_location is destination register index
	 *		- n_count is number of parameters to set
	 *		- returns true on success, false on failure
	 */
	virtual bool SetParamMatrix4x2fv(CGLState *p_state, int n_location,
		bool b_transpose, const float *p_value, int n_count = 1);

	/*
	 *	virtual bool CGL_Core_shader::SetParamMatrix2x3fv(CGLState *p_state, int n_location,
	 *		bool b_transpose, const float *p_value, int n_count = 1)
	 *		- set 2x3 float matrix uniform to 2x3 matrix form p_value
	 *		- note this is OpenGL 2.1 function
	 *		- n_location is destination register index
	 *		- n_count is number of parameters to set
	 *		- returns true on success, false on failure
	 */
	virtual bool SetParamMatrix2x3fv(CGLState *p_state, int n_location,
		bool b_transpose, const float *p_value, int n_count = 1);

	/*
	 *	virtual bool CGL_Core_shader::SetParamMatrix3x2fv(CGLState *p_state, int n_location,
	 *		bool b_transpose, const float *p_value, int n_count = 1)
	 *		- set 3x2 float matrix uniform to 3x2 matrix form p_value
	 *		- note this is OpenGL 2.1 function
	 *		- n_location is destination register index
	 *		- n_count is number of parameters to set
	 *		- returns true on success, false on failure
	 */
	virtual bool SetParamMatrix3x2fv(CGLState *p_state, int n_location,
		bool b_transpose, const float *p_value, int n_count = 1);

	/*
	 *	virtual bool CGL_Core_shader::SetParamMatrix3x4fv(CGLState *p_state, int n_location,
	 *		bool b_transpose, const float *p_value, int n_count = 1)
	 *		- set 3x4 float matrix uniform to 3x4 matrix form p_value
	 *		- note this is OpenGL 2.1 function
	 *		- n_location is destination register index
	 *		- n_count is number of parameters to set
	 *		- returns true on success, false on failure
	 */
	virtual bool SetParamMatrix3x4fv(CGLState *p_state, int n_location,
		bool b_transpose, const float *p_value, int n_count = 1);

	/*
	 *	virtual bool CGL_Core_shader::SetParamMatrix4x3fv(CGLState *p_state, int n_location,
	 *		bool b_transpose, const float *p_value, int n_count = 1)
	 *		- set 4x3 float matrix uniform to 4x3 matrix form p_value
	 *		- note this is OpenGL 2.1 function
	 *		- n_location is destination register index
	 *		- n_count is number of parameters to set
	 *		- returns true on success, false on failure
	 */
	virtual bool SetParamMatrix4x3fv(CGLState *p_state, int n_location,
		bool b_transpose, const float *p_value, int n_count = 1);

	/*
	 *	virtual void CGL_Core_shader::Bind(CGLState *p_state) const
	 *		- binds shader
	 */
	virtual void Bind(CGLState *p_state) const;

	/*
	 *	virtual void CGL_Core_shader::Release(CGLState *p_state) const
	 *		- un-binds shader
	 *		- use for safe switching between shaders with different api-s
	 */
	virtual void Release(CGLState *p_state) const;

	/*
	 *	virtual void CGL_Core_shader::Delete()
	 *		- free open-gl resources
	 *		- if program is about to be used again, it must be re-compiled,
	 *		  re-bound vertex attribs, re-linked and re-queried for unifroms
	 */
	virtual void Delete();

	/*
	 *	virtual int CGL_Core_shader::n_Api() const
	 *		- return which api is used (shader_api_Core_shader)
	 */
	virtual int n_Api() const;

	inline void _Bind(CGLState *p_state) const;
	inline void _Release(CGLState *p_state) const;

	// the following functions  doesn't do any parameter checking, they do assume shader is bound
	inline void _SetParam1fv(int n_location, int n_count, const float *p_value) const;
	inline void _SetParam2fv(int n_location, int n_count, const float *p_value) const;
	inline void _SetParam3fv(int n_location, int n_count, const float *p_value) const;
	inline void _SetParam4fv(int n_location, int n_count, const float *p_value) const;
	inline void _SetParam1i(int n_location, int n_value) const;
	inline void _SetParam1iv(int n_location, int n_count, const int *p_value) const;
	inline void _SetParam2iv(int n_location, int n_count, const int *p_value) const;
	inline void _SetParam3iv(int n_location, int n_count, const int *p_value) const;
	inline void _SetParam4iv(int n_location, int n_count, const int *p_value) const;
	inline void _SetParamMatrix2fv(int n_location,
		int n_count, bool b_transpose, const float *p_value) const;
	inline void _SetParamMatrix3fv(int n_location,
		int n_count, bool b_transpose, const float *p_value) const;
	inline void _SetParamMatrix4fv(int n_location,
		int n_count, bool b_transpose, const float *p_value) const;

	// OpenGL 2.1
	inline void _SetParamMatrix2x3fv(int n_location,
		int n_count, bool b_transpose, const float *p_value) const;
	inline void _SetParamMatrix3x2fv(int n_location,
		int n_count, bool b_transpose, const float *p_value) const;
	inline void _SetParamMatrix2x4fv(int n_location,
		int n_count, bool b_transpose, const float *p_value) const;
	inline void _SetParamMatrix4x2fv(int n_location,
		int n_count, bool b_transpose, const float *p_value) const;
	inline void _SetParamMatrix3x4fv(int n_location,
		int n_count, bool b_transpose, const float *p_value) const;
	inline void _SetParamMatrix4x3fv(int n_location,
		int n_count, bool b_transpose, const float *p_value) const;

	// GL_EXT_gpu_shader4
	inline void _SetParam1uiv(int n_location, int n_count, const unsigned int *p_value) const;
	inline void _SetParam2uiv(int n_location, int n_count, const unsigned int *p_value) const;
	inline void _SetParam3uiv(int n_location, int n_count, const unsigned int *p_value) const;
	inline void _SetParam4uiv(int n_location, int n_count, const unsigned int *p_value) const;
};

#include "Shader2.inl"
// fast inline functions

#endif // !__GL_SHADER2_INCLUDED
