//////////////////////////////////////////////////////////////////////////////
//
// Asura_PC_ShadowStorage.h
//
// Copyright (c) 2008 Rebellion. All rights reserved.
//
//////////////////////////////////////////////////////////////////////////////
#ifndef _ASURA_PC_SHADOWSTORAGE_H_
#define _ASURA_PC_SHADOWSTORAGE_H_

#ifdef ASURA_USE_PRAGMA_ONCE
#pragma once
#endif

#if defined(ASURA_TOOLS) && defined(ASURA_USE_SCREENSHOT_SYSTEM)
#define ASURA_HIGH_RES_SHADOW_MODE
#endif

#ifdef ASURA_HIGH_RES_SHADOW_MODE
#define ASURA_HIGH_RES_SHADOW_CHECK(a, b) (CheckHighResMode() ? (a) : (b))
#else
#define ASURA_HIGH_RES_SHADOW_CHECK(a, b) (b)
#endif

class Asura_ResizingMempool;

class Asura_PC_ShadowStorage
{
	Direct3D_CubeTexture*				m_pxEnvShadowCubeTexture;
	Direct3D_Surface*					m_ppxShadowDepthRenderTarget[ASURA_NUM_SHADOW_TEXTURE_SIZES];
	Direct3D_Surface*					m_ppxShadowDepthStencil[ASURA_NUM_SHADOW_TEXTURE_SIZES];
	Asura_PC_ShadowBuffer*				m_ppxShadowBuffers[ASURA_NUM_SHADOW_TEXTURE_SIZES * ASURA_NUM_SHADOWS_PER_TEXTURE_SIZE];
	Asura_ResizingMempool				m_xMemPool;
	u_int								m_uShadowTexturesAllocated;

#ifdef ASURA_HIGH_RES_SHADOW_MODE
	Direct3D_CubeTexture*				m_pxHRSEnvShadowCubeTexture;
	Direct3D_Surface**					m_ppxHRSShadowDepthRenderTarget;
	Direct3D_Surface**					m_ppxHRSShadowDepthStencil;
	Asura_PC_ShadowBuffer**				m_ppxHRSShadowBuffers;

	bool m_bHaveEnabledHRS;
	bool m_bIsEnabledHRS;
	bool CheckHighResMode()				{ return m_bIsEnabledHRS;}
	bool InitialiseHRS();				
#endif

	Asura_PC_ShadowBuffer *CreatePCShadowBuffer(u_int uTextureSize, Direct3D_Surface* pxDepthSurface);

public:
	static Asura_PC_ShadowStorage& Get() { static Asura_PC_ShadowStorage m_xShadowBuffers; return m_xShadowBuffers; }

	Asura_PC_ShadowStorage();
	~Asura_PC_ShadowStorage();

	void Initialise();
	void Shutdown();
	void Reset() { m_uShadowTexturesAllocated = 0;}

	static bool PreResetCB(void *)
	{
		Get().Shutdown();
		return true;
	}
	static bool PostResetCB(void *)
	{
		Get().Initialise();
		return true;
	}
#ifdef ASURA_HIGH_RES_SHADOW_MODE
	void SetHRS(bool bValue)					{ m_bIsEnabledHRS =  bValue && (m_bHaveEnabledHRS || InitialiseHRS()); }
#endif

	Direct3D_CubeTexture *GetEnvShadowCubeTexture()			{ return ASURA_HIGH_RES_SHADOW_CHECK(m_pxHRSEnvShadowCubeTexture, m_pxEnvShadowCubeTexture); }
	Direct3D_Surface *GetShadowDepthRenderTarget(u_int i)	{ return ASURA_HIGH_RES_SHADOW_CHECK(m_ppxHRSShadowDepthRenderTarget[i], m_ppxShadowDepthRenderTarget[i]); }
	Direct3D_Surface *GetShadowDepthStencil(u_int i)		{ return ASURA_HIGH_RES_SHADOW_CHECK(m_ppxHRSShadowDepthStencil[i], m_ppxShadowDepthStencil[i]); }
	Asura_PC_ShadowBuffer *GetShadowBuffer(u_int i)		{ return ASURA_HIGH_RES_SHADOW_CHECK(m_ppxHRSShadowBuffers[i], m_ppxShadowBuffers[i]); }
	Asura_PC_ShadowBuffer *GetNextShadowBuffer();
};



inline Asura_PC_ShadowBuffer *Asura_PC_ShadowStorage::GetNextShadowBuffer()
{
#ifdef ASURA_HIGH_RES_SHADOW_MODE
	if (CheckHighResMode())
	{
		if (m_uShadowTexturesAllocated < ASURA_NUM_HIRES_SCREENSHOT_SHADOW_TEXTURE_SIZES * ASURA_NUM_HIRES_SCREENSHOT_SHADOWS_PER_TEXTURE_SIZE)
		{
			return m_ppxHRSShadowBuffers[m_uShadowTexturesAllocated++];
		} 
		else 
		{
			return NULL;
		}
	}
	else
#endif
	{
		if (m_uShadowTexturesAllocated < (Asura_Shadow_System::s_uNumShadowTextureSizes * Asura_Shadow_System::s_uNumShadowsPerTextureSize))
		{
			return m_ppxShadowBuffers[m_uShadowTexturesAllocated++];
		} 
		else 
		{
			return NULL;
		}
	}
}
#endif
