//	Darkstar Engine  (c) UnderWorld Interactive Studio (all coding by Svarog    2007-2008)
//
//      Данный файл является частью Darkstar Engine. Любое использование кода файла
//      без согласия компании, является нарушением закона об авторском праве (в слу-
//      чае если не оговорено обратное).
//
//      Имя файла: render_state_manager_d3d10.hpp
//      Краткое описание: manager for render state blocks in DirectX 10
//

#ifdef GD_D3D10

#ifndef DSE_GS_RENDER_STATE_MANAGER_D3D10_HPP
#define DSE_GS_RENDER_STATE_MANAGER_D3D10_HPP

#include <Darkstar/common.hpp>
#include <Darkstar/Kernel/Misc/singleton.hpp>
#include <Darkstar/Graphic System/Render State/common_render_state.hpp>
#include <Darkstar/Graphic System/Render State/blend_render_state.hpp>
#include <Darkstar/Graphic System/Render State/colorwrite_render_state.hpp>
#include <Darkstar/Graphic System/Render State/cull_render_state.hpp>
#include <Darkstar/Graphic System/Render State/depth_render_state.hpp>
#include <Darkstar/Graphic System/Render State/fill_render_state.hpp>
#include <Darkstar/Graphic System/Render State/sampler_render_state.hpp>
#include <Darkstar/Graphic System/Direct3D/direct3d_include.hpp>

namespace gs
{
	class RenderStateManager : public ker::SingletonHolder<RenderStateManager>
	{
	private:
		// current values
		shared_ptr<BlendRenderState> new_blend_state;
		shared_ptr<DepthRenderState> new_depth_state;
		shared_ptr<ColorWriteRenderState> new_color_write_state;
		shared_ptr<FillModeRenderState> new_fill_mode_state;
		shared_ptr<SamplerRenderState> new_vs_sampler_state[sampler_num];
		shared_ptr<SamplerRenderState> new_ps_sampler_state[sampler_num];
		shared_ptr<SamplerRenderState> new_gs_sampler_state[sampler_num];
		shared_ptr<CullModeRenderState> new_cull_state;

		// RASTERIZER
		struct RasterizerUnit
		{
			ID3D10RasterizerState* state;
			shared_ptr<D3D10_RASTERIZER_DESC> desc;
		};

		unsigned int _getHashCode(const shared_ptr<D3D10_RASTERIZER_DESC>& desc);

		RasterizerUnit rasterizer_units[d3d_state_blocks_num];
		int rasterizer_cur_index;


		// BLENDER
		struct BlendUnit
		{
			ID3D10BlendState* state;
			shared_ptr<D3D10_BLEND_DESC> desc;
		};

		unsigned int _getHashCode(const shared_ptr<D3D10_BLEND_DESC>& desc);

		BlendUnit blend_units[d3d_state_blocks_num];
		int blend_cur_index;


		// DEPTH-STENCIL
		struct DepthStencilUnit
		{
			ID3D10DepthStencilState* state;
			shared_ptr<D3D10_DEPTH_STENCIL_DESC> desc;
		};

		unsigned int _getHashCode(const shared_ptr<D3D10_DEPTH_STENCIL_DESC>& desc);

		DepthStencilUnit depth_stencil_units[d3d_state_blocks_num];
		int depth_stencil_cur_index;


		// SAMPLER

		struct SamplerUnit
		{
			ID3D10SamplerState* state;
			shared_ptr<D3D10_SAMPLER_DESC> desc;
		};

		unsigned int _getHashCode(const shared_ptr<D3D10_SAMPLER_DESC>& desc);

		SamplerUnit sampler_units[d3d_state_blocks_num];
		int sampler_cur_vs_index[sampler_num];
		int sampler_cur_ps_index[sampler_num];
		int sampler_cur_gs_index[sampler_num];

		struct _SetSampler
		{
			unsigned int index;
			SAMPLER_TYPE type;
		};

		// this is a vector that contains new sampler which have set before next flush after flush
		// this vector have cleared
		std::vector<_SetSampler> _new_sampler;

		// private getter functions
		shared_ptr<D3D10_SAMPLER_DESC> _getD3D10SamplerStateFromCur(const unsigned int sampler_index, const SAMPLER_TYPE& sampler_type);
		shared_ptr<D3D10_BLEND_DESC> _getD3D10BlendStateFromCur();
		shared_ptr<D3D10_RASTERIZER_DESC> _getD3D10RasterizerStateFromCur();
		shared_ptr<D3D10_DEPTH_STENCIL_DESC> _getD3D10DepthStencilStateFromCur();
	public:
		RenderStateManager();
		~RenderStateManager();

		// set
		void setFillModeRenderState(const FillModeRenderState& fill_render_state);
		void setCullModeRenderState(const CullModeRenderState& cull_render_state);
		void setColorWriteRenderState(const ColorWriteRenderState& color_write_render_state);
		void setBlendRenderState(const BlendRenderState& blend_render_state);
		void setDepthRenderState(const DepthRenderState& depth_render_state);
		void setSamplerRenderState(const SamplerRenderState& sampler_render_state, const unsigned int sampler_index, const SAMPLER_TYPE& type);

		const shared_ptr<FillModeRenderState>& getCurFillModeRenderState() const;
		const shared_ptr<CullModeRenderState>& getCurCullModeRenderState() const;
		const shared_ptr<ColorWriteRenderState>& getCurColorWriteRenderState() const;
		const shared_ptr<BlendRenderState>& getCurBlendRenderState() const;
		const shared_ptr<DepthRenderState>& getCurDepthRenderState() const;
		const shared_ptr<SamplerRenderState>& getCurSamplerRenderState(const unsigned int sampler_index, const SAMPLER_TYPE& type) const;

		void flush();
	};
};

#endif

#endif