#include "Mix/Private/Graphics/Common/Manager.h"

#include "Mix/IEngine.h"
#include "Mix/Memory/IBuffer.h"
#include "Mix/IO/IManager.h"
#include "Mix/IO/IReader.h"
#include "Mix/Graphics/IVertexLayout.h"
#include "Mix/Graphics/IVertexBuffer.h"
#include "Mix/Graphics/IIndexBuffer.h"
#include "Mix/Graphics/IVertexShader.h"
#include "Mix/Graphics/IPixelShader.h"

#include "Mix/Private/Graphics/Common/Device.h"
#include "Mix/Private/Graphics/DX9/Device.h"
#include "Mix/Private/Graphics/DX11/Device.h"
#include "Mix/Private/Graphics/Utility/Common/TextPrinter.h"
#include "Mix/Private/Graphics/Utility/Common/TargetTextureChain.h"
#include "Mix/Private/Graphics/Utility/Common/Font.h"
#include "Mix/Private/Graphics/Utility/Common/PerspectiveRenderer.h"
#include "Mix/Private/Graphics/Utility/Common/CanvasRenderer.h"

namespace Mix{ namespace Graphics{ namespace Common{

////////////////////////////////////////////////////////////////////////////////////////////////////
// Manager : メッセージ
////////////////////////////////////////////////////////////////////////////////////////////////////

const wchar_t* Manager::FAILED_INITIALIZE                       = L"グラフィックマネージャの初期化に失敗";
const wchar_t* Manager::SUCCESS_INITIALIZE                      = L"グラフィックマネージャを初期化";
const wchar_t* Manager::FAILED_CREATETARGETTEXTURECHAIN         = L"ターゲットテクスチャチェインの作成に失敗";
const wchar_t* Manager::FAILED_CREATEFONT                       = L"フォントの作成に失敗";
const wchar_t* Manager::FAILED_CREATELINEART                    = L"パースペクティブレンダラーの作成に失敗";
const wchar_t* Manager::FAILED_CREATECANVAS                     = L"キャンバスレンダラーの作成に失敗";

////////////////////////////////////////////////////////////////////////////////////////////////////
// Manager : 定数
////////////////////////////////////////////////////////////////////////////////////////////////////

//バーテックレイアウト : サンプリング
static const Mix::Graphics::VERTEX_ELEMENT VL_SAMPLING[] =
{
	{ Mix::Graphics::VLS_POSITION, 0, Mix::Graphics::VLF_FLOAT32_4,  0, },
	{ Mix::Graphics::VLS_TEXTURE,  0, Mix::Graphics::VLF_FLOAT32_2, 16, },
};
static const UInt32 VL_SAMPLING_COUNT = sizeof( VL_SAMPLING ) / sizeof( Mix::Graphics::VERTEX_ELEMENT );
static const wchar_t* VL_SAMPLING_NAME = L"Sampling";

//バーテックレイアウト : ガウシアンブラー
static const Mix::Graphics::VERTEX_ELEMENT VL_GAUSSIAN_BLUR[] =
{
	{ Mix::Graphics::VLS_POSITION, 0, Mix::Graphics::VLF_FLOAT32_4,  0, },
	{ Mix::Graphics::VLS_TEXTURE,  0, Mix::Graphics::VLF_FLOAT32_2, 16, },
};
static const UInt32 VL_GAUSSIAN_BLUR_COUNT = sizeof( VL_GAUSSIAN_BLUR ) / sizeof( Mix::Graphics::VERTEX_ELEMENT );
static const wchar_t* VL_GAUSSIAN_BLUR_NAME = L"GaussianBlur";

//バーテックレイアウト : 大気
static const Mix::Graphics::VERTEX_ELEMENT VL_ATMOSPHERE[] =
{
	{ Mix::Graphics::VLS_POSITION, 0, Mix::Graphics::VLF_FLOAT32_4,  0, },
	{ Mix::Graphics::VLS_TEXTURE,  0, Mix::Graphics::VLF_FLOAT32_2, 16, },
};
static const UInt32 VL_ATMOSPHERE_COUNT = sizeof( VL_ATMOSPHERE ) / sizeof( Mix::Graphics::VERTEX_ELEMENT );
static const wchar_t* VL_ATMOSPHERE_NAME = L"Atmosphere";

//バーテックレイアウト : キャンバスレンダラー
static const Mix::Graphics::VERTEX_ELEMENT VL_CANVAS[] =
{
	{ Mix::Graphics::VLS_POSITION, 0, Mix::Graphics::VLF_FLOAT32_4,  0, },
	{ Mix::Graphics::VLS_COLOR,    0, Mix::Graphics::VLF_FLOAT32_4, 16, },
	{ Mix::Graphics::VLS_TEXTURE,  0, Mix::Graphics::VLF_FLOAT32_2, 32, },
};
static const UInt32 VL_CANVAS_COUNT = sizeof( VL_CANVAS ) / sizeof( Mix::Graphics::VERTEX_ELEMENT );
static const wchar_t* VL_CANVAS_NAME = L"CanvasRenderer";

//バーテックレイアウト : ライン
static const Mix::Graphics::VERTEX_ELEMENT VL_LINE[] =
{
	{ Mix::Graphics::VLS_POSITION, 0, Mix::Graphics::VLF_FLOAT32_4,  0, },
	{ Mix::Graphics::VLS_COLOR,    0, Mix::Graphics::VLF_FLOAT32_4, 16, },
};
static const UInt32 VL_LINE_COUNT = sizeof( VL_LINE ) / sizeof( Mix::Graphics::VERTEX_ELEMENT );
static const wchar_t* VL_LINE_NAME = L"Line";

////////////////////////////////////////////////////////////////////////////////////////////////////
// Manager::VERTEX_EFFECT
////////////////////////////////////////////////////////////////////////////////////////////////////

Manager::VERTEX_EFFECT::VERTEX_EFFECT( void )
{
	pLayout = NULL;

	for( UInt32 i = 0; i < Manager::VES_MAX; i++ )
	{
		pShader[i] = NULL;
	}
}

void Manager::VERTEX_EFFECT::Dispose( void )
{
	MIX_RELEASE( pLayout );

	for( UInt32 i = 0; i < Manager::VES_MAX; i++ )
	{
		MIX_RELEASE( pShader[i] );
	}
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// Manager::PIXEL_EFFECT
////////////////////////////////////////////////////////////////////////////////////////////////////

Manager::PIXEL_EFFECT::PIXEL_EFFECT( void )
{
	for( UInt32 i = 0; i < Manager::PES_MAX; i++ )
	{
		pShader[i] = NULL;
	}
}

void Manager::PIXEL_EFFECT::Dispose( void )
{
	for( UInt32 i = 0; i < Manager::PES_MAX; i++ )
	{
		MIX_RELEASE( pShader[i] );
	}
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// Manager
////////////////////////////////////////////////////////////////////////////////////////////////////

Manager::Manager( void ) :
m_pFileMgr( NULL ),
m_pTextPrinter( NULL )
{
	Mix::IO::IManager* pFileMgr = Mix::IO::GetManagerPtr();

	MIX_ADD_REF( pFileMgr );
	m_pFileMgr = pFileMgr;
}

Manager::~Manager( void )
{
	MIX_ASSERT( m_ResidentVEMap.size() == 0 );
	MIX_ASSERT( m_ResidentPEMap.size() == 0 );
	MIX_ASSERT( m_pTextPrinter == NULL );
	MIX_ASSERT( m_pFileMgr == NULL );
}

Boolean Manager::Initialize(	const Mix::Point& targetSize,
								Mix::Graphics::SHADER_MODEL shaderModel, Boolean bFullscreen, Boolean bWaitVSync,
								Int32 textTabSize, Int32 textTargetSize, Int32 initialTextTargetNum,
								Mix::UserFile* pSysReport )
{
	MIX_LOG_INFO_SECT_START( L"グラフィックスの初期化" );

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// シェーダーモデル毎の固有の初期化
	////////////////////////////////////////////////////////////////////////////////////////////////////

	Mix::Point modTargetSize;

	if( Mix::GetInternalEnginePtr()->IsSizeableWindow() == True )
	{
		modTargetSize.x = GetSystemMetrics( SM_CXSCREEN );
		modTargetSize.y = GetSystemMetrics( SM_CYSCREEN );
	}
	else
	{
		modTargetSize = targetSize;
	}

	if( OnInitialize(	modTargetSize,
						shaderModel, bFullscreen, bWaitVSync,
						pSysReport ) == False )
	{
		return False;
	}

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// 共通の初期化
	////////////////////////////////////////////////////////////////////////////////////////////////////

	// テキストプリンター

	m_pTextPrinter = Utility::Common::TextPrinter::CreateInstance(	GetDevicePtr(),
																	textTabSize, textTargetSize, initialTextTargetNum );

	if( m_pTextPrinter == NULL )
	{
		MIX_LOG_INFO_SECT_END();
		return False;
	}

	////////////////////////////////////////////////////////////////////////////////////////////////////

	MIX_LOG_INFO_SECT_END();

	return True;
}

Boolean Manager::Update( void )
{
	return GetDevicePtr()->Update();
}

void Manager::Dispose( void )
{
	////////////////////////////////////////////////////////////////////////////////////////////////////
	// 自身の解放
	////////////////////////////////////////////////////////////////////////////////////////////////////

	// エフェクト

	if( m_ResidentVEMap.size() > 0 )
	{
		for( Manager::VertexEffectMap::iterator it = m_ResidentVEMap.begin(); it != m_ResidentVEMap.end(); ++it )
		{
			it->second.Dispose();
		}

		m_ResidentVEMap.clear();
	}

	if( m_ResidentPEMap.size() > 0 )
	{
		for( Manager::PixelEffectMap::iterator it = m_ResidentPEMap.begin(); it != m_ResidentPEMap.end(); ++it )
		{
			it->second.Dispose();
		}

		m_ResidentPEMap.clear();
	}

	// テキストプリンター

	MIX_RELEASE( m_pTextPrinter );

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// シェーダーモデル毎の解放
	////////////////////////////////////////////////////////////////////////////////////////////////////

	OnDispose();

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// インターフェースの解放
	////////////////////////////////////////////////////////////////////////////////////////////////////

	MIX_RELEASE( m_pFileMgr );
}

void Manager::MessageProc( UInt32 msg, WPARAM wParam, LPARAM lParam )
{
	Mix::Graphics::Common::Device* pDevice = GetDevicePtr();

	if( pDevice != NULL )
	{
		pDevice->MessageProc( msg, wParam, lParam );
	}
}

Manager::VERTEX_EFFECT* Manager::GetVertexEffectPtr( UInt32 opt )
{
	Manager::VertexEffectMap::iterator it = m_ResidentVEMap.find( opt );

	if( it == m_ResidentVEMap.end() )
	{
		Manager::SHADER_BINARY binarys[Manager::VES_MAX] = { NULL };
		UInt32 binaryCount = 0;

		const Mix::Graphics::VERTEX_ELEMENT* elements = NULL;
		UInt32 elementCount = 0;
		const wchar_t* pLayoutName = NULL;

		switch( opt )
		{
		case Manager::ER_CANVAS:
			GetShaderBinary( Manager::SHADER_CANVAS_VS, binarys[Manager::VES_DEFAULT] );
			binaryCount = 1;
			elements = &( VL_CANVAS[0] );
			elementCount = VL_CANVAS_COUNT;
			pLayoutName = VL_CANVAS_NAME;
			break;
		case Manager::ER_LINE:
			GetShaderBinary( Manager::SHADER_LINE_VS, binarys[Manager::VES_DEFAULT] );
			binaryCount = 1;
			elements = &( VL_LINE[0] );
			elementCount = VL_LINE_COUNT;
			pLayoutName = VL_LINE_NAME;
			break;
		}

		if( ( binaryCount > 0 ) &&
			( elementCount > 0 ) )
		{
			Boolean bSuccess = True;
			Manager::VERTEX_EFFECT ve;

			for( UInt32 i = 0; ( i < binaryCount ) && ( bSuccess == True ); i++ )
			{
				const Manager::SHADER_BINARY* psb = &( binarys[i] );

				if( GetDevicePtr()->CreateVertexShaderFromMemory( psb->pData, psb->dataSize, &( ve.pShader[i] ), psb->name ) == False )
				{
					bSuccess = False;
				}
			}

			if( bSuccess == True )
			{
				MIX_ASSERT( ve.pShader[Manager::VES_DEFAULT] != NULL );

				if( GetDevicePtr()->CreateVertexLayout( elements, elementCount, ve.pShader[Manager::VES_DEFAULT], &( ve.pLayout ), pLayoutName ) == False )
				{
					bSuccess = False;
				}
			}

			if( bSuccess == True )
			{
				m_ResidentVEMap.insert( Manager::VertexEffectMap::value_type( opt, ve ) );

				it = m_ResidentVEMap.find( opt );
				if( it == m_ResidentVEMap.end() )
				{
					ve.Dispose();
				}
			}
			else
			{
				ve.Dispose();
			}
		}
	}

	return ( it != m_ResidentVEMap.end() )? &( it->second ) : NULL;
}

Manager::PIXEL_EFFECT* Manager::GetPixelEffectPtr( UInt32 opt )
{
	Manager::PixelEffectMap::iterator it = m_ResidentPEMap.find( opt );

	if( it == m_ResidentPEMap.end() )
	{
		Manager::SHADER_BINARY binarys[Manager::PES_MAX] = { NULL };
		UInt32 binaryCount = 0;
		Boolean bSuccess = True;

		Manager::PIXEL_EFFECT pe;

		switch( opt )
		{
		case Manager::ER_CANVAS:
			GetShaderBinary( Manager::SHADER_CANVAS_COLOR_PS, binarys[Manager::PES_CANVAS_COLOR] );
			GetShaderBinary( Manager::SHADER_CANVAS_COLOR_AND_TEXTURE_PS, binarys[Manager::PES_CANVAS_COLOR_TEX] );
			binaryCount = 2;
			break;
		case Manager::ER_LINE:
			GetShaderBinary( Manager::SHADER_LINE_PS, binarys[Manager::PES_DEFAULT] );
			binaryCount = 1;
			break;
		}

		for( UInt32 i = 0; ( i < binaryCount ) && ( bSuccess == True ); i++ )
		{
			const Manager::SHADER_BINARY* psb = &( binarys[i] );

			if( GetDevicePtr()->CreatePixelShaderFromMemory( psb->pData, psb->dataSize, &( pe.pShader[i] ), psb->name ) == False )
			{
				bSuccess = False;
			}
		}

		if( bSuccess == True )
		{
			m_ResidentPEMap.insert( Manager::PixelEffectMap::value_type( opt, pe ) );

			it = m_ResidentPEMap.find( opt );
			if( it == m_ResidentPEMap.end() )
			{
				pe.Dispose();
			}
		}
		else
		{
			pe.Dispose();
		}
	}

	return ( it != m_ResidentPEMap.end() )? &( it->second ) : NULL;
}

void Manager::GetTextPrinter( Mix::Graphics::Utility::Common::TextPrinter** ppTextPrinter )
{
	MIX_ASSERT( ppTextPrinter != NULL );

	MIX_ADD_REF( m_pTextPrinter );
	( *ppTextPrinter ) = m_pTextPrinter;
}

const Mix::Graphics::Utility::Common::TextPrinter* Manager::GetTextPrinterPtr( void ) const
{
	return m_pTextPrinter;
}

Boolean Manager::GetDevice( Mix::Graphics::IDevice** ppDevice )
{
	Mix::Graphics::IDevice* pDevice = GetDevicePtr();

	MIX_ADD_REF( pDevice );
	( *ppDevice ) = pDevice;

	return True;
}

Boolean Manager::CreateTargetTextureChain(	UInt32 width,
											UInt32 height,
											Mix::Graphics::FORMAT format,
											Mix::Graphics::Utility::ITargetTextureChain** ppTargetTextureChain,
											const wchar_t* pDebugName )
{
	if( ( width == 0 ) ||
		( height == 0 ) ||
		( ppTargetTextureChain == NULL ) )
	{
		MIX_LOG_ERROR( L"%s : %s : %s[%s] : %s[%dx%d] ppTargetTextureChain[%s]", FAILED_CREATETARGETTEXTURECHAIN,
			Mix::STR_ILLEGALARG,
			Mix::STR_DEBUGNAME,
			MIX_SAFE_NAME( pDebugName ),
			Mix::STR_SIZE,
			width,
			height,
			MIX_LOG_PTR( ppTargetTextureChain ) );

		return False;
	}

	Mix::Graphics::Utility::Common::TargetTextureChain* pTargetTextureChain;

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// ログ( 開始 )
	////////////////////////////////////////////////////////////////////////////////////////////////////

	MIX_LOG_INFO_SECT_START( L"ターゲットテクスチャチェインの作成 : %s[%s] %s[%dx%d] %s[%s]",
		Mix::STR_DEBUGNAME,
		MIX_SAFE_NAME( pDebugName ),
		Mix::STR_SIZE,
		width,
		height,
		Mix::STR_FORMAT,
		GetDevicePtr()->GetFormatText( format ) );

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// 作成
	////////////////////////////////////////////////////////////////////////////////////////////////////

	pTargetTextureChain = Utility::Common::TargetTextureChain::CreateInstance();
	if( pTargetTextureChain == NULL )
	{
		MIX_LOG_ERROR( L"%s : %s[%s]", Mix::STR_OUTOFMEMORY, Mix::STR_DEBUGNAME, MIX_SAFE_NAME( pDebugName ) );
		MIX_LOG_INFO_SECT_END();
		return False;
	}

	if( pTargetTextureChain->Initialize( GetDevicePtr(), width, height, format, MIX_SAFE_NAME( pDebugName ) ) == False )
	{
		MIX_LOG_INFO_SECT_END();
		MIX_RELEASE( pTargetTextureChain );
		return False;
	}

	( *ppTargetTextureChain ) = pTargetTextureChain;

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// ログ( 終了 )
	////////////////////////////////////////////////////////////////////////////////////////////////////

	MIX_LOG_INFO_SECT_END();

	////////////////////////////////////////////////////////////////////////////////////////////////////

	return True;
}

Boolean Manager::CreateFontFromFile( const wchar_t* pFilePath, Mix::Graphics::Utility::IFont** ppFont )
{
	if( ( pFilePath == NULL ) ||
		( ::wcslen( pFilePath ) == 0 ) ||
		( ppFont == NULL ) )
	{
		MIX_LOG_ERROR( L"%s : %s : pFilePath[%s] ppFont[%s]", FAILED_CREATEFONT, Mix::STR_ILLEGALARG,
			MIX_LOG_STR( pFilePath ),
			MIX_LOG_PTR( ppFont ) );

		return False;
	}

	Mix::Memory::IBuffer* pBuffer;
	Mix::Graphics::Utility::Common::Font* pFont;

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// ログ( 開始 )
	////////////////////////////////////////////////////////////////////////////////////////////////////

	MIX_LOG_INFO_SECT_START( L"フォントの作成 : %s[%s]", Mix::STR_FILEPATH, pFilePath );

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// 作成
	////////////////////////////////////////////////////////////////////////////////////////////////////

	if( m_pFileMgr->CreateBufferFromFile( pFilePath, &pBuffer ) == False )
	{
		MIX_LOG_INFO_SECT_END();

		return False;
	}

	if( Mix::Graphics::Utility::Common::Font::CheckFormat( pBuffer ) == False )
	{
		MIX_LOG_INFO_SECT_END();
		MIX_RELEASE( pBuffer );
		return False;
	}

	pFont = Mix::Graphics::Utility::Common::Font::CreateInstance( pBuffer );
	if( pFont == NULL )
	{
		MIX_LOG_ERROR( L"%s : %s : %s[%s]", FAILED_CREATEFONT, Mix::STR_OUTOFMEMORY, Mix::STR_FILEPATH, pFilePath );
		MIX_LOG_INFO_SECT_END();
		MIX_RELEASE( pBuffer );
		return False;
	}

	( *ppFont ) = pFont;

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// ログ( 終了 )
	////////////////////////////////////////////////////////////////////////////////////////////////////

	MIX_LOG_INFO_SECT_END();

	////////////////////////////////////////////////////////////////////////////////////////////////////

	return True;
}

Boolean Manager::CreateFontFromMemory( const wchar_t* pFilePath, Mix::Memory::IBuffer* pBuffer, Mix::Graphics::Utility::IFont** ppFont )
{
	if( ( pFilePath == NULL ) ||
		( pBuffer == NULL ) ||
		( ppFont == NULL ) )
	{
		MIX_LOG_ERROR( L"%s : %s : pBuffer[%s] ppFont[%s]", FAILED_CREATEFONT, Mix::STR_ILLEGALARG,
			MIX_LOG_PTR( pBuffer ),
			MIX_LOG_PTR( ppFont ) );

		return False;
	}

	Mix::Graphics::Utility::Common::Font* pFont;

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// ログ( 開始 )
	////////////////////////////////////////////////////////////////////////////////////////////////////

	MIX_LOG_INFO_SECT_START( L"フォントの作成 : %s[%s]", Mix::STR_FILEPATH, pFilePath );

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// 作成
	////////////////////////////////////////////////////////////////////////////////////////////////////

	if( Mix::Graphics::Utility::Common::Font::CheckFormat( pBuffer ) == False )
	{
		MIX_LOG_ERROR( L"%s : 不正なフォント : %s[%s]", FAILED_CREATEFONT, Mix::STR_FILEPATH, pFilePath );
		MIX_LOG_INFO_SECT_END();
		MIX_RELEASE( pBuffer );
		return False;
	}

	pFont = Mix::Graphics::Utility::Common::Font::CreateInstance( pBuffer );
	if( pFont != NULL )
	{
		MIX_ADD_REF( pBuffer );
	}
	else
	{
		MIX_LOG_ERROR( L"%s : %s : %s[%s]", FAILED_CREATEFONT, Mix::STR_OUTOFMEMORY, Mix::STR_FILEPATH, pFilePath );
		MIX_LOG_INFO_SECT_END();
		MIX_RELEASE( pBuffer );
		return False;
	}

	( *ppFont ) = pFont;

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// ログ( 終了 )
	////////////////////////////////////////////////////////////////////////////////////////////////////

	MIX_LOG_INFO_SECT_END();

	////////////////////////////////////////////////////////////////////////////////////////////////////

	return True;
}

Boolean Manager::CreateCanvasRenderer( Mix::Graphics::Utility::ICanvasRenderer** ppCanvasRenderer, const wchar_t* pDebugName )
{
	if( ppCanvasRenderer == NULL )
	{
		MIX_LOG_ERROR( L"%s : %s : %s[%s] : ppCanvasRenderer[%s]", FAILED_CREATECANVAS,
			Mix::STR_ILLEGALARG,
			Mix::STR_DEBUGNAME,
			MIX_SAFE_NAME( pDebugName ),
			MIX_LOG_PTR( ppCanvasRenderer ) );

		return False;
	}

	Mix::Graphics::Utility::Common::CanvasRenderer* pCanvasRenderer = NULL;

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// ログ( 開始 )
	////////////////////////////////////////////////////////////////////////////////////////////////////

	MIX_LOG_INFO_SECT_START( L"キャンバスレンダラーの作成 : %s[%s]", Mix::STR_DEBUGNAME, MIX_SAFE_NAME( pDebugName ) );

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// インターフェースを作成
	////////////////////////////////////////////////////////////////////////////////////////////////////

	pCanvasRenderer = Mix::Graphics::Utility::Common::CanvasRenderer::CreateInstance( MIX_SAFE_NAME( pDebugName ) );
	if( pCanvasRenderer == NULL )
	{
		MIX_LOG_ERROR( L"%s : %s[%s]", Mix::STR_OUTOFMEMORY, Mix::STR_DEBUGNAME, MIX_SAFE_NAME( pDebugName ) );
		MIX_LOG_INFO_SECT_END();
		return False;
	}

	if( pCanvasRenderer->Initialize() == False )
	{
		MIX_LOG_INFO_SECT_END();
		return False;
	}

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// 譲渡
	////////////////////////////////////////////////////////////////////////////////////////////////////

	( *ppCanvasRenderer ) = pCanvasRenderer;

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// ログ( 終了 )
	////////////////////////////////////////////////////////////////////////////////////////////////////

	MIX_LOG_INFO_SECT_END();

	////////////////////////////////////////////////////////////////////////////////////////////////////

	return True;
}

Boolean Manager::CreatePerspectiveRenderer( Mix::Graphics::Utility::IPerspectiveRenderer** ppPerspectiveRenderer, const wchar_t* pDebugName )
{
	if( ppPerspectiveRenderer == NULL )
	{
		MIX_LOG_ERROR( L"%s : %s : Name[%s] : ppPerspectiveRenderer[%s]", FAILED_CREATELINEART, Mix::STR_ILLEGALARG,
			MIX_SAFE_NAME( pDebugName ),
			MIX_LOG_PTR( ppPerspectiveRenderer ) );

		return False;
	}

	Mix::Graphics::Utility::Common::PerspectiveRenderer* pPerspectiveRenderer = NULL;

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// ログ( 開始 )
	////////////////////////////////////////////////////////////////////////////////////////////////////

	MIX_LOG_INFO_SECT_START( L"パースペクティブレンダラーの作成 : Name[%s]", MIX_SAFE_NAME( pDebugName ) );

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// インターフェースを作成
	////////////////////////////////////////////////////////////////////////////////////////////////////

	pPerspectiveRenderer = Mix::Graphics::Utility::Common::PerspectiveRenderer::CreateInstance( MIX_SAFE_NAME( pDebugName ) );
	if( pPerspectiveRenderer == NULL )
	{
		MIX_LOG_ERROR( L"%s : %s : Name[%s]", FAILED_CREATELINEART, Mix::STR_OUTOFMEMORY, MIX_SAFE_NAME( pDebugName ) );
		MIX_LOG_INFO_SECT_END();
		return False;
	}

	if( pPerspectiveRenderer->Initialize( this, MIX_SAFE_NAME( pDebugName ) ) == False )
	{
		MIX_LOG_ERROR( L"%s : 初期化中にエラーが発生しました : Name[%s]", FAILED_CREATELINEART, MIX_SAFE_NAME( pDebugName ) );
		MIX_LOG_INFO_SECT_END();
		return False;
	}

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// 譲渡
	////////////////////////////////////////////////////////////////////////////////////////////////////

	( *ppPerspectiveRenderer ) = pPerspectiveRenderer;

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// ログ( 終了 )
	////////////////////////////////////////////////////////////////////////////////////////////////////

	MIX_LOG_INFO_SECT_END();

	////////////////////////////////////////////////////////////////////////////////////////////////////

	return True;
}

}}}
