#include"CGraphic.h"
#include"CRenderMessageImpl1.h"
#include"CRenderMessageImpl2.h"
#include"CRenderMessageImpl3.h"
#include"CReturnMessageImpl1.h"

//	ここのソースには 基本処理を書く


namespace Maid
{
CGraphic*	GlobalPointer<CGraphic>::s_pPointer;

	/*!
	 	@class CVideoRender CVideoRender.h
	 	@brief グラフィック周りを管理するクラス
			   アプリケーション１つにつき、１つしか存在できません。
	 */

CGraphic::CGraphic()
{
	GlobalPointer<CGraphic>::Set();
}

CGraphic::~CGraphic()
{

}



/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! 初期化
/*!
 */
void CGraphic::Initialize( const SCREENMODE& mode, const SPFONTDRIVER& pFontDriver, FRAMEINFO* pInfo )
{
	m_ScreenMode = mode;
	m_pFrameInfo = pInfo;

	{
		m_pFontDriver = pFontDriver;
		m_FontCache.Initialize( pFontDriver );
	}

	{	//	メンバの初期化
		ZERO( m_pTextureCache, sizeof(m_pTextureCache) );

		m_Blt3DParentMatrix.SetIdentity();
	}

	//	各種セットアップ
	{	
		//	FillXXX() の時のシェーダー
		m_VertexShaderFill.resize(1);
		m_VertexShaderFill[0].Create( VERTEXSHADERNAME::RHWCOLOR );

		m_PixelShaderFill.resize(_BLTSTATE_MAX);
		m_PixelShaderFill[0].Create( PIXELSHADERNAME::VERTEXCOLOR_NORMAL );
		m_PixelShaderFill[1].Create( PIXELSHADERNAME::VERTEXCOLOR_ADD );
		m_PixelShaderFill[2].Create( PIXELSHADERNAME::VERTEXCOLOR_SUB );
		m_PixelShaderFill[3].Create( PIXELSHADERNAME::VERTEXCOLOR_MUL );
		m_PixelShaderFill[4].Create( PIXELSHADERNAME::VERTEXCOLOR_REVERSE );
		m_PixelShaderFill[5].Create( PIXELSHADERNAME::VERTEXCOLOR_MAX );
	}

	{	
		//	BltXXX() の時のシェーダー
		m_VertexShaderBlt.resize(1);
		m_VertexShaderBlt[0].Create( VERTEXSHADERNAME::SPRITE );

		m_PixelShaderBlt.resize(_BLTSTATE_MAX);
		m_PixelShaderBlt[0].Create( PIXELSHADERNAME::SPRITE_NORMAL );
		m_PixelShaderBlt[1].Create( PIXELSHADERNAME::SPRITE_ADD );
		m_PixelShaderBlt[2].Create( PIXELSHADERNAME::SPRITE_SUB );
		m_PixelShaderBlt[3].Create( PIXELSHADERNAME::SPRITE_MUL );
		m_PixelShaderBlt[4].Create( PIXELSHADERNAME::SPRITE_REVERSE );
		m_PixelShaderBlt[5].Create( PIXELSHADERNAME::SPRITE_MAX );
	}
	{	
		//	Blt3DXXX() の時のシェーダー
		m_VertexShaderBlt3D.resize(1);
		m_VertexShaderBlt3D[0].Create( VERTEXSHADERNAME::SPRITE3D );
	}

	{
		//	テキスト描画時のシェーダー
		m_PixelShaderFont.resize(1);
		m_PixelShaderFont[0].Create( PIXELSHADERNAME::FONT_NORMAL );
	}

	{
		m_VertexShaderModel.resize(2);
		m_VertexShaderModel[0].Create( VERTEXSHADERNAME::MODEL_COLOR );
		m_VertexShaderModel[1].Create( VERTEXSHADERNAME::MODEL_TEXTURE );

		m_PixelShaderModel.resize(2);
		m_PixelShaderModel[0].Create( PIXELSHADERNAME::MODEL_COLOR );
		m_PixelShaderModel[1].Create( PIXELSHADERNAME::MODEL_TEXTURE );

		m_DeclModel.resize(2);
		m_DeclModel[0].Create( VERTEXDECLARATIONNAME::XYZ0NORMAL1 );
		m_DeclModel[1].Create( VERTEXDECLARATIONNAME::XYZ0NORMAL1TEX2 );
	}

	{
		m_VertexShaderModelTone.resize(2);
		m_VertexShaderModelTone[0].Create( VERTEXSHADERNAME::MODELTONE_COLOR );
		m_VertexShaderModelTone[1].Create( VERTEXSHADERNAME::MODELTONE_TEXTURE );
		m_VertexShaderModelToneLine.resize(1);
		m_VertexShaderModelToneLine[0].Create( VERTEXSHADERNAME::MODELTONE_LINE );

		m_PixelShaderModelTone.resize(2);
		m_PixelShaderModelTone[0].Create( PIXELSHADERNAME::MODELTONE_COLOR );
		m_PixelShaderModelTone[1].Create( PIXELSHADERNAME::MODELTONE_TEXTURE );

		m_DeclModelTone.resize(2);
		m_DeclModelTone[0].Create( VERTEXDECLARATIONNAME::XYZ0NORMAL1 );
		m_DeclModelTone[1].Create( VERTEXDECLARATIONNAME::XYZ0NORMAL1TEX2 );
	}

	m_IsBlt3DZTest = false;
	SetBltState( BLTSTATE_NORMAL );
	SetFilterType( FILTERTYPE_LINEAR );

	SetSamplerStateAddressU( 0, TEXTUREADDRESS_CLAMP );
	SetSamplerStateAddressV( 0, TEXTUREADDRESS_CLAMP );

	LocalInitialize();
}

/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! 開放
/*!
 */
void CGraphic::Finalize()
{
	LocalFinalize();
	m_VertexShaderFill.clear();
	m_PixelShaderFill.clear();
	m_VertexShaderBlt.clear();
	m_PixelShaderBlt.clear();
	m_VertexShaderBlt3D.clear();
	m_PixelShaderFont.clear();
	m_DeclModel.clear();
	m_VertexShaderModel.clear();
	m_PixelShaderModel.clear();

	m_FontCache.Finalize();
}

void CGraphic::PostRenderMessage( const SPRENDERMESSAGE& pMess, bool IsForce )
{
	m_pFrameInfo->que.push_back( pMess );
	if( IsForce ) { m_pFrameInfo->IsForce = true; }
}


void CGraphic::NextFrame()
{
	m_FontCache.Garbage();
}

void CGraphic::OnReturnMessage( const RETURNMESSAGEQUE& ret )
{
	CThreadMutexLocker Lock(m_ReturnDateMutex);

	for( int i=0; i<(int)ret.size(); ++i )
	{
		const SPRETURNMESSAGE& pMess = ret[i];

		switch( pMess->Message )
		{
		case ReturnMessage::Base::GETSURFACE:
			{
				ReturnMessage::GetSurface* p = static_cast<ReturnMessage::GetSurface*>(pMess.get());

				m_MemorySurface[p->ID].pSurface = p->pSurface;

			}break;

		case ReturnMessage::Base::DRIVERCAPS:
			{
				ReturnMessage::DriverCaps* p = static_cast<ReturnMessage::DriverCaps*>(pMess.get());
				m_VideoInfo = p->CapsText;
				if( m_VideoInfo.empty() ) { m_VideoInfo = MAIDTEXT("Unkwon"); }
			}break;
		}
	}
}


CGraphic::FRAMEINFO* CGraphic::GetFrameInfo()
{
	return m_pFrameInfo;
}

const CGraphic::SCREENMODE& CGraphic::GetScreenMode()
{
	return m_ScreenMode;
}


/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! 描画モードの設定
/*!
	@param	state [i ]	描画するモード
 */
void CGraphic::SetBltState( BLTSTATE state )
{
	m_BltState = state;
}

void CGraphic::SetFilterType( FILTERTYPE type )
{
	m_FilterType = type;
}


SPFONT CGraphic::CreateFont( int FontNo, const SIZE2DI& size, bool IsAntialias, bool IsBold, bool IsItalic ) const
{
	return m_pFontDriver->Create( FontNo, size.w, size.h, IsAntialias, IsBold, IsItalic );
}

SPFONT CGraphic::CreateFont( const mstring& FontName, const SIZE2DI& size, bool IsAntialias, bool IsBold, bool IsItalic ) const
{
	return m_pFontDriver->Create( FontName, size.w, size.h, IsAntialias, IsBold, IsItalic );
}

void CGraphic::SetBlt3DZTest( bool IsEnable )
{
	m_IsBlt3DZTest = IsEnable;
}





void CGraphic::CopySurface( const mstring& id )
{
	boost::shared_ptr<RenderMessage::CopySurface> pMess( new RenderMessage::CopySurface );

	pMess->ID = id;

	PostRenderMessage( pMess, true );
}

bool CGraphic::IsCopySurfaceEnd( const mstring& id )
{
	CThreadMutexLocker Lock(m_ReturnDateMutex);

	return m_MemorySurface.find(id)!=m_MemorySurface.end();
}

SPSURFACEBUFFER CGraphic::GetCopySurface( const mstring& id )
{
	CThreadMutexLocker Lock(m_ReturnDateMutex);

	MEMORYSURFACEMAP::iterator ite = m_MemorySurface.find(id);

	MAID_ASSERT( ite==m_MemorySurface.end(), MAIDTEXT("指定した番号はありません ") << id );

	SPSURFACEBUFFER pRet = ite->second.pSurface;

	m_MemorySurface.erase( ite );

	return pRet;
}


}