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

namespace Mix{ namespace Graphics{ namespace DX9{

////////////////////////////////////////////////////////////////////////////////////////////////////
// Mix::Graphics::DX9::TextureDynamic
////////////////////////////////////////////////////////////////////////////////////////////////////

TextureDynamic* TextureDynamic::CreateInstance(	Mix::Graphics::DX9::Device* pDevice,
												UInt32 width, UInt32 height, Mix::Graphics::FORMAT format,
												IDirect3DTexture9* pD3DTexture, D3DFORMAT d3dFormat )
{
	return MIX_LIB_NEW_T( Mix::Memory::SECTION_GRAPHICS, TextureDynamic, pDevice, width, height, format, pD3DTexture, d3dFormat );
}

TextureDynamic::TextureDynamic(	Mix::Graphics::DX9::Device* pDevice,
								UInt32 width, UInt32 height, Mix::Graphics::FORMAT format,
								IDirect3DTexture9* pD3DTexture, D3DFORMAT D3DFormat ) :
DeviceObject( pDevice ),
m_pDevice( NULL ),
m_Width( width ),
m_Height( height ),
m_Format( format ),
m_LockFlags( D3DLOCK_DISCARD ),
m_bLock( False ),
m_pD3DTexture( pD3DTexture ),
m_D3DFormat( D3DFormat )
{
	MIX_ASSERT( pDevice != NULL );

	MIX_ADD_REF( pDevice );
	m_pDevice = pDevice;
}

TextureDynamic::~TextureDynamic( void )
{
	MIX_RELEASE( m_pD3DTexture );
	MIX_RELEASE( m_pDevice );
}

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

void TextureDynamic::Invalidate( void )
{
	MIX_RELEASE( m_pD3DTexture );
}

void TextureDynamic::Validate( void )
{
	HRESULT ret;

	ret = m_pDevice->CreateDynamicTexture( m_Width, m_Height, m_D3DFormat, &m_pD3DTexture );
	if( ret != D3D_OK )
	{
		MIX_LOG_ERROR( L"ダイナミックテクスチャの復帰に失敗 : Result[%s]", m_pDevice->GetD3DResultText( ret ) );
	}
}

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

IDirect3DBaseTexture9* TextureDynamic::GetInterface( void )
{
	return m_pD3DTexture;
}

IDirect3DSurface9* TextureDynamic::GetSurface( UInt32 index )
{
	return NULL;
}

UInt32 TextureDynamic::GetSurfaceCount( void ) const
{
	return 0;
}

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

Mix::Graphics::ITexture::DIMENSION_TYPE TextureDynamic::GetDimensionType( void ) const
{
	return Mix::Graphics::ITexture::DIMENSION_PLANE;
}

Mix::Graphics::ITexture::BIND_TYPE TextureDynamic::GetBindType( void ) const
{
	return Mix::Graphics::ITexture::BIND_DEFAULT;
}

UInt32 TextureDynamic::GetAccessFlags( void ) const
{
	return ITexture::ACCESS_CPU_WRITE | ITexture::ACCESS_GPU_READ;
}

UInt32 TextureDynamic::GetWidth( void ) const
{
	return m_Width;
}

UInt32 TextureDynamic::GetHeight( void ) const
{
	return m_Height;
}

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

const wchar_t* TextureDynamic::GetFilePath( void ) const
{
	return Mix::STR_NULL;
}

Boolean TextureDynamic::Lock( Mix::Graphics::ITexture::LOCK& lock )
{
	if( ( m_pD3DTexture == NULL ) || ( m_bLock == True ) )
	{
		return False;
	}

	HRESULT hRet;
	D3DLOCKED_RECT info;

	hRet = m_pD3DTexture->LockRect( 0, &info, NULL, m_LockFlags );
	if( hRet != D3D_OK )
	{
		MIX_LOG_ERROR( L"ダイナミックテクスチャのロックに失敗 : LockRect %s : Result[%s]",
			Mix::STR_RETERROR, m_pDevice->GetD3DResultText( hRet ) );

		return False;
	}

	lock.pitch = static_cast<UInt32>( info.Pitch );
	lock.bits = info.pBits;

	m_bLock = True;

	return True;
}

void TextureDynamic::Unlock( void )
{
	if( ( m_pD3DTexture == NULL ) || ( m_bLock == False ) )
	{
		return;
	}

	HRESULT hRet;

	hRet = m_pD3DTexture->UnlockRect( 0 );
	if( hRet != D3D_OK )
	{
		MIX_LOG_ERROR( L"ダイナミックテクスチャのアンロックに失敗 : UnlockRect %s : Result[%s]",
			Mix::STR_RETERROR, m_pDevice->GetD3DResultText( hRet ) );

		return;
	}

	m_bLock = False;
}

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

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

}}}
