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

namespace Mix{ namespace Graphics{ namespace DX9{

////////////////////////////////////////////////////////////////////////////////////////////////////
// Mix::Graphics::DX9::TextureCube
////////////////////////////////////////////////////////////////////////////////////////////////////

const D3DCUBEMAP_FACES TextureCube::D3DFACE_TABLE[Mix::Graphics::CUBEMAP_FACE_MAX] =
{
	D3DCUBEMAP_FACE_POSITIVE_X,
	D3DCUBEMAP_FACE_NEGATIVE_X,
	D3DCUBEMAP_FACE_POSITIVE_Y,
	D3DCUBEMAP_FACE_NEGATIVE_Y,
	D3DCUBEMAP_FACE_POSITIVE_Z,
	D3DCUBEMAP_FACE_NEGATIVE_Z,
};

TextureCube* TextureCube::CreateInstance(	Mix::Graphics::DX9::Device* pDevice,
											const wchar_t* pFilePath,
											UInt32 edgeLength, Mix::Graphics::FORMAT format,
											D3DFORMAT d3dFormat, IDirect3DCubeTexture9* pD3DCubeTexture )
{
	return MIX_LIB_NEW_T( Mix::Memory::SECTION_GRAPHICS, TextureCube, pDevice, pFilePath, edgeLength, format, d3dFormat, pD3DCubeTexture );
}

TextureCube::TextureCube(	Mix::Graphics::DX9::Device* pDevice,
							const wchar_t* pFilePath,
							UInt32 edgeLength, Mix::Graphics::FORMAT format,
							D3DFORMAT d3dFormat, IDirect3DCubeTexture9* pD3DCubeTexture ) :
DeviceObject( pDevice ),
m_pDevice( pDevice ),
m_FilePath( pFilePath ),
m_EdgeLength( edgeLength ),
m_Format( format ),
m_D3DFormat( d3dFormat ),
m_pD3DCubeTexture( pD3DCubeTexture )
{
	for( UInt32 i = 0; i < Mix::Graphics::CUBEMAP_FACE_MAX; i++ )
	{
		m_pD3DSurface[i] = NULL;
	}

	GetD3DCubeMapSurface();
}

TextureCube::~TextureCube( void )
{
	MIX_RELEASE( m_pD3DCubeTexture );

	for( UInt32 i = 0; i < Mix::Graphics::CUBEMAP_FACE_MAX; i++ )
	{
		MIX_RELEASE( m_pD3DSurface[i] );
	}
}

void TextureCube::GetD3DCubeMapSurface( void )
{
	UInt32 i;

	for( i = 0; i < Mix::Graphics::CUBEMAP_FACE_MAX; i++ )
	{
		m_pD3DCubeTexture->GetCubeMapSurface( TextureCube::D3DFACE_TABLE[i], 0, &( m_pD3DSurface[i] ) );
	}
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// Mix::Graphics::DeviceObject
////////////////////////////////////////////////////////////////////////////////////////////////////

void TextureCube::Invalidate( void )
{
	if( m_FilePath.GetNum() == 0 )
	{
		MIX_RELEASE( m_pD3DCubeTexture );

		for( UInt32 i = 0; i < Mix::Graphics::CUBEMAP_FACE_MAX; i++ )
		{
			MIX_RELEASE( m_pD3DSurface[i] );
		}
	}
}

void TextureCube::Validate( void )
{
	if( m_FilePath.GetNum() == 0 )
	{
		HRESULT ret;

		ret = m_pDevice->CreateCubeTexture( m_EdgeLength, m_D3DFormat, &m_pD3DCubeTexture );
		if( ret == D3D_OK )
		{
			GetD3DCubeMapSurface();
		}
		else
		{
			MIX_LOG_ERROR( L"キューブテクスチャの復帰に失敗 : Result[%s]", m_pDevice->GetD3DResultText( ret ) );
		}
	}
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// Mix::Graphics::Texture
////////////////////////////////////////////////////////////////////////////////////////////////////

IDirect3DBaseTexture9* TextureCube::GetInterface( void )
{
	return m_pD3DCubeTexture;
}

IDirect3DSurface9* TextureCube::GetSurface( UInt32 index )
{
	MIX_ASSERT( Mix::Graphics::CUBEMAP_FACE_MAX > index );
	return m_pD3DSurface[index];
}

UInt32 TextureCube::GetSurfaceCount( void ) const
{
	return Mix::Graphics::CUBEMAP_FACE_MAX;
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// Mix::Graphics::ITexture
////////////////////////////////////////////////////////////////////////////////////////////////////

Mix::Graphics::ITexture::DIMENSION_TYPE TextureCube::GetDimensionType( void ) const
{
	return Mix::Graphics::ITexture::DIMENSION_CUBE;
}

Mix::Graphics::ITexture::BIND_TYPE TextureCube::GetBindType( void ) const
{
	return Mix::Graphics::ITexture::BIND_TARGET;
}

UInt32 TextureCube::GetAccessFlags( void ) const
{
	return ITexture::ACCESS_GPU_READ | ITexture::ACCESS_GPU_WRITE;
}

UInt32 TextureCube::GetWidth( void ) const
{
	return m_EdgeLength;
}

UInt32 TextureCube::GetHeight( void ) const
{
	return m_EdgeLength;
}

Mix::Graphics::FORMAT TextureCube::GetFormat( void ) const
{
	return m_Format;
}

const wchar_t* TextureCube::GetFilePath( void ) const
{
	return m_FilePath.GetConstPtr();
}

Boolean TextureCube::Lock( Mix::Graphics::ITexture::LOCK& lock )
{
	return False;
}

void TextureCube::Unlock( void )
{
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// Mix::Graphics::IDeviceObject
////////////////////////////////////////////////////////////////////////////////////////////////////

Mix::Graphics::IDeviceObject::TYPE TextureCube::GetType( void ) const
{
	return Mix::Graphics::IDeviceObject::TEXTURE;
}

}}}
