#pragma once

#include "dllinterface.h"
#include "..\Utilities\list.h"
#include "rendertarget.h"

class ShaderEffect;
class DynamicVB;
class D3DApp;
class DeviceStateManager;
class CompositorChain;

class DXFUNCTIONS_API CompositorEffect
{
	CompositorChain*				m_Compositor;
	ListElement<CompositorEffect>*	m_ListElement;
	bool							m_Enabled;
	
	RenderTexture*					m_Input;

protected:
	friend CompositorChain;

	DeviceStateManager*				m_pDevice;
	DXViewPort*						m_pViewPort;

	RenderTexture* GetInput(void) const { return m_Input; }

	//overwrite to do intermediate target passes
	virtual void Process(void) {}

	//when this function is called the output rendertaret has already been set
	virtual void RenderTargetPass(void) {}

	void CreateInput(const FORMAT fmt, const float vpscale);
	void CreateInput(const FORMAT fmt, const unsigned width, const unsigned height);

public:
	
	//when inputwitdh or height is set to 0, the size will be taken from the viewport
	CompositorEffect(DeviceStateManager* const device, DXViewPort* const vp);
	~CompositorEffect(void);

	void AddToCompositorChain(CompositorChain* cmp);
	void RemoveFromCompositorChain(void);

	void Enable(const bool enable) { m_Enabled = enable; }
	bool IsEnabled(void) const {return m_Enabled;}

	DXViewPort* GetViewPort(void) const { return m_pViewPort; }

	CompositorChain* GetCompositor(void) const {return m_Compositor;}
};

class DXFUNCTIONS_API CompositorChain
{
	DeviceStateManager*	 m_Device;
	ListElement<CompositorEffect>*m_First;
	
	DynamicVB*						m_VB;
	LPDIRECT3DVERTEXDECLARATION9	m_VDeclFSQuad;

	//void DoRestore(void);
	//void DoInvalidate(void);

	double m_RenderTime;

protected:
	friend CompositorEffect;

	LList<CompositorEffect> m_EffectChain;

public:
	CompositorChain(DeviceStateManager* const device);
	~CompositorChain(void);

	void SetupRenderScene(void);

	void RenderEffects(void);

	void RenderQuad(const unsigned xl, const unsigned yl, ShaderEffect* const fx);

	DeviceStateManager* GetDevice(void) const { return m_Device; }

	double GetRenderTime(void) const { return m_RenderTime; }
};
