/*	Renegade Scripts.dll
	Shader State Manager
	Copyright 2007 Jonathan Wilson, Mark Sararu

	This file is part of the Renegade scripts.dll
	The Renegade scripts.dll is free software; you can redistribute it and/or modify it under
	the terms of the GNU General Public License as published by the Free
	Software Foundation; either version 2, or (at your option) any later
	version. See the file COPYING for more details.
	In addition, an exemption is given to allow Run Time Dynamic Linking of this code with any closed source module that does not contain code covered by this licence.
	Only the source code to the module(s) containing the licenced code has to be released.
*/
#define SM_CACHEDSAMPLERS 8

class ShaderStateManager : public ID3DXEffectStateManager {
private:
	unsigned long *RenderStates;
	unsigned long *SamplerStates[SM_CACHEDSAMPLERS];
	unsigned long *TextureStates[SM_CACHEDSAMPLERS];
	IDirect3DBaseTexture9 *Textures[SM_CACHEDSAMPLERS];
	IDirect3DSurface9* RenderTarget;
	bool *RenderStatesCached;
	bool *SamplerStatesCached[SM_CACHEDSAMPLERS];
	bool *TextureStatesCached[SM_CACHEDSAMPLERS];

	IDirect3DPixelShader9 *PixelShader;
	IDirect3DVertexShader9 *VertexShader;
	float NPatchMode;
protected:
	long ref; 
public:
	ShaderStateManager();
	virtual ~ShaderStateManager();
	virtual void Reset();
	
	virtual HRESULT __stdcall QueryInterface(const IID &iid,LPVOID *ppv);
	virtual unsigned long __stdcall AddRef();
	virtual unsigned long __stdcall Release();
	virtual HRESULT __stdcall LightEnable(DWORD Index,BOOL Enable);
	virtual HRESULT __stdcall SetFVF(DWORD FVF);
	virtual HRESULT __stdcall SetLight(DWORD Index,CONST D3DLIGHT9* pLight);
	virtual HRESULT __stdcall SetMaterial(CONST D3DMATERIAL9* pMaterial);
	virtual HRESULT __stdcall SetNPatchMode(FLOAT nSegments);
	virtual HRESULT __stdcall SetPixelShader(LPDIRECT3DPIXELSHADER9 pShader);
	virtual HRESULT __stdcall SetPixelShaderConstantB(UINT StartRegister, CONST BOOL* pConstantData, UINT RegisterCount);
	virtual HRESULT __stdcall SetPixelShaderConstantF(UINT StartRegister, CONST FLOAT* pConstantData, UINT RegisterCount);
	virtual HRESULT __stdcall SetPixelShaderConstantI(UINT StartRegister, CONST INT* pConstantData, UINT RegisterCount);
	virtual HRESULT __stdcall SetRenderState(D3DRENDERSTATETYPE State, DWORD Value);
	virtual HRESULT __stdcall GetRenderState(D3DRENDERSTATETYPE State, DWORD* pValue);
	virtual DWORD   __stdcall GetRenderState(D3DRENDERSTATETYPE State);
	virtual HRESULT __stdcall SetRenderTarget(DWORD RenderTargetIndex,LPDIRECT3DSURFACE9 pRenderTarget);
	virtual HRESULT __stdcall SetSamplerState(DWORD Sampler, D3DSAMPLERSTATETYPE Type, DWORD Value);
	virtual HRESULT __stdcall GetSamplerState(DWORD Sampler, D3DSAMPLERSTATETYPE Type, DWORD *pValue);
	virtual HRESULT __stdcall SetTextureStageState(DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD Value);
	virtual HRESULT __stdcall GetTextureStageState(DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD *pValue);
	virtual HRESULT __stdcall SetTexture(DWORD Stage, LPDIRECT3DBASETEXTURE9 pTexture);
	virtual HRESULT __stdcall SetTransform(D3DTRANSFORMSTATETYPE State, CONST D3DMATRIX* pMatrix);
	virtual HRESULT __stdcall SetVertexShader(LPDIRECT3DVERTEXSHADER9 pShader);
	virtual HRESULT __stdcall SetVertexShaderConstantB(UINT StartRegister,CONST BOOL* pConstantData,UINT RegisterCount);
	virtual HRESULT __stdcall SetVertexShaderConstantF(UINT StartRegister, CONST FLOAT* pConstantData, UINT RegisterCount);
	virtual HRESULT __stdcall SetVertexShaderConstantI(UINT StartRegister, CONST INT* pConstantData, UINT RegisterCount);
};

extern ShaderStateManager *StateManager;

class ShaderStateSaver
{
protected:
	bool StateSaved;
	D3DRENDERSTATETYPE State;
	DWORD Value;
public:
	ShaderStateSaver(D3DRENDERSTATETYPE state)
	{
		State = state;
		Value = StateManager->GetRenderState(state);
		StateSaved = true;
	};
	ShaderStateSaver(D3DRENDERSTATETYPE state, float MinVertexShaderVersion, float MinPixelShaderVersion)
	{
		if ((ShaderCaps::VertexShaderVersion >= MinVertexShaderVersion) && (ShaderCaps::PixelShaderVersion >= MinPixelShaderVersion))
		{
			State = state;
			Value = StateManager->GetRenderState(state);
			StateSaved = true;
		}
		else
		{
			StateSaved = false;
		}
	};
	ShaderStateSaver(D3DRENDERSTATETYPE state, float MinShaderVersion)
	{
		if ((ShaderCaps::VertexShaderVersion >= MinShaderVersion) && (ShaderCaps::PixelShaderVersion >= MinShaderVersion))
		{
			State = state;
			Value = StateManager->GetRenderState(state);
			StateSaved = true;
		}
		else
		{
			StateSaved = false;
		}
	};
	~ShaderStateSaver()
	{
		if (StateSaved)
		{
			StateManager->SetRenderState(State,Value);
		}
	};
};
