#ifndef D3D9Include_h
#define D3D9Include_h

/*!	
	@file
	@brief	Direct3D9 を扱うのに便利なマクロ
*/


#include"../../../../../Setup/CompileMode.h"
#include"../../../../../template/com_ptr.h"
#include"../../../../../auxiliary/Debug/CAssert.h"
#include"../../../../CCustomVertexTemplate.h"
#include"../../../../CSurfaceInfo.h"
#include"../../CVideoCardDriver.h"

#include<d3d9.h>


namespace Maid
{

	typedef com_ptr<IDirect3D9>			SPD3D;
	typedef com_ptr<IDirect3DDevice9>	SPD3DDEVICE;
	typedef com_ptr<IDirect3DSurface9>			SPD3DSURFACEBUFFER;
	typedef com_ptr<IDirect3DTexture9>			SPD3DTEXTUREBUFFER;
	typedef com_ptr<IDirect3DIndexBuffer9>			SPD3DINDEXBUFFER;
	typedef com_ptr<IDirect3DVertexBuffer9>			SPD3DVERTEXBUFFER;
	typedef com_ptr<IDirect3DVertexShader9>			SPD3DVERTEXSHADERBUFFER;
	typedef com_ptr<IDirect3DVertexDeclaration9>	SPD3DVERTEXDECLARATION;
	typedef com_ptr<IDirect3DPixelShader9>			SPD3DPIXELSHADERBUFFER;


	/*!
	 	@fn DWORD VERTEXFORMAT2FVF( VERTEXFORMAT Format )
	 
	 	VERTEXFORMAT を DirectGraphic9 で使用されている
	\n	FVFに変換します
	 
	 	@param	eFormat	[i ]	変換したい頂点フォーマット
	 
	 	@return	変換後のフォーマット
	\n			判別できなかったら 0
	 */
	inline DWORD VERTEXFORMAT2FVF( VERTEXFORMAT Format )
	{
		switch( Format )
		{
		case VERTEXFORMAT_COLOR:			{ return (D3DFVF_XYZRHW|D3DFVF_DIFFUSE);					}break;
		case VERTEXFORMAT_SPRITE:			{ return (D3DFVF_XYZRHW|D3DFVF_DIFFUSE|D3DFVF_TEX1);		}break;
		case VERTEXFORMAT_SPRITE2:			{ return (D3DFVF_XYZRHW|D3DFVF_DIFFUSE|D3DFVF_TEX2);		}break;
		case VERTEXFORMAT_SPRITE3:			{ return (D3DFVF_XYZRHW|D3DFVF_DIFFUSE|D3DFVF_TEX3);		}break;
		case VERTEXFORMAT_SPRITE4:			{ return (D3DFVF_XYZRHW|D3DFVF_DIFFUSE|D3DFVF_TEX4);		}break;
		case VERTEXFORMAT_3DCOLOR:			{ return (D3DFVF_XYZ|D3DFVF_DIFFUSE);						}break;
		case VERTEXFORMAT_3DSPRITE:			{ return (D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_TEX1);			}break;
		case VERTEXFORMAT_3DSPRITE2:		{ return (D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_TEX2);			}break;
		case VERTEXFORMAT_3DSPRITE3:		{ return (D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_TEX3);			}break;
		case VERTEXFORMAT_3DSPRITE4:		{ return (D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_TEX4);			}break;
		case VERTEXFORMAT_3DCOLORNORMAL:	{ return (D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_NORMAL);			}break;
		case VERTEXFORMAT_3DSPRITENORMAL:	{ return (D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_TEX1|D3DFVF_NORMAL);	}break;
		case VERTEXFORMAT_3DSPRITENORMAL2:	{ return (D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_TEX2|D3DFVF_NORMAL);	}break;

		case VERTEXFORMAT_3DT0W1:	{ return (D3DFVF_XYZB1|D3DFVF_LASTBETA_UBYTE4|D3DFVF_NORMAL|D3DFVF_DIFFUSE); }break;
		case VERTEXFORMAT_3DT0W2:	{ return (D3DFVF_XYZB2|D3DFVF_LASTBETA_UBYTE4|D3DFVF_NORMAL|D3DFVF_DIFFUSE); }break;
		case VERTEXFORMAT_3DT0W3:	{ return (D3DFVF_XYZB3|D3DFVF_LASTBETA_UBYTE4|D3DFVF_NORMAL|D3DFVF_DIFFUSE); }break;
		case VERTEXFORMAT_3DT0W4:	{ return (D3DFVF_XYZB4|D3DFVF_LASTBETA_UBYTE4|D3DFVF_NORMAL|D3DFVF_DIFFUSE); }break;
		case VERTEXFORMAT_3DT1W1:	{ return (D3DFVF_XYZB1|D3DFVF_LASTBETA_UBYTE4|D3DFVF_NORMAL|D3DFVF_DIFFUSE|D3DFVF_TEX1); }break;
		case VERTEXFORMAT_3DT1W2:	{ return (D3DFVF_XYZB2|D3DFVF_LASTBETA_UBYTE4|D3DFVF_NORMAL|D3DFVF_DIFFUSE|D3DFVF_TEX1); }break;
		case VERTEXFORMAT_3DT1W3:	{ return (D3DFVF_XYZB3|D3DFVF_LASTBETA_UBYTE4|D3DFVF_NORMAL|D3DFVF_DIFFUSE|D3DFVF_TEX1); }break;
		case VERTEXFORMAT_3DT1W4:	{ return (D3DFVF_XYZB4|D3DFVF_LASTBETA_UBYTE4|D3DFVF_NORMAL|D3DFVF_DIFFUSE|D3DFVF_TEX1); }break;

		case VERTEXFORMAT_XYZ:			{ return (D3DFVF_XYZ);		}break;
		case VERTEXFORMAT_NORMAL:		{ return (D3DFVF_NORMAL);	}break;
		case VERTEXFORMAT_TEX1:			{ return (D3DFVF_TEX1);		}break;
		}

		MAID_ASSERT( true, MAIDTEXT("識別できないFVF ") << Format );
		return 0;
	}

	/*!
	 	@fn D3DFORMAT PIXELFORMATtoD3DFORMAT( PIXELFORMAT eFormat )
	 
	 	PIXELFORMAT を DirectGraphic9 で使用されている
	\n	ピクセルフォーマットに変換します
	 
	 	@param	eFormat	[i ]	変換したいフォーマット
	 
	 	@return	変換後のフォーマット
	\n			判別できなかったら D3DFMT_UNKNOWN
	 */
	inline D3DFORMAT PIXELFORMATtoD3DFORMAT( PIXELFORMAT eFormat )
	{
		switch( eFormat )
		{
		case PIXELFORMAT_A08R08G08B08I:		{ return D3DFMT_A8R8G8B8;	}break;
		case PIXELFORMAT_X08R08G08B08I:		{ return D3DFMT_X8R8G8B8;	}break;
		case PIXELFORMAT_R08G08B08I:		{ return D3DFMT_R8G8B8;		}break;
		case PIXELFORMAT_A04R04G04B04I:		{ return D3DFMT_A4R4G4B4;	}break;
		case PIXELFORMAT_R05G06B05I:		{ return D3DFMT_R5G6B5;		}break;
		case PIXELFORMAT_X01R05G05B05I:		{ return D3DFMT_X1R5G5B5;	}break;
		case PIXELFORMAT_A01R05G05B05I:		{ return D3DFMT_A1R5G5B5;	}break;
		case PIXELFORMAT_P08A08R08G08B08I:	{ return D3DFMT_P8;			}break;
		case PIXELFORMAT_P08X08R08G08B08I:	{ return D3DFMT_P8;			}break;
		case PIXELFORMAT_DXT1:				{ return D3DFMT_DXT1;		}break;
		case PIXELFORMAT_DXT2:				{ return D3DFMT_DXT2;		}break;
		case PIXELFORMAT_DXT3:				{ return D3DFMT_DXT3;		}break;
		case PIXELFORMAT_DXT4:				{ return D3DFMT_DXT4;		}break;
		case PIXELFORMAT_DXT5:				{ return D3DFMT_DXT5;		}break;
		case PIXELFORMAT_D16:				{ return D3DFMT_D16;		}break;
		case PIXELFORMAT_D24X8:				{ return D3DFMT_D24X8;		}break;
		case PIXELFORMAT_D24S8:				{ return D3DFMT_D24S8;		}break;
		case PIXELFORMAT_NONE:				{ return D3DFMT_UNKNOWN;	}break;
		}

		MAID_ASSERT( true, "識別できないPIXELFORMATです %d" << eFormat );

		return D3DFMT_UNKNOWN;
	}

	/*!
	 	@fn PIXELFORMAT D3DFORMATtoPIXELFORMAT( D3DFORMAT eFormat )
	 
	 	DirectGraphic9 で使用されているピクセルフォーマットを
	 	PIXELFORMAT に変換します
	 
	 	@param	eFormat	[i ]	変換したい頂点フォーマット
	 
	 	@return	変換後のフォーマット
	\n			判別できなかったら PIXELFORMAT_NONE
	 */
	inline PIXELFORMAT D3DFORMATtoPIXELFORMAT( D3DFORMAT eFormat )
	{
		switch( eFormat )
		{
		case D3DFMT_A8R8G8B8:	{ return PIXELFORMAT_A08R08G08B08I;		}break;
		case D3DFMT_X8R8G8B8:	{ return PIXELFORMAT_X08R08G08B08I;		}break;
		case D3DFMT_R8G8B8:		{ return PIXELFORMAT_R08G08B08I;		}break;
		case D3DFMT_A4R4G4B4:	{ return PIXELFORMAT_A04R04G04B04I;		}break;
		case D3DFMT_R5G6B5:		{ return PIXELFORMAT_R05G06B05I;		}break;
		case D3DFMT_X1R5G5B5:	{ return PIXELFORMAT_X01R05G05B05I;		}break;
		case D3DFMT_A1R5G5B5:	{ return PIXELFORMAT_A01R05G05B05I;		}break;
		case D3DFMT_P8:			{ return PIXELFORMAT_P08A08R08G08B08I;	}break;

		case D3DFMT_DXT1:		{ return PIXELFORMAT_DXT1;			}break;
		case D3DFMT_DXT2:		{ return PIXELFORMAT_DXT2;			}break;
		case D3DFMT_DXT3:		{ return PIXELFORMAT_DXT3;			}break;
		case D3DFMT_DXT4:		{ return PIXELFORMAT_DXT4;			}break;
		case D3DFMT_DXT5:		{ return PIXELFORMAT_DXT5;			}break;

		case D3DFMT_D16:		{ return PIXELFORMAT_D16;			}break;
		case D3DFMT_D24X8:		{ return PIXELFORMAT_D24X8;			}break;
		case D3DFMT_D24S8:		{ return PIXELFORMAT_D24S8;			}break;
		case D3DFMT_UNKNOWN:	{ return PIXELFORMAT_NONE;			}break;
		}

		MAID_ASSERT( true, "識別できないD3DFORMATです %d" << eFormat );

		return PIXELFORMAT_NONE;
	}

	inline D3DCMPFUNC CMPTYPE2D3DCMPFUNC( IVideoCardDriver::CMPTYPE eType )
	{
		switch( eType )
		{
		case IVideoCardDriver::CMPTYPE_NEVER:		{ return D3DCMP_NEVER;		}break;
		case IVideoCardDriver::CMPTYPE_LESS:		{ return D3DCMP_LESS;		}break;
		case IVideoCardDriver::CMPTYPE_EQUAL:		{ return D3DCMP_EQUAL;		}break;
		case IVideoCardDriver::CMPTYPE_LESSEQUAL:	{ return D3DCMP_LESSEQUAL;	}break;
		case IVideoCardDriver::CMPTYPE_GREATER:		{ return D3DCMP_GREATER;	}break;
		case IVideoCardDriver::CMPTYPE_NOTEQUAL:	{ return D3DCMP_NOTEQUAL;	}break;
		case IVideoCardDriver::CMPTYPE_GREATEREQUAL:{ return D3DCMP_GREATEREQUAL;}break;
		case IVideoCardDriver::CMPTYPE_ALWAYS:		{ return D3DCMP_ALWAYS;		}break;
		}

		MAID_ASSERT( true, "識別できないMATRIXTYPE " << eType );

		return D3DCMP_FORCE_DWORD;
	}


	// fmt に限りなく近いピクセルフォーマットを列挙する
	// 指定されたフォーマット以上のものは出てこないようにする
	inline MySTL::vector<PIXELFORMAT> EnumFormat( PIXELFORMAT fmt )
	{
		MySTL::vector<PIXELFORMAT> vec;
		vec.reserve( 4 );
		switch( fmt )
		{
		case PIXELFORMAT_A08R08G08B08I: {vec.push_back(PIXELFORMAT_A08R08G08B08I);
									vec.push_back(PIXELFORMAT_A04R04G04B04I);  }break;

		case PIXELFORMAT_X08R08G08B08I: {vec.push_back(PIXELFORMAT_X08R08G08B08I); vec.push_back(PIXELFORMAT_R08G08B08I  );vec.push_back(PIXELFORMAT_A08R08G08B08I); 
									vec.push_back(PIXELFORMAT_X01R05G05B05I); vec.push_back(PIXELFORMAT_R05G06B05I  );vec.push_back(PIXELFORMAT_A01R05G05B05I);
									vec.push_back(PIXELFORMAT_A04R04G04B04I);}break;

		case PIXELFORMAT_R08G08B08I:  { vec.push_back(PIXELFORMAT_R08G08B08I  ); vec.push_back(PIXELFORMAT_X08R08G08B08I);vec.push_back(PIXELFORMAT_A08R08G08B08I); 
									vec.push_back(PIXELFORMAT_R05G06B05I  ); vec.push_back(PIXELFORMAT_X01R05G05B05I);vec.push_back(PIXELFORMAT_A01R05G05B05I);
									vec.push_back(PIXELFORMAT_A04R04G04B04I); }break;

		case PIXELFORMAT_A04R04G04B04I: { vec.push_back(PIXELFORMAT_A04R04G04B04I); }break;

		case PIXELFORMAT_R05G06B05I:   {vec.push_back(PIXELFORMAT_R05G06B05I  ); vec.push_back(PIXELFORMAT_X01R05G05B05I);vec.push_back(PIXELFORMAT_A01R05G05B05I);
									vec.push_back(PIXELFORMAT_A04R04G04B04I); }break;

		case PIXELFORMAT_X01R05G05B05I: {vec.push_back(PIXELFORMAT_X01R05G05B05I); vec.push_back(PIXELFORMAT_R05G06B05I  );vec.push_back(PIXELFORMAT_A01R05G05B05I);
									vec.push_back(PIXELFORMAT_A04R04G04B04I); }break;

		case PIXELFORMAT_A01R05G05B05I: {vec.push_back(PIXELFORMAT_A01R05G05B05I);
									vec.push_back(PIXELFORMAT_A04R04G04B04I); }break;

		case PIXELFORMAT_P08X08R08G08B08I:
		case PIXELFORMAT_P08A08R08G08B08I:{	vec.push_back(PIXELFORMAT_A08R08G08B08I);
										vec.push_back(PIXELFORMAT_A04R04G04B04I); }break;

		case PIXELFORMAT_DXT1: {	vec.push_back(PIXELFORMAT_DXT1);
									vec.push_back(PIXELFORMAT_A08R08G08B08I);
									vec.push_back(PIXELFORMAT_A01R05G05B05I);
									vec.push_back(PIXELFORMAT_A04R04G04B04I); }break;
		case PIXELFORMAT_DXT2: {	vec.push_back(PIXELFORMAT_DXT2);
									vec.push_back(PIXELFORMAT_A08R08G08B08I);
									vec.push_back(PIXELFORMAT_A04R04G04B04I); }break;
		case PIXELFORMAT_DXT3: {	vec.push_back(PIXELFORMAT_DXT3);
									vec.push_back(PIXELFORMAT_A08R08G08B08I);
									vec.push_back(PIXELFORMAT_A04R04G04B04I); }break;
		case PIXELFORMAT_DXT4: {	vec.push_back(PIXELFORMAT_DXT4);
									vec.push_back(PIXELFORMAT_A08R08G08B08I);
									vec.push_back(PIXELFORMAT_A04R04G04B04I); }break;
		case PIXELFORMAT_DXT5: {	vec.push_back(PIXELFORMAT_DXT5);
									vec.push_back(PIXELFORMAT_A08R08G08B08I);
									vec.push_back(PIXELFORMAT_A04R04G04B04I); }break;

		}

		return vec;
	}

	// fmt に限りなく近いピクセルフォーマットを列挙する（BPPの低いのが優先されるバージョン)
	// 指定されたフォーマット以上のものは出てこないようにする
	inline MySTL::vector<PIXELFORMAT> EnumFormatLowCost( PIXELFORMAT fmt )
	{
		MySTL::vector<PIXELFORMAT> vec;
		vec.reserve( 4 );
		switch( fmt )
		{
		case PIXELFORMAT_A08R08G08B08I: {vec.push_back(PIXELFORMAT_A04R04G04B04I);
									vec.push_back(PIXELFORMAT_A08R08G08B08I);  }break;

		case PIXELFORMAT_X08R08G08B08I: {vec.push_back(PIXELFORMAT_X01R05G05B05I); vec.push_back(PIXELFORMAT_R05G06B05I  );vec.push_back(PIXELFORMAT_A01R05G05B05I);
									vec.push_back(PIXELFORMAT_A04R04G04B04I);
									vec.push_back(PIXELFORMAT_X08R08G08B08I); vec.push_back(PIXELFORMAT_R08G08B08I  );vec.push_back(PIXELFORMAT_A08R08G08B08I); 
								}break;

		case PIXELFORMAT_R08G08B08I:  { vec.push_back(PIXELFORMAT_R05G06B05I  ); vec.push_back(PIXELFORMAT_X01R05G05B05I);vec.push_back(PIXELFORMAT_A01R05G05B05I);
									vec.push_back(PIXELFORMAT_A04R04G04B04I); 
									vec.push_back(PIXELFORMAT_R08G08B08I  ); vec.push_back(PIXELFORMAT_X08R08G08B08I);vec.push_back(PIXELFORMAT_A08R08G08B08I); 
								}break;

		case PIXELFORMAT_A04R04G04B04I:{ vec.push_back(PIXELFORMAT_A04R04G04B04I); }break;

		case PIXELFORMAT_R05G06B05I:  { vec.push_back(PIXELFORMAT_R05G06B05I  ); vec.push_back(PIXELFORMAT_X01R05G05B05I);vec.push_back(PIXELFORMAT_A01R05G05B05I);
									vec.push_back(PIXELFORMAT_A04R04G04B04I); }break;

		case PIXELFORMAT_X01R05G05B05I:{ vec.push_back(PIXELFORMAT_X01R05G05B05I); vec.push_back(PIXELFORMAT_R05G06B05I  );vec.push_back(PIXELFORMAT_A01R05G05B05I);
									vec.push_back(PIXELFORMAT_A04R04G04B04I); }break;

		case PIXELFORMAT_A01R05G05B05I:{ vec.push_back(PIXELFORMAT_A01R05G05B05I);
									vec.push_back(PIXELFORMAT_A04R04G04B04I); }break;

		case PIXELFORMAT_P08X08R08G08B08I:
		case PIXELFORMAT_P08A08R08G08B08I:{	vec.push_back(PIXELFORMAT_A04R04G04B04I);
										vec.push_back(PIXELFORMAT_A08R08G08B08I); }break;
		case PIXELFORMAT_DXT1: {	vec.push_back(PIXELFORMAT_DXT1);
									vec.push_back(PIXELFORMAT_A01R05G05B05I);
									vec.push_back(PIXELFORMAT_A04R04G04B04I);
									vec.push_back(PIXELFORMAT_A08R08G08B08I); }break;
		case PIXELFORMAT_DXT2: {	vec.push_back(PIXELFORMAT_DXT2);
									vec.push_back(PIXELFORMAT_A04R04G04B04I);
									vec.push_back(PIXELFORMAT_A08R08G08B08I); }break;
		case PIXELFORMAT_DXT3: {	vec.push_back(PIXELFORMAT_DXT3);
									vec.push_back(PIXELFORMAT_A04R04G04B04I);
									vec.push_back(PIXELFORMAT_A08R08G08B08I); }break;
		case PIXELFORMAT_DXT4: {	vec.push_back(PIXELFORMAT_DXT4);
									vec.push_back(PIXELFORMAT_A04R04G04B04I);
									vec.push_back(PIXELFORMAT_A08R08G08B08I); }break;
		case PIXELFORMAT_DXT5: {	vec.push_back(PIXELFORMAT_DXT5);
									vec.push_back(PIXELFORMAT_A04R04G04B04I);
									vec.push_back(PIXELFORMAT_A08R08G08B08I); }break;

		}

		return vec;
	}

}

#endif
