#include "Mix/Private/Graphics/DX9/Device.h"

#include "Mix/ScopedLock.h"
#include "Mix/Memory/IBuffer.h"

#include "Mix/Private/UserFile.h"
#include "Mix/Private/Graphics/DX9/VertexLayout.h"
#include "Mix/Private/Graphics/DX9/VertexShader.h"
#include "Mix/Private/Graphics/DX9/PixelShader.h"
#include "Mix/Private/Graphics/DX9/VertexBuffer.h"
#include "Mix/Private/Graphics/DX9/IndexBuffer.h"
#include "Mix/Private/Graphics/DX9/TexturePlane.h"
#include "Mix/Private/Graphics/DX9/TextureVolume.h"
#include "Mix/Private/Graphics/DX9/TextureCube.h"
#include "Mix/Private/Graphics/DX9/TextureDynamic.h"
#include "Mix/Private/Graphics/DX9/TextureTarget.h"
#include "Mix/Private/Graphics/DX9/TextureTargetL.h"
#include "Mix/Private/Graphics/DX9/TextureDepth.h"
#include "Mix/Private/Graphics/DX9/Query.h"

namespace Mix{ namespace Graphics{ namespace DX9{

const char* Device::VS_UNKNOWN	= "";
const char* Device::VS_1_1		= "vs_1_1";
const char* Device::VS_2_A		= "vs_2_a";
const char* Device::VS_2_0		= "vs_2_0";
const char* Device::VS_3_0		= "vs_3_0";

const char* Device::PS_UNKNOWN	= "";
const char* Device::PS_1_1		= "ps_1_1";
const char* Device::PS_1_2		= "ps_1_2";
const char* Device::PS_1_3		= "ps_1_3";
const char* Device::PS_1_4		= "ps_1_4";
const char* Device::PS_2_A		= "ps_2_a";
const char* Device::PS_2_B		= "ps_2_b";
const char* Device::PS_2_0		= "ps_2_0";
const char* Device::PS_3_0		= "ps_3_0";

//D3D : バーテックスレイアウトのセマンティックタイプテーブル
const UInt8 Device::D3DVLSemanticTypeTable[Mix::Graphics::VERTEX_ELEMENT_SEMANTIC_MAX] =
{
	D3DDECLUSAGE_POSITION,
	D3DDECLUSAGE_BLENDWEIGHT,
	D3DDECLUSAGE_BLENDINDICES,
	D3DDECLUSAGE_NORMAL,
	D3DDECLUSAGE_PSIZE,
	D3DDECLUSAGE_TEXCOORD,
	D3DDECLUSAGE_TANGENT,
	D3DDECLUSAGE_BINORMAL,
	D3DDECLUSAGE_COLOR,
};

//D3D : バーテックスレイストのフォーマットテーブル
const UInt8 Device::D3DVLFormatTable[Mix::Graphics::VERTEX_ELEMENT_FORMAT_MAX] =
{
	D3DDECLTYPE_FLOAT1,
	D3DDECLTYPE_FLOAT2,
	D3DDECLTYPE_FLOAT3,
	D3DDECLTYPE_FLOAT4,
	D3DDECLTYPE_UBYTE4,
	D3DDECLTYPE_SHORT2,
	D3DDECLTYPE_SHORT4,
	D3DDECLTYPE_UBYTE4N,
	D3DDECLTYPE_SHORT2N,
	D3DDECLTYPE_SHORT4N,
	D3DDECLTYPE_USHORT2N,
	D3DDECLTYPE_USHORT4N,
	D3DDECLTYPE_FLOAT16_2,
	D3DDECLTYPE_FLOAT16_4,
};

//D3D : フォーマットテキスト
const wchar_t* Device::D3DFormatTextArray[20] =
{
	L"UNKNOWN",
	L"X8R8G8B8",
	L"A8R8G8B8",
	L"X1R5G5B5",
	L"R5G6B5",
	L"A8",
	L"R16F",
	L"R32F",
	L"G16R16F",
	L"G32R32F",
	L"A16B16G16R16F",
	L"A32B32G32R32F",
	L"BC1 ( DXT1 )",
	L"BC1 ( DXT2 )",
	L"BC2 ( DXT3 )",
	L"BC2 ( DXT4 )",
	L"BC3 ( DXT5 )",
	L"D16",
	L"D32",
	L"D24S8",
};

//D3D : リザルトテキスト配列
const wchar_t* Device::D3DResultTextArray[6] =
{
	L"不明なエラーが発生しました",
	L"サブシステム内で原因不明のエラーが発生しました",
	L"デバイスは、照会されたテクニックをサポートしていません",
	L"ビデオメモリが不足しています",
	L"メソッドの呼び出しが無効です( パラメータに無効な値が設定されている可能性があります )",
	L"システムメモリが不足しています",
};

//D3D : カリングモードテーブル
const UInt32 Device::D3DCullModeTable[] =
{
	D3DCULL_NONE,
	D3DCULL_CW,
	D3DCULL_CCW,
};

//D3D : Zファンクションテーブル
const UInt32 Device::D3DZFuncTable[Mix::Graphics::ZFUNC_MAX] =
{
	D3DCMP_ALWAYS,
	D3DCMP_NEVER,
	D3DCMP_LESS,
	D3DCMP_EQUAL,
	D3DCMP_LESSEQUAL,
	D3DCMP_GREATER,
	D3DCMP_NOTEQUAL,
	D3DCMP_GREATEREQUAL,
};

//D3D : プリミティブタイプテーブル
const D3DPRIMITIVETYPE Device::D3DPrimitiveTypeTable[Mix::Graphics::PT_MAX] =
{
	D3DPT_POINTLIST,
	D3DPT_LINELIST,
	D3DPT_LINESTRIP,
	D3DPT_TRIANGLELIST,
	D3DPT_TRIANGLESTRIP,
};

//D3D : クエリタイプテーブル
const D3DQUERYTYPE Device::D3DQueryTypeTable[Mix::Graphics::QT_MAX] =
{
	D3DQUERYTYPE_EVENT,
	D3DQUERYTYPE_OCCLUSION,
};

//D3D : クエリ名テーブル
const wchar_t* Device::D3DQueryTextTable[Mix::Graphics::QT_MAX] =
{
	L"EVENT",
	L"OCCLUSION",
};

//D3D : キューブテクスチャフェイステーブル
const D3DCUBEMAP_FACES Device::D3DCubeFaceTable[] =
{
	D3DCUBEMAP_FACE_POSITIVE_X,
	D3DCUBEMAP_FACE_NEGATIVE_X,
	D3DCUBEMAP_FACE_POSITIVE_Y,
	D3DCUBEMAP_FACE_NEGATIVE_Y,
	D3DCUBEMAP_FACE_POSITIVE_Z,
	D3DCUBEMAP_FACE_NEGATIVE_Z,
};
const UInt32 Device::D3DCubeFaceCount = sizeof( D3DCubeFaceTable ) / sizeof( D3DCUBEMAP_FACES );

////////////////////////////////////////////////////////////////////////////////////////////////////
// Mix::Graphics::DX9::Device
////////////////////////////////////////////////////////////////////////////////////////////////////

Device* Device::CreateInstance( Boolean bWaitVSync )
{
	return MIX_LIB_NEW_T( Mix::Memory::SECTION_GRAPHICS, Device, bWaitVSync );
}

Device::Device( Boolean bWaitVSync ) : Common::Device( bWaitVSync ),
m_pD3D( NULL ),
m_pD3DDevice( NULL ),
m_pD3DBackBuffer( NULL ),
m_Status( STATUS_OK ),
m_DrawPrimitiveCount( 0 )
{
	UInt32 i;

	::ZeroMemory( &m_Caps, sizeof( m_Caps ) );

	//ビューポートを初期化
	m_Viewport.X = 0;
	m_Viewport.Y = 0;
	m_Viewport.Width = 0;
	m_Viewport.Height = 0;
	m_Viewport.MinZ = 0.0f;
	m_Viewport.MaxZ = 1.0f;

	//ラスタライザステートを初期化
	m_RasterizeDesc.fillMode = Mix::Graphics::FILL_SOLID;
	m_RasterizeDesc.cullMode = Mix::Graphics::CULL_BACK;
	m_RasterizeDesc.bScissoring = False;

	//デプスステートを初期化
	m_DepthDesc.bTest = True;
	m_DepthDesc.bWrite = True;
	m_DepthDesc.func = Mix::Graphics::ZFUNC_LESSEQUAL;

	//ブレンドステートを初期化
	m_BlendDesc.type = Mix::Graphics::BLEND_COPY;
	m_BlendDesc.colorWriteMask = Mix::Graphics::COLOR_WRITE_RGBA;

	//ターゲットステートを初期化
	m_TargetState.rect = Mix::Rectangle( 0, 0, 0, 0 );
	for( i = 0; i < Mix::Graphics::TARGET_MAX; i++ )
	{
		m_TargetState.pTex[i] = NULL;
	}
	m_TargetState.pDSTex = NULL;
}

Device::~Device( void )
{
}

Boolean Device::EnumDisplay( Mix::UserFile* pSysReport )
{
	Mix::String strTemp;
	std::list<D3DFORMAT> adapFormatList;
	UInt32 adapModeCount;
	UInt32 i;
	UInt32 j;
	UInt32 k;

	//アダプタ、バックバッファフォーマットテーブル
	const D3DFORMAT abFormatTable[] =
	{
		D3DFMT_X8R8G8B8,
		D3DFMT_X1R5G5B5,
		D3DFMT_R5G6B5,
	};
	const UInt32 MAX_ABFORMAT = ( sizeof( abFormatTable ) / sizeof( D3DFORMAT ) );

	//テクスチャフォーマットテーブル
	const D3DFORMAT texFormatTable[] =
	{
		D3DFMT_A8R8G8B8,
		D3DFMT_A8,
		D3DFMT_R16F,
		D3DFMT_R32F,
		D3DFMT_G16R16F,
		D3DFMT_G32R32F,
		D3DFMT_A16B16G16R16F,
		D3DFMT_A32B32G32R32F,
		D3DFMT_DXT1,
		D3DFMT_DXT2,
		D3DFMT_DXT3,
		D3DFMT_DXT4,
		D3DFMT_DXT5,
	};
	const UInt32 MAX_TEXFORMAT = ( sizeof( texFormatTable ) / sizeof( D3DFORMAT ) );

	//ターゲットテクスチャフォーマットリスト
	const D3DFORMAT targetFormatTable[] =
	{
		D3DFMT_A8R8G8B8,
		D3DFMT_R16F,
		D3DFMT_R32F,
		D3DFMT_G16R16F,
		D3DFMT_G32R32F,
		D3DFMT_A16B16G16R16F,
		D3DFMT_A32B32G32R32F,
	};
	const UInt32 MAX_TARGETFORMAT = ( sizeof( targetFormatTable ) / sizeof( D3DFORMAT ) );

	//キューブテクスチャフォーマットリスト
	const D3DFORMAT cubeTexFormatTable[] =
	{
		D3DFMT_A8R8G8B8,
		D3DFMT_R16F,
		D3DFMT_R32F,
		D3DFMT_G16R16F,
		D3DFMT_G32R32F,
		D3DFMT_A16B16G16R16F,
		D3DFMT_A32B32G32R32F,
	};
	const UInt32 MAX_CUBETEXFORMAT = ( sizeof( cubeTexFormatTable ) / sizeof( D3DFORMAT ) );

	//デプスステンシルフォーマットテーブル
	const D3DFORMAT dsFormatTable[] =
	{
		D3DFMT_D16,			//デプス(16ビット) ステンシル(無し)
		D3DFMT_D32,			//デプス(32ビット) ステンシル(無し)
		D3DFMT_D24S8,		//デプス(24ビット) ステンシル(8ビット)
	};
	const UInt32 MAX_DSFORMAT = ( sizeof( dsFormatTable ) / sizeof( D3DFORMAT ) );

	//CheckDeviceFormat 用のテーブル
	const DEVFORMAT DEVFORMAT_TABLE[] =
	{
		{ FLAG_RESOURCE_SURFACE,                     0, D3DRTYPE_SURFACE },
		{ FLAG_RESOURCE_PLANE,                       0, D3DRTYPE_TEXTURE },
		{ FLAG_RESOURCE_VOLUME,                      0, D3DRTYPE_VOLUMETEXTURE },
		{ FLAG_RESOURCE_CUBE,                        0, D3DRTYPE_CUBETEXTURE },
		{ FLAG_RESOURCE_DYNAMIC,      D3DUSAGE_DYNAMIC, D3DRTYPE_TEXTURE },
		{ FLAG_RESOURCE_TARGET,  D3DUSAGE_RENDERTARGET, D3DRTYPE_TEXTURE },
		{ FLAG_RESOURCE_TARGET,  D3DUSAGE_RENDERTARGET, D3DRTYPE_SURFACE },
		{ FLAG_RESOURCE_TARGET,  D3DUSAGE_RENDERTARGET, D3DRTYPE_CUBETEXTURE },
	};
	const UInt32 MAX_DEVFORMAT = ( sizeof( DEVFORMAT_TABLE ) / sizeof( DEVFORMAT ) );

	//ディスプレイモードを列挙
	for( i = 0; i < MAX_ABFORMAT; i++ )
	{
		D3DFORMAT eAdapterFormat = abFormatTable[i];

		adapModeCount = m_pD3D->GetAdapterModeCount( 0, eAdapterFormat );
		for( j = 0; j < adapModeCount; j++ )
		{
			D3DDISPLAYMODE sDispMode;

			//ディスプレイモードを取得
			::ZeroMemory( &sDispMode, sizeof( sDispMode ) );
			if( m_pD3D->EnumAdapterModes( 0, eAdapterFormat, j, &sDispMode ) != D3D_OK )
			{
				continue;
			}

			//画面サイズのチェック
			if( ( static_cast<UInt32>( m_TargetSize.x ) > sDispMode.Width ) ||
				( static_cast<UInt32>( m_TargetSize.y ) > sDispMode.Height ) )
			{
				continue;
			}

			//アダプターフォーマット
			std::list<D3DFORMAT>::iterator it;
			for( it = adapFormatList.begin(); it != adapFormatList.end(); ++it )
			{
				if( ( *it ) == sDispMode.Format )
				{
					break;
				}
			}
			if( it == adapFormatList.end() )
			{
				adapFormatList.push_back( sDispMode.Format );
			}

			//ディスプレイモード
			m_DisplayModeList.push_back( sDispMode );
		}
	}

	//ディスプレイモードリストをソート
	m_DisplayModeList.sort( SORT_DISPLAYMODE() );

	//ディスプレイモードリストをレポート
	if( pSysReport->Open() == True )
	{
		wchar_t formatStr[12];

		pSysReport->WriteLine( L"[ディスプレイモード一覧]" );

		for( DisplayModeList::iterator it = m_DisplayModeList.begin(); it != m_DisplayModeList.end(); ++it )
		{
			switch( ( *it ).Format )
			{
			case D3DFMT_A2R10G10B10:
				::wcscpy_s( formatStr, L"A2R10G10B10" );
				break;
			case D3DFMT_X8R8G8B8:
				::wcscpy_s( formatStr, L"X8R8G8B8" );
				break;
			case D3DFMT_X1R5G5B5:
				::wcscpy_s( formatStr, L"X1R5G5B5" );
				break;
			case D3DFMT_R5G6B5:
				::wcscpy_s( formatStr, L"R5G6B5" );
				break;
			default:
				::wcscpy_s( formatStr, L"UNKNOWN" );
			}

			pSysReport->WriteLine( L"  Width[%d] Height[%d] RefreshRate[%d] Format[%s]", ( *it ).Width, ( *it ).Height, ( *it ).RefreshRate, formatStr );
		}

		pSysReport->WriteLine( L"" );
		pSysReport->Close();
	}

	//デバイスコンボを作成
	for( std::list<D3DFORMAT>::iterator it = adapFormatList.begin(); it != adapFormatList.end(); ++it )
	{
		D3DFORMAT adapterFormat = ( *it );

		for( j = 0; j < MAX_ABFORMAT; j++ )
		{
			D3DFORMAT backBufferFormat = abFormatTable[j];
			DEVICECOMBO devCombo;

			//アダプタとバックバッファのフォーマットが一致しないものはスキップ
			if( adapterFormat != backBufferFormat )
			{
				continue;
			}

			//初期化
			devCombo.flags = 0;
			devCombo.adapterFormat = adapterFormat;
			devCombo.backBufferFormat = backBufferFormat;
			devCombo.formatTable[Mix::Graphics::FMT_UNKNOWN].format			= D3DFMT_UNKNOWN;
			devCombo.formatTable[Mix::Graphics::FMT_UNKNOWN].flags			= 0;
			devCombo.formatTable[Mix::Graphics::FMT_D16].format				= D3DFMT_D16;
			devCombo.formatTable[Mix::Graphics::FMT_D16].flags				= 0;
			devCombo.formatTable[Mix::Graphics::FMT_D32].format				= D3DFMT_D32;
			devCombo.formatTable[Mix::Graphics::FMT_D32].flags				= 0;
			devCombo.formatTable[Mix::Graphics::FMT_D24S8].format			= D3DFMT_D24S8;
			devCombo.formatTable[Mix::Graphics::FMT_D24S8].flags			= 0;
			devCombo.formatTable[Mix::Graphics::FMT_R8G8B8A8].format		= D3DFMT_A8R8G8B8;
			devCombo.formatTable[Mix::Graphics::FMT_R8G8B8A8].flags			= 0;
			devCombo.formatTable[Mix::Graphics::FMT_A8].format				= D3DFMT_A8;
			devCombo.formatTable[Mix::Graphics::FMT_A8].flags				= 0;
			devCombo.formatTable[Mix::Graphics::FMT_R16F].format			= D3DFMT_R16F;
			devCombo.formatTable[Mix::Graphics::FMT_R16F].flags				= 0;
			devCombo.formatTable[Mix::Graphics::FMT_R32F].format			= D3DFMT_R32F;
			devCombo.formatTable[Mix::Graphics::FMT_R32F].flags				= 0;
			devCombo.formatTable[Mix::Graphics::FMT_R16G16F].format			= D3DFMT_G16R16F;
			devCombo.formatTable[Mix::Graphics::FMT_R16G16F].flags			= 0;
			devCombo.formatTable[Mix::Graphics::FMT_R32G32F].format			= D3DFMT_G32R32F;
			devCombo.formatTable[Mix::Graphics::FMT_R32G32F].flags			= 0;
			devCombo.formatTable[Mix::Graphics::FMT_R16G16B16A16F].format	= D3DFMT_A16B16G16R16F;
			devCombo.formatTable[Mix::Graphics::FMT_R16G16B16A16F].flags	= 0;
			devCombo.formatTable[Mix::Graphics::FMT_R32G32B32A32F].format	= D3DFMT_A32B32G32R32F;
			devCombo.formatTable[Mix::Graphics::FMT_R32G32B32A32F].flags	= 0;
			devCombo.formatTable[Mix::Graphics::FMT_BC1].format				= D3DFMT_DXT1;
			devCombo.formatTable[Mix::Graphics::FMT_BC1].flags				= 0;
			devCombo.formatTable[Mix::Graphics::FMT_BC2].format				= D3DFMT_DXT3;
			devCombo.formatTable[Mix::Graphics::FMT_BC2].flags				= 0;
			devCombo.formatTable[Mix::Graphics::FMT_BC3].format				= D3DFMT_DXT5;
			devCombo.formatTable[Mix::Graphics::FMT_BC3].flags				= 0;

			//ウィンドウモードのチェック
			if( ( m_pD3D->CheckDeviceType(	0,
											D3DDEVTYPE_HAL,
											adapterFormat,
											backBufferFormat,
											True ) == D3D_OK ) )
			{
				devCombo.flags |= FLAG_MODE_WINDOW;
			}

			//フルスクリーンモードのチェック
			if( ( m_pD3D->CheckDeviceType(	0,
											D3DDEVTYPE_HAL,
											adapterFormat,
											backBufferFormat,
											False ) == D3D_OK ) )
			{
				devCombo.flags |= FLAG_MODE_FULLSCREEN;
			}

			//デプスステンシルフォーマットの列挙
			for( k = 0; k < MAX_DSFORMAT; k++ )
			{
				D3DFORMAT dsFormat = dsFormatTable[k];

				if( m_pD3D->CheckDeviceFormat(	0,
												D3DDEVTYPE_HAL,
												adapterFormat,
												D3DUSAGE_DEPTHSTENCIL,
												D3DRTYPE_SURFACE,
												dsFormat ) != D3D_OK )
				{
					continue;
				}

				if( m_pD3D->CheckDepthStencilMatch(	0,
													D3DDEVTYPE_HAL,
													adapterFormat,
													backBufferFormat,
													dsFormat ) != D3D_OK )
				{
					continue;
				}

				switch( dsFormat )
				{
				case D3DFMT_D16:
					devCombo.formatTable[Mix::Graphics::FMT_D16].flags |= FLAG_RESOURCE_DEPTHSTENCIL;
					break;
				case D3DFMT_D32:
					devCombo.formatTable[Mix::Graphics::FMT_D32].flags |= FLAG_RESOURCE_DEPTHSTENCIL;
					break;
				case D3DFMT_D24S8:
					devCombo.formatTable[Mix::Graphics::FMT_D24S8].flags |= FLAG_RESOURCE_DEPTHSTENCIL;
					break;
				}
			}

			//テクスチャ、サーフェイスのフォーマットの列挙
			for( k = 0; k < MAX_DEVFORMAT; k++ )
			{
				const DEVFORMAT& devFmt = DEVFORMAT_TABLE[k];

				for( UInt32 l = 0; l < MAX_TEXFORMAT; l++ )
				{
					D3DFORMAT texFmt = texFormatTable[l];

					if( m_pD3D->CheckDeviceFormat(	0,
													D3DDEVTYPE_HAL,
													adapterFormat,
													devFmt.usage,
													devFmt.resType,
													texFmt ) == D3D_OK )
					{
						MIX_SETBIT( devCombo.formatTable[ConvertTextureFormat( texFmt )].flags, devFmt.flag );
					}
				}
			}

			m_DeviceComboList.push_back( devCombo );
		}
	}

	return True;
}

Boolean Device::CreatePresentation( Boolean bWindowed )
{
	DEVICECOMBO* pBestDevCombo = NULL;
	UInt32 width = 0;
	UInt32 height = 0;
	UInt32 refreshRate = 0;
	UInt32 interval = 0;

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// 最適なデバイスコンボを取得
	////////////////////////////////////////////////////////////////////////////////////////////////////

	if( bWindowed == True )
	{
		for( DeviceComboList::iterator it = m_DeviceComboList.begin(); ( it != m_DeviceComboList.end() ) && ( pBestDevCombo == NULL ); ++it )
		{
			DEVICECOMBO* pDevCombo = &( *it );

			if( MIX_TESTBIT( pDevCombo->flags, FLAG_MODE_WINDOW ) == FLAG_MODE_WINDOW )
			{
				pBestDevCombo = pDevCombo;
			}
		}

		if( pBestDevCombo == NULL )
		{
			return False;
		}

		width = m_TargetSize.x;
		height = m_TargetSize.y;
		refreshRate = 0;
		interval = D3DPRESENT_INTERVAL_IMMEDIATE;
	}
	else
	{
		D3DDISPLAYMODE desktopMode;
		D3DDISPLAYMODE* pBestDispMode = NULL;
		Boolean bFindBestDevCombo = False;

		//デスクトップのモードを取得
		if( m_pD3D->GetAdapterDisplayMode( 0, &desktopMode ) != D3D_OK )
		{
			return False;
		}

		//現在のディスプレイモードとマッチするデバイスコンボを探す
		for( DeviceComboList::iterator it = m_DeviceComboList.begin(); ( it != m_DeviceComboList.end() ) && ( bFindBestDevCombo == False ); ++it )
		{
			DEVICECOMBO* pDevCombo = &( *it );

			if( MIX_TESTBIT( pDevCombo->flags, FLAG_MODE_FULLSCREEN ) != FLAG_MODE_FULLSCREEN )
			{
				continue;
			}

			Boolean bMatchesBackBuffer = ( pDevCombo->backBufferFormat == pDevCombo->adapterFormat );
			Boolean bMatchesDesktop = ( pDevCombo->adapterFormat == desktopMode.Format );

			if( ( pBestDevCombo == NULL ) ||
				( ( pBestDevCombo->adapterFormat != desktopMode.Format ) && ( bMatchesDesktop == True ) ||
				( ( bMatchesBackBuffer == True ) && ( bMatchesDesktop == True ) ) ) )
			{
				pBestDevCombo = pDevCombo;
				if( ( bMatchesBackBuffer == True ) &&
					( bMatchesDesktop == True ) )
				{
					bFindBestDevCombo = True;
				}
			}
		}

		//最適なディスプレイモードを探す
		for( DisplayModeList::iterator it = m_DisplayModeList.begin(); ( it != m_DisplayModeList.end() ) && ( pBestDispMode == NULL ); ++it )
		{
			D3DDISPLAYMODE* pDispMode = &( *it );

			//フォーマットチェック
			if( pDispMode->Format != pBestDevCombo->adapterFormat )
			{
				continue;
			}

			//リフレッシュレートのチェック
			if( desktopMode.RefreshRate != pDispMode->RefreshRate )
			{
				continue;
			}

			//サイズのチェック
			if( ( static_cast<UInt32>( m_TargetSize.x ) > pDispMode->Width ) ||
				( static_cast<UInt32>( m_TargetSize.y ) > pDispMode->Height ) )
			{
				continue;
			}

			pBestDispMode = pDispMode;
		}

		if( pBestDispMode == NULL )
		{
			return False;
		}

		width = pBestDispMode->Width;
		height = pBestDispMode->Height;
		refreshRate = pBestDispMode->RefreshRate;
		interval = ( m_bWaitVSync == True )? D3DPRESENT_INTERVAL_DEFAULT : D3DPRESENT_INTERVAL_IMMEDIATE;
	}

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// プレゼンテーションパラメータを設定
	////////////////////////////////////////////////////////////////////////////////////////////////////

	m_DeviceParam.next.screenSize.x = width;
	m_DeviceParam.next.screenSize.y = height;
	m_DeviceParam.next.formatTable = &( pBestDevCombo->formatTable[0] );
	m_DeviceParam.next.params.Windowed = bWindowed;
	m_DeviceParam.next.params.BackBufferCount = 1;
	m_DeviceParam.next.params.SwapEffect = ( m_pEngine->IsSizeableWindow() == True )? D3DSWAPEFFECT_COPY : D3DSWAPEFFECT_DISCARD;
	m_DeviceParam.next.params.hDeviceWindow = m_pEngine->GetWindowHandle();
	m_DeviceParam.next.params.EnableAutoDepthStencil = FALSE;
	m_DeviceParam.next.params.AutoDepthStencilFormat = D3DFMT_UNKNOWN;
	m_DeviceParam.next.params.Flags = 0;
	m_DeviceParam.next.params.MultiSampleType = D3DMULTISAMPLE_NONE;
	m_DeviceParam.next.params.MultiSampleQuality = 0;
	m_DeviceParam.next.params.BackBufferWidth = width;
	m_DeviceParam.next.params.BackBufferHeight = height;
	m_DeviceParam.next.params.BackBufferFormat = pBestDevCombo->backBufferFormat;
	m_DeviceParam.next.params.FullScreen_RefreshRateInHz = refreshRate;
	m_DeviceParam.next.params.PresentationInterval = interval;

	return True;
}

void Device::ChangePresentation( Boolean bWindowed )
{
	HRESULT hRet;

	if( CreatePresentation( bWindowed ) == True )
	{
		ResetDrawState();
		ResetSamplerState();
		ResetRenderState();

		//バックバッファを解放
		MIX_RELEASE( m_pD3DBackBuffer );

		//デバイスオブジェクトを無効にする
		InvalidateDeviceObject();

		//ウィンドウ→フルスクリーンの場合は、リセット前にウィンドウスタイルを変更する
		if( m_DeviceParam.next.params.Windowed == False )
		{
			m_pEngine->SetWindowStyle( m_DeviceParam.next.params.Windowed );
		}

		//リセット
		hRet = m_pD3DDevice->Reset( &( m_DeviceParam.next.params ) );
		if( hRet == D3D_OK )
		{
			//フルスクリーン→ウィンドウの場合は、リセット後にウィンドウスタイルを変更する
			if( m_DeviceParam.next.params.Windowed == True )
			{
				m_pEngine->SetWindowStyle( m_DeviceParam.next.params.Windowed );
			}

			m_DeviceParam.current = m_DeviceParam.next;

			TracePresentation( L"グラフィックデバイスの設定を変更" );
		}
		else
		{
			//ウィンドウ→フルスクリーンの場合は、リセット前にウィンドウスタイルを変更する
			if( m_DeviceParam.current.params.Windowed == False )
			{
				m_pEngine->SetWindowStyle( m_DeviceParam.current.params.Windowed );
			}

			//再リセット
			hRet = m_pD3DDevice->Reset( &( m_DeviceParam.current.params ) );
			if( hRet == D3D_OK )
			{
				//フルスクリーン→ウィンドウの場合は、リセット後にウィンドウスタイルを変更する
				if( m_DeviceParam.current.params.Windowed == True )
				{
					m_pEngine->SetWindowStyle( m_DeviceParam.current.params.Windowed );
				}
			}
		}

		if( hRet == D3D_OK )
		{
			//バックバッファを再取得
			m_pD3DDevice->GetBackBuffer( 0, 0, D3DBACKBUFFER_TYPE_MONO, &m_pD3DBackBuffer );

			//デバイスオブジェクトを有効にする
			ValidateDeviceObject();

			//描画先ターゲットをフラッシュ
			FlushTargetState();

			m_Status = Device::STATUS_OK;
		}
		else
		{
			::SendMessage( m_pEngine->GetWindowHandle(), WM_MIX_INTERNALERROR, Mix::ERR_GRAPHICS_CHANGEMODE, 0 );
		}
	}
}

void Device::ResetPresentation( void )
{
	HRESULT hRet;

	hRet = m_pD3DDevice->TestCooperativeLevel();
	if( hRet != D3D_OK )
	{
		if( hRet == D3DERR_DEVICENOTRESET )
		{
			ResetDrawState();
			ResetSamplerState();
			ResetRenderState();

			MIX_RELEASE( m_pD3DBackBuffer );

			InvalidateDeviceObject();

			hRet = m_pD3DDevice->Reset( &( m_DeviceParam.current.params ) );

			switch( hRet )
			{
			case D3D_OK:
				m_pD3DDevice->GetBackBuffer( 0, 0, D3DBACKBUFFER_TYPE_MONO, &m_pD3DBackBuffer );
				ValidateDeviceObject();
				FlushTargetState();
				m_Status = Device::STATUS_OK;
				break;

			case D3DERR_DEVICELOST:
				::SleepEx( 200, TRUE );
				break;
			}
		}
		else
		{
			::SleepEx( 200, TRUE );
		}
	}
	else
	{
		m_Status = Device::STATUS_OK;
	}
}

void Device::TracePresentation( const wchar_t* pTitle )
{
	MIX_ASSERT( pTitle != NULL );

	int refreshRate;

	if( m_DeviceParam.current.params.Windowed == True )
	{
		HDC hDC = ::GetDC( m_pEngine->GetWindowHandle() );
		if( hDC != NULL )
		{
			refreshRate = ::GetDeviceCaps( hDC, VREFRESH );
			::ReleaseDC( m_pEngine->GetWindowHandle(), hDC );
		}
		else
		{
			refreshRate = 0;
		}
	}
	else
	{
		refreshRate = static_cast<UINT>( m_DeviceParam.current.params.FullScreen_RefreshRateInHz );
	}

	MIX_LOG_INFO( L"%s : Mode[%s] Size[%dx%d] BackBufferFormat[%s] RefreshRate[%dHz]",
		pTitle,
		( m_DeviceParam.current.params.Windowed == True )? L"Window" : L"Fullscreen",
		m_DeviceParam.current.params.BackBufferWidth,
		m_DeviceParam.current.params.BackBufferHeight,
		GetD3DFormatText( m_DeviceParam.current.params.BackBufferFormat ),
		refreshRate );
}

void Device::ResetTargetState( void )
{
	UInt32 i;

	m_TargetState.rect = Mix::Rectangle( 0, 0, m_DeviceParam.current.screenSize.x, m_DeviceParam.current.screenSize.y );

	m_pD3DDevice->SetRenderTarget( 0, m_pD3DBackBuffer );
	MIX_RELEASE( m_TargetState.pTex[0] );

	for( i = 1; i < Mix::Graphics::TARGET_MAX; i++ )
	{
		m_pD3DDevice->SetRenderTarget( i, NULL );
		MIX_RELEASE( m_TargetState.pTex[i] );
	}

	m_pD3DDevice->SetDepthStencilSurface( NULL );
	MIX_RELEASE( m_TargetState.pDSTex );
}

void Device::FlushTargetState( void )
{
	UInt32 i;
	
	for( i = 0; i < Mix::Graphics::TARGET_MAX; i++ )
	{
		IDirect3DSurface9* pD3DSurface = NULL;

		if( m_TargetState.pTex[i] != NULL )
		{
			pD3DSurface = static_cast<Mix::Graphics::DX9::Texture*>( m_TargetState.pTex[i] )->GetSurface();
		}
		else if( i == 0 )
		{
			pD3DSurface = m_pD3DBackBuffer;
		}

		m_pD3DDevice->SetRenderTarget( i, pD3DSurface );
	}

	if( m_TargetState.pDSTex != NULL )
	{
		m_pD3DDevice->SetDepthStencilSurface( static_cast<Mix::Graphics::DX9::TextureDepth*>( m_TargetState.pDSTex )->GetSurface( 0 ) );
	}
	else
	{
		m_pD3DDevice->SetDepthStencilSurface( NULL );
	}
}

void Device::ResetRenderState( void )
{
	UInt32 i;
	DWORD value;

	for( i = 0; i < Device::RENDERSTATETYPE_MAX; i++ )
	{
		m_RenderStateTable[i].value = m_RenderStateTable[i].defValue;
	}

	if( ( m_pD3DDevice->GetRenderState( D3DRS_LIGHTING, &value ) == D3D_OK ) &&
		( value == TRUE ) )
	{
		m_pD3DDevice->SetRenderState( D3DRS_LIGHTING, FALSE );
	}

	m_RasterizeDesc.fillMode = Mix::Graphics::FILL_SOLID;
	m_RasterizeDesc.cullMode = Mix::Graphics::CULL_BACK;
	m_RasterizeDesc.bScissoring = False;

	m_DepthDesc.bTest = False;
	m_DepthDesc.bWrite = True;
	m_DepthDesc.func = Mix::Graphics::ZFUNC_LESSEQUAL;

	m_BlendDesc.type = Mix::Graphics::BLEND_COPY;
	m_BlendDesc.colorWriteMask = Mix::Graphics::COLOR_WRITE_RGBA;
}

void Device::ResetRenderState( RENDERSTATETYPE type )
{
	RENDERSTATE* pRenderState = &( m_RenderStateTable[type] );

	if( ( pRenderState->value != pRenderState->defValue ) &&
		( m_pD3DDevice->SetRenderState( pRenderState->type, pRenderState->defValue ) == D3D_OK ) )
	{
		pRenderState->value = pRenderState->defValue;
	}
}

void Device::SetRenderState( RENDERSTATETYPE type, UInt32 value )
{
	RENDERSTATE* pRenderState;
	
	pRenderState = &( m_RenderStateTable[type] );

	if( ( pRenderState->value != value ) &&
		( m_pD3DDevice->SetRenderState( pRenderState->type, value ) == D3D_OK ) )
	{
		pRenderState->value = value;
	}
}

void Device::ResetSamplerState( void )
{
	UInt32 i;
	UInt32 j;

	for( i = 0; i < Mix::Graphics::TEXTURESTAGE_MAX; i++ )
	{
		for( j = 0; j < Device::SAMPLERSTATETYPE_MAX; j++ )
		{
			m_SamplerStateTable[i][j].value = m_SamplerStateTable[i][j].defValue;
		}
	}
}

void Device::SetSamplerState( UInt32 slot, SAMPLERSTATETYPE type, UInt32 value )
{
	SAMPLERSTATE* pSamplerState;

	pSamplerState = &( m_SamplerStateTable[slot][type] );

	if( ( pSamplerState->value != value ) &&
		( m_pD3DDevice->SetSamplerState( slot, pSamplerState->type, value ) == D3D_OK ) )
	{
		pSamplerState->value = value;
	}
}

void Device::ResetDrawState( void )
{
	UInt32 i;

	m_DrawState.current.pVertexLayout = NULL;
	m_DrawState.current.pVertexShader = NULL;
	m_DrawState.current.pPixelShader = NULL;
	m_DrawState.current.pVertexBuffer = NULL;
	m_DrawState.current.pIndexBuffer = NULL;

	m_DrawState.next.pVertexLayout = NULL;
	m_DrawState.next.pVertexShader = NULL;
	m_DrawState.next.pPixelShader = NULL;
	m_DrawState.next.pVertexBuffer = NULL;
	m_DrawState.next.pIndexBuffer = NULL;

	if( m_pD3DDevice != NULL )
	{
		for( i = 0; i < Mix::Graphics::TEXTURESTAGE_MAX; i++ )
		{
			m_DrawState.textureTable[i] = NULL;
			m_pD3DDevice->SetTexture( i, NULL );
		}
	}
	else
	{
		for( i = 0; i < Mix::Graphics::TEXTURESTAGE_MAX; i++ )
		{
			m_DrawState.textureTable[i] = NULL;
		}
	}
}

void Device::FlushDrawState( void )
{
	//頂点レイアウトの設定
	if( ( m_DrawState.next.pVertexLayout != NULL ) &&
		( m_DrawState.current.pVertexLayout != m_DrawState.next.pVertexLayout ) )
	{
		m_pD3DDevice->SetVertexDeclaration( static_cast<Mix::Graphics::DX9::VertexLayout*>( m_DrawState.next.pVertexLayout )->GetInterface() );
		m_DrawState.current.pVertexLayout = m_DrawState.next.pVertexLayout;
	}

	//バーテックスシェーダーの設定
	if( ( m_DrawState.next.pVertexShader != NULL ) &&
		( m_DrawState.current.pVertexShader != m_DrawState.next.pVertexShader ) )
	{
		m_pD3DDevice->SetVertexShader( static_cast<Mix::Graphics::DX9::VertexShader*>( m_DrawState.next.pVertexShader )->GetInsterface() );
		m_DrawState.current.pVertexShader = m_DrawState.next.pVertexShader;
	}

	//ピクセルシェーダーの設定
	if( ( m_DrawState.next.pPixelShader != NULL ) &&
		( m_DrawState.current.pPixelShader != m_DrawState.next.pPixelShader ) )
	{
		m_pD3DDevice->SetPixelShader( static_cast<Mix::Graphics::DX9::PixelShader*>( m_DrawState.next.pPixelShader )->GetInsterface() );
		m_DrawState.current.pPixelShader = m_DrawState.next.pPixelShader;
	}

	//頂点バッファの設定
	if( ( m_DrawState.next.pVertexBuffer != NULL ) &&
		( m_DrawState.current.pVertexBuffer != m_DrawState.next.pVertexBuffer ) )
	{
		m_pD3DDevice->SetStreamSource( 0, static_cast<Mix::Graphics::DX9::VertexBuffer*>( m_DrawState.next.pVertexBuffer )->GetInterface(), 0, m_DrawState.next.pVertexBuffer->GetStride() );
		m_DrawState.current.pVertexBuffer = m_DrawState.next.pVertexBuffer;
	}

	//インデックスバッファの設定
	if( ( m_DrawState.next.pIndexBuffer != NULL ) &&
		( m_DrawState.current.pIndexBuffer != m_DrawState.next.pIndexBuffer ) )
	{
		m_pD3DDevice->SetIndices( static_cast<Mix::Graphics::DX9::IndexBuffer*>( m_DrawState.next.pIndexBuffer )->GetInterface() );
		m_DrawState.current.pIndexBuffer = m_DrawState.next.pIndexBuffer;
	}
}

UInt32 Device::ComputePrimitiveCount( Mix::Graphics::PRIMITIVE_TYPE primitiveType, UInt32 num )
{
	UInt32 count = 0;

	switch( primitiveType )
	{
	case PRIMITIVE_POINTLIST:
		count = num;
		break;
	case PRIMITIVE_LINELIST:
		count = ( num >> 1 );
		break;
	case PRIMITIVE_LINESTRIP:
		if( num >= 2 )
		{
			count = ( num - 1 );
		}
		break;
	case PRIMITIVE_TRIANGLELIST:
		count = ( num / 3 );
		break;
	case PRIMITIVE_TRIANGLESTRIP:
		if( num >= 3 )
		{
			count = ( num - 2 );
		}
		break;
	}

	return count;
}

void Device::AdjustTexturePow2( UInt32& width, UInt32& height )
{
	UInt32 i;

	//幅
	for( i = 1; i < m_Caps.MaxTextureWidth; i += i )
	{
		if( i >= width )
		{
			width = i;
			break;
		}
	}

	//高さ
	for( i = 1; i < m_Caps.MaxTextureHeight; i += i )
	{
		if( i >= height )
		{
			height = i;
			break;
		}
	}
}

void Device::AdjustTextureSquare( UInt32& width, UInt32& height )
{
	//正方形に修正
	UInt32 temp = max( width, height );
	width = temp;
	height = temp;
}

const char* Device::GetVertexShaderProfile( void )
{
	D3DCAPS9 caps;

	if( m_pD3DDevice->GetDeviceCaps( &caps ) == D3D_OK )
	{
		return Device::VS_UNKNOWN;
	}

	switch( caps.VertexShaderVersion )
	{
	case D3DVS_VERSION( 1, 1 ):
		return Device::VS_1_1;

	case D3DVS_VERSION( 2, 0 ):
		if( ( caps.VS20Caps.NumTemps >= 13 ) &&
			( caps.VS20Caps.DynamicFlowControlDepth == 24 ) &&
			( caps.VS20Caps.Caps & D3DPS20CAPS_PREDICATION ) )
		{
			return Device::VS_2_A;
		}
		else
		{
			return Device::VS_2_0;
		}

	case D3DVS_VERSION( 3, 0 ):
		return Device::VS_3_0;
	}

	return Device::VS_UNKNOWN;
}

const char* Device::GetPixelShaderProfile( void )
{
	D3DCAPS9 caps;

	if( m_pD3DDevice->GetDeviceCaps( &caps ) != D3D_OK )
	{
		return Device::PS_UNKNOWN;
	}

	switch( caps.PixelShaderVersion )
	{
	case D3DPS_VERSION( 1, 1 ):
		return Device::PS_1_1;

	case D3DPS_VERSION( 1, 2 ):
		return Device::PS_1_2;

	case D3DPS_VERSION( 1, 3 ):
		return Device::PS_1_3;

	case D3DPS_VERSION( 1, 4 ):
		return Device::PS_1_4;

	case D3DPS_VERSION( 2, 0 ):
		if( ( caps.PS20Caps.NumTemps >= 22 ) &&
			( caps.PS20Caps.Caps & D3DPS20CAPS_ARBITRARYSWIZZLE ) &&
			( caps.PS20Caps.Caps & D3DPS20CAPS_GRADIENTINSTRUCTIONS ) &&
			( caps.PS20Caps.Caps & D3DPS20CAPS_PREDICATION ) &&
			( caps.PS20Caps.Caps & D3DPS20CAPS_NODEPENDENTREADLIMIT ) &&
			( caps.PS20Caps.Caps & D3DPS20CAPS_NOTEXINSTRUCTIONLIMIT ) )
		{
			return Device::PS_2_A;
		}
		else if(	( caps.PS20Caps.NumTemps >= 32 ) &&
					( caps.PS20Caps.Caps & D3DPS20CAPS_NOTEXINSTRUCTIONLIMIT ) )
		{
			return Device::PS_2_B;
		}
		else
		{
			return Device::PS_2_0;
		}

	case D3DPS_VERSION( 3, 0 ):
		return Device::PS_3_0;
	}

	return Device::PS_UNKNOWN;
}

void Device::UpdateScreenValidRect( void )
{
	Mix::Point size = m_pEngine->GetClientSize();

	Int32 sw = static_cast<Int32>( m_DeviceParam.current.params.BackBufferWidth );
	Int32 sh = static_cast<Int32>( m_DeviceParam.current.params.BackBufferHeight );
	Int32 vw = min( sw, size.x );
	Int32 vh = min( sh, size.y );

	m_ScreenValidBounds.x = max( 0, ( sw - size.x ) / 2 );
	m_ScreenValidBounds.y = max( 0, ( sh - size.y ) / 2 );
	m_ScreenValidBounds.width = vw;
	m_ScreenValidBounds.height = vh;
}

HRESULT Device::CreateVertexBuffer( UInt32 count, UInt32 stride, Boolean bDynamic, IDirect3DVertexBuffer9** ppVertexBuffer )
{
	UInt32 size = ( stride * count );
	UInt32 usage = ( bDynamic == True )? D3DUSAGE_DYNAMIC : 0;
	D3DPOOL poolArray[] = { D3DPOOL_DEFAULT, D3DPOOL_SYSTEMMEM, };
	UInt32 numPool = ( sizeof( poolArray ) / sizeof( D3DPOOL ) );
	UInt32 i;
	HRESULT hRet;

	for( i = 0; i < numPool; i++ )
	{
		hRet = m_pD3DDevice->CreateVertexBuffer( size, D3DUSAGE_WRITEONLY | usage, 0, poolArray[i], ppVertexBuffer, NULL );
		if( hRet == D3D_OK )
		{
			break;
		}
	}

	return hRet;
}

HRESULT Device::CreateIndexBuffer( D3DFORMAT format, UInt32 count, Boolean bDynamic, IDirect3DIndexBuffer9** ppIndexBuffer )
{
	if( ( format != D3DFMT_INDEX16 ) &&
		( format != D3DFMT_INDEX32 ) )
	{
		return D3DERR_INVALIDCALL;
	}

	UInt32 stride = ( format == D3DFMT_INDEX16 )? 2 : 4;
	UInt32 size = ( stride * count );
	UInt32 usage = ( bDynamic == True )? D3DUSAGE_DYNAMIC : 0;
	D3DPOOL poolArray[] = { D3DPOOL_DEFAULT, D3DPOOL_SYSTEMMEM, };
	UInt32 numPool = ( sizeof( poolArray ) / sizeof( D3DPOOL ) );
	UInt32 i;
	HRESULT hRet;

	for( i = 0; i < numPool; i++ )
	{
		hRet = m_pD3DDevice->CreateIndexBuffer( size, D3DUSAGE_WRITEONLY | usage, format, poolArray[i], ppIndexBuffer, NULL );
		if( hRet == D3D_OK )
		{
			break;
		}
	}

	return hRet;
}

HRESULT Device::CreateDynamicTexture( UInt32& width, UInt32& height, D3DFORMAT format, IDirect3DTexture9** ppTexture )
{
	D3DPOOL poolArray[] = { D3DPOOL_DEFAULT, D3DPOOL_MANAGED, };
	UInt32 poolNum = ( sizeof( poolArray ) / sizeof( D3DPOOL ) );
	UInt32 usage;
	UInt32 i;
	HRESULT hRet;

	if( ( m_Caps.TextureCaps & D3DPTEXTURECAPS_POW2 ) == D3DPTEXTURECAPS_POW2 )
	{
		//2のべき乗に修正
		AdjustTexturePow2( width, height );
	}
	if( ( m_Caps.TextureCaps & D3DPTEXTURECAPS_SQUAREONLY ) == D3DPTEXTURECAPS_SQUAREONLY )
	{
		//正方形に修正
		AdjustTextureSquare( width, height );
	}

	for( i = 0; i < poolNum; i++ )
	{
		usage = ( poolArray[i] != D3DPOOL_MANAGED )? D3DUSAGE_DYNAMIC : 0;

		hRet = m_pD3DDevice->CreateTexture(	width,
											height,
											1,
											usage,
											format,
											poolArray[i],
											ppTexture,
											NULL );
		if( hRet == D3D_OK )
		{
			break;
		}
	}

	return hRet;
}

HRESULT Device::CreateCubeTexture( UInt32 edgeLength, D3DFORMAT format, IDirect3DCubeTexture9** ppTexture )
{
	return m_pD3DDevice->CreateCubeTexture( edgeLength, 1, D3DUSAGE_RENDERTARGET, format, D3DPOOL_DEFAULT, ppTexture, NULL );
}

HRESULT Device::CreateTargetTexture( UInt32& width, UInt32& height, D3DFORMAT format, IDirect3DTexture9** ppTexture )
{
	if( ( m_Caps.MaxTextureWidth < width ) ||
		( m_Caps.MaxTextureHeight < height ) )
	{
		//テクスチャサイズを飽和( アスペクト比を維持 )
		Float32 ratio;

		if( ( m_Caps.MaxTextureWidth < width ) &&
			( m_Caps.MaxTextureHeight >= height ) )
		{
			ratio = static_cast<Float32>( m_Caps.MaxTextureWidth ) / static_cast<Float32>( width );
		}
		else if( ( m_Caps.MaxTextureWidth >= width ) &&
				( m_Caps.MaxTextureHeight < height ) )
		{
			ratio = static_cast<Float32>( m_Caps.MaxTextureHeight ) / static_cast<Float32>( height );
		}
		else
		{
			if( ( width - m_Caps.MaxTextureWidth ) >= ( height - m_Caps.MaxTextureHeight ) )
			{
				ratio = static_cast<Float32>( m_Caps.MaxTextureWidth ) / static_cast<Float32>( width );
			}
			else
			{
				ratio = static_cast<Float32>( m_Caps.MaxTextureHeight ) / static_cast<Float32>( height );
			}
		}

		width = static_cast<UInt32>( static_cast<Float32>( width ) * ratio );
		height = static_cast<UInt32>( static_cast<Float32>( height ) * ratio );
	}

	if( ( m_Caps.TextureCaps & D3DPTEXTURECAPS_POW2 ) == D3DPTEXTURECAPS_POW2 )
	{
		//2のべき乗に修正
		AdjustTexturePow2( width, height );
	}
	if( ( m_Caps.TextureCaps & D3DPTEXTURECAPS_SQUAREONLY ) == D3DPTEXTURECAPS_SQUAREONLY )
	{
		//正方形に修正
		AdjustTextureSquare( width, height );
	}

	return m_pD3DDevice->CreateTexture( width, height, 1, D3DUSAGE_RENDERTARGET, format, D3DPOOL_DEFAULT, ppTexture, NULL );
}

HRESULT Device::CreateTargetSurface( UInt32 width, UInt32 height, D3DFORMAT format, IDirect3DSurface9** ppSurface )
{
	IDirect3DSurface9* pD3DSurface = NULL;
	HRESULT hRet;

	hRet = m_pD3DDevice->CreateRenderTarget( width, height, format, D3DMULTISAMPLE_NONE, 0, TRUE, &pD3DSurface, NULL );
	if( hRet != D3D_OK )
	{
		return hRet;
	}

	( *ppSurface ) = pD3DSurface;

	return hRet;
}

HRESULT Device::CreateDepthTexture( UInt32 width, UInt32 height, D3DFORMAT format, IDirect3DSurface9** ppSurface )
{
	return m_pD3DDevice->CreateDepthStencilSurface( width, height, format, D3DMULTISAMPLE_NONE, 0, FALSE, ppSurface, NULL );
}

HRESULT Device::CreateQuery( Mix::Graphics::QUERY_FORMAT format, IDirect3DQuery9** ppQuery )
{
	return m_pD3DDevice->CreateQuery( Device::D3DQueryTypeTable[format], ppQuery );
}

Mix::Graphics::FORMAT Device::ConvertTextureFormat( D3DFORMAT d3dFormat )
{
	switch( d3dFormat )
	{
	case D3DFMT_D16:
		return Mix::Graphics::FMT_D16;
	case D3DFMT_D32:
		return Mix::Graphics::FMT_D32;
	case D3DFMT_D24S8:
		return Mix::Graphics::FMT_D24S8;

	case D3DFMT_A8R8G8B8:
		return Mix::Graphics::FMT_R8G8B8A8;
	case D3DFMT_A8:
		return Mix::Graphics::FMT_A8;
	case D3DFMT_R16F:
		return Mix::Graphics::FMT_R16F;
	case D3DFMT_R32F:
		return Mix::Graphics::FMT_R32F;
	case D3DFMT_G16R16F:
		return Mix::Graphics::FMT_R16G16F;
	case D3DFMT_G32R32F:
		return Mix::Graphics::FMT_R32G32F;
	case D3DFMT_A16B16G16R16F:
		return Mix::Graphics::FMT_R16G16B16A16F;
	case D3DFMT_A32B32G32R32F:
		return Mix::Graphics::FMT_R32G32B32A32F;

	case D3DFMT_DXT1:
		return Mix::Graphics::FMT_BC1;
	case D3DFMT_DXT3:
		return Mix::Graphics::FMT_BC2;
	case D3DFMT_DXT5:
		return Mix::Graphics::FMT_BC3;
	}

	return Mix::Graphics::FMT_UNKNOWN;
}

const wchar_t* Device::GetD3DFormatText( D3DFORMAT fmt )
{
	switch( fmt )
	{
		case D3DFMT_X8R8G8B8:
			return Device::D3DFormatTextArray[1];
		case D3DFMT_A8R8G8B8:
			return Device::D3DFormatTextArray[2];
		case D3DFMT_X1R5G5B5:
			return Device::D3DFormatTextArray[3];
		case D3DFMT_R5G6B5:
			return Device::D3DFormatTextArray[4];
		case D3DFMT_A8:
			return Device::D3DFormatTextArray[5];
		case D3DFMT_R16F:
			return Device::D3DFormatTextArray[6];
		case D3DFMT_R32F:
			return Device::D3DFormatTextArray[7];
		case D3DFMT_G16R16F:
			return Device::D3DFormatTextArray[8];
		case D3DFMT_G32R32F:
			return Device::D3DFormatTextArray[9];
		case D3DFMT_A16B16G16R16F:
			return Device::D3DFormatTextArray[10];
		case D3DFMT_A32B32G32R32F:
			return Device::D3DFormatTextArray[11];
		case D3DFMT_DXT1:
			return Device::D3DFormatTextArray[12];
		case D3DFMT_DXT2:
			return Device::D3DFormatTextArray[13];
		case D3DFMT_DXT3:
			return Device::D3DFormatTextArray[14];
		case D3DFMT_DXT4:
			return Device::D3DFormatTextArray[15];
		case D3DFMT_DXT5:
			return Device::D3DFormatTextArray[16];
		case D3DFMT_D16:
			return Device::D3DFormatTextArray[17];
		case D3DFMT_D32:
			return Device::D3DFormatTextArray[18];
		case D3DFMT_D24S8:
			return Device::D3DFormatTextArray[19];
	}

	return Device::D3DFormatTextArray[0];
}

const wchar_t* Device::GetD3DResultText( HRESULT result )
{
	switch( result )
	{
	case E_FAIL:
		return Device::D3DResultTextArray[1];
	case D3DERR_NOTAVAILABLE:
		return Device::D3DResultTextArray[2];
	case D3DERR_OUTOFVIDEOMEMORY:
		return Device::D3DResultTextArray[3];
	case D3DERR_INVALIDCALL:
		return Device::D3DResultTextArray[4];
	case E_OUTOFMEMORY:
		return Device::D3DResultTextArray[5];
	}

	return Device::D3DResultTextArray[0];
}

const wchar_t* Device::GetQueryText( Mix::Graphics::QUERY_FORMAT format )
{
	return Device::D3DQueryTextTable[format];
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// Mix::Graphics::Common::Device
////////////////////////////////////////////////////////////////////////////////////////////////////

Mix::Graphics::ITexture* Device::CreatePlaneTexture(	const wchar_t* pFilePath,
														const Device::TEXTURE_DESC& desc,
														UInt32 subResourceCount,
														const Device::TEXTURE_SUBRESOURCE_DATA* subResources )
{
	if( IsPlaneTextureSupported( desc.format ) == False )
	{
		MIX_LOG_ERROR( L"%s : %s : %s[%s] %s[%d]", FAILED_CREATE_TEXTURE_PLANE,
			Mix::STR_FORMAT_NOT_SUPPORT,
			Mix::STR_FILEPATH, pFilePath, Mix::STR_FORMAT, GetFormatText( desc.format ) );

		return NULL;
	}

	D3DFORMAT d3dFormat = m_DeviceParam.current.formatTable[desc.format].format;
	IDirect3DTexture9* pD3DTex = NULL;
	Mix::Graphics::DX9::TexturePlane* pTex = NULL;
	HRESULT ret;

	ret = m_pD3DDevice->CreateTexture( desc.width, desc.height, subResourceCount, 0, d3dFormat, D3DPOOL_MANAGED, &pD3DTex, NULL );
	if( ret != D3D_OK )
	{
		MIX_LOG_ERROR( L"%s : IDirect3DDevice9::CreateTexture %s : %s[%s] %s[%s]", FAILED_CREATE_TEXTURE_PLANE,
			Mix::STR_RETERROR, Mix::STR_FILEPATH, pFilePath, Mix::STR_RESULT, GetD3DResultText( ret ) );

		return NULL;
	}

	if( desc.format == Mix::Graphics::FMT_R8G8B8A8 )
	{
		D3DLOCKED_RECT lockedRect;

		for( UInt32 i = 0; i < desc.mipLevels; i++ )
		{
			if( pD3DTex->LockRect( i, &lockedRect, NULL, 0 ) == D3D_OK )
			{
				const Device::TEXTURE_SUBRESOURCE_DATA& src = subResources[i];

				Device::CopyTexture_R8G8B8A8( lockedRect.pBits, lockedRect.Pitch, src.pMem, src.memSize, src.memRowPitch );

				pD3DTex->UnlockRect( i );
			}
		}
	}
	else if(	( desc.format == Mix::Graphics::FMT_BC1 ) ||
				( desc.format == Mix::Graphics::FMT_BC2 ) ||
				( desc.format == Mix::Graphics::FMT_BC3 ) )
	{
		D3DLOCKED_RECT lockedRect;

		for( UInt32 i = 0; i < desc.mipLevels; i++ )
		{
			const Device::TEXTURE_SUBRESOURCE_DATA& src = subResources[i];

			if( pD3DTex->LockRect( i, &lockedRect, NULL, 0 ) == D3D_OK )
			{
				Mix::Memory::Copy( lockedRect.pBits, src.pMem, src.memSize );
				pD3DTex->UnlockRect( i );
			}
		}
	}
	else
	{
		MIX_LOG_ERROR( L"%s : %s : %s[%s] %s[%d]", FAILED_CREATE_TEXTURE_PLANE,
			Mix::STR_FORMAT_NOT_SUPPORT,
			Mix::STR_FILEPATH, pFilePath, Mix::STR_FORMAT, GetFormatText( desc.format ) );

		MIX_RELEASE( pD3DTex );

		return NULL;
	}

	pTex = Mix::Graphics::DX9::TexturePlane::CreateInstance( this, pFilePath, desc.width, desc.height, desc.format, pD3DTex, d3dFormat );
	if( pTex == NULL )
	{
		MIX_LOG_ERROR( L"%s : %s : %s[%s]", FAILED_CREATE_TEXTURE_PLANE, Mix::STR_OUTOFMEMORY, Mix::STR_FILEPATH, pFilePath );
		MIX_RELEASE( pD3DTex );
		return NULL;
	}

	return pTex;
}

Mix::Graphics::ITexture* Device::CreateVolumeTexture(	const wchar_t* pFilePath,
														const Device::TEXTURE_DESC& desc,
														UInt32 subResourceCount,
														const Device::TEXTURE_SUBRESOURCE_DATA* subResources )
{
	if( IsVolumeTextureSupported( desc.format ) == False )
	{
		MIX_LOG_ERROR( L"%s : %s : %s[%s] %s[%d]", FAILED_CREATE_TEXTURE_VOLUME,
			Mix::STR_FORMAT_NOT_SUPPORT,
			Mix::STR_FILEPATH, pFilePath, Mix::STR_FORMAT, GetFormatText( desc.format ) );

		return NULL;
	}

	D3DFORMAT d3dFormat = m_DeviceParam.current.formatTable[desc.format].format;
	IDirect3DVolumeTexture9* pD3DTex = NULL;
	Mix::Graphics::DX9::TextureVolume* pTex = NULL;
	HRESULT ret;

	ret = m_pD3DDevice->CreateVolumeTexture( desc.width, desc.height, desc.depth, desc.mipLevels, 0, d3dFormat, D3DPOOL_MANAGED, &pD3DTex, NULL );
	if( ret != D3D_OK )
	{
		MIX_LOG_ERROR( L"%s : IDirect3DDevice9::CreateVolumeTexture %s : %s[%s] %s[%s]", FAILED_CREATE_TEXTURE_VOLUME,
			Mix::STR_RETERROR, Mix::STR_FILEPATH, pFilePath, Mix::STR_RESULT, GetD3DResultText( ret ) );

		return NULL;
	}

	UInt32 sliceCount = desc.depth;
	D3DLOCKED_BOX lockedBox;
	const UInt8* pSrc;
	UInt8* pDst;

	if( desc.format == Mix::Graphics::FMT_R8G8B8A8 )
	{
		for( UInt32 i = 0; i < desc.mipLevels; i++ )
		{
			if( pD3DTex->LockBox( i, &lockedBox, NULL, 0 ) == D3D_OK )
			{
				const Device::TEXTURE_SUBRESOURCE_DATA& src = subResources[i];
				MIX_ASSERT( lockedBox.SlicePitch >= static_cast<Int32>( src.memSlicePitch ) );

				pSrc = static_cast<const UInt8*>( src.pMem );
				pDst = static_cast<UInt8*>( lockedBox.pBits );

				for( UInt32 j = 0; j < sliceCount; j++ )
				{
					Device::CopyTexture_R8G8B8A8( pDst, lockedBox.RowPitch, pSrc, src.memSlicePitch, src.memRowPitch );

					pSrc += src.memSlicePitch;
					pDst += lockedBox.SlicePitch;
				}

				pD3DTex->UnlockBox( i );
				sliceCount = max( 1, sliceCount >> 1 );
			}
		}
	}
	else if(	( desc.format == Mix::Graphics::FMT_BC1 ) ||
				( desc.format == Mix::Graphics::FMT_BC2 ) ||
				( desc.format == Mix::Graphics::FMT_BC3 ) )
	{
		for( UInt32 i = 0; i < desc.mipLevels; i++ )
		{
			if( pD3DTex->LockBox( i, &lockedBox, NULL, 0 ) == D3D_OK )
			{
				const Device::TEXTURE_SUBRESOURCE_DATA& src = subResources[i];
				MIX_ASSERT( lockedBox.SlicePitch >= static_cast<Int32>( src.memSlicePitch ) );

				pSrc = static_cast<const UInt8*>( src.pMem );
				pDst = static_cast<UInt8*>( lockedBox.pBits );

				for( UInt32 j = 0; j < sliceCount; j++ )
				{
					Mix::Memory::Copy( pDst, pSrc, src.memSlicePitch );

					pSrc += src.memSlicePitch;
					pDst += lockedBox.SlicePitch;
				}

				pD3DTex->UnlockBox( i );
				sliceCount = max( 1, sliceCount >> 1 );
			}
		}
	}
	else
	{
		MIX_LOG_ERROR( L"%s : %s : %s[%s] %s[%d]", FAILED_CREATE_TEXTURE_VOLUME,
			Mix::STR_FORMAT_NOT_SUPPORT, Mix::STR_FILEPATH, pFilePath, Mix::STR_FORMAT, GetFormatText( desc.format ) );

		MIX_RELEASE( pD3DTex );

		return NULL;
	}

	pTex = Mix::Graphics::DX9::TextureVolume::CreateInstance( this, pFilePath, desc.width, desc.height, desc.format, pD3DTex );
	if( pTex == NULL )
	{
		MIX_LOG_ERROR( L"%s : %s : %s[%s]", FAILED_CREATE_TEXTURE_VOLUME, Mix::STR_OUTOFMEMORY, Mix::STR_FILEPATH, pFilePath );
		MIX_RELEASE( pD3DTex );
		return NULL;
	}

	return pTex;
}

Mix::Graphics::ITexture* Device::CreateCubeTexture(	const wchar_t* pFilePath,
													const Device::TEXTURE_DESC& desc,
													UInt32 subResourceCount,
													const Device::TEXTURE_SUBRESOURCE_DATA* subResources )
{
	if( IsCubeTextureSupported( desc.format ) == False )
	{
		MIX_LOG_ERROR( L"%s : %s : %s[%s] %s[%d]", FAILED_CREATE_TEXTURE_CUBE,
			Mix::STR_FORMAT_NOT_SUPPORT,
			Mix::STR_FILEPATH, pFilePath, Mix::STR_FORMAT, GetFormatText( desc.format ) );

		return NULL;
	}

	D3DFORMAT d3dFormat = m_DeviceParam.current.formatTable[desc.format].format;
	IDirect3DCubeTexture9* pD3DTex = NULL;
	Mix::Graphics::DX9::TextureCube* pTex = NULL;
	HRESULT ret;

	ret = m_pD3DDevice->CreateCubeTexture( desc.width, desc.mipLevels, 0, d3dFormat, D3DPOOL_MANAGED, &pD3DTex, NULL );
	if( ret != D3D_OK )
	{
		MIX_LOG_ERROR( L"%s : IDirect3DDevice9::CreateTexture %s : %s[%s] Result[%s]", FAILED_CREATE_TEXTURE_CUBE,
			Mix::STR_RETERROR, Mix::STR_FILEPATH, pFilePath, GetD3DResultText( ret ) );

		return NULL;
	}

	if( desc.format == Mix::Graphics::FMT_R8G8B8A8 )
	{
		UInt32 faceCount = 0;

		for( UInt32 i = 0; i < Device::D3DCubeFaceCount; i++ )
		{
			UInt32 cubeFaceMask = 1 << i;

			if( MIX_TESTBIT( desc.flags, cubeFaceMask ) == cubeFaceMask )
			{
				D3DCUBEMAP_FACES cubeFace = Device::D3DCubeFaceTable[i];

				for( UInt32 j = 0; j < desc.mipLevels; j++ )
				{
					D3DLOCKED_RECT lockedRect;

					if( pD3DTex->LockRect( cubeFace, j, &lockedRect, NULL, 0 ) == D3D_OK )
					{
						const Device::TEXTURE_SUBRESOURCE_DATA& src = subResources[faceCount * desc.mipLevels + j];

						Device::CopyTexture_R8G8B8A8( lockedRect.pBits, lockedRect.Pitch, src.pMem, src.memSize, src.memRowPitch );

						pD3DTex->UnlockRect( cubeFace, j );
					}
				}

				faceCount++;
			}
		}
	}
	else if(	( desc.format == Mix::Graphics::FMT_BC1 ) ||
				( desc.format == Mix::Graphics::FMT_BC2 ) ||
				( desc.format == Mix::Graphics::FMT_BC3 ) )
	{
		UInt32 faceCount = 0;

		for( UInt32 i = 0; i < Device::D3DCubeFaceCount; i++ )
		{
			UInt32 cubeFaceMask = 1 << i;

			if( MIX_TESTBIT( desc.flags, cubeFaceMask ) == cubeFaceMask )
			{
				D3DCUBEMAP_FACES cubeFace = Device::D3DCubeFaceTable[i];

				for( UInt32 j = 0; j < desc.mipLevels; j++ )
				{
					D3DLOCKED_RECT lockedRect;

					if( pD3DTex->LockRect( cubeFace, j, &lockedRect, NULL, 0 ) == D3D_OK )
					{
						const Device::TEXTURE_SUBRESOURCE_DATA& src = subResources[faceCount * desc.mipLevels + j];

						Mix::Memory::Copy( lockedRect.pBits, src.pMem, src.memSize );

						pD3DTex->UnlockRect( cubeFace, j );
					}
				}

				faceCount++;
			}
		}
	}
	else
	{
		MIX_LOG_ERROR( L"%s : %s : %s[%s] %s[%d]", FAILED_CREATE_TEXTURE_CUBE,
			Mix::STR_FORMAT_NOT_SUPPORT,
			Mix::STR_FILEPATH, pFilePath, Mix::STR_FORMAT, GetFormatText( desc.format ) );

		MIX_RELEASE( pD3DTex );

		return NULL;
	}

	pTex = Mix::Graphics::DX9::TextureCube::CreateInstance( this, pFilePath, desc.width, desc.format, d3dFormat, pD3DTex );
	if( pTex == NULL )
	{
		MIX_LOG_ERROR( L"%s : %s : %s[%s]", FAILED_CREATE_TEXTURE_CUBE, Mix::STR_OUTOFMEMORY, Mix::STR_FILEPATH, pFilePath );
		MIX_RELEASE( pD3DTex );
		return NULL;
	}

	return pTex;
}

void Device::CopyTexture_R8G8B8A8( void* pTex, UInt32 texPitch, const void* pMem, UInt32 memSize, UInt32 memPitch )
{
	unsigned int height = memSize / memPitch;

	const UInt8* pSrc = reinterpret_cast<const UInt8*>( pMem );
	UInt8* pDst = reinterpret_cast<UInt8*>( pTex );

	for( UInt32 y = 0; y < height; y++ )
	{
		Mix::Memory::Copy( pDst, pSrc, memPitch );

		pDst += texPitch;
		pSrc += memPitch;
	}
}

Boolean Device::Initialize( const Mix::Point& targetSize, Mix::Graphics::SHADER_MODEL shaderModel, Boolean bFullscreen, Mix::UserFile* pSysReport )
{
	MIX_ASSERT( shaderModel == Mix::Graphics::SHADER_MODEL_3 );

	//レンダーステートタイプテーブル(D3D)
	const D3DRENDERSTATETYPE renderStateTypeTable[Device::RENDERSTATETYPE_MAX] =
	{
		D3DRS_FILLMODE,
		D3DRS_CULLMODE,
		D3DRS_SCISSORTESTENABLE,
		D3DRS_MULTISAMPLEANTIALIAS,
		D3DRS_ZENABLE,
		D3DRS_ZWRITEENABLE,
		D3DRS_ZFUNC,
		D3DRS_ALPHABLENDENABLE,
		D3DRS_SRCBLEND,
		D3DRS_DESTBLEND,
		D3DRS_BLENDOP,
		D3DRS_SRCBLENDALPHA,
		D3DRS_DESTBLENDALPHA,
		D3DRS_BLENDOPALPHA,
		D3DRS_COLORWRITEENABLE,
	};

	//サンプラーステートタイプテーブル(D3D)
	const D3DSAMPLERSTATETYPE samplerStateTypeTable[Device::SAMPLERSTATETYPE_MAX] =
	{
		D3DSAMP_MAGFILTER,
		D3DSAMP_MINFILTER,
		D3DSAMP_MIPFILTER,
		D3DSAMP_ADDRESSU,
		D3DSAMP_ADDRESSV,
		D3DSAMP_ADDRESSW,
		D3DSAMP_MAXANISOTROPY,
	};

	const UInt32 vpTable[] =
	{
		D3DCREATE_HARDWARE_VERTEXPROCESSING,
		D3DCREATE_MIXED_VERTEXPROCESSING,
		D3DCREATE_SOFTWARE_VERTEXPROCESSING,
	};
	const UInt32 MAX_VP = ( sizeof( vpTable ) / sizeof( UInt32 ) );

	UInt32 i;
	UInt32 j;
	HRESULT hRet;
	Boolean bCreateDevice = False;
	Mix::String moduleName;

	UInt32 backBuffWidth;
	UInt32 backBuffHeight;

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// D3D9 モジュール
	////////////////////////////////////////////////////////////////////////////////////////////////////

	// ロード

#ifdef _DEBUG
	if( m_D3D9Module.Load( L"d3d9d.dll" ) == True )
	{
	}
	else if( m_D3D9Module.Load( L"d3d9.dll" ) == True )
	{
		MIX_LOG_INFO( L"リリース版 DirectX9 モジュールを使用します" );
	}
	else
	{
		::MessageBox( m_pEngine->GetWindowHandle(), L"DirectX が正しくインストールされていません D3D9(1)", Mix::STR_ERROR, MB_OK | MB_ICONSTOP );
		return False;
	}
#else //_DEBUG
	if( m_D3D9Module.Load( L"d3d9.dll" ) == False )
	{
		::MessageBox( m_pEngine->GetWindowHandle(), L"DirectX が正しくインストールされていません D3D9(1)", Mix::STR_ERROR, MB_OK | MB_ICONSTOP );
		return False;
	}
#endif //_DEBUG

	// ファンクションの登録

	if( m_D3D9Module.RegisterFunction( L"Direct3DCreate9" ) == False )
	{
		::MessageBox( m_pEngine->GetWindowHandle(), L"DirectX が正しくインストールされていません D3D9(2)", Mix::STR_ERROR, MB_OK | MB_ICONSTOP );
		return False;
	}

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// 初期化
	////////////////////////////////////////////////////////////////////////////////////////////////////

	//ターゲットサイズ
	m_TargetSize = targetSize;

	//Direct3Dの作成
	typedef IDirect3D9 * ( WINAPI *Direct3DCreate9Function )( UINT SDKVersion );
	Direct3DCreate9Function Direct3DCreate9 = static_cast<Direct3DCreate9Function>(m_D3D9Module.GetFunction( L"Direct3DCreate9" ) );
	m_pD3D = Direct3DCreate9( D3D_SDK_VERSION );
	if( m_pD3D == NULL )
	{
		MIX_LOG_ERROR( L"%s : Direct3DCreate9 %s", FAILED_INITIALIZE, Mix::STR_RETERROR );
		return False;
	}

	//デバイス固有情報の取得
	hRet = m_pD3D->GetDeviceCaps( 0, D3DDEVTYPE_HAL, &m_Caps );
	if( hRet != D3D_OK )
	{
		MIX_LOG_ERROR( L"%s : GetDeviceCaps %s : Result[%s]", FAILED_INITIALIZE, Mix::STR_RETERROR, GetD3DResultText( hRet ) );
		return False;
	}

	//デバイスをレポート
	if( pSysReport->Open() == True )
	{
		D3DADAPTER_IDENTIFIER9 adapIdent;

		pSysReport->WriteLine( L"////////////////////////////////////////////////////////////////////////////////////////////////////" );
		pSysReport->WriteLine( L"// グラフィックス( DirectX9 )                                                                     //" );
		pSysReport->WriteLine( L"////////////////////////////////////////////////////////////////////////////////////////////////////" );
		pSysReport->WriteLine( L"" );

		//ディスプレイアダプタ
		::ZeroMemory( &adapIdent, sizeof( adapIdent ) );
		if( m_pD3D->GetAdapterIdentifier( 0, 0, &adapIdent ) == D3D_OK )
		{
			pSysReport->WriteLine( L"[ディスプレイアダプタ]" );
			pSysReport->WriteLine( L"  ドライバ名 : \"%s\"", Mix::String( adapIdent.Driver ).GetConstPtr() );
			pSysReport->WriteLine( L"  ドライバの説明 : \"%s\"", Mix::String( adapIdent.Description ).GetConstPtr() );
			pSysReport->WriteLine( L"  ドライバのバージョン : 0x%08x%08x", adapIdent.DriverVersion.HighPart, adapIdent.DriverVersion.LowPart );
			pSysReport->WriteLine( L"  デバイス名 : \"%s\"", Mix::String( adapIdent.DeviceName ) );
			pSysReport->WriteLine( L"  デバイスID : 0x%08x", adapIdent.DeviceId );
			pSysReport->WriteLine( L"  ベンダーID : 0x%08x", adapIdent.VendorId );
			pSysReport->WriteLine( L"  サブシステムID : 0x%08x", adapIdent.SubSysId );
			pSysReport->WriteLine( L"  リビジョン : 0x%08x", adapIdent.Revision );
			pSysReport->WriteLine( L"  GUID : %08x-%04x-%04x-%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x", adapIdent.DeviceIdentifier.Data1, adapIdent.DeviceIdentifier.Data2, adapIdent.DeviceIdentifier.Data3, adapIdent.DeviceIdentifier.Data4[0], adapIdent.DeviceIdentifier.Data4[1], adapIdent.DeviceIdentifier.Data4[2], adapIdent.DeviceIdentifier.Data4[3], adapIdent.DeviceIdentifier.Data4[4], adapIdent.DeviceIdentifier.Data4[5], adapIdent.DeviceIdentifier.Data4[6], adapIdent.DeviceIdentifier.Data4[7] );
			pSysReport->WriteLine( L"  WHQL : 0x%08x", adapIdent.WHQLLevel );
		}
		else
		{
			pSysReport->WriteLine( L"[ディスプレイアダプタ]" );
			pSysReport->WriteLine( L"  取得に失敗しました!" );
		}

		pSysReport->WriteLine( L"" );

		pSysReport->WriteLine( L"[ディスプレイアダプタの固有情報]" );
		pSysReport->WriteLine( L"  [%s] ミップマップの自動生成", ( ( m_Caps.Caps2 & D3DCAPS2_CANAUTOGENMIPMAP ) == D3DCAPS2_CANAUTOGENMIPMAP )? L"○" : L"×" );
		pSysReport->WriteLine( L"  [%s] 動的テクスチャ", ( ( m_Caps.Caps2 & D3DCAPS2_DYNAMICTEXTURES ) == D3DCAPS2_DYNAMICTEXTURES )? L"○" : L"×" );

		pSysReport->WriteLine( L"  [%s] フルスクリーンでのアルファブレンドをサポートする", ( ( m_Caps.Caps3 & D3DCAPS3_ALPHA_FULLSCREEN_FLIP_OR_DISCARD ) == D3DCAPS3_ALPHA_FULLSCREEN_FLIP_OR_DISCARD )? L"○" : L"×" );

		pSysReport->WriteLine( L"  [%s] 即時プレゼンテーションスワップ間隔をサポートする", ( ( m_Caps.PresentationIntervals & D3DPRESENT_INTERVAL_IMMEDIATE ) == D3DPRESENT_INTERVAL_IMMEDIATE )? L"○" : L"×" );

		pSysReport->WriteLine( L"  [%s] テクスチャのシステムメモリから非ローカルビデオメモリへのブリット", ( ( m_Caps.DevCaps & D3DDEVCAPS_CANBLTSYSTONONLOCAL ) == D3DDEVCAPS_CANBLTSYSTONONLOCAL )? L"○" : L"×" );
		pSysReport->WriteLine( L"  [%s] システムメモリにある実行バッファを使用できる", ( ( m_Caps.DevCaps & D3DDEVCAPS_EXECUTESYSTEMMEMORY ) == D3DDEVCAPS_EXECUTESYSTEMMEMORY )? L"○" : L"×" );
		pSysReport->WriteLine( L"  [%s] ビデオメモリにある実行バッファを使用できる", ( ( m_Caps.DevCaps & D3DDEVCAPS_EXECUTEVIDEOMEMORY ) == D3DDEVCAPS_EXECUTEVIDEOMEMORY )? L"○" : L"×" );
		pSysReport->WriteLine( L"  [%s] シーンのラスタ化用のハードウェアアクセラレーションがある", ( ( m_Caps.DevCaps & D3DDEVCAPS_HWRASTERIZATION ) == D3DDEVCAPS_HWRASTERIZATION )? L"○" : L"×" );
		pSysReport->WriteLine( L"  [%s] ハードウェアでトランスフォーム、ライティング", ( ( m_Caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT ) == D3DDEVCAPS_HWTRANSFORMANDLIGHT )? L"○" : L"×" );
		pSysReport->WriteLine( L"  [%s] Nパッチのサポート", ( ( m_Caps.DevCaps & D3DDEVCAPS_NPATCHES ) == D3DDEVCAPS_NPATCHES )? L"○" : L"×" );
		pSysReport->WriteLine( L"  [%s] ハードウェアでラスタ化、トランスフォーム、ライティング、シェーディング", ( ( m_Caps.DevCaps & D3DDEVCAPS_PUREDEVICE ) == D3DDEVCAPS_PUREDEVICE )? L"○" : L"×" );
		pSysReport->WriteLine( L"  [%s] 5次ベジェ曲線、Bスプライン", ( ( m_Caps.DevCaps & D3DDEVCAPS_QUINTICRTPATCHES ) == D3DDEVCAPS_QUINTICRTPATCHES )? L"○" : L"×" );
		pSysReport->WriteLine( L"  [%s] 矩形、三角形パッチをサポート", ( ( m_Caps.DevCaps & D3DDEVCAPS_RTPATCHES ) == D3DDEVCAPS_RTPATCHES )? L"○" : L"×" );
		pSysReport->WriteLine( L"  [%s] 独立したメモリプールからテクスチャ処理を行っている", ( ( m_Caps.DevCaps & D3DDEVCAPS_SEPARATETEXTUREMEMORIES ) == D3DDEVCAPS_SEPARATETEXTUREMEMORIES )? L"○" : L"×" );
		pSysReport->WriteLine( L"  [%s] 非ローカル ビデオ メモリからテクスチャを取得できる", ( ( m_Caps.DevCaps & D3DDEVCAPS_TEXTURENONLOCALVIDMEM ) == D3DDEVCAPS_TEXTURENONLOCALVIDMEM )? L"○" : L"×" );
		pSysReport->WriteLine( L"  [%s] システムメモリからテクスチャを取得できる", ( ( m_Caps.DevCaps & D3DDEVCAPS_TEXTURESYSTEMMEMORY ) == D3DDEVCAPS_TEXTURESYSTEMMEMORY )? L"○" : L"×" );
		pSysReport->WriteLine( L"  [%s] ビデオメモリからテクスチャを取得できる", ( ( m_Caps.DevCaps & D3DDEVCAPS_TEXTUREVIDEOMEMORY ) == D3DDEVCAPS_TEXTUREVIDEOMEMORY )? L"○" : L"×" );
		pSysReport->WriteLine( L"  [%s] トランスフォーム、ライティング済みの頂点に、システムメモリのバッファを使用できる", ( ( m_Caps.DevCaps & D3DDEVCAPS_TLVERTEXSYSTEMMEMORY ) == D3DDEVCAPS_TLVERTEXSYSTEMMEMORY )? L"○" : L"×" );
		pSysReport->WriteLine( L"  [%s] トランスフォーム、ライティング済みの頂点に、ビデオメモリのバッファを使用できる", ( ( m_Caps.DevCaps & D3DDEVCAPS_TLVERTEXVIDEOMEMORY ) == D3DDEVCAPS_TLVERTEXVIDEOMEMORY )? L"○" : L"×" );

		pSysReport->WriteLine( L"  [%s] 異方性フィルタリング", ( ( m_Caps.RasterCaps & D3DPRASTERCAPS_ANISOTROPY ) == D3DPRASTERCAPS_ANISOTROPY )? L"○" : L"×" );
		pSysReport->WriteLine( L"  [%s] 色のパースペクティブを正しく補間する", ( ( m_Caps.RasterCaps & D3DPRASTERCAPS_COLORPERSPECTIVE ) == D3DPRASTERCAPS_COLORPERSPECTIVE )? L"○" : L"×" );
		pSysReport->WriteLine( L"  [%s] ディザリングを使用して良質な色を再現できる", ( ( m_Caps.RasterCaps & D3DPRASTERCAPS_DITHER ) == D3DPRASTERCAPS_DITHER )? L"○" : L"×" );
		pSysReport->WriteLine( L"  [%s] 以前の深度バイアスをサポートする", ( ( m_Caps.RasterCaps & D3DPRASTERCAPS_DEPTHBIAS ) == D3DPRASTERCAPS_DEPTHBIAS )? L"○" : L"×" );
		pSysReport->WriteLine( L"  [%s] ピクセルの深さを指すフォグ値を含む参照テーブルと照合して、フォグ値を算出する", ( ( m_Caps.RasterCaps & D3DPRASTERCAPS_FOGTABLE ) == D3DPRASTERCAPS_FOGTABLE )? L"○" : L"×" );
		pSysReport->WriteLine( L"  [%s] ライティング処理の際にフォグ値を計算し、ラスタ化の際にフォグ値を補間する", ( ( m_Caps.RasterCaps & D3DPRASTERCAPS_FOGVERTEX ) == D3DPRASTERCAPS_FOGVERTEX )? L"○" : L"×" );
		pSysReport->WriteLine( L"  [%s] LODバイアス調整をサポートする", ( ( m_Caps.RasterCaps & D3DPRASTERCAPS_MIPMAPLODBIAS ) == D3DPRASTERCAPS_MIPMAPLODBIAS )? L"○" : L"×" );
		pSysReport->WriteLine( L"  [%s] マルチサンプリングのオンとオフの切り替え", ( ( m_Caps.RasterCaps & D3DPRASTERCAPS_MULTISAMPLE_TOGGLE ) == D3DPRASTERCAPS_MULTISAMPLE_TOGGLE )? L"○" : L"×" );
		pSysReport->WriteLine( L"  [%s] シザーテストをサポートする", ( ( m_Caps.RasterCaps & D3DPRASTERCAPS_SCISSORTEST ) == D3DPRASTERCAPS_SCISSORTEST )? L"○" : L"×" );
		pSysReport->WriteLine( L"  [%s] 真のスロープスケールベースの深度バイアスを実行する", ( ( m_Caps.RasterCaps & D3DPRASTERCAPS_SLOPESCALEDEPTHBIAS ) == D3DPRASTERCAPS_SLOPESCALEDEPTHBIAS )? L"○" : L"×" );
		pSysReport->WriteLine( L"  [%s] w を使用する深度バッファリング", ( ( m_Caps.RasterCaps & D3DPRASTERCAPS_WBUFFER ) == D3DPRASTERCAPS_WBUFFER )? L"○" : L"×" );
		pSysReport->WriteLine( L"  [%s] w ベースのフォグをサポートする", ( ( m_Caps.RasterCaps & D3DPRASTERCAPS_WFOG ) == D3DPRASTERCAPS_WFOG )? L"○" : L"×" );
		pSysReport->WriteLine( L"  [%s] HRSを実行でき、このときポリゴンのソートや深度バッファの割り当てを必要としない", ( ( m_Caps.RasterCaps & D3DPRASTERCAPS_ZBUFFERLESSHSR ) == D3DPRASTERCAPS_ZBUFFERLESSHSR )? L"○" : L"×" );
		pSysReport->WriteLine( L"  [%s] z ベースのフォグをサポートする", ( ( m_Caps.RasterCaps & D3DPRASTERCAPS_ZFOG ) == D3DPRASTERCAPS_ZFOG )? L"○" : L"×" );
		pSysReport->WriteLine( L"  [%s] z テスト処理を実行できる", ( ( m_Caps.RasterCaps & D3DPRASTERCAPS_ZTEST ) == D3DPRASTERCAPS_ZTEST )? L"○" : L"×" );

		pSysReport->WriteLine( L"  [%s] テクスチャは、すべて正方形でなければならない", ( ( m_Caps.TextureCaps & D3DPTEXTURECAPS_SQUAREONLY ) == D3DPTEXTURECAPS_SQUAREONLY )? L"○" : L"×" );
		pSysReport->WriteLine( L"  [%s] ミップマップ化テクスチャ", ( ( m_Caps.TextureCaps & D3DPTEXTURECAPS_MIPMAP ) == D3DPTEXTURECAPS_MIPMAP )? L"○" : L"×" );
		pSysReport->WriteLine( L"  [%s] テクスチャの幅と高さは、2 の累乗で指定する", ( ( m_Caps.TextureCaps & D3DPTEXTURECAPS_POW2 ) == D3DPTEXTURECAPS_POW2 )? L"○" : L"×" );
		pSysReport->WriteLine( L"  [%s] ボリュームテクスチャ", ( ( m_Caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP ) == D3DPTEXTURECAPS_VOLUMEMAP )? L"○" : L"×" );
		pSysReport->WriteLine( L"  [%s] ミップマップ化ボリュームテクスチャ", ( ( m_Caps.TextureCaps & D3DPTEXTURECAPS_MIPVOLUMEMAP ) == D3DPTEXTURECAPS_MIPVOLUMEMAP )? L"○" : L"×" );
		pSysReport->WriteLine( L"  [%s] ミップマップ化キューブテクスチャ", ( ( m_Caps.TextureCaps & D3DPTEXTURECAPS_MIPCUBEMAP ) == D3DPTEXTURECAPS_MIPCUBEMAP )? L"○" : L"×" );
		pSysReport->WriteLine( L"  [%s] ボリュームテクスチャのディメンジョンは 2 の累乗で指定する", ( ( m_Caps.TextureCaps & D3DPTEXTURECAPS_VOLUMEMAP_POW2 ) == D3DPTEXTURECAPS_VOLUMEMAP_POW2 )? L"○" : L"×" );
		pSysReport->WriteLine( L"  [%s] キューブテクスチャ", ( ( m_Caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP ) == D3DPTEXTURECAPS_CUBEMAP )? L"○" : L"×" );
		pSysReport->WriteLine( L"  [%s] キューブテクスチャのディメンジョンは 2 の累乗で指定する", ( ( m_Caps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP_POW2 ) == D3DPTEXTURECAPS_CUBEMAP_POW2 )? L"○" : L"×" );
		pSysReport->WriteLine( L"  [%s] テクスチャピクセルにおいてのアルファ", ( ( m_Caps.TextureCaps & D3DPTEXTURECAPS_ALPHA ) == D3DPTEXTURECAPS_ALPHA )? L"○" : L"×" );
		pSysReport->WriteLine( L"  [%s] テクスチャパレットからアルファを描画できる", ( ( m_Caps.TextureCaps & D3DPTEXTURECAPS_ALPHAPALETTE ) == D3DPTEXTURECAPS_ALPHAPALETTE )? L"○" : L"×" );
		pSysReport->WriteLine( L"  [%s] 条件付きで 2 の累乗でないディメンジョンでの2Dテクスチャ", ( ( m_Caps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL ) == D3DPTEXTURECAPS_NONPOW2CONDITIONAL )? L"○" : L"×" );
		pSysReport->WriteLine( L"  [%s] プログラム可能および固定機能シェーダ内での射影バンプ環境ルックアップ演算をサポートしない", ( ( m_Caps.TextureCaps & D3DPTEXTURECAPS_NOPROJECTEDBUMPENV ) == D3DPTEXTURECAPS_NOPROJECTEDBUMPENV )? L"○" : L"×" );
		pSysReport->WriteLine( L"  [%s] パースペクティブ補正のテクスチャリング", ( ( m_Caps.TextureCaps & D3DPTEXTURECAPS_PERSPECTIVE ) == D3DPTEXTURECAPS_PERSPECTIVE )? L"○" : L"×" );
		pSysReport->WriteLine( L"  [%s] テクスチャインデックスは、補間実行前にテクスチャサイズに合わせてスケーリングされない", ( ( m_Caps.TextureCaps & D3DPTEXTURECAPS_TEXREPEATNOTSCALEDBYSIZE ) == D3DPTEXTURECAPS_TEXREPEATNOTSCALEDBYSIZE )? L"○" : L"×" );

		pSysReport->WriteLine( L"  [%s] RTパッチの適応型テセレーション", ( ( m_Caps.DevCaps2 & D3DDEVCAPS2_ADAPTIVETESSRTPATCH ) == D3DDEVCAPS2_ADAPTIVETESSRTPATCH )? L"○" : L"×" );
		pSysReport->WriteLine( L"  [%s] Nパッチの適応型テセレーション", ( ( m_Caps.DevCaps2 & D3DDEVCAPS2_ADAPTIVETESSNPATCH ) == D3DDEVCAPS2_ADAPTIVETESSNPATCH )? L"○" : L"×" );
		pSysReport->WriteLine( L"  [%s] テクスチャをソースとして使う IDirect3DDevice9::StretchRect をサポートする", ( ( m_Caps.DevCaps2 & D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES ) == D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES )? L"○" : L"×" );
		pSysReport->WriteLine( L"  [%s] Nパッチのディスプレースメントマップ", ( ( m_Caps.DevCaps2 & D3DDEVCAPS2_DMAPNPATCH ) == D3DDEVCAPS2_DMAPNPATCH )? L"○" : L"×" );
		pSysReport->WriteLine( L"  [%s] Nパッチの事前にサンプリングされたディスプレースメントマップ", ( ( m_Caps.DevCaps2 & D3DDEVCAPS2_PRESAMPLEDDMAPNPATCH ) == D3DDEVCAPS2_PRESAMPLEDDMAPNPATCH )? L"○" : L"×" );
		pSysReport->WriteLine( L"  [%s] ストリームオフセット", ( ( m_Caps.DevCaps2 & D3DDEVCAPS2_STREAMOFFSET ) == D3DDEVCAPS2_STREAMOFFSET )? L"○" : L"×" );
		pSysReport->WriteLine( L"  [%s] 条件付で複数の頂点要素が 1 つのストリーム内の同じオフセットを共有できる", ( ( m_Caps.DevCaps2 & D3DDEVCAPS2_VERTEXELEMENTSCANSHARESTREAMOFFSET ) == D3DDEVCAPS2_VERTEXELEMENTSCANSHARESTREAMOFFSET )? L"○" : L"×" );
		pSysReport->WriteLine( L"" );

		pSysReport->WriteLine( L"  [%s] カラーバッファへのチャンネルごとの書き込みをサポートする", MIX_LOG_BOOLEAN( ( m_Caps.PrimitiveMiscCaps & D3DPMISCCAPS_COLORWRITEENABLE ) == D3DPMISCCAPS_COLORWRITEENABLE ) );
		pSysReport->WriteLine( L"  [%s] カラーバッファ個別の書き込みマスクの使用をサポートする", MIX_LOG_BOOLEAN( ( m_Caps.PrimitiveMiscCaps & D3DPMISCCAPS_INDEPENDENTWRITEMASKS ) == D3DPMISCCAPS_INDEPENDENTWRITEMASKS ) );
		pSysReport->WriteLine( L"" );

		pSysReport->WriteLine( L"  [%d] テクスチャの幅の最大値", m_Caps.MaxTextureWidth );
		pSysReport->WriteLine( L"  [%d] テクスチャの高さの最大値", m_Caps.MaxTextureHeight );
		pSysReport->WriteLine( L"  [%d] ボリュームテクスチャのディメンジョンの最大値", m_Caps.MaxVolumeExtent );
		pSysReport->WriteLine( L"  [%d] 正規化した後のテクスチャ座標の整数ビットの最大範囲", m_Caps.MaxTextureRepeat );
		pSysReport->WriteLine( L"  [%d] テクスチャの最大アスペクト比", m_Caps.MaxTextureAspectRatio );
		pSysReport->WriteLine( L"  [%d] 異方性の最大値", m_Caps.MaxAnisotropy );
		pSysReport->WriteLine( L"  [%f] Wベースの最大深度値", m_Caps.MaxVertexW );
		pSysReport->WriteLine( L"  [%d] テクスチャブレンディングステージの最大数", m_Caps.MaxTextureBlendStages );
		pSysReport->WriteLine( L"  [%d] テクスチャブレンディングステージに同時にバインドできるテクスチャの最大数", m_Caps.MaxSimultaneousTextures );
		pSysReport->WriteLine( L"  [%f] ポイントプリミティブの最大サイズ", m_Caps.MaxPointSize );
		pSysReport->WriteLine( L"  [%d] 最大プリミティブ数", m_Caps.MaxPrimitiveCount );
		pSysReport->WriteLine( L"  [%d] 頂点処理に対してサポートされるインデックスの最大サイズ", m_Caps.MaxVertexIndex );
		pSysReport->WriteLine( L"  [%d] データストリームの最大数", m_Caps.MaxStreams );
		pSysReport->WriteLine( L"  [%d] データストリームの最大ストライド", m_Caps.MaxStreamStride );
		pSysReport->WriteLine( L"  [%d.%d] バーテックスシェーダーのバージョン", D3DSHADER_VERSION_MAJOR( m_Caps.VertexShaderVersion ), D3DSHADER_VERSION_MINOR( m_Caps.VertexShaderVersion ) );
		pSysReport->WriteLine( L"  [%d] バーテックスシェーダーの定数用に予約されているレジスタ - vs_1_1 の数", m_Caps.MaxVertexShaderConst );
		pSysReport->WriteLine( L"  [%d.%d] ピクセルシェーダーのバージョン", D3DSHADER_VERSION_MAJOR( m_Caps.PixelShaderVersion ), D3DSHADER_VERSION_MINOR( m_Caps.PixelShaderVersion ) );
		pSysReport->WriteLine( L"  [%f] ピクセルシェーダの算術コンポーネントの最大値", m_Caps.PixelShader1xMaxValue );
		pSysReport->WriteLine( L"" );

		pSysReport->WriteLine( L"  [%f] Nパッチの分割レベルの最大数", m_Caps.MaxNpatchTessellationLevel );
		pSysReport->WriteLine( L"  [%u] 同時レンダリングターゲットの数", m_Caps.NumSimultaneousRTs );
		pSysReport->WriteLine( L"  [%u] バーテックスシェーダの実行できる命令の最大数", m_Caps.MaxVShaderInstructionsExecuted );
		pSysReport->WriteLine( L"  [%u] ピクセルシェーダの実行できる命令の最大数", m_Caps.MaxPShaderInstructionsExecuted );
		pSysReport->WriteLine( L"  [%u] バーテックスシェーダの命令スロットの最大数", m_Caps.MaxVertexShader30InstructionSlots );
		pSysReport->WriteLine( L"  [%u] ピクセルシェーダの命令スロットの最大数", m_Caps.MaxPixelShader30InstructionSlots );
		pSysReport->WriteLine( L"" );

		pSysReport->Close();
	}

	//シェーダーモデルを決定
	if( ( m_Caps.VertexShaderVersion < D3DVS_VERSION( 3, 0 ) ) ||
		( m_Caps.PixelShaderVersion < D3DPS_VERSION( 3, 0 ) ) )
	{
		MIX_LOG_ERROR( L"%s : シェーダーモデルは3以上である必要があります", FAILED_INITIALIZE );
		return False;
	}

	//ディスプレイを列挙
	if( EnumDisplay( pSysReport ) == False )
	{
		MIX_LOG_ERROR( L"%s : 使用できるディスプレイが見つかりません", FAILED_INITIALIZE );
		return False;
	}

	//デバイスコンボをレポート
	if( pSysReport->Open() == True )
	{
		Device::DeviceComboList::iterator it_dc;
		Device::DeviceComboList::iterator it_dc_begin = m_DeviceComboList.begin();
		Device::DeviceComboList::iterator it_dc_end = m_DeviceComboList.end();

		UInt32 testFlags;

		for( it_dc = it_dc_begin; it_dc != it_dc_end; ++it_dc )
		{
			Device::DEVICECOMBO* pdb = &( *it_dc );

			pSysReport->WriteLine( L"[デバイスの設定]" );
			pSysReport->WriteLine( L"  アダプタフォーマット : %s", GetD3DFormatText( pdb->adapterFormat ) );
			pSysReport->WriteLine( L"  バックバッファフォーマット : %s", GetD3DFormatText( pdb->backBufferFormat ) );
			pSysReport->WriteLine( L"" );
			pSysReport->WriteLine( L"  [%s] ウィンドウモード", ( ( pdb->flags & Device::FLAG_MODE_WINDOW ) == FLAG_MODE_WINDOW )? L"○" : L"×" );
			pSysReport->WriteLine( L"  [%s] フルスクリーンモード", ( ( pdb->flags & Device::FLAG_MODE_FULLSCREEN ) == FLAG_MODE_FULLSCREEN )? L"○" : L"×" );
			pSysReport->WriteLine( L"" );

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

			pSysReport->WriteLine( L"  [ファイルテクスチャ]" );

			pSysReport->WriteLine( L"    [プレーン]" );
			for( i = 1 ; i < Mix::Graphics::FMT_MAX; i++ )
			{
				testFlags = FLAG_RESOURCE_PLANE;

				pSysReport->WriteLine( L"      [%s] %s",
					( ( pdb->formatTable[i].flags & testFlags ) == testFlags )? L"○" : L"×",
					GetD3DFormatText( pdb->formatTable[i].format ) );
			}

			pSysReport->WriteLine( L"    [ボリューム]" );
			for( i = 1 ; i < Mix::Graphics::FMT_MAX; i++ )
			{
				testFlags = FLAG_RESOURCE_VOLUME;

				pSysReport->WriteLine( L"      [%s] %s",
					( ( pdb->formatTable[i].flags & testFlags ) == testFlags )? L"○" : L"×",
					GetD3DFormatText( pdb->formatTable[i].format ) );
			}

			pSysReport->WriteLine( L"    [キューブ]" );
			for( i = 1 ; i < Mix::Graphics::FMT_MAX; i++ )
			{
				testFlags = FLAG_RESOURCE_CUBE;

				pSysReport->WriteLine( L"      [%s] %s",
					( ( pdb->formatTable[i].flags & testFlags ) == testFlags )? L"○" : L"×",
					GetD3DFormatText( pdb->formatTable[i].format ) );
			}

			pSysReport->WriteLine( L"" );

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

			pSysReport->WriteLine( L"  [ダイナミックテクスチャ]" );

			pSysReport->WriteLine( L"    [プレーン]" );
			for( i = 1 ; i < Mix::Graphics::FMT_MAX; i++ )
			{
				testFlags = FLAG_RESOURCE_PLANE | FLAG_RESOURCE_DYNAMIC;

				pSysReport->WriteLine( L"      [%s] %s",
					( ( pdb->formatTable[i].flags & testFlags ) == testFlags )? L"○" : L"×",
					GetD3DFormatText( pdb->formatTable[i].format ) );
			}

			pSysReport->WriteLine( L"" );

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

			pSysReport->WriteLine( L"  [ターゲットテクスチャ]" );

			pSysReport->WriteLine( L"    [プレーン]" );
			for( i = 1 ; i < Mix::Graphics::FMT_MAX; i++ )
			{
				testFlags = FLAG_RESOURCE_PLANE | FLAG_RESOURCE_TARGET;

				pSysReport->WriteLine( L"      [%s] %s",
					( ( pdb->formatTable[i].flags & testFlags ) == testFlags )? L"○" : L"×",
					GetD3DFormatText( pdb->formatTable[i].format ) );
			}

			pSysReport->WriteLine( L"    [プレーン ( Lockable ) ]" );
			for( i = 1 ; i < Mix::Graphics::FMT_MAX; i++ )
			{
				testFlags = FLAG_RESOURCE_SURFACE | FLAG_RESOURCE_TARGET;

				pSysReport->WriteLine( L"      [%s] %s",
					( ( pdb->formatTable[i].flags & testFlags ) == testFlags )? L"○" : L"×",
					GetD3DFormatText( pdb->formatTable[i].format ) );
			}

			pSysReport->WriteLine( L"    [キューブ]" );
			for( i = 1 ; i < Mix::Graphics::FMT_MAX; i++ )
			{
				testFlags = FLAG_RESOURCE_CUBE | FLAG_RESOURCE_TARGET;

				pSysReport->WriteLine( L"      [%s] %s",
					( ( pdb->formatTable[i].flags & testFlags ) == testFlags )? L"○" : L"×",
					GetD3DFormatText( pdb->formatTable[i].format ) );
			}

			pSysReport->WriteLine( L"" );

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

			pSysReport->WriteLine( L"  [デプステクスチャ]" );

			for( i = 1 ; i < Mix::Graphics::FMT_MAX; i++ )
			{
				testFlags = FLAG_RESOURCE_DEPTHSTENCIL;

				pSysReport->WriteLine( L"      [%s] %s",
					( ( pdb->formatTable[i].flags & testFlags ) == testFlags )? L"○" : L"×",
					GetD3DFormatText( pdb->formatTable[i].format ) );
			}

			pSysReport->WriteLine( L"" );
		}

		pSysReport->Close();
	}

	//レポート終了
	pSysReport->WriteLine( L"" );

	//デバイスパラメータを作成
	if( CreatePresentation( True ) == True )
	{
		m_DeviceParam.current = m_DeviceParam.next;
	}
	else
	{
		MIX_LOG_ERROR( L"%s : グラフィックデバイス( DirectX9 )のパラメータを作成できませんでした", FAILED_INITIALIZE );
		return False;
	}

	//デバイスを作成
	for( i = 0; ( i < MAX_VP ) && ( bCreateDevice == False ); i++ )
	{
		hRet = m_pD3D->CreateDevice(	0,
										D3DDEVTYPE_HAL,
										m_pEngine->GetWindowHandle(),
										D3DCREATE_MULTITHREADED | vpTable[i],
										&( m_DeviceParam.next.params ),
										&m_pD3DDevice );
		if( hRet == D3D_OK )
		{
			bCreateDevice = True;
		}
	}
	if( bCreateDevice == False )
	{
		MIX_LOG_ERROR( L"%s : CreateDevice %s : Result[%s]", FAILED_INITIALIZE, Mix::STR_RETERROR, GetD3DResultText( hRet ) );
		return False;
	}

	//レンダーステートテーブルを初期化
	for( i = 0; i < Device::RENDERSTATETYPE_MAX; i++ )
	{
		D3DRENDERSTATETYPE type = renderStateTypeTable[i];
		DWORD value = 0;

		m_pD3DDevice->GetRenderState( type, &value );

		m_RenderStateTable[i].type = type;
		m_RenderStateTable[i].defValue = value;
		m_RenderStateTable[i].value = value;
	}

	//サンプラーステートテーブルを初期化
	for( i = 0; i < Mix::Graphics::TEXTURESTAGE_MAX; i++ )
	{
		for( j = 0; j < Device::SAMPLERSTATETYPE_MAX; j++ )
		{
			D3DSAMPLERSTATETYPE type = samplerStateTypeTable[j];
			DWORD value = 0;

			m_pD3DDevice->GetSamplerState( i, type, &value );

			m_SamplerStateTable[i][j].type = type;
			m_SamplerStateTable[i][j].defValue = value;
			m_SamplerStateTable[i][j].value = value;
		}
	}

	//描画ステートを初期化
	ResetDrawState();

	//シェーダープロファイルの取得
	m_VertexShaderProfile = GetVertexShaderProfile();
	m_PixelShaderProfile = GetPixelShaderProfile();

	//バックバッファを取得
	hRet = m_pD3DDevice->GetBackBuffer( 0, 0, D3DBACKBUFFER_TYPE_MONO, &m_pD3DBackBuffer );
	if( hRet != D3D_OK )
	{
		MIX_LOG_ERROR( L"%s : GetBackBuffer %s : Result[%s]", FAILED_INITIALIZE, Mix::STR_RETERROR, GetD3DResultText( hRet ) );
		return False;
	}

	//バックバッファのサイズ
	backBuffWidth = m_DeviceParam.current.params.BackBufferWidth;
	backBuffHeight = m_DeviceParam.current.params.BackBufferHeight;

	//ターゲットの矩形
	m_TargetState.rect = Mix::Rectangle( 0, 0, backBuffWidth, backBuffHeight );

	//ビューの範囲を設定
	SetViewBounds( 0, 0, backBuffWidth, backBuffHeight );

	//シザリングの範囲を設定
	SetScissorBounds( 0, 0, backBuffWidth, backBuffHeight );

	if( ( m_pEngine->IsSizeableWindow() == False  ) && ( bFullscreen == True ) )
	{
		//ウィンドウが固定サイズで、フルスクリーン指定があった場合は、フルスクリーンにする
		m_Status = Device::STATUS_CHANGE_FULLSCREEN;
	}

	TracePresentation( L"DirectX9( ShaderModel3 )" );

	return True;
}

Boolean Device::Update( void )
{
	switch( m_Status )
	{
	//ウィンドウモードへ変更
	case Device::STATUS_CHANGE_WINDOW:
		ChangePresentation( True );
		break;

	//フルスクリーンモードモードへ変更
	case Device::STATUS_CHANGE_FULLSCREEN:
		ChangePresentation( False );
		break;

	//ロスト
	case Device::STATUS_LOST:
		ResetPresentation();
		break;
	}

	if( m_Status != Device::STATUS_OK )
	{
		return False;
	}

	//スクリーンの有効な矩形を更新
	UpdateScreenValidRect();

	return True;
}

Boolean Device::MessageProc( UInt32 msg, WPARAM wParam, LPARAM lParam )
{
	switch( msg )
	{
	case WM_SYSKEYDOWN:
		if( wParam == VK_RETURN )
		{
			ToggleDisplayMode();
		}
		break;
	}

	return True;
}

void Device::OnDispose( void )
{
	UInt32 i;

	for( i = 0; i < Mix::Graphics::TARGET_MAX; i++ )
	{
		MIX_RELEASE( m_TargetState.pTex[i] );
	}

	MIX_RELEASE( m_TargetState.pDSTex );

	MIX_RELEASE( m_pD3DBackBuffer );
	MIX_RELEASE( m_pD3DDevice );
	MIX_RELEASE( m_pD3D );
}

Mix::Graphics::ITexture* Device::OnCreateTexture(	const wchar_t* pFilePath,
													const Device::TEXTURE_DESC& desc,
													UInt32 subResourceCount,
													const Device::TEXTURE_SUBRESOURCE_DATA* subResources )
{
	D3DFORMAT d3dFmt = m_DeviceParam.current.formatTable[desc.format].format;

	if( desc.type == Mix::Plugin::Graphics::ITextureKit::PLANE )
	{
		return CreatePlaneTexture( pFilePath, desc, subResourceCount, subResources );
	}
	else if( desc.type == Mix::Plugin::Graphics::ITextureKit::CUBE )
	{
		return CreateCubeTexture( pFilePath, desc, subResourceCount, subResources );
	}
	else if( desc.type == Mix::Plugin::Graphics::ITextureKit::VOLUME )
	{
		return CreateVolumeTexture( pFilePath, desc, subResourceCount, subResources );
	}
	else
	{
		MIX_LOG_ERROR( L"%s : %s : %s[%s] %s[%d]", FAILED_CREATE_TEXTURE,
			Mix::STR_TYPE_NOT_SUPPORT,
			Mix::STR_FILEPATH, pFilePath, Mix::STR_TYPE, desc.type );
	}

	return NULL;
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// Mix::Graphics::IDevice
////////////////////////////////////////////////////////////////////////////////////////////////////

Boolean Device::IsHullShaderSupported( void ) const
{
	return False;
}

Boolean Device::IsDomainShaderSupported( void ) const
{
	return False;
}

Boolean Device::IsGeometryShaderSupported( void ) const
{
	return False;
}

Boolean Device::IsShaderConstantSupported( void ) const
{
	return False;
}

Boolean Device::IsIndexSupported( Mix::Graphics::INDEX_FORMAT format ) const
{
	Boolean ret = False;

	switch( format )
	{
	case Mix::Graphics::INDEX_USHORT:
		ret = ( m_Caps.MaxVertexIndex >= 0x0000FFFF );
		break;

	case Mix::Graphics::INDEX_UINT:
		ret = ( m_Caps.MaxVertexIndex > 0x0000FFFF );
		break;
	}

	return ret;
}

Boolean Device::IsPlaneTextureSupported( Mix::Graphics::FORMAT format ) const
{
	return ( ( m_DeviceParam.current.formatTable[format].flags & FLAG_RESOURCE_PLANE ) == FLAG_RESOURCE_PLANE );
}

Boolean Device::IsVolumeTextureSupported( Mix::Graphics::FORMAT format ) const
{
	return ( ( m_DeviceParam.current.formatTable[format].flags & FLAG_RESOURCE_VOLUME ) == FLAG_RESOURCE_VOLUME );
}

Boolean Device::IsCubeTextureSupported( Mix::Graphics::FORMAT format ) const
{
	return ( ( m_DeviceParam.current.formatTable[format].flags & FLAG_RESOURCE_CUBE ) == FLAG_RESOURCE_CUBE );
}

Boolean Device::IsDynamicPlaneTextureSupported( Mix::Graphics::FORMAT format ) const
{
	return ( ( m_DeviceParam.current.formatTable[format].flags & ( FLAG_RESOURCE_PLANE | FLAG_RESOURCE_DYNAMIC ) ) == ( FLAG_RESOURCE_PLANE | FLAG_RESOURCE_DYNAMIC ) );
}

Boolean Device::IsTargetPlaneTextureSupported( Mix::Graphics::FORMAT format ) const
{
	return ( ( m_DeviceParam.current.formatTable[format].flags & ( FLAG_RESOURCE_PLANE | FLAG_RESOURCE_TARGET ) ) == ( FLAG_RESOURCE_PLANE | FLAG_RESOURCE_TARGET ) );
}

Boolean Device::IsLockableTargetPlaneTextureSupported( Mix::Graphics::FORMAT format ) const
{
	return ( ( m_DeviceParam.current.formatTable[format].flags & ( FLAG_RESOURCE_SURFACE | FLAG_RESOURCE_TARGET ) ) == ( FLAG_RESOURCE_SURFACE | FLAG_RESOURCE_TARGET ) );
}

Boolean Device::IsTargetCubeTextureSupported( Mix::Graphics::FORMAT format ) const
{
	return ( ( m_DeviceParam.current.formatTable[format].flags & ( FLAG_RESOURCE_CUBE | FLAG_RESOURCE_TARGET ) ) == ( FLAG_RESOURCE_CUBE | FLAG_RESOURCE_TARGET ) );
}

Boolean Device::IsDepthTextureSupported( Mix::Graphics::FORMAT format ) const
{
	return ( ( m_DeviceParam.current.formatTable[format].flags & FLAG_RESOURCE_DEPTHSTENCIL ) == FLAG_RESOURCE_DEPTHSTENCIL );
}

Boolean Device::CreateHullShaderFromFile( const wchar_t* pFilePath, Mix::Graphics::IHullShader** ppHullShader )
{
	return False;
}

Boolean Device::CreateHullShaderFromMemory( const void* pSrc, UInt32 srcSize, Mix::Graphics::IHullShader** ppHullShader, const wchar_t* pDebugName )
{
	return False;
}

Boolean Device::CreateDomainShaderFromFile( const wchar_t* pFilePath, Mix::Graphics::IDomainShader** ppDomainShader )
{
	return False;
}

Boolean Device::CreateDomainShaderFromMemory( const void* pSrc, UInt32 srcSize, Mix::Graphics::IDomainShader** ppDomainShader, const wchar_t* pDebugName )
{
	return False;
}

Boolean Device::CreateGeometryShaderFromFile( const wchar_t* pFilePath, Mix::Graphics::IGeometryShader** ppGeometryShader )
{
	return False;
}

Boolean Device::CreateGeometryShaderFromMemory( const void* pSrc, UInt32 srcSize, Mix::Graphics::IGeometryShader** ppGeometryShader, const wchar_t* pDebugName )
{
	return False;
}

Boolean Device::CreateVertexShaderFromMemory( const void* pSrc, UInt32 srcSize, Mix::Graphics::IVertexShader** ppVertexShader, const wchar_t* pDebugName )
{
	if( ( pSrc == NULL ) ||
		( srcSize == 0 ) ||
		( ppVertexShader == NULL ) )
	{
		MIX_LOG_ERROR( L"%s : %s : %s[%s] : pSrc[%s] srcSize[%d] ppVertexShader[%s]",
			FAILED_CREATE_VERTEX_SHADER,
			Mix::STR_ILLEGALARG,
			Mix::STR_DEBUGNAME,
			MIX_SAFE_NAME( pDebugName ),
			MIX_LOG_PTR( pSrc ),
			srcSize,
			MIX_LOG_PTR( ppVertexShader ) );

		return False;
	}

	HRESULT ret;
	Mix::Graphics::DX9::VertexShader* pVertexShader;
	IDirect3DVertexShader9* pD3DVertexShader;
	
	ret = m_pD3DDevice->CreateVertexShader( static_cast<const DWORD*>( pSrc ), &pD3DVertexShader );
	if( ret != D3D_OK )
	{
		MIX_LOG_ERROR( L"%s : CreateVertexShader %s : %s[%s]", FAILED_CREATE_VERTEX_SHADER,
			Mix::STR_RETERROR, Mix::STR_DEBUGNAME, MIX_SAFE_NAME( pDebugName ) );
		return False;
	}

	pVertexShader = Mix::Graphics::DX9::VertexShader::CreateInstance( this, pD3DVertexShader );
	if( pVertexShader != NULL )
	{
		( *ppVertexShader ) = pVertexShader;
	}
	else
	{
		MIX_LOG_ERROR( L"%s : %s : %s[%s]", FAILED_CREATE_VERTEX_SHADER,
			Mix::STR_OUTOFMEMORY, Mix::STR_DEBUGNAME, MIX_SAFE_NAME( pDebugName ) );

		MIX_RELEASE( pD3DVertexShader );

		return False;
	}

	return True;
}

Boolean Device::CreateVertexShaderFromFile( const wchar_t* pFilePath, Mix::Graphics::IVertexShader** ppVertexShader )
{
	if( ( pFilePath == NULL ) ||
		( ::wcslen( pFilePath ) == 0 ) ||
		( ppVertexShader == NULL ) )
	{
		MIX_LOG_ERROR( L"%s : %s : pFilePath[%s] ppVertexShader[%s]", FAILED_CREATE_VERTEX_SHADER,
			Mix::STR_ILLEGALARG,
			MIX_LOG_STR( pFilePath ),
			MIX_LOG_PTR( ppVertexShader ) );

		return False;
	}

	HRESULT ret;
	Mix::Memory::IBuffer* pBuffer = NULL;
	Mix::Graphics::DX9::VertexShader* pVertexShader;
	IDirect3DVertexShader9* pD3DVertexShader = NULL;

	if( m_pFileMgr->CreateBufferFromFile( pFilePath, &pBuffer ) == False )
	{
		MIX_LOG_ERROR( L"%s : ファイルが見つかりません : File[%s]", FAILED_CREATE_VERTEX_SHADER, pFilePath );
		return False;
	}

	ret = m_pD3DDevice->CreateVertexShader( static_cast<const DWORD*>( pBuffer->GetConstPointer() ), &pD3DVertexShader );
	if( ret != D3D_OK )
	{
		MIX_LOG_ERROR( L"%s : CreateVertexShader %s : File[%s]", FAILED_CREATE_VERTEX_SHADER, Mix::STR_RETERROR, pFilePath );
		MIX_RELEASE( pBuffer );
		return False;
	}

	MIX_RELEASE( pBuffer );

	pVertexShader = Mix::Graphics::DX9::VertexShader::CreateInstance( this, pD3DVertexShader );
	if( pVertexShader == NULL )
	{
		MIX_RELEASE( pD3DVertexShader );
		MIX_LOG_ERROR( L"%s : %s : File[%s]", FAILED_CREATE_VERTEX_SHADER, Mix::STR_OUTOFMEMORY, pFilePath );
		return False;
	}

	( *ppVertexShader ) = pVertexShader;

	return True;
}

Boolean Device::CreatePixelShaderFromMemory( const void* pSrc, UInt32 srcSize, Mix::Graphics::IPixelShader** ppPixelShader, const wchar_t* pDebugName )
{
	if( ( pSrc == NULL ) ||
		( srcSize == 0 ) ||
		( ppPixelShader == NULL ) )
	{
		MIX_LOG_ERROR( L"%s : %s : %s[%s] : pSrc[%s] srcSize[%d] ppPixelShader[%s]",
			FAILED_CREATE_PIXEL_SHADER,
			Mix::STR_ILLEGALARG,
			Mix::STR_DEBUGNAME,
			MIX_SAFE_NAME( pDebugName ),
			MIX_LOG_PTR( pSrc ),
			srcSize,
			MIX_LOG_PTR( ppPixelShader ) );

		return False;
	}

	HRESULT ret;
	Mix::Graphics::DX9::PixelShader* pPixelShader;
	IDirect3DPixelShader9* pD3DPixelShader;
	
	ret = m_pD3DDevice->CreatePixelShader( static_cast<const DWORD*>( pSrc ), &pD3DPixelShader );
	if( ret != D3D_OK )
	{
		MIX_LOG_ERROR( L"%s : CreatePixelShader %s : %s[%s]", FAILED_CREATE_PIXEL_SHADER,
			Mix::STR_RETERROR, Mix::STR_DEBUGNAME, MIX_SAFE_NAME( pDebugName ) );

		return False;
	}

	pPixelShader = Mix::Graphics::DX9::PixelShader::CreateInstance( this, pD3DPixelShader );
	if( pPixelShader == NULL )
	{
		MIX_LOG_ERROR( L"%s : %s : Name[%s]", FAILED_CREATE_PIXEL_SHADER,
			Mix::STR_OUTOFMEMORY, Mix::STR_DEBUGNAME, MIX_SAFE_NAME( pDebugName ) );

		MIX_RELEASE( pD3DPixelShader );

		return False;
	}

	( *ppPixelShader ) = pPixelShader;

	return True;
}

Boolean Device::CreatePixelShaderFromFile( const wchar_t* pFilePath, Mix::Graphics::IPixelShader** ppPixelShader )
{
	if( ( pFilePath == NULL ) ||
		( ::wcslen( pFilePath ) == 0 ) ||
		( ppPixelShader == NULL ) )
	{
		MIX_LOG_ERROR( L"%s : %s : pFilePath[%s] ppPixelShader[%s]", FAILED_CREATE_PIXEL_SHADER,
			Mix::STR_ILLEGALARG,
			MIX_LOG_STR( pFilePath ),
			MIX_LOG_PTR( ppPixelShader ) );

		return False;
	}

	HRESULT ret;
	Mix::Memory::IBuffer* pBuffer = NULL;
	Mix::Graphics::DX9::PixelShader* pPixelShader;
	IDirect3DPixelShader9* pD3DPixelShader = NULL;

	if( m_pFileMgr->CreateBufferFromFile( pFilePath, &pBuffer ) == False )
	{
		MIX_LOG_ERROR( L"%s : ファイルが見つかりません : %s[%s]", FAILED_CREATE_PIXEL_SHADER, Mix::STR_FILEPATH, pFilePath );
		return False;
	}

	ret = m_pD3DDevice->CreatePixelShader( static_cast<const DWORD*>( pBuffer->GetConstPointer() ), &pD3DPixelShader );
	if( ret != D3D_OK )
	{
		MIX_LOG_ERROR( L"%s : CreatePixelShader %s : %s[%s]", FAILED_CREATE_PIXEL_SHADER,
			Mix::STR_RETERROR, Mix::STR_FILEPATH, pFilePath );

		MIX_RELEASE( pBuffer );

		return False;
	}

	MIX_RELEASE( pBuffer );

	pPixelShader = Mix::Graphics::DX9::PixelShader::CreateInstance( this, pD3DPixelShader );
	if( pPixelShader == NULL )
	{
		MIX_LOG_ERROR( L"%s : %s : %s[%s]", FAILED_CREATE_PIXEL_SHADER, Mix::STR_OUTOFMEMORY, Mix::STR_FILEPATH, pFilePath );
		MIX_RELEASE( pD3DPixelShader );
		return False;
	}

	( *ppPixelShader ) = pPixelShader;

	return True;
}

Boolean Device::CreateShaderConstant( UInt32 size, Boolean bDynamic, const void* pInitialData, Mix::Graphics::IShaderConstant** ppShaderConstant, const wchar_t* pDebugName )
{
	return False;
}

Boolean Device::CreateVertexLayout( const Mix::Graphics::VERTEX_ELEMENT* pElements, UInt32 elementCount, const Mix::Graphics::IVertexShader* pVertexShader, Mix::Graphics::IVertexLayout** ppVertexLayout, const wchar_t* pDebugName )
{
	if( ( pElements == NULL ) ||
		( elementCount == 0 ) ||
		( pVertexShader == NULL ) ||
		( ppVertexLayout == NULL ) )
	{
		MIX_LOG_ERROR( L"%s : %s : %s[%s] : pElements[%s] elementCount[%d] pVertexShader[%s] ppVertexLayout[%s]",
			FAILED_CREATE_VERTEX_LAYOUT,
			Mix::STR_ILLEGALARG,
			Mix::STR_DEBUGNAME,
			MIX_SAFE_NAME( pDebugName ),
			MIX_LOG_PTR( pElements ),
			elementCount,
			MIX_LOG_PTR( pVertexShader ),
			MIX_LOG_PTR( ppVertexLayout ) );

		return False;
	}

	UInt32 i;
	UInt32 stride;
	HRESULT ret;
	Mix::Graphics::DX9::VertexLayout* pVertexLayout;
	D3DVERTEXELEMENT9* pD3DElements;
	IDirect3DVertexDeclaration9* pD3DVertexLayout;

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// バーテックスデクラレーションを作成
	////////////////////////////////////////////////////////////////////////////////////////////////////

	stride = 0;

	pD3DElements = static_cast<D3DVERTEXELEMENT9*>( MIX_LIB_MALLOC( Mix::Memory::SECTION_GRAPHICS, sizeof( D3DVERTEXELEMENT9 ) * ( elementCount + 1 ) ) );
	if( pD3DElements == NULL )
	{
		MIX_LOG_ERROR( L"%s : %s : %s[%s]", FAILED_CREATE_VERTEX_LAYOUT,
			Mix::STR_OUTOFMEMORY, Mix::STR_DEBUGNAME, MIX_SAFE_NAME( pDebugName ) );
		return False;
	}

	for( i = 0; i < elementCount; i++ )
	{
		UInt32 format = pElements[i].format;

		pD3DElements[i].Stream = 0;
		pD3DElements[i].Offset = static_cast<WORD>( pElements[i].offset );
		pD3DElements[i].Type = Device::D3DVLFormatTable[format];
		pD3DElements[i].Method = D3DDECLMETHOD_DEFAULT;
		pD3DElements[i].Usage = Device::D3DVLSemanticTypeTable[pElements[i].semanticType];
		pD3DElements[i].UsageIndex = static_cast<BYTE>( pElements[i].semanticIndex );

		stride += Device::GetVertexElementSize( format );
	}
	
	pD3DElements[elementCount].Stream = 0xFF;
	pD3DElements[elementCount].Offset = 0;
	pD3DElements[elementCount].Type = D3DDECLTYPE_UNUSED;
	pD3DElements[elementCount].Method = 0;
	pD3DElements[elementCount].Usage = 0;
	pD3DElements[elementCount].UsageIndex = 0;

	ret = m_pD3DDevice->CreateVertexDeclaration( &( pD3DElements[0] ), &pD3DVertexLayout );
	if( ret != D3D_OK )
	{
		MIX_LOG_ERROR( L"%s : CreateVertexDeclaration %s : %s[%s] Result[%s]", FAILED_CREATE_VERTEX_LAYOUT,
			Mix::STR_RETERROR, Mix::STR_DEBUGNAME, MIX_SAFE_NAME( pDebugName ), GetD3DResultText( ret ) );

		MIX_LIB_FREE( pD3DElements );

		return False;
	}

	MIX_LIB_FREE( pD3DElements );

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

	pVertexLayout = Mix::Graphics::DX9::VertexLayout::CreateInstance(	this,
																		pD3DVertexLayout,
																		pElements,
																		elementCount,
																		stride );
	if( pVertexLayout == NULL )
	{
		MIX_LOG_ERROR( L"%s : %s : %s[%s]", FAILED_CREATE_VERTEX_LAYOUT,
			Mix::STR_OUTOFMEMORY, Mix::STR_DEBUGNAME, MIX_SAFE_NAME( pDebugName ) );

		MIX_RELEASE( pD3DVertexLayout );

		return False;
	}

	( *ppVertexLayout ) = pVertexLayout;

	return True;
}

Boolean Device::CreateVertexBuffer( UInt32 count, UInt32 stride, Boolean bDynamic, UInt32 resizeStep, const void* pInitialData, Mix::Graphics::IVertexBuffer** ppVertexBuffer, const wchar_t* pDebugName )
{
	if( ( count == 0 ) ||
		( stride == 0 ) ||
		( ppVertexBuffer == NULL ) )
	{
		MIX_LOG_ERROR( L"%s : %s : %s[%s] : count[%d] stride[%d] ppVertexBuffer[%s]",
			FAILED_CREATE_VERTEX_BUFFER,
			Mix::STR_ILLEGALARG,
			Mix::STR_DEBUGNAME,
			MIX_SAFE_NAME( pDebugName ),
			count,
			stride,
			MIX_LOG_PTR( ppVertexBuffer ) );

		return False;
	}

	HRESULT ret;
	IDirect3DVertexBuffer9* pD3DVertexBuffer;

	//D3Dバーテックスバッファの作成
	ret = CreateVertexBuffer( count, stride, bDynamic, &pD3DVertexBuffer );
	if( ret != D3D_OK )
	{
		MIX_LOG_ERROR( L"%s : CreateVertexBuffer %s : %s[%d] %s[%s]", FAILED_CREATE_VERTEX_BUFFER,
			Mix::STR_RETERROR, Mix::STR_DEBUGNAME, MIX_SAFE_NAME( pDebugName ), Mix::STR_RESULT, GetD3DResultText( ret ) );
		return False;
	}

	//バーテックスバッファインターフェースを作成
	Mix::Graphics::DX9::VertexBuffer* pVertexBuffer = Mix::Graphics::DX9::VertexBuffer::CreateInstance( this, count, stride, bDynamic, resizeStep, pD3DVertexBuffer );
	if( pVertexBuffer == NULL )
	{
		MIX_LOG_ERROR( L"%s : %s : %s[%s]", FAILED_CREATE_VERTEX_BUFFER,
			Mix::STR_OUTOFMEMORY, Mix::STR_DEBUGNAME, MIX_SAFE_NAME( pDebugName ) );

		MIX_RELEASE( pD3DVertexBuffer );

		return False;
	}

	//バーテックスバッファを初期化
	ret = pVertexBuffer->Initialize( pInitialData );
	if( ret != D3D_OK )
	{
		MIX_LOG_ERROR( L"%s : Initialize %s : %s[%s] %s[%s]", FAILED_CREATE_VERTEX_BUFFER,
			Mix::STR_RETERROR, Mix::STR_DEBUGNAME, MIX_SAFE_NAME( pDebugName ), Mix::STR_RESULT, GetD3DResultText( ret ) );

		MIX_RELEASE( pVertexBuffer );

		return False;
	}

#ifdef _DEBUG
	pVertexBuffer->SetDebugName( MIX_SAFE_NAME( pDebugName ) );
#endif //_DEBUG

	( *ppVertexBuffer ) = pVertexBuffer;

	return True;
}

Boolean Device::CreateIndexBuffer( Mix::Graphics::INDEX_FORMAT format, UInt32 count, Boolean bDynamic, UInt32 resizeStep, const void* pInitialData, Mix::Graphics::IIndexBuffer** ppIndexBuffer, const wchar_t* pDebugName )
{
	if( ( count == 0 ) ||
		( ppIndexBuffer == NULL ) )
	{
		MIX_LOG_ERROR( L"%s : %s : %s[%s] : count[%d] ppIndexBuffer[%s]",
			FAILED_CREATE_INDEX_BUFFER,
			Mix::STR_ILLEGALARG,
			Mix::STR_DEBUGNAME,
			MIX_SAFE_NAME( pDebugName ),
			count,
			MIX_LOG_PTR( ppIndexBuffer ) );

		return False;
	}

	HRESULT ret;
	D3DFORMAT d3dFormat;
	IDirect3DIndexBuffer9* pD3DIndexBuffer;

	//フォーマットを決定
	switch( format )
	{
	case Mix::Graphics::INDEX_USHORT:
		d3dFormat = D3DFMT_INDEX16;
		break;
	case Mix::Graphics::INDEX_UINT:
		d3dFormat = D3DFMT_INDEX32;
		break;
	}

	//D3Dインデックスバッファを作成
	ret = CreateIndexBuffer( d3dFormat, count, bDynamic, &pD3DIndexBuffer );
	if( ret != D3D_OK )
	{
		MIX_LOG_ERROR( L"%s : CreateIndexBuffer %s : %s[%s] %s[%s]", FAILED_CREATE_INDEX_BUFFER,
			Mix::STR_RETERROR, Mix::STR_DEBUGNAME, MIX_SAFE_NAME( pDebugName ), Mix::STR_RESULT, GetD3DResultText( ret ) );
		return False;
	}

	//インデックスバッファインターフェースを作成
	Mix::Graphics::DX9::IndexBuffer* pIndexBuffer = Mix::Graphics::DX9::IndexBuffer::CreateInstance( this, format, d3dFormat, count, bDynamic, resizeStep, pD3DIndexBuffer );
	if( pIndexBuffer == NULL )
	{
		MIX_LOG_ERROR( L"%s : %s : %s[%s]", FAILED_CREATE_INDEX_BUFFER,
			Mix::STR_OUTOFMEMORY, Mix::STR_DEBUGNAME, MIX_SAFE_NAME( pDebugName ) );

		MIX_RELEASE( pD3DIndexBuffer );

		return False;
	}

	//インデックスバッファを初期化
	ret = pIndexBuffer->Initialize( pInitialData );
	if( ret != D3D_OK )
	{
		MIX_LOG_ERROR( L"%s : Initialize %s : %s[%s] %s[%s]", FAILED_CREATE_INDEX_BUFFER,
			Mix::STR_RETERROR, Mix::STR_DEBUGNAME, MIX_SAFE_NAME( pDebugName ), Mix::STR_RESULT, GetD3DResultText( ret ) );

		MIX_RELEASE( pIndexBuffer );

		return False;
	}

#ifdef _DEBUG
	pIndexBuffer->SetDebugName( MIX_SAFE_NAME( pDebugName ) );
#endif //_DEBUG

	( *ppIndexBuffer ) = pIndexBuffer;

	return True;
}

Boolean Device::CreateTextureFromFile( const wchar_t* pFilePath, Mix::Graphics::ITexture** ppTexture )
{
	if( ( pFilePath == NULL ) ||
		( wcslen( pFilePath ) == 0 ) ||
		( ppTexture == NULL ) )
	{
		MIX_LOG_ERROR( L"%s : %s : pFilePath[%s] ppTexture[%s]", FAILED_CREATE_TEXTURE,
			Mix::STR_ILLEGALARG,
			MIX_LOG_STR( pFilePath ),
			MIX_LOG_PTR( ppTexture ) );

		return False;
	}

	Mix::Memory::IBuffer* pBuffer;
	Mix::Graphics::ITexture* pTexture = NULL;

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

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

	pTexture = CreateTextureFromPlugin( pFilePath, pBuffer->GetConstPointer(), MIX_UIT_TO_UI32( pBuffer->GetSize() ) );
	if( pTexture == NULL )
	{
		MIX_RELEASE( pBuffer );
		return False;
	}

	MIX_RELEASE( pBuffer );

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

	( *ppTexture ) = pTexture;

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

	return True;
}

Boolean Device::CreateTextureFromMemory( const wchar_t* pFilePath, const void* pSrc, UInt32 srcSize, Mix::Graphics::ITexture** ppTexture )
{
	if( ( pFilePath == NULL ) ||
		( wcslen( pFilePath ) == 0 ) ||
		( pSrc == NULL ) ||
		( srcSize == 0 ) ||
		( ppTexture == NULL ) )
	{
		MIX_LOG_ERROR( L"%s : %s : pFilePath[%s] pSrc, srcSize[%d] ppTexture[%s]", FAILED_CREATE_TEXTURE,
			Mix::STR_ILLEGALARG,
			MIX_LOG_STR( pFilePath ),
			MIX_LOG_PTR( pSrc ),
			MIX_LOG_PTR( pSrc ),
			srcSize,
			MIX_LOG_PTR( ppTexture ) );

		return False;
	}

	Mix::Graphics::ITexture* pTexture;

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

	pTexture = CreateTextureFromPlugin( pFilePath, pSrc, srcSize );
	if( pTexture == NULL )
	{
		return False;
	}

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

	( *ppTexture ) = pTexture;

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

	return True;
}

Boolean Device::CreateDynamicPlaneTexture( UInt32 width, UInt32 height, Mix::Graphics::FORMAT format, Mix::Graphics::ITexture** ppTexture, const wchar_t* pDebugName )
{
	if( ( width == 0 ) ||
		( height == 0 ) ||
		( ppTexture == NULL ) )
	{
		MIX_LOG_ERROR( L"%s : %s : %s[%s] : width[%d] height[%d] ppTexture[%s]",
			FAILED_CREATE_TEXTURE_DYNAMIC_PLANE,
			Mix::STR_ILLEGALARG,
			Mix::STR_DEBUGNAME,
			MIX_SAFE_NAME( pDebugName ),
			width,
			height,
			MIX_LOG_PTR( ppTexture ) );

		return False;
	}

	HRESULT ret;
	const FORMATINFO* pFmtInfo;
	IDirect3DTexture9* pD3DTexture;
	Mix::Graphics::DX9::TextureDynamic* pTexture;

	// フォーマットを取得

	if( IsDynamicPlaneTextureSupported( format ) == False )
	{
		MIX_LOG_ERROR( L"%s : サポートされないフォーマット : %s[%s] %s[%s]", FAILED_CREATE_TEXTURE_DYNAMIC_PLANE,
			Mix::STR_DEBUGNAME, MIX_SAFE_NAME( pDebugName ), Mix::STR_FORMAT, GetFormatText( format ) );

		return False;
	}

	pFmtInfo = &( m_DeviceParam.current.formatTable[format] );

	// D3D テクスチャを作成

	ret = CreateDynamicTexture( width, height, pFmtInfo->format, &pD3DTexture );
	if( ret != D3D_OK )
	{
		MIX_LOG_ERROR( L"%s : CreateDynamicTexture %s : %s[%s] Result[%s]", FAILED_CREATE_TEXTURE_DYNAMIC_PLANE,
			Mix::STR_RETERROR, Mix::STR_DEBUGNAME, MIX_SAFE_NAME( pDebugName ), GetD3DResultText( ret ) );
		return False;
	}

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

	pTexture = Mix::Graphics::DX9::TextureDynamic::CreateInstance(	this,
																	width, height, Device::ConvertTextureFormat( pFmtInfo->format ),
																	pD3DTexture, pFmtInfo->format );
	if( pTexture == NULL )
	{
		MIX_LOG_ERROR( L"%s : %s : %s[%s]", FAILED_CREATE_TEXTURE_DYNAMIC_PLANE,
			Mix::STR_OUTOFMEMORY, Mix::STR_DEBUGNAME, MIX_SAFE_NAME( pDebugName ) );

		MIX_RELEASE( pD3DTexture );

		return False;
	}

	( *ppTexture ) = pTexture;

	return True;
}

Boolean Device::CreateTargetPlaneTexture( UInt32 width, UInt32 height, Mix::Graphics::FORMAT format, Mix::Graphics::ITexture** ppTexture, const wchar_t* pDebugName )
{
	if( ( width == 0 ) ||
		( height == 0 ) ||
		( ppTexture == NULL ) )
	{
		MIX_LOG_ERROR( L"%s : %s : %s[%s] : width[%d] height[%d] ppTexture[%s]",
			FAILED_CREATE_TEXTURE_TARGET_PLANE,
			Mix::STR_ILLEGALARG,
			Mix::STR_DEBUGNAME,
			MIX_SAFE_NAME( pDebugName ),
			width,
			height,
			MIX_LOG_PTR( ppTexture ) );

		return False;
	}

	HRESULT ret;
	const FORMATINFO* pFmtInfo;
	IDirect3DTexture9* pD3DTexture;
	IDirect3DSurface9* pD3DSurface;
	Mix::Graphics::DX9::TextureTarget* pTexture;

	// フォーマットを取得

	if( IsTargetPlaneTextureSupported( format ) == False )
	{
		MIX_LOG_ERROR( L"%s : サポートされないフォーマット : %s[%s] %s[%s]", FAILED_CREATE_TEXTURE_TARGET_PLANE,
			Mix::STR_DEBUGNAME, MIX_SAFE_NAME( pDebugName ), Mix::STR_FORMAT, GetFormatText( format ) );

		return False;
	}

	pFmtInfo = &( m_DeviceParam.current.formatTable[format] );

	// D3D テクスチャを作成

	ret = CreateTargetTexture( width, height, pFmtInfo->format, &pD3DTexture );
	if( ret != D3D_OK )
	{
		MIX_LOG_ERROR( L"%s : CreateTargetTexture %s : %s[%s] %s[%s]", FAILED_CREATE_TEXTURE_TARGET_PLANE,
			Mix::STR_RETERROR, Mix::STR_DEBUGNAME, MIX_SAFE_NAME( pDebugName ), Mix::STR_RESULT, GetD3DResultText( ret ) );

		return False;
	}

	// D3D サーフェイスを取得

	ret = pD3DTexture->GetSurfaceLevel( 0, &pD3DSurface );
	if( ret != D3D_OK )
	{
		MIX_LOG_ERROR( L"%s : GetSurfaceLevel %s : %s[%s] %s[%s]", FAILED_CREATE_TEXTURE_TARGET_PLANE,
			Mix::STR_RETERROR, Mix::STR_DEBUGNAME, MIX_SAFE_NAME( pDebugName ), Mix::STR_RESULT, GetD3DResultText( ret ) );

		MIX_RELEASE( pD3DTexture );

		return False;
	}

	// テクスチャインターフェースを作成

	pTexture = Mix::Graphics::DX9::TextureTarget::CreateInstance(	this,
																	width, height, Device::ConvertTextureFormat( pFmtInfo->format ),
																	pD3DTexture, pD3DSurface, pFmtInfo->format );
	if( pTexture != NULL )
	{
		( *ppTexture ) = pTexture;
	}
	else
	{
		MIX_LOG_ERROR( L"%s : %s : %s[%s]", FAILED_CREATE_TEXTURE_TARGET_PLANE,
			Mix::STR_OUTOFMEMORY, Mix::STR_DEBUGNAME, MIX_SAFE_NAME( pDebugName ) );

		MIX_RELEASE( pD3DSurface );
		MIX_RELEASE( pD3DTexture );

		return False;
	}

	return True;
}

Boolean Device::CreateLockableTargetPlaneTexture( UInt32 width, UInt32 height, Mix::Graphics::FORMAT format, Mix::Graphics::ITexture** ppTexture, const wchar_t* pDebugName )
{
	if( ( width == 0 ) ||
		( height == 0 ) ||
		( ppTexture == NULL ) )
	{
		MIX_LOG_ERROR( L"%s : %s : %s[%s] : width[%d] height[%d] ppTexture[%s]",
			FAILED_CREATE_TEXTURE_LOCKABLE_TARGET_PLANE,
			Mix::STR_ILLEGALARG,
			Mix::STR_DEBUGNAME,
			MIX_SAFE_NAME( pDebugName ),
			width,
			height,
			MIX_LOG_PTR( ppTexture ) );

		return False;
	}

	HRESULT hRet;
	const FORMATINFO* pFmtInfo;
	IDirect3DSurface9* pD3DSurface;
	Mix::Graphics::DX9::TextureTargetL* pTexture;

	// フォーマットを取得

	if( IsLockableTargetPlaneTextureSupported( format ) == False )
	{
		MIX_LOG_ERROR( L"%s : サポートされないフォーマット : %s[%s] %s[%s]", FAILED_CREATE_TEXTURE_LOCKABLE_TARGET_PLANE,
			Mix::STR_DEBUGNAME, MIX_SAFE_NAME( pDebugName ), Mix::STR_FORMAT, GetFormatText( format ) );

		return False;
	}

	pFmtInfo = &( m_DeviceParam.current.formatTable[format] );

	// D3D サーフェイスを作成

	hRet = CreateTargetSurface( width, height, pFmtInfo->format, &pD3DSurface );
	if( hRet != D3D_OK )
	{
		MIX_LOG_ERROR( L"%s : CreateTargetTexture %s : %s[%s] %s[%s]", FAILED_CREATE_TEXTURE_LOCKABLE_TARGET_PLANE,
			Mix::STR_RETERROR, Mix::STR_DEBUGNAME, MIX_SAFE_NAME( pDebugName ), Mix::STR_RESULT, GetD3DResultText( hRet ) );

		return False;
	}

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

	pTexture = Mix::Graphics::DX9::TextureTargetL::CreateInstance(	this,
																	width, height, Device::ConvertTextureFormat( pFmtInfo->format ),
																	pD3DSurface, pFmtInfo->format );
	if( pTexture == NULL )
	{
		MIX_LOG_ERROR( L"%s : %s : %s[%s]", FAILED_CREATE_TEXTURE_LOCKABLE_TARGET_PLANE,
			Mix::STR_OUTOFMEMORY, Mix::STR_DEBUGNAME, MIX_SAFE_NAME( pDebugName ) );

		MIX_RELEASE( pD3DSurface );

		return False;
	}

	( *ppTexture ) = pTexture;

	return True;
}

Boolean Device::CreateTargetCubeTexture( UInt32 edgeLength, Mix::Graphics::FORMAT format, Mix::Graphics::ITexture** ppTexture, const wchar_t* pDebugName )
{
	if( ( edgeLength == 0 ) ||
		( ppTexture == NULL ) )
	{
		MIX_LOG_ERROR( L"%s : %s : %s[%s] : edgeLength[%d] ppTexture[%s]",
			FAILED_CREATE_TEXTURE_TARGET_CUBE,
			Mix::STR_ILLEGALARG,
			Mix::STR_DEBUGNAME,
			MIX_SAFE_NAME( pDebugName ),
			edgeLength,
			MIX_LOG_PTR( ppTexture ) );

		return False;
	}

	HRESULT ret;
	const FORMATINFO* pFmtInfo;
	IDirect3DCubeTexture9* pD3DTexture;
	Mix::Graphics::DX9::TextureCube* pTexture;

	// フォーマットを取得

	if( IsTargetCubeTextureSupported( format ) == False )
	{
		MIX_LOG_ERROR( L"%s : サポートされないフォーマット : %s[%s] %s[%s]", FAILED_CREATE_TEXTURE_TARGET_CUBE,
			Mix::STR_DEBUGNAME, MIX_SAFE_NAME( pDebugName ), Mix::STR_FORMAT, GetFormatText( format ) );

		return False;
	}

	pFmtInfo = &( m_DeviceParam.current.formatTable[format] );

	// D3D テクスチャを作成

	ret = CreateCubeTexture( edgeLength, pFmtInfo->format, &pD3DTexture );
	if( ret != D3D_OK )
	{
		MIX_LOG_ERROR( L"%s : CreateCubeTexture %s : %s[%s] %s[%s]", FAILED_CREATE_TEXTURE_TARGET_CUBE,
			Mix::STR_RETERROR, Mix::STR_DEBUGNAME, MIX_SAFE_NAME( pDebugName ), Mix::STR_RESULT, GetD3DResultText( ret ) );

		return False;
	}

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

	pTexture = Mix::Graphics::DX9::TextureCube::CreateInstance(	this,
																NULL,
																edgeLength, Device::ConvertTextureFormat( pFmtInfo->format ),
																pFmtInfo->format, pD3DTexture );
	if( pTexture == NULL )
	{
		MIX_LOG_ERROR( L"%s : %s : %s[%s]", FAILED_CREATE_TEXTURE_TARGET_CUBE,
			Mix::STR_OUTOFMEMORY, Mix::STR_DEBUGNAME, MIX_SAFE_NAME( pDebugName ) );

		MIX_RELEASE( pD3DTexture );

		return False;
	}

	( *ppTexture ) = pTexture;

	return True;
}

Boolean Device::CreateDepthTexture( UInt32 width, UInt32 height, Mix::Graphics::FORMAT format, Mix::Graphics::ITexture** ppTexture, const wchar_t* pDebugName )
{
	if( ( width == 0 ) ||
		( height == 0 ) ||
		( ppTexture == NULL ) )
	{
		MIX_LOG_ERROR( L"%s : %s : %s[%s] : width[%d] height[%d] ppTexture[%s]",
			FAILED_CREATE_TEXTURE_DEPTH,
			Mix::STR_ILLEGALARG,
			Mix::STR_DEBUGNAME,
			MIX_SAFE_NAME( pDebugName ),
			width,
			height,
			MIX_LOG_PTR( ppTexture ) );

		return False;
	}

	HRESULT ret;
	const FORMATINFO* pFmtInfo;
	IDirect3DSurface9* pD3DSurface;
	Mix::Graphics::DX9::TextureDepth* pTexture;

	// フォーマットを取得

	if( IsDepthTextureSupported( format ) == False )
	{
		MIX_LOG_ERROR( L"%s : サポートされないフォーマット : %s[%s] %s[%s]", FAILED_CREATE_TEXTURE_DEPTH,
			Mix::STR_DEBUGNAME, MIX_SAFE_NAME( pDebugName ), Mix::STR_FORMAT, GetFormatText( format ) );

		return False;
	}

	pFmtInfo = &( m_DeviceParam.current.formatTable[format] );

	// D3D テクスチャを作成

	ret = CreateDepthTexture( width, height, pFmtInfo->format, &pD3DSurface );
	if( ret != D3D_OK )
	{
		MIX_LOG_ERROR( L"%s : CreateDepthTexture %s : %s[%s] %s[%s]", FAILED_CREATE_TEXTURE_DEPTH,
			Mix::STR_RETERROR, Mix::STR_DEBUGNAME, MIX_SAFE_NAME( pDebugName ), Mix::STR_RESULT, GetD3DResultText( ret ) );

		return False;
	}

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

	pTexture = Mix::Graphics::DX9::TextureDepth::CreateInstance(	this,
																	width, height, Device::ConvertTextureFormat( pFmtInfo->format ),
																	pFmtInfo->format, pD3DSurface );
	if( pTexture == NULL )
	{
		MIX_LOG_ERROR( L"%s : %s : %s[%s]", FAILED_CREATE_TEXTURE_DEPTH,
			Mix::STR_OUTOFMEMORY, Mix::STR_DEBUGNAME, MIX_SAFE_NAME( pDebugName ) );

		MIX_RELEASE( pD3DSurface );

		return False;
	}

	( *ppTexture ) = pTexture;

	return True;
}

Boolean Device::CreateQuery( Mix::Graphics::QUERY_FORMAT format, Mix::Graphics::IQuery** ppQuery, const wchar_t* pDebugName )
{
	if( ppQuery == NULL )
	{
		MIX_LOG_ERROR( L"%s : %s : %s[%s] ppQuery[%s]", FAILED_CREATE_QUERY,
			Mix::STR_ILLEGALARG,
			Mix::STR_DEBUGNAME,
			MIX_SAFE_NAME( pDebugName ),
			MIX_LOG_PTR( ppQuery ) );

		return False;
	}

	HRESULT ret;
	IDirect3DQuery9* pD3DQuery;
	Mix::Graphics::DX9::Query* pQuery; 

	ret = CreateQuery( format, &pD3DQuery );
	if( ret != D3D_OK )
	{
		MIX_LOG_ERROR( L"%s : CreateQuery %s : %s[%s] %s[%s] %s[%s]", FAILED_CREATE_QUERY,
			Mix::STR_RETERROR,
			Mix::STR_DEBUGNAME,
			MIX_SAFE_NAME( pDebugName ),
			Mix::STR_FORMAT,
			Device::D3DQueryTextTable[format],
			Mix::STR_RESULT,
			GetD3DResultText( ret ) );

		return False;
	}

	pQuery = Mix::Graphics::DX9::Query::CreateInstance( this, format, pD3DQuery );
	if( pQuery == NULL )
	{
		MIX_LOG_ERROR( L"%s : %s : %s[%s] %s[%s]", FAILED_CREATE_QUERY,
			Mix::STR_OUTOFMEMORY, Mix::STR_DEBUGNAME, MIX_SAFE_NAME( pDebugName ), Mix::STR_FORMAT, Device::D3DQueryTextTable[format] );

		MIX_RELEASE( pD3DQuery );

		return False;
	}

	( *ppQuery ) = pQuery;

	return True;
}

Mix::Graphics::IDevice::DISPLAY_MODE Device::GetDisplayMode( void ) const
{
	return ( m_DeviceParam.current.params.Windowed == TRUE )? Mix::Graphics::IDevice::WINDOW : Mix::Graphics::IDevice::FULLSCREEN;
}

void Device::SetDisplayMode( Mix::Graphics::IDevice::DISPLAY_MODE dispMode )
{
	if( ( m_Status != Device::STATUS_OK ) || ( m_pEngine->IsSizeableWindow() == True ) )
	{
		// ステータスが正常ではない、サイズ変更可能なウィンドウの場合は変更できない
		return;
	}

	m_Status = ( GetDisplayMode() == Mix::Graphics::IDevice::WINDOW )? Device::STATUS_CHANGE_FULLSCREEN : Device::STATUS_CHANGE_WINDOW;
}

void Device::ToggleDisplayMode( void )
{
	SetDisplayMode( ( GetDisplayMode() == Mix::Graphics::IDevice::WINDOW )? Mix::Graphics::IDevice::FULLSCREEN : Mix::Graphics::IDevice::WINDOW );
}

Boolean Device::Begin( void )
{
	//プリミティブ描画数をリセット
	m_DrawPrimitiveCount = 0;

	//描画ステートをリセット
//	ResetDrawState();

	//シーンを開始する
	return ( m_pD3DDevice->BeginScene() == D3D_OK );
}

void Device::End( void )
{
	if( m_pD3DDevice->EndScene() != D3D_OK )
	{
		MIX_LOG_ERROR( L"Mix::Graphics::IDevice::End : IDirect3DDevice9::EndScene %s", Mix::STR_RETERROR );
	}

	ResetTargetState();
	ResetDrawState();
}

void Device::Present( void )
{
	HRESULT hRet;

	if( m_pEngine->IsSizeableWindow() == True )
	{
		const Mix::Point& size = m_pEngine->GetClientSize();

		RECT dstRect;
		RECT srcRect;

		srcRect.left = m_ScreenValidBounds.x;
		srcRect.top = m_ScreenValidBounds.y;
		srcRect.right = srcRect.left + m_ScreenValidBounds.width;
		srcRect.bottom = srcRect.top + m_ScreenValidBounds.height;

		dstRect.left = ( size.x - m_ScreenValidBounds.width ) >> 1;
		dstRect.top = ( size.y - m_ScreenValidBounds.height ) >> 1;
		dstRect.right = dstRect.left + m_ScreenValidBounds.width;
		dstRect.bottom = dstRect.top + m_ScreenValidBounds.height;

		hRet = m_pD3DDevice->Present( &srcRect, &dstRect, NULL, NULL );
	}
	else
	{
		hRet = m_pD3DDevice->Present( NULL, NULL, NULL, NULL );
	}

	switch( hRet )
	{
	case D3DERR_DEVICELOST:
		m_Status = Device::STATUS_LOST;
		break;
	case D3DERR_INVALIDCALL:
		MIX_LOG_ERROR( L"Mix::Graphics::IDevice::Present : IDirect3DDevice9::Present %s", Mix::STR_RETERROR );
		break;
	case D3DERR_DRIVERINTERNALERROR:
		::SendMessage( m_pEngine->GetWindowHandle(), WM_MIX_INTERNALERROR, Mix::ERR_GRAPHICS_DRIVERERROR, 0 );
		break;
	}
}

void Device::SetTarget( Mix::Graphics::ITexture* pT0, Mix::Graphics::ITexture* pT1, Mix::Graphics::ITexture* pT2, Mix::Graphics::ITexture* pT3, Mix::Graphics::ITexture* pDS )
{
	if( ( ( pT0 != NULL ) && ( pT0->GetBindType() != Mix::Graphics::ITexture::BIND_TARGET ) ) ||
		( ( pT1 != NULL ) && ( pT1->GetBindType() != Mix::Graphics::ITexture::BIND_TARGET ) ) ||
		( ( pT2 != NULL ) && ( pT2->GetBindType() != Mix::Graphics::ITexture::BIND_TARGET ) ) ||
		( ( pT3 != NULL ) && ( pT3->GetBindType() != Mix::Graphics::ITexture::BIND_TARGET ) ) ||
		( ( pDS != NULL ) && ( pDS->GetBindType() != Mix::Graphics::ITexture::BIND_DEPTH ) ) )
	{
		MIX_LOG_ERROR( L"%s : %s : pT0[%s] pT1[%s] pT2[%s] pT3[%s] pDS[%s]",
			FAILED_SET_TARGET,
			Mix::STR_ILLEGALARG,
			( ( pT0 == NULL ) || ( pT0->GetType() == Mix::Graphics::ITexture::BIND_TARGET ) )? L"○" : L"×",
			( ( pT1 == NULL ) || ( pT1->GetType() == Mix::Graphics::ITexture::BIND_TARGET ) )? L"○" : L"×",
			( ( pT2 == NULL ) || ( pT2->GetType() == Mix::Graphics::ITexture::BIND_TARGET ) )? L"○" : L"×",
			( ( pT3 == NULL ) || ( pT3->GetType() == Mix::Graphics::ITexture::BIND_TARGET ) )? L"○" : L"×",
			( ( pDS == NULL ) || ( pDS->GetType() == Mix::Graphics::ITexture::BIND_DEPTH ) )? L"○" : L"×" );

		return;
	}

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// テクスチャの破棄( DirectX11 と動作を同じにするため )
	////////////////////////////////////////////////////////////////////////////////////////////////////

	for( UInt32 i = 0; i < Mix::Graphics::TEXTURESTAGE_MAX; i++ )
	{
		m_pD3DDevice->SetTexture( i, NULL );
		m_DrawState.textureTable[i] = NULL;
	}

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// 復帰用にターゲットを保存
	////////////////////////////////////////////////////////////////////////////////////////////////////

	if( pT0 != NULL )
	{
		m_TargetState.rect = Mix::Rectangle( 0, 0, pT0->GetWidth(), pT0->GetHeight() );
	}
	else
	{
		m_TargetState.rect = Mix::Rectangle( 0, 0, m_DeviceParam.current.screenSize.x, m_DeviceParam.current.screenSize.y );
	}

	MIX_RELEASE( m_TargetState.pTex[0] );
	MIX_ADD_REF( pT0 );
	m_TargetState.pTex[0] = pT0;

	MIX_RELEASE( m_TargetState.pTex[1] );
	MIX_ADD_REF( pT1 );
	m_TargetState.pTex[1] = pT1;

	MIX_RELEASE( m_TargetState.pTex[2] );
	MIX_ADD_REF( pT2 );
	m_TargetState.pTex[2] = pT2;

	MIX_RELEASE( m_TargetState.pTex[3] );
	MIX_ADD_REF( pT3 );
	m_TargetState.pTex[3] = pT3;

	MIX_RELEASE( m_TargetState.pDSTex );
	MIX_ADD_REF( pDS );
	m_TargetState.pDSTex = pDS;

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// ターゲットをフラッシュ
	////////////////////////////////////////////////////////////////////////////////////////////////////

	FlushTargetState();
}

void Device::GetTarget( Mix::Graphics::ITexture** ppT0, Mix::Graphics::ITexture** ppT1, Mix::Graphics::ITexture** ppT2, Mix::Graphics::ITexture** ppT3, Mix::Graphics::ITexture** ppDS )
{
	if( ppT0 != NULL )
	{
		MIX_ADD_REF( m_TargetState.pTex[0] );
		( *ppT0 ) = m_TargetState.pTex[0];
	}

	if( ppT1 != NULL )
	{
		MIX_ADD_REF( m_TargetState.pTex[1] );
		( *ppT1 ) = m_TargetState.pTex[1];
	}

	if( ppT2 != NULL )
	{
		MIX_ADD_REF( m_TargetState.pTex[2] );
		( *ppT2 ) = m_TargetState.pTex[2];
	}

	if( ppT3 != NULL )
	{
		MIX_ADD_REF( m_TargetState.pTex[3] );
		( *ppT3 ) = m_TargetState.pTex[3];
	}

	if( ppDS != NULL )
	{
		MIX_ADD_REF( m_TargetState.pDSTex );
		( *ppDS ) = m_TargetState.pDSTex;
	}
}

const Mix::Rectangle& Device::GetViewBounds( void ) const
{
	return m_ViewportRect;
}

void Device::SetViewBounds( const Mix::Rectangle& rect )
{
	SetViewBounds( rect.x, rect.y, rect.width, rect.height );
}

void Device::SetViewBounds( Int32 x, Int32 y, Int32 width, Int32 height )
{
	if( m_TargetState.rect.Contains( Mix::Rectangle( x, y, width, height ), &m_ViewportRect ) == False )
	{
		m_ViewportRect.x = 0;
		m_ViewportRect.y = 0;
		m_ViewportRect.width = 1;
		m_ViewportRect.height = 1;
	}

	m_Viewport.X = m_ViewportRect.x;
	m_Viewport.Y = m_ViewportRect.y;
	m_Viewport.Width = m_ViewportRect.width;
	m_Viewport.Height = m_ViewportRect.height;

	m_pD3DDevice->SetViewport( &m_Viewport );
}

const Mix::Rectangle& Device::GetScissorBounds( void ) const
{
	return m_ScissorRect;
}

void Device::SetScissorBounds( const Mix::Rectangle& rect )
{
	SetScissorBounds( rect.x, rect.y, rect.width, rect.height );
}

void Device::SetScissorBounds( Int32 x, Int32 y, Int32 width, Int32 height )
{
	RECT rect;

	if( m_TargetState.rect.Contains( Mix::Rectangle( x, y, width, height ), &m_ScissorRect ) == False )
	{
		m_ScissorRect.x = 0;
		m_ScissorRect.y = 0;
		m_ScissorRect.width = 1;
		m_ScissorRect.height = 1;
	}

	rect.left = m_ScissorRect.x;
	rect.top = m_ScissorRect.y;
	rect.right = m_ScissorRect.x + m_ScissorRect.width;
	rect.bottom = m_ScissorRect.y + m_ScissorRect.height;

	m_pD3DDevice->SetScissorRect( &rect );
}

void Device::Clear( Boolean clearTarget, Boolean clearDepth, const Mix::Vector4& color, Float32 z )
{
	DWORD flags = 0;

	if( clearTarget == True ) { flags |= D3DCLEAR_TARGET; }
	if( clearDepth == True ) { flags |= D3DCLEAR_ZBUFFER; }

	if( flags != 0 )
	{
		UInt32 colorI;

		colorI = MIX_CLAMP( static_cast<UInt32>( color.a * 255.0f ), 0, 255 ) << 24;
		colorI |= MIX_CLAMP( static_cast<UInt32>( color.r * 255.0f ), 0, 255 ) << 16;
		colorI |= MIX_CLAMP( static_cast<UInt32>( color.g * 255.0f ), 0, 255 ) << 8;
		colorI |= MIX_CLAMP( static_cast<UInt32>( color.b * 255.0f ), 0, 255 );

		m_pD3DDevice->Clear( 0, NULL, flags, colorI, z, 0L );
	}
}

void Device::SetRasterizerState( Mix::Graphics::FILL_TYPE fillMode, Mix::Graphics::CULL_TYPE cullMode, Boolean bScissoring )
{
	Mix::Graphics::RASTERIZER_DESC desc;

	desc.fillMode = fillMode;
	desc.cullMode = cullMode;
	desc.bScissoring = bScissoring;

	SetRasterizerState( desc );
}

void Device::SetRasterizerState( const Mix::Graphics::RASTERIZER_DESC& desc )
{
	m_RasterizeDesc = desc;

	SetRenderState( Device::RENDERSTATETYPE_FILLMODE, ( m_RasterizeDesc.fillMode == Mix::Graphics::FILL_WIREFRAME )? D3DFILL_WIREFRAME : D3DFILL_SOLID );
	SetRenderState( Device::RENDERSTATETYPE_CULLMODE, Device::D3DCullModeTable[m_RasterizeDesc.cullMode] );
	SetRenderState( Device::RENDERSTATETYPE_SCISSORTESTENABLE, m_RasterizeDesc.bScissoring );
}

const Mix::Graphics::RASTERIZER_DESC& Device::GetRasterizerState( void ) const
{
	return m_RasterizeDesc;
}

void Device::SetDepthState( Boolean bTest, Boolean bWrite, Mix::Graphics::ZFUNC_TYPE func )
{
	Mix::Graphics::DEPTH_DESC desc;

	desc.bTest = bTest;
	desc.bWrite = bWrite;
	desc.func = func;

	SetDepthState( desc );
}

void Device::SetDepthState( const Mix::Graphics::DEPTH_DESC& desc )
{
	m_DepthDesc = desc;

	SetRenderState( Device::RENDERSTATETYPE_ZENABLE, ( m_DepthDesc.bTest == True )? D3DZB_TRUE : D3DZB_FALSE );
	SetRenderState( Device::RENDERSTATETYPE_ZWRITEENABLE, m_DepthDesc.bWrite );
	SetRenderState( Device::RENDERSTATETYPE_ZFUNC, Device::D3DZFuncTable[m_DepthDesc.func] );
}

const Mix::Graphics::DEPTH_DESC& Device::GetDepthState( void ) const
{
	return m_DepthDesc;
}

void Device::SetBlendState( Mix::Graphics::BLEND_TYPE type, Mix::Graphics::COLOR_WRITE_MASK colorWriteMask )
{
	Mix::Graphics::BLEND_DESC desc;

	desc.type = type;
	desc.colorWriteMask = colorWriteMask;

	SetBlendState( desc );
}

void Device::SetBlendState( const Mix::Graphics::BLEND_DESC& desc )
{
	UInt32 mask;

	m_BlendDesc = desc;

	switch( m_BlendDesc.type )
	{
	case Mix::Graphics::BLEND_COPY:
		SetRenderState( Device::RENDERSTATETYPE_SRCBLEND, D3DBLEND_ONE );
		SetRenderState( Device::RENDERSTATETYPE_DESTBLEND, D3DBLEND_ZERO );
		SetRenderState( Device::RENDERSTATETYPE_BLENDOP, D3DBLENDOP_ADD );
		SetRenderState( Device::RENDERSTATETYPE_SRCBLEND_ALPHA, D3DBLEND_ONE );
		SetRenderState( Device::RENDERSTATETYPE_DESTBLEND_ALPHA, D3DBLEND_ZERO );
		SetRenderState( Device::RENDERSTATETYPE_BLENDOP_ALPHA, D3DBLENDOP_ADD );
		SetRenderState( Device::RENDERSTATETYPE_ALPHABLENDENABLE, FALSE );
		break;
	case Mix::Graphics::BLEND_NORMAL:
		SetRenderState( Device::RENDERSTATETYPE_SRCBLEND, D3DBLEND_SRCALPHA );
		SetRenderState( Device::RENDERSTATETYPE_DESTBLEND, D3DBLEND_INVSRCALPHA );
		SetRenderState( Device::RENDERSTATETYPE_BLENDOP, D3DBLENDOP_ADD );
		SetRenderState( Device::RENDERSTATETYPE_SRCBLEND_ALPHA, D3DBLEND_SRCALPHA );
		SetRenderState( Device::RENDERSTATETYPE_DESTBLEND_ALPHA, D3DBLEND_INVSRCALPHA );
		SetRenderState( Device::RENDERSTATETYPE_BLENDOP_ALPHA, D3DBLENDOP_ADD );
		SetRenderState( Device::RENDERSTATETYPE_ALPHABLENDENABLE, TRUE );
		break;
	case Mix::Graphics::BLEND_ADD:
		SetRenderState( Device::RENDERSTATETYPE_SRCBLEND, D3DBLEND_SRCALPHA );
		SetRenderState( Device::RENDERSTATETYPE_DESTBLEND, D3DBLEND_ONE );
		SetRenderState( Device::RENDERSTATETYPE_BLENDOP, D3DBLENDOP_ADD );
		SetRenderState( Device::RENDERSTATETYPE_ALPHABLENDENABLE, TRUE );
//		SetRenderState( Device::RENDERSTATETYPE_SRCBLEND_ALPHA, D3DBLEND_ONE );
//		SetRenderState( Device::RENDERSTATETYPE_DESTBLEND_ALPHA, D3DBLEND_ZERO );
//		SetRenderState( Device::RENDERSTATETYPE_BLENDOP_ALPHA, D3DBLENDOP_ADD );
		SetRenderState( Device::RENDERSTATETYPE_SRCBLEND_ALPHA, D3DBLEND_SRCALPHA );
		SetRenderState( Device::RENDERSTATETYPE_DESTBLEND_ALPHA, D3DBLEND_ONE );
		SetRenderState( Device::RENDERSTATETYPE_BLENDOP_ALPHA, D3DBLENDOP_ADD );
		SetRenderState( Device::RENDERSTATETYPE_ALPHABLENDENABLE, TRUE );
		break;
	case Mix::Graphics::BLEND_SUB:
		SetRenderState( Device::RENDERSTATETYPE_SRCBLEND, D3DBLEND_SRCALPHA );
		SetRenderState( Device::RENDERSTATETYPE_DESTBLEND, D3DBLEND_ONE );
		SetRenderState( Device::RENDERSTATETYPE_BLENDOP, D3DBLENDOP_REVSUBTRACT );
		SetRenderState( Device::RENDERSTATETYPE_SRCBLEND_ALPHA, D3DBLEND_SRCALPHA );
		SetRenderState( Device::RENDERSTATETYPE_DESTBLEND_ALPHA, D3DBLEND_ONE );
		SetRenderState( Device::RENDERSTATETYPE_BLENDOP_ALPHA, D3DBLENDOP_REVSUBTRACT );
		SetRenderState( Device::RENDERSTATETYPE_ALPHABLENDENABLE, TRUE );
		break;
	case Mix::Graphics::BLEND_MUL:
		SetRenderState( Device::RENDERSTATETYPE_SRCBLEND, D3DBLEND_ZERO );
		SetRenderState( Device::RENDERSTATETYPE_DESTBLEND, D3DBLEND_SRCCOLOR );
		SetRenderState( Device::RENDERSTATETYPE_BLENDOP, D3DBLENDOP_ADD );
		SetRenderState( Device::RENDERSTATETYPE_SRCBLEND_ALPHA, D3DBLEND_ZERO );
		SetRenderState( Device::RENDERSTATETYPE_DESTBLEND_ALPHA, D3DBLEND_SRCALPHA );
		SetRenderState( Device::RENDERSTATETYPE_BLENDOP_ALPHA, D3DBLENDOP_ADD );
		SetRenderState( Device::RENDERSTATETYPE_ALPHABLENDENABLE, TRUE );
		break;
	case Mix::Graphics::BLEND_SCREEN:
		SetRenderState( Device::RENDERSTATETYPE_SRCBLEND, D3DBLEND_INVDESTCOLOR );
		SetRenderState( Device::RENDERSTATETYPE_DESTBLEND, D3DBLEND_ONE );
		SetRenderState( Device::RENDERSTATETYPE_BLENDOP, D3DBLENDOP_ADD );
		SetRenderState( Device::RENDERSTATETYPE_SRCBLEND_ALPHA, D3DBLEND_INVDESTALPHA );
		SetRenderState( Device::RENDERSTATETYPE_DESTBLEND_ALPHA, D3DBLEND_ONE );
		SetRenderState( Device::RENDERSTATETYPE_BLENDOP_ALPHA, D3DBLENDOP_ADD );
		SetRenderState( Device::RENDERSTATETYPE_ALPHABLENDENABLE, TRUE );
		break;
	}

	switch( m_BlendDesc.colorWriteMask )
	{
	case Mix::Graphics::COLOR_WRITE_RGBA:
		mask = D3DCOLORWRITEENABLE_RED | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_BLUE | D3DCOLORWRITEENABLE_ALPHA;
		break;
	case Mix::Graphics::COLOR_WRITE_RGB:
		mask = D3DCOLORWRITEENABLE_RED | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_BLUE;
		break;
	case Mix::Graphics::COLOR_WRITE_A:
		mask = D3DCOLORWRITEENABLE_ALPHA;
		break;
	}

	SetRenderState( Device::RENDERSTATETYPE_WRITECOLOR, mask );
}

const Mix::Graphics::BLEND_DESC& Device::GetBlendState( void ) const
{
	return m_BlendDesc;
}

void Device::SetVertexLayout( Mix::Graphics::IVertexLayout* pVertexLayout )
{
	m_DrawState.next.pVertexLayout = pVertexLayout;
}

void Device::SetHullShader( Mix::Graphics::IHullShader* pHullShader )
{
}

void Device::SetDomainShader( Mix::Graphics::IDomainShader* pDomainShader )
{
}

void Device::SetGeometryShader( Mix::Graphics::IGeometryShader* pGeometryShader )
{
}

void Device::SetVertexShader( Mix::Graphics::IVertexShader* pVertexShader )
{
	m_DrawState.next.pVertexShader = pVertexShader;
}

void Device::SetPixelShader( Mix::Graphics::IPixelShader* pPixelShader )
{
	m_DrawState.next.pPixelShader = pPixelShader;
}

void Device::SetVertexShaderConstantB( UInt32 startRegister, const Boolean* data, UInt32 count )
{
	MIX_ASSERT( ( data != NULL ) && ( count > 0 ) );

	m_pD3DDevice->SetVertexShaderConstantB( startRegister, data, count );
}

void Device::SetVertexShaderConstantI( UInt32 startRegister, const Int32* data, UInt32 count )
{
	MIX_ASSERT( ( data != NULL ) && ( count > 0 ) );

	m_pD3DDevice->SetVertexShaderConstantI( startRegister, data, count );
}

void Device::SetVertexShaderConstantF( UInt32 startRegister, const Float32* data, UInt32 count )
{
	MIX_ASSERT( ( data != NULL ) && ( count > 0 ) );

	m_pD3DDevice->SetVertexShaderConstantF( startRegister, data, count );
}

void Device::SetVertexShaderConstantF( UInt32 startRegister, const Mix::Vector4* data, UInt32 count )
{
	MIX_ASSERT( ( data != NULL ) && ( count > 0 ) );

	m_pD3DDevice->SetVertexShaderConstantF( startRegister, reinterpret_cast<const Float32*>( data ), count );
}

void Device::SetVertexShaderConstantF( UInt32 startRegister, const Mix::Matrix4x4* data, UInt32 count )
{
	MIX_ASSERT( ( data != NULL ) && ( count > 0 ) );

	m_pD3DDevice->SetVertexShaderConstantF( startRegister, reinterpret_cast<const Float32*>( data ), 4 * count );
}

void Device::SetPixelShaderConstantB( UInt32 startRegister, const Boolean* data, UInt32 count )
{
	MIX_ASSERT( ( data != NULL ) && ( count > 0 ) );

	m_pD3DDevice->SetPixelShaderConstantB( startRegister, data, count );
}

void Device::SetPixelShaderConstantI( UInt32 startRegister, const Int32* data, UInt32 count )
{
	MIX_ASSERT( ( data != NULL ) && ( count > 0 ) );

	m_pD3DDevice->SetPixelShaderConstantI( startRegister, data, count );
}

void Device::SetPixelShaderConstantF( UInt32 startRegister, const Float32* data, UInt32 count )
{
	MIX_ASSERT( ( data != NULL ) && ( count > 0 ) );

	m_pD3DDevice->SetPixelShaderConstantF( startRegister, data, count );
}

void Device::SetPixelShaderConstantF( UInt32 startRegister, const Mix::Vector4* data, UInt32 count )
{
	MIX_ASSERT( ( data != NULL ) && ( count > 0 ) );

	m_pD3DDevice->SetPixelShaderConstantF( startRegister, reinterpret_cast<const Float32*>( data ), count );
}

void Device::SetPixelShaderConstantF( UInt32 startRegister, const Mix::Matrix4x4* data, UInt32 count )
{
	MIX_ASSERT( ( data != NULL ) && ( count > 0 ) );

	m_pD3DDevice->SetPixelShaderConstantF( startRegister, reinterpret_cast<const Float32*>( data ), 4 * count );
}

void Device::SetHullShaderConstant( UInt32 slot, Mix::Graphics::IShaderConstant* pShaderConstant )
{
}

void Device::SetDomainShaderConstant( UInt32 slot, Mix::Graphics::IShaderConstant* pShaderConstant )
{
}

void Device::SetGeometryShaderConstant( UInt32 slot, Mix::Graphics::IShaderConstant* pShaderConstant )
{
}

void Device::SetVertexShaderConstant( UInt32 slot, Mix::Graphics::IShaderConstant* pShaderConstant )
{
}

void Device::SetPixelShaderConstant( UInt32 slot, Mix::Graphics::IShaderConstant* pShaderConstant )
{
}

void Device::SetVertexBuffer( Mix::Graphics::IVertexBuffer* pVertexBuffer )
{
	m_DrawState.next.pVertexBuffer = pVertexBuffer;
}

void Device::SetIndexBuffer( Mix::Graphics::IIndexBuffer* pIndexBuffer )
{
	m_DrawState.next.pIndexBuffer = pIndexBuffer;
}

UInt32 Device::GetTextureStageMax( void ) const
{
	return m_Caps.MaxTextureBlendStages;
}

void Device::SetTexture( UInt32 stage, Mix::Graphics::TEXTURE_FILTER_TYPE filter, Mix::Graphics::TEXTURE_ADDRESS_TYPE address, Mix::Graphics::ITexture* pTexture )
{
	if( ( GetTextureStageMax() <= stage ) ||
		( ( pTexture != NULL ) && ( ( pTexture->GetAccessFlags() & ITexture::ACCESS_GPU_READ ) != ITexture::ACCESS_GPU_READ ) ) )
	{
		UInt32 stageLast = GetTextureStageMax() - 1;

		MIX_LOG_ERROR( L"%s : %s : stage[%d/%d] pTexture[%s]",
			FAILED_SET_TEXTURE,
			Mix::STR_ILLEGALARG,
			stage, stageLast,
			( ( pTexture == NULL ) || ( ( pTexture->GetAccessFlags() & ITexture::ACCESS_GPU_READ ) == ITexture::ACCESS_GPU_READ ) )? L"○" : L"×" );

		return;
	}

	UInt32 d3dMinFilter;
	UInt32 d3dMagFilter;
	UInt32 d3dMipFilter;
	UInt32 d3dAddress;
	UInt32 d3dAnisotropy;

	switch( filter )
	{
		case Mix::Graphics::TEXTURE_FILTER_POINT:
			d3dMinFilter = D3DTEXF_POINT;
			d3dMagFilter = D3DTEXF_POINT;
			d3dMipFilter = D3DTEXF_POINT;
			d3dAnisotropy = 1;
			break;
		case Mix::Graphics::TEXTURE_FILTER_LINEAR:
			d3dMinFilter = D3DTEXF_LINEAR;
			d3dMagFilter = D3DTEXF_LINEAR;
			d3dMipFilter = D3DTEXF_LINEAR;
			d3dAnisotropy = 1;
			break;
		case Mix::Graphics::TEXTURE_FILTER_ANISOTROPIC:
			d3dMinFilter = D3DTEXF_ANISOTROPIC;
			d3dMagFilter = D3DTEXF_LINEAR;
			d3dMipFilter = D3DTEXF_LINEAR;
			d3dAnisotropy = 8;
			break;

		default:
			d3dMinFilter = D3DTEXF_POINT;
			d3dAnisotropy = 1;
	}

	switch( address )
	{
	case Mix::Graphics::TEXTURE_ADDRESS_WRAP:
		d3dAddress = D3DTADDRESS_WRAP;
		break;
	case Mix::Graphics::TEXTURE_ADDRESS_CLAMP:
		d3dAddress = D3DTADDRESS_CLAMP;
		break;

	default:
		d3dAddress = D3DTADDRESS_WRAP;
	}

	SetSamplerState( stage, Device::SAMPLERSTATETYPE_MINFILTER, d3dMinFilter );
	SetSamplerState( stage, Device::SAMPLERSTATETYPE_MAGFILTER, d3dMagFilter );
	SetSamplerState( stage, Device::SAMPLERSTATETYPE_MIPFILTER, d3dMipFilter );
	SetSamplerState( stage, Device::SAMPLERSTATETYPE_ANISOTROPY, d3dAnisotropy );
	SetSamplerState( stage, Device::SAMPLERSTATETYPE_ADDRESSU, d3dAddress );
	SetSamplerState( stage, Device::SAMPLERSTATETYPE_ADDRESSV, d3dAddress );
	SetSamplerState( stage, Device::SAMPLERSTATETYPE_ADDRESSW, D3DTADDRESS_CLAMP );

	if( m_DrawState.textureTable[stage] != pTexture )
	{
		if( pTexture != NULL )
		{
			m_pD3DDevice->SetTexture( stage, static_cast<Mix::Graphics::DX9::Texture*>( pTexture )->GetInterface() );
		}
		else
		{
			m_pD3DDevice->SetTexture( stage, NULL );
		}

		m_DrawState.textureTable[stage] = pTexture;
	}
}

void Device::ResetTexture( UInt32 stage )
{
	if( GetTextureStageMax() <= stage )
	{
		UInt32 stageLast = GetTextureStageMax() - 1;
		MIX_LOG_ERROR( L"%s : %s : stage[%d/%d]", FAILED_RESET_TEXTURE, Mix::STR_ILLEGALARG, stage, stageLast );
		return;
	}

	if( m_DrawState.textureTable[stage] != NULL )
	{
		m_pD3DDevice->SetTexture( stage, NULL );
		m_DrawState.textureTable[stage] = NULL;
	}
}

void Device::Draw( Mix::Graphics::PRIMITIVE_TYPE primitiveType, UInt32 startVertex, UInt32 numVertex )
{
	UInt32 numPrimitive;

	if( numVertex == 0 )
	{
		MIX_LOG_ERROR( L"%s : %s : numVertex[%d > 0]", FAILED_DRAW, Mix::STR_ILLEGALARG, numVertex );
		return;
	}

	if( ( m_DrawState.next.pVertexLayout == NULL ) ||
		( m_DrawState.next.pVertexShader == NULL ) ||
		( m_DrawState.next.pPixelShader == NULL ) ||
		( m_DrawState.next.pVertexBuffer == NULL ) )
	{
		MIX_LOG_WARNING( L"%s : %s\n{\n  IVertexLayout %s\n  IVertexShader %s \n  IPixelShader  %s\n  IVertexBuffer %s\n}",
			FAILED_DRAW,
			MSG_NOT_SET_DEVOBJ,
			MIX_LOG_PTR( m_DrawState.next.pVertexLayout ), 
			MIX_LOG_PTR( m_DrawState.next.pVertexShader ), 
			MIX_LOG_PTR( m_DrawState.next.pPixelShader ), 
			MIX_LOG_PTR( m_DrawState.next.pVertexBuffer ) );

		return;
	}

	numPrimitive = ComputePrimitiveCount( primitiveType, numVertex );
	if( numPrimitive == 0 )
	{
		MIX_LOG_ERROR( L"%s : %s", FAILED_DRAW, MSG_MISSING_PT_VE );
		return;
	}

	FlushDrawState();

	m_pD3DDevice->DrawPrimitive( Device::D3DPrimitiveTypeTable[primitiveType], startVertex, numPrimitive );

	m_DrawPrimitiveCount += numPrimitive;
}

void Device::DrawIndexed( Mix::Graphics::PRIMITIVE_TYPE primitiveType, UInt32 startVertex, UInt32 numVertex, UInt32 startIndex, UInt32 numIndex )
{
	UInt32 numPrimitive;

	if( ( numVertex == 0 ) ||
		( numIndex == 0 ) )
	{
		MIX_LOG_ERROR( L"%s : %s : numVertex[%d > 0] numIndex[%d > 0]", FAILED_DRAW_INDEXED,
			Mix::STR_ILLEGALARG,
			numVertex,
			numIndex );

		return;
	}

	if( ( m_DrawState.next.pVertexLayout == NULL ) ||
		( m_DrawState.next.pVertexShader == NULL ) ||
		( m_DrawState.next.pPixelShader == NULL ) ||
		( m_DrawState.next.pVertexBuffer == NULL ) ||
		( m_DrawState.next.pIndexBuffer == NULL ) )
	{
		MIX_LOG_WARNING( L"%s : %s\n{\n  IVertexLayout %s\n  IVertexShader %s \n  IPixelShader  %s\n  IVertexBuffer %s \n  IIndexBuffer  %s\n}",
			FAILED_DRAW_INDEXED,
			MSG_NOT_SET_DEVOBJ,
			MIX_LOG_PTR( m_DrawState.next.pVertexLayout ), 
			MIX_LOG_PTR( m_DrawState.next.pVertexShader ), 
			MIX_LOG_PTR( m_DrawState.next.pPixelShader ), 
			MIX_LOG_PTR( m_DrawState.next.pVertexBuffer ), 
			MIX_LOG_PTR( m_DrawState.next.pIndexBuffer ) );
	}

	numPrimitive = ComputePrimitiveCount( primitiveType, numIndex );
	if( numPrimitive == 0 )
	{
		MIX_LOG_ERROR( L"%s : %s", FAILED_DRAW_INDEXED, MSG_MISSING_PT_VE );
		return;
	}

	FlushDrawState();

	m_pD3DDevice->DrawIndexedPrimitive( Device::D3DPrimitiveTypeTable[primitiveType], 0, startVertex, numVertex, startIndex, numPrimitive );

	m_DrawPrimitiveCount += numPrimitive;
}

Boolean Device::SaveScreenshot( const wchar_t* pFilePath )
{
	if( ( pFilePath == NULL ) ||
		( ::wcslen( pFilePath ) < 4 ) )
	{
		return False;
	}

	wchar_t fileExt[5];

	D3DSURFACE_DESC surfDesc;
	LPDIRECT3DSURFACE9 pD3DSurface;
	D3DLOCKED_RECT lockedRect;

	UInt32 imgByteSize;
	UInt32* pImage;

	BITMAPFILEHEADER bmpFileHeader;
	BITMAPCOREHEADER bmpCoreHeader;

	HANDLE hFile;
	DWORD writeSize;

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

	::wcscpy_s( fileExt, 5, &( pFilePath[( ::wcslen( pFilePath ) - 4 )] ) );
	::_wcsupr_s( fileExt, 5 );

	if( ::wcscmp( fileExt, L".BMP" ) != 0 )
	{
		//ビットマップでしか保存できない
		return False;
	}

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

	if( m_pD3DBackBuffer->GetDesc( &surfDesc ) != D3D_OK )
	{
		return False;
	}

	if( m_pD3DDevice->CreateOffscreenPlainSurface( surfDesc.Width, surfDesc.Height, surfDesc.Format, D3DPOOL_SYSTEMMEM, &pD3DSurface, NULL ) != D3D_OK )
	{
		return False;
	}

	if( m_pD3DDevice->GetRenderTargetData( m_pD3DBackBuffer, pD3DSurface ) != D3D_OK )
	{
		MIX_RELEASE( pD3DSurface );
		return False;
	}

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

	imgByteSize = surfDesc.Width * surfDesc.Height * 4;

	pImage = reinterpret_cast<UInt32*>( MIX_LIB_MALLOC( Mix::Memory::SECTION_GRAPHICS, imgByteSize ) );
	if( pImage == NULL )
	{
		MIX_RELEASE( pD3DSurface );
		return False;
	}

	if( pD3DSurface->LockRect( &lockedRect, NULL, 0 ) == D3D_OK )
	{
		if( surfDesc.Format == D3DFMT_X8R8G8B8 )
		{
			UInt32 imgBytePitch = surfDesc.Width * 4;
			UInt32 srcPitch = lockedRect.Pitch / 4;

			UInt32* pSrc = reinterpret_cast<UInt32*>( lockedRect.pBits );
			UInt32* pDst = pImage + ( surfDesc.Width * surfDesc.Height ) - surfDesc.Width;

			for( UInt32 i = 0; i < surfDesc.Height; i++ )
			{
				Mix::Memory::Copy( pDst, pSrc, imgBytePitch );

				pSrc += srcPitch;
				pDst -= surfDesc.Width;
			}
		}
		else if( surfDesc.Format == D3DFMT_X1R5G5B5 )
		{
			UInt32 srcPitch = lockedRect.Pitch / 2;

			UInt16* pSrcBegin = reinterpret_cast<UInt16*>( lockedRect.pBits );
			UInt16* pSrc = NULL;
			UInt16* pSrcEnd;

			UInt32* pDstBegin = pImage + ( surfDesc.Width * surfDesc.Height ) - surfDesc.Width;
			UInt32* pDst = NULL;

			for( UInt32 i = 0; i < surfDesc.Height; i++ )
			{
				pSrc = pSrcBegin;
				pSrcEnd = pSrc + surfDesc.Width;

				pDst = pDstBegin;

				while( pSrc != pSrcEnd )
				{
					UInt32 b = ( ( *pSrc & 0xF800 ) >> 11 ) * 8;
					UInt32 g = ( ( *pSrc & 0x07C0 ) >> 6 ) * 8;
					UInt32 r = ( ( *pSrc & 0x003E ) >> 1 ) * 8;

					UInt32 dat = ( b << 16 ) | ( g << 8 ) | r;

					pSrc++;
					*pDst++ = dat;
				}

				pSrcBegin += srcPitch;
				pDstBegin -= surfDesc.Width;
			}
		}
		else if( surfDesc.Format == D3DFMT_R5G6B5 )
		{
			UInt32 srcPitch = lockedRect.Pitch / 2;

			UInt16* pSrcBegin = reinterpret_cast<UInt16*>( lockedRect.pBits );
			UInt16* pSrc = NULL;
			UInt16* pSrcEnd;

			UInt32* pDstBegin = pImage + ( surfDesc.Width * surfDesc.Height ) - surfDesc.Width;
			UInt32* pDst = NULL;

			for( UInt32 i = 0; i < surfDesc.Height; i++ )
			{
				pSrc = pSrcBegin;
				pSrcEnd = pSrc + surfDesc.Width;

				pDst = pDstBegin;

				while( pSrc != pSrcEnd )
				{
					UInt32 b = ( ( *pSrc & 0xF800 ) >> 11 ) * 8;
					UInt32 g = ( ( *pSrc & 0x07E0 ) >> 5 ) * 4;
					UInt32 r = ( ( *pSrc & 0x001F ) ) * 8;

					UInt32 dat = ( b << 16 ) | ( g << 8 ) | r;

					pSrc++;
					*pDst++ = dat;
				}

				pSrcBegin += srcPitch;
				pDstBegin -= surfDesc.Width;
			}
		}

		pD3DSurface->UnlockRect();
	}
	else
	{
		MIX_LIB_FREE( pImage );
		MIX_RELEASE( pD3DSurface );
		return False;
	}

	MIX_RELEASE( pD3DSurface );

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

	bmpFileHeader.bfType = 0x4D42; //BM
	bmpFileHeader.bfSize = sizeof( BITMAPFILEHEADER ) + sizeof( BITMAPCOREHEADER ) + imgByteSize;
	bmpFileHeader.bfReserved1 = 0;
	bmpFileHeader.bfReserved2 = 0;
	bmpFileHeader.bfOffBits = sizeof( BITMAPFILEHEADER ) + sizeof( BITMAPCOREHEADER );

	bmpCoreHeader.bcSize = sizeof( BITMAPCOREHEADER );
	bmpCoreHeader.bcWidth = surfDesc.Width;
	bmpCoreHeader.bcHeight = surfDesc.Height;
	bmpCoreHeader.bcPlanes = 1;
	bmpCoreHeader.bcBitCount = 32;

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

	hFile = CreateFile( pFilePath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
	if( hFile == INVALID_HANDLE_VALUE )
	{
		MIX_LIB_FREE( pImage );
		return False;
	}

	if( WriteFile( hFile, &bmpFileHeader, sizeof( BITMAPFILEHEADER ), &writeSize, NULL ) == FALSE )
	{
		CloseHandle( hFile );
		MIX_LIB_FREE( pImage );
		return False;
	}

	if( WriteFile( hFile, &bmpCoreHeader, sizeof( BITMAPCOREHEADER ), &writeSize, NULL ) == FALSE )
	{
		CloseHandle( hFile );
		MIX_LIB_FREE( pImage );
		return False;
	}

	if( WriteFile( hFile, pImage, imgByteSize, &writeSize, NULL ) == FALSE )
	{
		CloseHandle( hFile );
		MIX_LIB_FREE( pImage );
		return False;
	}

	CloseHandle( hFile );

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

	MIX_LIB_FREE( pImage );

	MIX_LOG_INFO( L"%s : %s[%s]", SAVE_SCREEN_SHOT, Mix::STR_FILEPATH, pFilePath );

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

	return True;
}

const Mix::Point& Device::GetScreenSize( void ) const
{
	return m_DeviceParam.current.screenSize;
}

const Mix::Rectangle& Device::GetScreenValidBounds( void ) const
{
	return m_ScreenValidBounds;
}

UInt32 Device::GetDrawPrimitiveCount( void ) const
{
	return m_DrawPrimitiveCount;
}

Mix::Graphics::SHADER_MODEL Device::GetShaderModel( void ) const
{
	return Mix::Graphics::SHADER_MODEL_3;
}

}}}
