#ifndef _C4D_GL_H_
#define _C4D_GL_H_


#ifndef __API_INTERN__
#include "c4d_basedocument.h"
#include "ge_matrix.h"
#include "matrix4.h"
#endif // __API_INTERN__

#ifndef C4D_GL_VARS_DEFINED
#if defined __PC
typedef	UINT C4DGLuint;
typedef INT C4DGLint;
#elif defined __MAC
typedef	ULONG C4DGLuint;
typedef LONG C4DGLint;
#elif defined __LINUX
typedef	UINT C4DGLuint;
typedef INT C4DGLint;
#endif
typedef VLONG GlProgramParameter;
#define C4D_GL_VARS_DEFINED
#endif

// use as program parameters (while processing the GL_GET_IDENTITY message)
#define GL_PROGRAM_PARAM_OBJECTCOORD			0x00000001
#define GL_PROGRAM_PARAM_WORLDCOORD				0x00000002
#define GL_PROGRAM_PARAM_NORMALS					0x00000004
#define GL_PROGRAM_PARAM_DUDV							0x00000008 // TEXCOORD1, TEXCOORD2, you must also set GL_PROGRAM_PARAM_NORMALS
#define GL_PROGRAM_PARAM_UV								0x00000010 // TEXCOORD3 + n
#define GL_PROGRAM_PARAM_UVW							0x00000030 // implies UV
#define GL_PROGRAM_PARAM_COLOR						0x00000040
#define GL_PROGRAM_USE_NORMALIZE_CUBMAP		0x00000080
#define GL_PROGRAM_PARAM_EYEPOSITION			0x00000400
#define GL_PROGRAM_PARAM_POLYNORMALS			0x00000800
#define GL_PROGRAM_PARAM_POLYNORMALS_FP		0x00001800 // implies polynormals
#define GL_PROGRAM_PARAM_EYEDIRECTION			0x00002000
#define GL_PROGRAM_PARAM_VP_ATTRIB0				0x00010000 // TEXCOORD0 (cannot be set by a shader or material)
#define GL_PROGRAM_PARAM_UVW4_FP					0x00100000 // pass 4-component UVW coordinates to the fragment program
#define GL_PROGRAM_PARAM_OBJECTMATRIX_FP	0x00200000 // pass object matrix to the fragment program, you must set GL_PROGRAM_PARAM_NORMALS, too
#define GL_PROGRAM_PARAM_DISPLACE					0x00400000 // execute GL_PASS_DISPLACE pass, you must set GL_PROGRAM_PARAM_DUDV, too
#define GL_PROGRAM_PARAM_CHANGE_NORMAL		0x00800000 // execute GL_PASS_BEFORE_LIGHT pass
#define GL_PROGRAM_PARAM_AFTER_LIGHT			0x01000000 // execute GL_PASS_AFTER_LIGHT pass
#define GL_PROGRAM_PARAM_UVW_VERTEX				0x02000000 // calculate correct UVW coordinates in the vertex program
#define GL_PROGRAM_PARAM_FRAGMENT_COORD		0x04000000 // make fragment coordinates available in the fragment shader
#define GL_PROGRAM_PARAM_NOISE						0x08000000 // the fragment program needs a noise function

// use for AddParameters (format)
#define GL_FORMAT_NORMAL_FLOAT					0x00000001 // request normal vector as float values
#define GL_FORMAT_UV_FLOAT							0x00000002 // request UV(W) coordinates as float values
#define GL_FORMAT_DUDV_FLOAT						0x00000004 // request DU and DV vectors as float values
#define GL_FORMAT_COLOR_FLOAT						0x00000008 // request color (RGBA) as float values 

// GetFlags
#define GL_PROGRAM_FACTORY_STATUS_OK							0x00000001 // program compiled and linked successfully and runs in hardware
#define GL_PROGRAM_FACTORY_STATUS_PARAM_UNIFORM_V	0x00000002 // too many uniform parameters in the vertex program
#define GL_PROGRAM_FACTORY_STATUS_PARAM_UNIFORM_F	0x00000004 // too many uniform parameters in the fragment program
#define GL_PROGRAM_FACTORY_STATUS_PARAM_TEXTURE_V	0x00000008 // too many textures used in the vertex program
#define GL_PROGRAM_FACTORY_STATUS_PARAM_TEXTURE_F	0x00000010 // too many textures used in the fragment program
#define GL_PROGRAM_FACTORY_STATUS_COMPILE_ERR_V		0x00000020 // vertex program compilation error
#define GL_PROGRAM_FACTORY_STATUS_COMPILE_ERR_F		0x00000040 // vertex program compilation error

// messages
#define GL_GET_IDENTITY									450000200
#define GL_ADD_UNIFORM_PRARAMETERS			450000201
#define GL_ADD_PROGRAM_CODE							450000202
#define GL_INIT_DESCRIPTION							450000203
#define GL_SET_UNIFORM_PARAMETERS				450000204

// framebuffer flags
#define C4D_FRAMEBUFFER_COLOR				1
#define C4D_FRAMEBUFFER_DEPTH				2
#define C4D_FRAMEBUFFER_ALPHA				4
#define C4D_FRAMEBUFFER_SCALEUP			256
#define C4D_FRAMEBUFFER_SCALEDOWN		512
#define C4D_FRAMEBUFFER_ALLOW_NPOT	1024

// noise types
#define GL_NOISE_SNOISE_1D							-1 // SNoise1D(float pos)
#define GL_NOISE_SNOISE_2D							-2 // SNoise2D(vec2 pos)
#define GL_NOISE_SNOISE_3D							-3 // SNoise3D(vec3 pos)
#define GL_NOISE_SNOISE_4D							-4 // SNoise4D(vec4 pos, float repeat)
#define GL_NOISE_TURBULENCE_3D					-8
#define GL_NOISE_TURBULENCE_4D					-9 // Turbulence4D(vec4 pos, float octaves, float repeat)
#define GL_NOISE_FBM_3D									-12 // 
#define GL_NOISE_FBM_4D									-13 // Fbm4D(vec4 pos, float octaves, float repeat)
#define GL_NOISE_RIDGEDMULTIFRACTAL_3D	-14 // RidgedMultifractal3D(vec3 pos, float octaves, float offset, float gain)
#define GL_NOISE_RIDGEDMULTIFRACTAL_4D	-15 // RidgedMultifractal4D(vec4 pos, float octaves, float offset, float gain, float repeat)
// allowed noises from lib_noise.h:
//NOISE_BOX_NOISE NoiseBoxNoise(vec4 pos, float repeat)
//NOISE_BLIST_TURB NoiseBisteredTurb(vec4 pos, float octaves, float repeat)
//NOISE_BUYA NoiseBuya(vec4 pos, float octaves, float repeat)
//NOISE_CELL_NOISE NoiseCellNoise(vec4 pos, float repeat)
//NOISE_CRANAL NoiseCranal(vec4 pos, float octaves, float repeat)
//NOISE_DENTS NoiseDents(vec4 pos, float octaves, float repeat)
//NOISE_DISPL_TURB NoiseDisplTurbulence(vec4 pos, float octaves, float repeat)
//NOISE_FBM NoiseFbm(vec4 pos, float octaves, float repeat)
//NOISE_HAMA NoiseHama(vec4 pos, float octaves, float repeat)
//NOISE_LUKA NoiseLuka(vec4 pos, float octaves, float repeat)
//NOISE_MOD_NOISE NoiseModNoise(vec4 pos, float repeat)
//NOISE_NAKI NoiseNaki(vec4 pos, float octaves, float repeat)
//NOISE_NOISE NoiseNoise(vec4 pos, float repeat)
//NOISE_NUTOUS NoiseNutous(vec4 pos, float octaves, float repeat)
//NOISE_OBER NoiseOber(vec4 pos, float octaves, float repeat)
//NOISE_PEZO NoisePezo(vec4 pos, float octaves, float repeat)
//NOISE_POXO NoisePoxo(vec4 pos, float octaves, float repeat)
//NOISE_RANDOM NoiseRandom(float pos)
//NOISE_SEMA NoiseSema(vec4 pos, float octaves, float repeat)
//NOISE_STUPL NoiseStupl(vec4 pos, float octaves, float repeat)
//NOISE_TURBULENCE NoiseTurbulence(vec4 pos, float octaves, float repeat)
//NOISE_VL_NOISE NoiseVlNoise(vec4 pos, float repeat)
//NOISE_WAVY_TURB NoiseWavyTurbulence(vec4 pos, float octaves, float repeat)
//NOISE_FIRE NoiseFire(vec4 pos, float octaves, float repeat)
//NOISE_ELECTRIC NoiseElectric(vec4 pos, float repeat)
//NOISE_GASEOUS NoiseGaseous(vec4 pos, float repeat)
//NOISE_ZADA NoiseZada(vec4 pos, float octaves, float repeat)

// return values for GlMessage
#define GL_MESSAGE_OK								1
#define GL_MESSAGE_ERROR						0
#define GL_MESSAGE_FORCE_EMULATION	2

class GlProgramFactory;
class GlString;

#define LightHasAspect(_type_) (_type_ == RT_LT_SPOT || _type_ == RT_LT_SPOTRECT || _type_ ==	RT_LT_PARSPOT || _type_ == RT_LT_PARSPOTRECT)
#define LightHasEdgeFalloff(_type_) (_type_ == RT_LT_SPOT || _type_ == RT_LT_SPOTRECT || _type_ ==	RT_LT_PARSPOT || _type_ == RT_LT_PARSPOTRECT)
#define LightHasFalloff(_f_) ((_f_) == RT_FALLOFF_STEP || (_f_) == RT_FALLOFF_LINEAR || (_f_) == RT_FALLOFF_INVERSE || \
															(_f_) == RT_FALLOFF_INVERSE_CLAMPED || (_f_) == RT_FALLOFF_SQUARE || (_f_) == RT_FALLOFF_SQUARE_CLAMPED || (_f_) == 2 || (_f_) == 3)
#define GlShaderAddCodeBump(_pass_, _channel_) ((_channel_) == CHANNEL_BUMP && (_pass_) == GL_PASS_BEFORE_LIGHT)
#define GlShaderAddCodeColor(_pass_, _channel_) ( \
																								((_pass_) == GL_PASS_BEFORE_LIGHT && (((_channel_) == CHANNEL_NORMAL) || ((_channel_) == CHANNEL_DIFFUSION))) || \
																								((_pass_) == GL_PASS_LIGHT && ((_channel_) == CHANNEL_COLOR)) || \
																								((_pass_) == GL_PASS_AFTER_LIGHT && (((_channel_) == CHANNEL_ENVIRONMENT) || ((_channel_) == CHANNEL_LUMINANCE)))  \
																								)
#define GlShaderAddCodeTransp(_pass_, _channel_) ((_channel_) == CHANNEL_TRANSPARENCY && (_pass_) == GL_PASS_AFTER_LIGHT)
#define GlShaderAddCodeAlpha(_pass_, _channel_) ((_channel_) == CHANNEL_ALPHA && (_pass_) == GL_PASS_AFTER_LIGHT)
#define GlShaderAddCodeDisplace(_pass_, _channel_) ((_channel_) == CHANNEL_DISPLACEMENT && (_pass_) == GL_PASS_DISPLACE)

// vertex buffer defines
// keep this order in your data structure for maximal performance
#define C4D_VERTEX_BUFFER_VERTEX				0
#define C4D_VERTEX_BUFFER_NORMAL				2 // has always 3 elements
#define C4D_VERTEX_BUFFER_COLOR				3
#define C4D_VERTEX_BUFFER_POLYNORMAL	4
//#define C4D_VERTEX_BUFFER_FOG_COORD		5
#define C4D_VERTEX_BUFFER_TEX_COORD_0	8
#define C4D_VERTEX_BUFFER_TEX_COORD_1	9
#define C4D_VERTEX_BUFFER_TEX_COORD_2	10
#define C4D_VERTEX_BUFFER_TEX_COORD_3	11
#define C4D_VERTEX_BUFFER_TEX_COORD_4	12
#define C4D_VERTEX_BUFFER_TEX_COORD_5	13
#define C4D_VERTEX_BUFFER_TEX_COORD_6	14
#define C4D_VERTEX_BUFFER_TEX_COORD_7	15

#define C4D_VERTEX_BUFFER_TRIANGLES				0
#define C4D_VERTEX_BUFFER_QUADS						1
#define C4D_VERTEX_BUFFER_TRIANGLES_WIRE	2
#define C4D_VERTEX_BUFFER_QUADS_WIRE			3
#define C4D_VERTEX_BUFFER_TRIANGLE_FAN		4

#define C4D_VERTEXBUFFER_MAX_DATACOUNT			16

// the same like the OpenGL types
#define C4D_VERTEX_BUFFER_BYTE                0x1400
#define C4D_VERTEX_BUFFER_UNSIGNED_BYTE       0x1401
#define C4D_VERTEX_BUFFER_SHORT               0x1402
#define C4D_VERTEX_BUFFER_UNSIGNED_SHORT      0x1403
#define C4D_VERTEX_BUFFER_INT                 0x1404
#define C4D_VERTEX_BUFFER_UNSIGNED_INT        0x1405
#define C4D_VERTEX_BUFFER_FLOAT               0x1406
#define C4D_VERTEX_BUFFER_2_BYTES             0x1407
#define C4D_VERTEX_BUFFER_3_BYTES             0x1408
#define C4D_VERTEX_BUFFER_4_BYTES             0x1409
#define C4D_VERTEX_BUFFER_DOUBLE              0x140A

#define C4D_VERTEX_BUFFER_FORCE_DELETE				0x00000001
#define C4D_VERTEX_BUFFER_GET_ANY							0x00000002

class Gradient;
class UVWTag;

struct GlLight
{
	VLONG lSize;

	// affect Cg program
	LONG lType;
	Bool bUseAspectRatio;
	Bool bUseInner;
	Bool bHasShadows; // only assign TRUE or FALSE here
	Bool bSpecular, bDiffuse, bUseShadowColor;
	Gradient* pEdgeFalloff;
	BaseObject* pLight; // must be a valid light source if pEdgeFalloff != NULL
	LONG lFalloff;

	// state variables
	Vector vColor, vShadowColor;
	Matrix mg;
	Real rInnerCos, rOuterCos;
	Real rInnerSin, rOuterSin;
	Real rInnerSize, rOuterSize;
	Real rAspect;
	Real rShadowIntensity;
	UINT nShadowTextures[6];
	Matrix4 mLightProjections[6];
	Vector4 vInvCoeffs[6];
	Real rContrast; // must be Exp(-contrast)
	Real rGradientMultiplier;
	Real rFalloff[4]; // inner dist, outer dist, normed dist, energy level
};

struct GlGetIdentity
{
	BaseDocument* pDoc;
	BaseDraw* pBaseDraw;
	void* pData;
	VLONG lDataSize, lMaxDataSize;
	ULONG ulParameters;
	LONG lChannel;
	Bool bDontShade;
	Bool bXRay;
	Bool bTintedSelection;
	Bool bImageAlpha; // only valid if the shader is in the alpha channel
	BaseMaterial* pMaterial;
	BaseObject* pObj;
	TextureTag* pTextureTag;
	Bool bTile, bSeamless, bObjHandle;
	Bool bAnimatePreview;
	UVWTag* pUVWTag;
	LONG lPreviewSize;
};

#ifndef __OPERATINGSYSTEM_H

enum GlProgramType { VertexProgram = 1, FragmentProgram = 2, CompiledProgram = 3 };
enum GlUniformParamType { UniformFloat1 = 0, UniformFloat2 = 1, UniformFloat3 = 2, UniformFloat4 = 3, 
			UniformFloatMatrix2 = 4, UniformFloatMatrix3 = 5, UniformFloatMatrix4 = 6, 
			UniformTexture1D = 7, UniformTexture2D = 8, UniformTexture3D = 9, UniformTextureCube = 10 };

typedef void* (*GlProgramFactoryAllocPrivate)();
typedef void (*GlProgramFactoryFreePrivate)(void* pData);
typedef void* (*GlProgramFactoryAllocDescription)();
typedef void (*GlProgramFactoryFreeDescription)(void* pData);
typedef void (*GlProgramFactoryCreateFnCallback)(const Real* prIn, Real* prOut, void* pData);
typedef LONG (*GlProgramFactoryErrorHandler)(GlProgramType type, const char* pszError);
typedef void (*GlVertexBufferDrawFanCallback)(LONG nFan, void* pData);

#endif

#ifndef __API_INTERN__

class GlString
{
private:
#ifndef __C4D_64BIT
	char priv[24];
#else
	char priv[48];
#endif

public:
	GlString();
	GlString(const char* pszString);
	GlString(const GlString& str);
	explicit GlString(LONG n);
	explicit GlString(Real r, const char* pszFormat);
	~GlString();

	const GlString& operator = (const GlString &str);
	const GlString& operator = (const char* pszString);

	friend const GlString operator + (const GlString &str1, const GlString &str2);
	const GlString& operator += (const GlString &str);
	friend const GlString operator + (const GlString &str1, const char* str2);
	const GlString& operator += (const char* str);

	const char* GetCString() const;
	VLONG GetLength() const;
};

#define IncreaseBufferSize(_ident_, _size_) _IncreaseBufferSize(_ident_, _size_, __LINE__, __FILE__)
#define AlignedBufferSize(_size_) ((_size_ + 3) & ~3)

class GlProgramFactory
{
private:
	GlProgramFactory();
	~GlProgramFactory();

public:
	static GlProgramFactory* GetFactory(C4DAtom* pObj, LONG lIndex, BaseDraw* pBaseDraw, GlLight* pLights, LONG lLightCount,
		void* pIdentity, VLONG lIdentityLength, LONG lTexCoordIndex = NOTOK, Bool bAllowSharing = TRUE); // lIndex must be positive
	static void RemoveReference(C4DAtom* pObj, LONG lIndex = NOTOK);
	static void RemoveTextureReference(C4DAtom* pObj, LONG lIndex); // this may not be called in a ::Draw function
	static void* _IncreaseBufferSize(GlGetIdentity* pIdentity, VLONG lNeededSize, LONG lLine, char* pszFile);

	Bool BindToView(BaseDraw* pDraw);
	Bool CompilePrograms();
	Bool BindPrograms();
	Bool UnbindPrograms();
	Bool DestroyPrograms(Bool bChangeContext);
	void LockFactory();
	void Unlock();
	void* GetPrivateData(C4DAtom* pObj, LONG lDataIndex, GlProgramFactoryAllocPrivate fnAlloc = NULL, GlProgramFactoryFreePrivate fnFree = NULL);
	void* GetDescriptionData(LONG lObjIndex, LONG lDataIndex, GlProgramFactoryAllocDescription fnAlloc = NULL, GlProgramFactoryFreeDescription fnFree = NULL);
	Bool IsProgram(GlProgramType t);
	Bool InitLightParameters();
	LONG GetMaxLights();
	Bool AddLightProjection();
	UCHAR* GetIdentity();
	GlProgramParameter GetParameterHandle(GlProgramType t, const char* pszName);

	void InitSetParameters();
	void SetScreenCoordinates(BaseDraw* pBaseDraw);
	void AddErrorHandler(GlProgramFactoryErrorHandler fn);

	// set functions
	Bool SetParameterMatrixState(GlProgramType t, const char* pszName);
	Bool SetParameterMatrix(GlProgramType t, const char* pszName, const Matrix4 &m);
	Bool SetParameterMatrix3x3(GlProgramType t, const char* pszName, const Real* r);
	Bool SetParameterMatrix4x4(GlProgramType t, const char* pszName, const Real* r);
	Bool SetParameterVector(GlProgramType t, const char* pszName, const Vector &v);
	Bool SetParameterVector(GlProgramType t, const char* pszName, const Vector &v, Real w);
	Bool SetParameterReal(GlProgramType t, const char* pszName, const Real r);
	Bool SetParameterReal2(GlProgramType t, const char* pszName, Real a, Real b);
	Bool SetParameterReal2(GlProgramType t, const char* pszName, const Real* v);
	Bool SetParameterReal3(GlProgramType t, const char* pszName, Real a, Real b, Real c);
	Bool SetParameterReal3(GlProgramType t, const char* pszName, const Real* v);
	Bool SetParameterReal4(GlProgramType t, const char* pszName, Real a, Real b, Real c, Real d);
	Bool SetParameterReal4(GlProgramType t, const char* pszName, const Real* v);
	Bool SetParameterRealArray(GlProgramType t, const char* pszName, LONG lElements, const Real *r);
	Bool SetParameterTexture2D(GlProgramType t, const char* pszName, const BaseBitmap* pBmp, Bool bTile, LONG lAlphaMode, C4DGLuint* pnHandle = NULL);
	Bool SetParameterTexture2D(GlProgramType t, const char* pszName, const Filename &fn, LONG lFrame, C4DAtom* pObj, LONG lIndex, Bool bTile, LONG lAlphaMode, Bool bInterpolate, LONG lMaxSize, LayerSetSelection* pLayerSet = NULL, LONG* plWidth = NULL, LONG* plHeight = NULL, LONG* plTextureDepth = NULL, C4DGLuint* pnHandle = NULL);
	Bool SetParameterTexture(GlProgramType t, const char* pszName, LONG lDimension, C4DGLuint nTexture);
	Bool SetParameterGradient(GlProgramType t, const char* pszName, Gradient* pGradient, C4DAtom* pObj, LONG lIndex, C4DGLuint* pnHandle = NULL);
	Bool SetParameterFunctionTexture(GlProgramType t, const char* pszName, C4DAtom* pObj, LONG lIndex, GlProgramFactoryCreateFnCallback fn, void* pData, VLONG lDataLen,
		LONG lInParams, LONG lOutParams, LONG lCycle, Bool bInterpolate, LONG lSizeX, LONG lSizeY, LONG lSizeZ, Bool bParallel, C4DGLuint* pnHandle = NULL);
	// when the parameter handle is known
	Bool SetParameterMatrixState(GlProgramParameter param);
	Bool SetParameterMatrix(GlProgramParameter param, const Matrix4 &m);
	Bool SetParameterMatrix3x3(GlProgramParameter param, const Real* r);
	Bool SetParameterMatrix4x4(GlProgramParameter param, const Real* r);
	Bool SetParameterVector(GlProgramParameter param, const Vector &v);
	Bool SetParameterVector(GlProgramParameter param, const Vector &v, Real w);
	Bool SetParameterReal(GlProgramParameter param, const Real r);
	Bool SetParameterReal2(GlProgramParameter param, Real a, Real b);
	Bool SetParameterReal2(GlProgramParameter param, const Real* v);
	Bool SetParameterReal3(GlProgramParameter param, Real a, Real b, Real c);
	Bool SetParameterReal3(GlProgramParameter param, const Real* v);
	Bool SetParameterReal4(GlProgramParameter param, Real a, Real b, Real c, Real d);
	Bool SetParameterReal4(GlProgramParameter param, const Real* v);
	Bool SetParameterRealArray(GlProgramParameter param, LONG lElements, const Real *r);
	Bool SetParameterTexture2D(GlProgramParameter param, const BaseBitmap* pBmp, Bool bTile, LONG lAlphaMode, C4DGLuint* pnHandle = NULL);
	Bool SetParameterTexture2D(GlProgramParameter param, const Filename &fn, LONG lFrame, C4DAtom* pObj, LONG lIndex, Bool bTile, LONG lAlphaMode, Bool bInterpolate, LONG lMaxSize, LayerSetSelection* pLayerSet = NULL, LONG* plWidth = NULL, LONG* plHeight = NULL, LONG* plTextureDepth = NULL, C4DGLuint* pnHandle = NULL);
	Bool SetParameterTexture2D(GlProgramParameter param, BaseBitmap* pBmp, ULONG ulDirty, C4DAtom* pObj, LONG lIndex, Bool bTile, LONG lAlphaMode, Bool bInterpolate, LONG lMaxSize, LONG* plWidth = NULL, LONG* plHeight = NULL, LONG* plTextureDepth = NULL, C4DGLuint* pnHandle = NULL);
	Bool SetParameterTexture(GlProgramParameter param, LONG lDimension, C4DGLuint nTexture);
	Bool SetParameterGradient(GlProgramParameter param, Gradient* pGradient, C4DAtom* pObj, LONG lIndex, C4DGLuint* pnHandle = NULL);
	Bool SetParameterFunctionTexture(GlProgramParameter param, C4DAtom* pObj, LONG lIndex, GlProgramFactoryCreateFnCallback fn, void* pData, VLONG lDataLen,
		LONG lInParams, LONG lOutParams, LONG lCycle, Bool bInterpolate, LONG lSizeX, LONG lSizeY, LONG lSizeZ, Bool bParallel, C4DGLuint* pnHandle = NULL);
	static Bool CacheTextureFn(BaseDraw* pBaseDraw, const Filename &fn, LONG lFrame, C4DAtom* pObj, LONG lIndex, Bool bTile, LONG lAlphaMode, Bool bInterpolate, LONG lMaxSize, GlProgramType progType, LayerSetSelection* pLayerSet = NULL, LONG* plWidth = NULL, LONG* plHeight = NULL, LONG* plTextureDepth = NULL, C4DGLuint* pnHandle = NULL);
	static Bool CacheTextureBmp(BaseDraw* pBaseDraw, BaseBitmap* pBmp, ULONG ulDirty, C4DAtom* pObj, LONG lIndex, Bool bTile, LONG lAlphaMode, Bool bInterpolate, LONG lMaxSize, GlProgramType progType, LONG* plWidth = NULL, LONG* plHeight = NULL, LONG* plTextureDepth = NULL, C4DGLuint* pnHandle = NULL);
	
	Bool SetLightParameters(GlLight* pLights, LONG lLightCount, const Matrix4 &mObject);

	ULONG Init();
	void AddParameters(ULONG ulParameters, ULONG ulFormat = 0);
	ULONG GetParameters();
	ULONG GetParameterFormats();
	GlString AddUniformParameter(GlProgramType t, GlUniformParamType p, const char* pszName);
	GlString AddUniformParameter(GlProgramType t, GlUniformParamType p, LONG lCount, const char* pszName);
	Bool HeaderFinished();
	void AddLine(GlProgramType t, const GlString &strLine);
	Bool AddEncryptedBlock(GlProgramType t, const char* pchData, VLONG lDataLength, const UCHAR* pchKey, LONG lKeyLength);
	GlString AddColorBlendFunction(GlProgramType t, LONG lBlendMode);
	GlString AddRGBToHSVFunction(GlProgramType t);
	GlString AddHSVToRGBFunction(GlProgramType t);
	GlString AddRGBToHLSFunction(GlProgramType t);
	GlString AddHLSToRGBFunction(GlProgramType t);
	void StartLightLoop();
	Bool EndLightLoop();
	GlString GetUniqueID();
	static Bool HasNoiseSupport(GlProgramType t, LONG lNoise);
	const GlString& AddNoiseFunction(GlProgramType t, LONG lNoise, Bool bAbsolute);
};

class GlFrameBuffer
{
private:
	GlFrameBuffer();
	~GlFrameBuffer();

public:
	static GlFrameBuffer* GetFrameBuffer(BaseDraw* pBaseDraw, VULONG lID1, LONG lID2, UINT nWidth, UINT nHeight, LONG lColorTextureCount, 
		LONG lDepthTextureCount, LONG lFlags);

	static void RemoveObject(VULONG lID1, LONG lID2);

	void PrepareForRendering(LONG lTexture = NOTOK);
	void SetInterpolation(LONG lInterpolate, LONG lTexture = NOTOK);
	Bool Activate(BaseDraw* pBaseDraw);
	void Deactivate(BaseDraw* pBaseDraw);
	Bool SetRenderTarget(LONG lTexture, LONG lFlags); // lFlags may be C4D_FRAMEBUFFER_COLOR or C4D_FRAMEBUFFER_DEPTH
	void GetRatios(Real& rWidth, Real& rHeight);
	void GetSize(UINT &nWidth, UINT &nHeight, Bool bFramesize);

	C4DGLuint GetTexture(LONG lTexture, LONG lFlags);
	LONG SaveTextureToDisk(const Filename &fn, LONG lTexture, LONG lFlags); // mainly for debugging purposes, the texture is saved as a .tif image
	Bool CopyToBitmap(BaseBitmap* pBmp, LONG lTexture, LONG lFlags);
	void Clear();
	void Clear(const Vector &vColor, Real rAlpha);
	Bool IsNPOTBuffer();
	Bool DrawBuffer(LONG lTexture, LONG lFlags, Real rAlpha = 1.0f, const Vector &vColor = Vector(1.0f));
};

class GlVertexBuffer
{
private:
	GlVertexBuffer();
	~GlVertexBuffer();

public:
	static GlVertexBuffer* GetVertexBuffer(BaseDraw* pBaseDraw, C4DAtom* pObj, LONG lIndex, void* pIdentity, VLONG lIdentityLen, LONG lFlags = 0);
	static void RemoveObject(C4DAtom* pObj, LONG lIndex);
	static VLONG GetDefaultSize();
	static void SetDefaultSize(VLONG lSize);

	VLONG GetBufferSize();
	void SetSubBufferSize(VLONG lSize);

	Bool SetDataOffset(LONG lElement, LONG lID, LONG lDataFormat, LONG lCount, VLONG lOffset, VLONG lStride);
	void ResetDataOffsets();
	Bool IsDirty();
	void SetDirty(Bool bDirty = TRUE);
	Bool Draw(BaseDraw* pBaseDraw, LONG lID1 = NOTOK, VLONG lID2 = NOTOK, const Vector* pvColor = NULL, Real* prAlpha = NULL);
	Bool DrawSubBuffer(BaseDraw* pBaseDraw, LONG lID1, VLONG lID2, LONG lMode, LONG lIndex, LONG lFirst, LONG lCount, 
		BaseSelect* pDrawElements, const Vector* pvColor = NULL, Real* prAlpha = NULL);
	Bool DrawSubBufferFan(BaseDraw* pBaseDraw, LONG lID1, VLONG lID2, LONG lMode, LONG lIndex, LONG lStripCount, 
		LONG lFirst, LONG *plCount, const Vector* pvColor = NULL, Real* prAlpha = NULL, GlVertexBufferDrawFanCallback fn = NULL, void* pCallbackData = NULL, 
		Bool bReverse = FALSE);
	Bool AllocSubBuffers(LONG lID1, VLONG lID2, LONG lElementCount, VLONG lElementSize, LONG &lCount, VLONG &lBufferElementCount);
	Bool AllocSubBuffersFan(LONG lID1, VLONG lID2, LONG lPolyCount, LONG* plCount, VLONG lElementSize, LONG &lCount, VLONG &lBufferElementCount);
	VLONG GetSubBufferElementCount(LONG lID1, VLONG lID2);
	LONG GetSubBufferCount(LONG lID1, VLONG lID2);
	void* GetSubBufferData(LONG lID1, VLONG lID2);
	Bool UpdateSubBuffer(BaseDraw* pBaseDraw, LONG lID1, VLONG lID2, LONG lIndex, Bool bFreeTempData);
	void TouchAllBuffers();
	void FreeUnusedBuffers();
};

#endif // __API_INTERN__

struct GlAddUniformParametersMsg
{
	BaseDocument* pDoc;
	BaseDraw* pBaseDraw;
	GlProgramFactory* pFactory;
	LONG lObjIndex;
	UCHAR* pchIdentity;
	LONG lChannel;
	Bool bDontShade;
	BaseObject* pObj;
	TextureTag* pTextureTag;
};

struct GlInitDescriptionMsg
{
	BaseDocument* pDoc;
	BaseDraw* pBaseDraw;
	GlProgramFactory* pFactory;
	LONG lObjIndex;
	UCHAR* pchIdentity;
	LONG lChannel;
	Bool bDontShade;
	BaseObject* pObj;
	TextureTag* pTextureTag;
};

#define GL_PASS_DISPLACE			1
#define GL_PASS_BEFORE_LIGHT	2
#define GL_PASS_LIGHT					3
#define GL_PASS_AFTER_LIGHT		4

struct GlAddProgramCodeMsg
{
	BaseDocument* pDoc;
	BaseDraw* pBaseDraw;
	GlProgramFactory* pFactory;
	LONG lObjIndex;
	LONG lChannel;
	LONG lPass; // 0: collect normals, 1: before light loop, 2: in light loop, 3: after light loop
	GlString* pstrColorVar; // always != NULL, shaders must create a new variable (e.g. "color"+GetUniqueID()) and return it here
	GlString* pstrDisplaceVar; // always != NULL, shaders must create a new variable (e.g. "displace"+GetUniqueID()) and return it here
	UCHAR* pchIdentity;
	ULONG ulParameters; // factory parameters (it's the same like pFactory->GetParameters)
	Bool bDontShade;
	BaseObject* pObj;
	TextureTag* pTextureTag;
	Bool bTile, bSeamless;
};

struct GlSetUniformParametersMsg
{
	BaseDocument* pDoc;
	BaseDraw* pBaseDraw;
	GlProgramFactory* pFactory;
	LONG lObjIndex;
	UCHAR* pchIdentity;
	Vector vObjectColor;
	LONG lChannel;
	Bool bAnimatePreview;
	Bool bDontShade;
	BaseObject* pObj;
	TextureTag* pTextureTag;
	LONG lPreviewSize;
};

#endif // _C4D_GL_H_
