///////////////////////////////////////////////////////////////////////////////
/// @file RenderTexture.cpp
///
/// @brief class for texture renderstate settings
///
/// @author Lightning
///
/// This file is the intellectual property of Novus Delta, LLC.. Usage of the
/// contents of this file is subject to the Destiny3D Member License which
/// can be found at http://www.destiny3d.com.  Any other usage is prohibited.
///
/// This file is distributed "AS IS" without warranty of any kind.  Novus
/// Delta, LLC. does not guarantee the fitness of the contents of this file
/// for any particular purpose.
///
/// Copyright (C) 2001-2003 Novus Delta, LLC. All Rights Reserved.
///
/// <hr>
///                                 Change History
/// <hr>
///
/// @date Aug 2001
/// @author Lightning
/// @remarks Creation
///
///////////////////////////////////////////////////////////////////////////////

#include "deRenderStates_priv.hpp"
#include "debitmap.hpp"

#define VerifyStage(Return)			if(Stage < 0 || Stage >= TEXTURESTAGE_COUNT) return Return;
#define VerifyStage2(Stage,Return)	if(Stage < 0 || Stage >= TEXTURESTAGE_COUNT) return Return;

WorldObjectClassImp(deRenderTexture);

IdeRenderTexture::TextureFilter deRenderTexture::DefaultMinFilter = IdeRenderTexture::TEXTUREFILTER_POINT;
IdeRenderTexture::TextureFilter deRenderTexture::DefaultMagFilter = IdeRenderTexture::TEXTUREFILTER_LINEAR;
IdeRenderTexture::TextureFilter deRenderTexture::DefaultMipFilter = IdeRenderTexture::TEXTUREFILTER_POINT;
deBoolean deRenderTexture::DefaultToMip = deTRUE;

deBoolean IdeRenderState_SetDefaultTextureFilters(long MinFilter, long MagFilter, long MipFilter, deBoolean EnableMip)
{
	deRenderTexture::DefaultMinFilter = (IdeRenderTexture::TextureFilter)(MinFilter);
	deRenderTexture::DefaultMagFilter = (IdeRenderTexture::TextureFilter)(MagFilter);
	deRenderTexture::DefaultMipFilter = (IdeRenderTexture::TextureFilter)(MipFilter);

	deRenderTexture::DefaultToMip = EnableMip;

	return deTRUE;
}

//constructor and destructor
deRenderTexture::deRenderTexture()
{
	long Counter;
	
	//set all 8 texture stages
	for(Counter=0; Counter < TEXTURESTAGE_COUNT; Counter++)
	{
		//set the defaults for the values
		m_ColorArgs[Counter][0] = TEXTUREARG_TEXTURE;
		m_ColorArgs[Counter][1] = TEXTUREARG_DIFFUSE;
		m_ColorArgs[Counter][2] = TEXTUREARG_DIFFUSE;
		m_ColorArgs[Counter][3] = TEXTUREARG_PREVIOUS;

		//defaults for alpha values
		m_AlphaArgs[Counter][0] = TEXTUREARG_DIFFUSE;
		m_AlphaArgs[Counter][1] = TEXTUREARG_DIFFUSE;
		m_AlphaArgs[Counter][2] = TEXTUREARG_DIFFUSE;
	
		//default operations
		m_ColorOperation[Counter] = TEXTUREOP_DISABLE;
		m_AlphaOperation[Counter] = TEXTUREOP_DISABLE;

		m_TextureAddressU[Counter] = TEXTUREADDRESS_WRAP;
		m_TextureAddressV[Counter] = TEXTUREADDRESS_WRAP;

		m_TextureFilterMin[Counter] = DefaultMinFilter;
		m_TextureFilterMag[Counter] = DefaultMagFilter;
		m_TextureFilterMip[Counter] = DefaultMipFilter;

		m_EnableMipMaps = DefaultToMip;

		m_TextureProjection[Counter] = deFALSE;
		m_TexCoordSource[Counter] = Counter;

		//default texture is nothing
		m_Bitmaps[Counter] = NULL;

		m_CachedBitmapIDs[Counter].wid = 0;
		m_CachedBitmapIDs[Counter].oid = 0;
	}

	return;
}

deRenderTexture::~deRenderTexture()
{
	long Counter;
	
	//release textures as necessary
	for(Counter=0; Counter < TEXTURESTAGE_COUNT; Counter++)
	{
		if (m_Bitmaps[Counter])
			m_Bitmaps[Counter]->Release();		
	}

	return;
}

IdeRenderState::Type deRenderTexture::GetRSType() const
{
	//return the type of renderstate we are
	return IdeRenderState::TYPE_TEXTURE;
}

void * deRenderTexture::GetRSInterface(IdeRenderState::Type type) const
{
	if (type == TYPE_TEXTURE)
		return ((IdeRenderTexture*)this);
	if (type == IdeRenderState::TYPE_RSTATE)
		return ((IdeRenderState*)this);
	return NULL;
}

struct deRenderTexture_Header_t
{
	short VersionMajor;
	short VersionMinor;
};
static const deRenderTexture_Header_t deRenderTexture_Header = {0,2};
/*
Version 0.1:
October 3, 2002
32-bit enum TextureOp {start:TEXTUREOP_INVALID=-1, end:TEXTUREOP_LERP}
32-bit enum TextureAddress {TEXTUREADDRESS_WRAP,TEXTUREADDRESS_MIRROR,TEXTUREADDRESS_CLAMP}
32-bit enum TextureFilter {TEXTUREFILTER_POINT,TEXTUREFILTER_LINEAR,TEXTUREFILTER_ANISOTROPIC}
#define TEXTURESTAGE_COUNT 8

short			Version_Major
short			Version_Minor
char			num_stages
[header length = 5 bytes]
for up to 8 stages:
	uchar			num_chars
	char			bitmap_name[num_chars]
	long			ColorArgs[3]
	long			AlphaArgs[3]
	TextureOp		ColorOperation
	TextureOp		AlphaOperation
	TextureAddress	TextureAddressU
	TextureAddress	TextureAddressV
	TextureFilter	TextureFilterMin
	TextureFilter	TextureFilterMag
[stage length = 50 bytes MIN, 305 bytes MAX]
[header + 8 stages = 2445 bytes MAX]

Version 0.2:
August 4, 2003
same as 0.1 except this section:
	char			num_chars
	char			bitmap_name[num_chars]
is replaced with:
	ushort			bitmap_world_id
	ulong			bitmap_object_id
[stage length = 54 bytes]
[header + 8 stages = 437 bytes]
*/

#include "deConsole.hpp"

deBoolean deRenderTexture::Serialize(IdeFile* FS)
{
	if (FS == NULL)
		return deFALSE;

	u8			StagesUsed;
	int			Counter;
	deWorldID	wid;
	deObjectID	oid;

	StagesUsed = 0;
	for (Counter = 0; Counter < TEXTURESTAGE_COUNT; ++Counter)
	{
		if (m_Bitmaps[Counter])
			StagesUsed = (u8)(Counter + 1);
	}

	DE3D_STREAM_PUT(FS, deRenderTexture_Header.VersionMajor, u16);
	DE3D_STREAM_PUT(FS, deRenderTexture_Header.VersionMinor, u16);
	//number of stages
	DE3D_STREAM_PUT(FS, StagesUsed, u8);
	for (Counter = 0; Counter < StagesUsed; ++Counter)
	{
		//bitmap info
		/*
		// 0.1:
		char		FileName[256];
		int			NameLength;
		m_Bitmaps[Counter]->GetFilenameBuffer(FileName, 255);
		FileName[255] = '\0';
		NameLength = strlen(FileName);
		DE3D_STREAM_PUT(FS, NameLength, u8);
		DE3D_STREAM_PUTP(FS, FileName, NameLength);
		*/
		// 0.2
		wid = m_Bitmaps[Counter]->GetWorldID();
		oid = m_Bitmaps[Counter]->GetObjectID();
		DE3D_STREAM_PUT(FS, wid, u16);
		DE3D_STREAM_PUT(FS, oid, u32);
		//color args
		DE3D_STREAM_PUT(FS, m_ColorArgs[Counter][0], s32);
		DE3D_STREAM_PUT(FS, m_ColorArgs[Counter][1], s32);
		DE3D_STREAM_PUT(FS, m_ColorArgs[Counter][2], s32);
		//alpha args
		DE3D_STREAM_PUT(FS, m_AlphaArgs[Counter][0], s32);
		DE3D_STREAM_PUT(FS, m_AlphaArgs[Counter][1], s32);
		DE3D_STREAM_PUT(FS, m_AlphaArgs[Counter][2], s32);
		//color op
		DE3D_STREAM_PUT(FS, m_ColorOperation[Counter], s32);
		//alpha op
		DE3D_STREAM_PUT(FS, m_AlphaOperation[Counter], s32);
		//U address mode
		DE3D_STREAM_PUT(FS, m_TextureAddressU[Counter], s32);
		//V address mode
		DE3D_STREAM_PUT(FS, m_TextureAddressV[Counter], s32);
		//Min filter
		DE3D_STREAM_PUT(FS, m_TextureFilterMin[Counter], s32);
		//Mag filter
		DE3D_STREAM_PUT(FS, m_TextureFilterMag[Counter], s32);
	}

	return deTRUE;
}

deBoolean deRenderTexture::DeSerialize(IdeFile* FS, long DataLength)
{
	if (FS == NULL)
		return deFALSE;
	
	u32 AmtRead = 0;
	short VersionMajor, VersionMinor;
	char StagesUsed;
	int Counter;
	deWorldID wid;
	deObjectID oid;

	DE3D_STREAM_GET(FS, VersionMajor, u16, AmtRead, DataLength);
	DE3D_STREAM_GET(FS, VersionMinor, u16, AmtRead, DataLength);
	if (VersionMajor > deRenderTexture_Header.VersionMajor ||
		(VersionMajor == deRenderTexture_Header.VersionMajor && VersionMinor > deRenderTexture_Header.VersionMinor))
		return deFALSE;
	
	for (Counter = 0; Counter < TEXTURESTAGE_COUNT; ++Counter)
	{
		if (m_Bitmaps[Counter])
			m_Bitmaps[Counter]->Release();
		m_Bitmaps[Counter] = NULL;
	}

	if (VersionMajor == 0 && (VersionMinor == 1 || VersionMinor == 2))
	{
		DE3D_STREAM_GET(FS, StagesUsed, s8, AmtRead, DataLength);
		for (Counter = 0; Counter < StagesUsed; ++Counter)
		{
			//bitmap info
			if (VersionMinor == 1)
			{
				// 0.1
				BYTE StringLength;
				char BitmapName[256];
				DE3D_STREAM_GET(FS, StringLength, u8, AmtRead, DataLength);
				DE3D_STREAM_GETP(FS, BitmapName, StringLength, AmtRead, DataLength);
				BitmapName[StringLength] = '\0';
				IdeResourceBase* rsc = IdeResourceManager_GetManager()->GetResource(BitmapName, NULL);
				m_Bitmaps[Counter] = IdeBitmap_CreateProxy(rsc);
				m_CachedBitmapIDs[Counter].wid = 0;
				m_CachedBitmapIDs[Counter].oid = 0;
			}
			else if(VersionMinor == 2)
			{
				// 0.2:
				DE3D_STREAM_GET(FS, wid, s16, AmtRead, DataLength);
				DE3D_STREAM_GET(FS, oid, s32, AmtRead, DataLength);
				m_CachedBitmapIDs[Counter].wid = wid;
				m_CachedBitmapIDs[Counter].oid = oid;
				if (m_Bitmaps[Counter])
					m_Bitmaps[Counter]->Release();
				m_Bitmaps[Counter] = NULL;
			}
			//color args
			DE3D_STREAM_GET(FS, m_ColorArgs[Counter][0], s32, AmtRead, DataLength);
			DE3D_STREAM_GET(FS, m_ColorArgs[Counter][1], s32, AmtRead, DataLength);
			DE3D_STREAM_GET(FS, m_ColorArgs[Counter][2], s32, AmtRead, DataLength);
			//alpha args
			DE3D_STREAM_GET(FS, m_AlphaArgs[Counter][0], s32, AmtRead, DataLength);
			DE3D_STREAM_GET(FS, m_AlphaArgs[Counter][1], s32, AmtRead, DataLength);
			DE3D_STREAM_GET(FS, m_AlphaArgs[Counter][2], s32, AmtRead, DataLength);
			//color op
			DE3D_STREAM_GET(FS, m_ColorOperation[Counter], s32, AmtRead, DataLength);
			//alpha op
			DE3D_STREAM_GET(FS, m_AlphaOperation[Counter], s32, AmtRead, DataLength);
			//U address mode
			DE3D_STREAM_GET(FS, m_TextureAddressU[Counter], s32, AmtRead, DataLength);
			//V address mode
			DE3D_STREAM_GET(FS, m_TextureAddressV[Counter], s32, AmtRead, DataLength);
			//Min filter
			DE3D_STREAM_GET(FS, m_TextureFilterMin[Counter], s32, AmtRead, DataLength);
			//Mag filter
			DE3D_STREAM_GET(FS, m_TextureFilterMag[Counter], s32, AmtRead, DataLength);
		}
	}
	else
		return deFALSE;
	
	return deTRUE;
}

deBoolean deRenderTexture::DeSerializeLoad()
{
	int Counter;
	deWorldID wid;
	deObjectID oid;
	IdeWorldObject* pObject;
	IdeWorldManager* manager;
	IdeBitmapProxy* proxy;
	manager = IdeWorld_GetManager();
	for (Counter = 0; Counter < TEXTURESTAGE_COUNT; ++Counter)
	{
		proxy = NULL;
		wid = m_CachedBitmapIDs[Counter].wid;
		if (wid)
		{
			oid = m_CachedBitmapIDs[Counter].oid;
			pObject = manager->GetWorldObject(wid, oid);
			if (pObject)
				proxy = (IdeBitmapProxy*)pObject->GetWOInterface(IdeBitmapProxy_GetWOInterfaceID());
			else
				DEBUGMSG2("deRenderTexture::DeSerializeLoad - failure loading object with WID=%d and OID=%d", wid, oid);
		}
		if (m_Bitmaps[Counter] != proxy)
		{
			if (proxy)
				proxy->Claim();
			if (m_Bitmaps[Counter])
				m_Bitmaps[Counter]->Release();
			m_Bitmaps[Counter] = proxy;
		}
	}
	return deTRUE;
}

deBoolean deRenderTexture::SetColorOperation(long Stage, TextureOp ColorOp)
{
	//set the color operation

	//if not locked, fail
	if(!m_LockFlag)
		DEBUGRETURN(deFALSE, "SetColorOperation: Not Locked");

	//make sure it is valid
	if(ColorOp >= TEXTUREOP_COUNT || ColorOp <= TEXTUREOP_INVALID)
		DEBUGRETURN(deFALSE, "SetColorOperation: Bad ColorOp");

	//make sure the stage is valid
	VerifyStage(deFALSE);

	//set it and exit
	m_ColorOperation[Stage] = ColorOp;
	return deTRUE;
}

deBoolean deRenderTexture::SetAlphaOperation(long Stage, TextureOp AlphaOp)
{
	//set the alpha operation

	//if not locked, fail
	if(!m_LockFlag)
		DEBUGRETURN(deFALSE, "SetAlphaOperation: Not Locked");

	//make sure it is valid
	if(AlphaOp >= TEXTUREOP_COUNT || AlphaOp <= TEXTUREOP_INVALID)
		DEBUGRETURN(deFALSE, "SetAlphaOperation: Bad AlphaOp");

	//make sure the stage is valid
	VerifyStage(deFALSE);

	//set it and exit
	m_AlphaOperation[Stage] = AlphaOp;
	return deTRUE;
}

deBoolean deRenderTexture::SetResultTarget(long Stage, TextureArg Target)
{
	//set the result target register
	
	//if not locked, fail
	if(!m_LockFlag)
		DEBUGRETURN(deFALSE, "SetResultTarget: Not Locked");

	if(Target != TEXTUREARG_PREVIOUS && Target != TEXTUREARG_TEMPREG)
		DEBUGRETURN(deFALSE, "SetResultTarget: Bad Target");

	//make sure the stage is valid
	VerifyStage(deFALSE);

	m_ColorArgs[Stage][3] = Target;

	return deTRUE;
}

IdeRenderTexture::TextureOp deRenderTexture::GetColorOperation(long Stage) const
{
	//get a color operation for a stage

	//make sure the stage is valid
	VerifyStage(TEXTUREOP_INVALID);

	//return the color operation
	return m_ColorOperation[Stage];
}

IdeRenderTexture::TextureOp deRenderTexture::GetAlphaOperation(long Stage) const
{
	//get an alpha operation for a stage

	//make sure the stage is valid
	VerifyStage(TEXTUREOP_INVALID);

	//return the alpha operation
	return m_AlphaOperation[Stage];
}

IdeRenderTexture::TextureArg deRenderTexture::GetResultTarget(long Stage)
{
	//get the result target register
	
	//make sure the stage is valid
	VerifyStage(TEXTUREARG_PREVIOUS);
	
	return 	m_ColorArgs[Stage][3];	
}

//functions for setting the arguements
deBoolean deRenderTexture::SetColorArg(long Stage, long ArgNum, TextureArg Arg)
{
	//set the color arguments

	//if not locked, fail
	if(!m_LockFlag)
		DEBUGRETURN(deFALSE, "SetColorArg: Not Locked");

	//make sure the argument number is valid (1 thru 3)
	if(ArgNum < 1 || ArgNum > 3)
		DEBUGRETURN(deFALSE, "SetColorArg: ArgNum outside valid range (1-3)");

	//make sure it is valid
	TextureArg Temp = TextureArg(Arg & 0x00ff);
	if(Temp >= TEXTUREARG_COUNT || Temp <= TEXTUREARG_INVALID)
		DEBUGRETURN(deFALSE, "SetColorArg: Bad Arg");
	
	//make sure the stage is valid
	VerifyStage(deFALSE);

	//set it
	m_ColorArgs[Stage][ArgNum - 1] = Arg;
	return deTRUE;
}

deBoolean deRenderTexture::SetAlphaArg(long Stage, long ArgNum, TextureArg Arg)
{
	//set the alpha arguments

	//if not locked, fail
	if(!m_LockFlag)
		DEBUGRETURN(deFALSE, "SetAlphaArg: Not Locked");

	//make sure the argument number is valid (1 thru 3)
	if(ArgNum < 1 || ArgNum > 3)
		DEBUGRETURN(deFALSE, "SetAlphaArg: ArgNum outside valid range (1-3)");

	//make sure it is valid
	TextureArg Temp = TextureArg(Arg & 0x00ff);
	if(Temp >= TEXTUREARG_COUNT || Temp <= TEXTUREARG_INVALID)
		DEBUGRETURN(deFALSE, "SetAlphaArg: Bad Arg");
	
	//make sure the stage is valid
	VerifyStage(deFALSE);

	//set it
	m_AlphaArgs[Stage][ArgNum - 1] = Arg;
	return deTRUE;
}

IdeRenderTexture::TextureArg deRenderTexture::GetColorArg(long Stage, long ArgNum) const
{
	//get the color argument

	//make sure the argument number is valid
	if(ArgNum < 1 || ArgNum > 3)
		return TEXTUREARG_INVALID;

	//make sure the stage is valid
	VerifyStage(TEXTUREARG_INVALID);

	//return the argument's value
	return m_ColorArgs[Stage][ArgNum - 1];
}

IdeRenderTexture::TextureArg deRenderTexture::GetAlphaArg(long Stage, long ArgNum) const
{
	//get the alpha argument

	//make sure the argument number is valid
	if(ArgNum < 1 || ArgNum > 3)
		return TEXTUREARG_INVALID;

	//make sure the stage is valid
	VerifyStage(TEXTUREARG_INVALID);

	//return the argument's value
	return m_AlphaArgs[Stage][ArgNum - 1];
}

deBoolean deRenderTexture::SetBitmap(long Stage, IdeBitmapProxy* BitmapProxy)
{
	//set the texture

	//if not locked, fail
	if(!m_LockFlag)
		DEBUGRETURN(deFALSE, "SetBitmap: Not Locked");

	//make sure the stage is valid
	VerifyStage(deFALSE);

	if (m_Bitmaps[Stage] == BitmapProxy)
		return deTRUE;

	if (BitmapProxy)
		BitmapProxy->Claim();

	if (m_Bitmaps[Stage])
		m_Bitmaps[Stage]->Release();

	m_Bitmaps[Stage] = BitmapProxy;
	
	return deTRUE;
}

IdeBitmapProxy* deRenderTexture::GetBitmap(long Stage) const
{
	//get a texture for a stage

	//make sure the stage is valid
	VerifyStage(NULL);

	//return the texture
	return m_Bitmaps[Stage];
}

deBoolean deRenderTexture::SetTextureAddressU(long Stage, TextureAddress Address)
{
	//set a texture address for U

	//if not locked, fail
	if(!m_LockFlag)
		DEBUGRETURN(deFALSE, "SetTextureAddressU: Not Locked");

	//make sure the stage is valid
	VerifyStage(deFALSE);
	
	//verify we know of the stage
	if(Address < 0 || Address >= TEXTUREADDRESS_COUNT)
		DEBUGRETURN(deFALSE, "SetAlphaArg: Bad Address");
	
	//set the address
	m_TextureAddressU[Stage] = Address;

	return deTRUE;
}

deBoolean deRenderTexture::SetTextureAddressV(long Stage, TextureAddress Address)
{
	//set a texture address for V

	//if not locked, fail
	if(!m_LockFlag)
		DEBUGRETURN(deFALSE, "SetTextureAddressV: Not Locked");

	//make sure the stage is valid
	VerifyStage(deFALSE);
	
	//verify we know of the stage
	if(Address < 0 || Address >= TEXTUREADDRESS_COUNT)
		DEBUGRETURN(deFALSE, "SetAlphaArg: Bad Address");

	//set the address
	m_TextureAddressV[Stage] = Address;

	return deTRUE;
}

deRenderTexture::TextureAddress deRenderTexture::GetTextureAddressU(long Stage) const
{
	//get the address of a texture for U

	//make sure the stage is valid
	VerifyStage(TEXTUREADDRESS_INVALID);

	return m_TextureAddressU[Stage];
}

deRenderTexture::TextureAddress deRenderTexture::GetTextureAddressV(long Stage) const
{
	//get the address of a texture for V

	//make sure the stage is valid
	VerifyStage(TEXTUREADDRESS_INVALID);

	return m_TextureAddressV[Stage];
}

deBoolean deRenderTexture::SetTextureMinFilter(long Stage, TextureFilter Filter)
{
	//set the texture minification filter

	//if not locked, fail
	if(!m_LockFlag)
		DEBUGRETURN(deFALSE, "SetTextureMinFilter: Not Locked");

	//make sure the stage is valid
	VerifyStage(deFALSE);
	
	//verify we know of the stage
	if(Filter < 0 || Filter >= TEXTUREFILTER_COUNT)
		DEBUGRETURN(deFALSE, "SetAlphaArg: Bad Filter");
	
	//set the address
	m_TextureFilterMin[Stage] = Filter;

	return deTRUE;
}

deBoolean deRenderTexture::SetTextureMagFilter(long Stage, TextureFilter Filter)
{
	//set the texture magnification filter

	//if not locked, fail
	if(!m_LockFlag)
		DEBUGRETURN(deFALSE, "SetTextureMagFilter: Not Locked");

	//make sure the stage is valid
	VerifyStage(deFALSE);
	
	//verify we know of the stage
	if(Filter < 0 || Filter >= TEXTUREFILTER_COUNT)
		DEBUGRETURN(deFALSE, "SetAlphaArg: Bad Filter");

	//set the address
	m_TextureFilterMag[Stage] = Filter;

	return deTRUE;
}

deBoolean deRenderTexture::SetTextureMipFilter(long Stage, TextureFilter Filter)
{
	//set the texture mipmap filter
	
	//if not locked, fail
	if(!m_LockFlag)
		DEBUGRETURN(deFALSE, "SetTextureMipFilter: Not Locked");
	
	//make sure the stage is valid
	VerifyStage(deFALSE);
	
	//verify we know of the stage
	if(Filter < 0 || Filter >= TEXTUREFILTER_COUNT)
		DEBUGRETURN(deFALSE, "SetAlphaArg: Bad Filter");
	
	//set the address
	m_TextureFilterMip[Stage] = Filter;
	
	return deTRUE;
}

IdeRenderTexture::TextureFilter deRenderTexture::GetTextureMinFilter(long Stage) const
{
	//get the texture minification filter

	//make sure the stage is valid
	VerifyStage(TEXTUREFILTER_INVALID);

	return m_TextureFilterMag[Stage];
}

IdeRenderTexture::TextureFilter deRenderTexture::GetTextureMagFilter(long Stage) const
{
	//get the texture magnification filter

	//make sure the stage is valid
	VerifyStage(TEXTUREFILTER_INVALID);

	return m_TextureFilterMag[Stage];
}

IdeRenderTexture::TextureFilter deRenderTexture::GetTextureMipFilter(long Stage) const
{
	//get the texture mipmap filter
	
	//make sure the stage is valid
	VerifyStage(TEXTUREFILTER_INVALID);
	
	return m_TextureFilterMip[Stage];
}

deBoolean deRenderTexture::SetTexCoordSource(long Stage, long SourceStage)
{
	//if not locked, fail
	if(!m_LockFlag)
		DEBUGRETURN(deFALSE, "SetTexCoordSource: Not Locked");
	
	//make sure the stage is valid
	VerifyStage(deFALSE);
	VerifyStage2(SourceStage, deFALSE);
	
	m_TexCoordSource[Stage] = SourceStage;
	
	return deTRUE;
}

deBoolean deRenderTexture::SetTexCoordGen(long Stage, TextureCoordSource SourcePipe, long CopyWrapModeStage)
{
	//if not locked, fail
	if(!m_LockFlag)
		DEBUGRETURN(deFALSE, "SetTexCoordGen: Not Locked");
	
	//make sure the stage is valid
	VerifyStage(deFALSE);
	VerifyStage2(CopyWrapModeStage, deFALSE);
	
	m_TexCoordSource[Stage] = CopyWrapModeStage | ((long)SourcePipe);
	
	return deTRUE;
}

deBoolean deRenderTexture::GetTexCoordSource(long Stage, long &SourceStage, TextureCoordSource &SourceFlags)
{
	//make sure the stage is valid
	VerifyStage(deFALSE);

	SourceStage = m_TexCoordSource[Stage] & 0x0000ffff;
	SourceFlags = (TextureCoordSource)(m_TexCoordSource[Stage] & 0xffff0000);

	return deTRUE;
}

long deRenderTexture::GetTexCoordSourceCombined(long Stage)
{
	//make sure the stage is valid
	VerifyStage(0);

	return m_TexCoordSource[Stage] & 0x0003001f;
}

deBoolean deRenderTexture::SetTextureProjection(long Stage, deBoolean Enable)
{
	//if not locked, fail
	if(!m_LockFlag)
		DEBUGRETURN(deFALSE, "SetTexCoordGen: Not Locked");
	
	//make sure the stage is valid
	VerifyStage(deFALSE);

	m_TextureProjection[Stage] = Enable;
	return deTRUE;
}

deBoolean deRenderTexture::GetTextureProjection(long Stage)
{
	return m_TextureProjection[Stage];
}

deBoolean deRenderTexture::CopyStageSettings(IdeRenderTexture* Target, long SourceStage, long TargetStage) const
{
	//make sure the stages are valid
	VerifyStage2(SourceStage, deFALSE);
	VerifyStage2(TargetStage, deFALSE);

	deRenderTexture* pTarget = (deRenderTexture*)Target;

	if (!pTarget->m_LockFlag)
		DEBUGRETURN(deFALSE, "CopyStageSettings: Not Locked");
	
	if (pTarget->m_Bitmaps[TargetStage])
		pTarget->m_Bitmaps[TargetStage]->Release();
	pTarget->m_Bitmaps[TargetStage] = m_Bitmaps[SourceStage];
	if (pTarget->m_Bitmaps[TargetStage])
		pTarget->m_Bitmaps[TargetStage]->Claim();
	pTarget->m_EnableMipMaps = m_EnableMipMaps;
	pTarget->m_ColorArgs[TargetStage][0] = m_ColorArgs[SourceStage][0];
	pTarget->m_ColorArgs[TargetStage][1] = m_ColorArgs[SourceStage][1];
	pTarget->m_ColorArgs[TargetStage][2] = m_ColorArgs[SourceStage][2];
	pTarget->m_AlphaArgs[TargetStage][0] = m_AlphaArgs[SourceStage][0];
	pTarget->m_AlphaArgs[TargetStage][1] = m_AlphaArgs[SourceStage][1];
	pTarget->m_AlphaArgs[TargetStage][2] = m_AlphaArgs[SourceStage][2];
	pTarget->m_ColorOperation[TargetStage] = m_ColorOperation[SourceStage];
	pTarget->m_AlphaOperation[TargetStage] = m_AlphaOperation[SourceStage];
	pTarget->m_TextureAddressU[TargetStage] = m_TextureAddressU[SourceStage];
	pTarget->m_TextureAddressV[TargetStage] = m_TextureAddressV[SourceStage];
	pTarget->m_TextureFilterMin[TargetStage] = m_TextureFilterMin[SourceStage];
	pTarget->m_TextureFilterMag[TargetStage] = m_TextureFilterMag[SourceStage];
	pTarget->m_TextureFilterMip[TargetStage] = m_TextureFilterMip[SourceStage];
#pragma todo (this might need adjusting to pick from the right stream)
	pTarget->m_TexCoordSource[TargetStage] = m_TexCoordSource[SourceStage];
	pTarget->m_TextureProjection[TargetStage] = m_TextureProjection[SourceStage];

	return deTRUE;
}
