DragonNest/Common/EternityEngine/D3DDevice9/EtDevice.cpp
2024-12-19 09:48:26 +08:00

1822 lines
46 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "StdAfx.h"
#include "EtDevice.h"
#include <direct.h>
#include "EtStateManager.h"
#include "EtSystemFont.h"
#include "EternityEngine/EternityEngine.h"
#include "EtTexture.h"
//#include "..\\..\\..\\Client\\DragonNest\\LogWnd.h"
//#define USE_PERF_TEST
#ifdef _DEBUG
#define new new(_NORMAL_BLOCK,__FILE__,__LINE__)
#endif
CEtDevice g_EtDevice;
DWORD g_dwTextureColorKey = 0;
CEtDevice::CEtDevice()
{
m_pD3D = NULL;
m_pDD = NULL;
m_pDevice = NULL;
m_pBackBufferSurface = NULL;
m_pDepthStencilSurface = NULL;
m_pFont = NULL;
m_pCurSetRenderTarget = NULL;
m_pCurSetDepthStencil = NULL;
m_bShaderDebug = false;
m_SupportedAntiAliasType = MULTISAMPLE_NONE;
m_pOutOfMemoryCallBack = &FnDeviceOutOfMemory();
m_vecVertexDecl.reserve( 256 );
#ifdef PRE_MOD_MEMORY_CHECK
m_dwLocalVideoMemory = 0;
#else
m_bUseDDrawMemCheck = true;
#endif
m_dwTotalAvailTextureMemory = 0;
m_pPrePresentCallback = NULL;
m_nCurrentPolyCount = 0;
m_nPolyCountPerFrame = 0;
m_bCallOutOfMemory = false;
#ifdef PRE_FIX_CLIENT_MEMOPTIMIZE
m_pFlushWaitDeleteCallback = NULL;
#endif
m_hWnd = 0;
m_pSystemFont = NULL;
memset( &m_Param, 0, sizeof( D3DPRESENT_PARAMETERS ) );
}
CEtDevice::~CEtDevice()
{
Clear();
}
void CEtDevice::Clear()
{
ClearEffectMacro();
for( std::vector< VertexDecl >::iterator it = m_vecVertexDecl.begin(); it != m_vecVertexDecl.end(); ++it ) {
SAFE_RELEASE( it->pDecl );
}
m_vecVertexDecl.clear();
SAFE_RELEASE( m_pFont );
SAFE_RELEASE( m_pBackBufferSurface );
SAFE_RELEASE( m_pDepthStencilSurface );
SAFE_RELEASE( m_pDevice );
SAFE_RELEASE( m_pD3D );
SAFE_RELEASE( m_pDD );
m_vecApplyQualityPath.clear();
}
void CEtDevice::CreateDDraw()
{
ScopeLock<CSyncLock> Lock(m_DeviceLostLock);
SAFE_RELEASE( m_pDD );
DirectDrawCreateEx( NULL, ( VOID** )&m_pDD, IID_IDirectDraw7, NULL );
ADD_D3D_RES( m_pDD );
}
void CEtDevice::EnumDisplayMode()
{
int i, nCount;
D3DDISPLAYMODE DisplayMode;
m_vecDisplayMode.clear();
nCount = m_pD3D->GetAdapterModeCount( 0, D3DFMT_X8R8G8B8 );
for( i = 0; i < nCount; i++ )
{
m_pD3D->EnumAdapterModes( 0, D3DFMT_X8R8G8B8, i, &DisplayMode );
if( ( DisplayMode.Height / ( float )DisplayMode.Width ) > 0.5f ) // 16 : 9 <20><><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20>ػ󵵴<D8BB> <20><><EFBFBD><EFBFBD><EFBFBD>Ѵ<EFBFBD>.
{
m_vecDisplayMode.push_back( DisplayMode );
}
}
}
void CEtDevice::FindSuitableDisplayMode( int &nWidth, int &nHeight )
{
int i;
std::vector< int > vecSuitableDisplayMode;
bool bWide = false;;
if( nHeight / ( float )nWidth < 0.7f )
{
bWide = true;
}
for( i = 0; i < ( int )m_vecDisplayMode.size(); i++ )
{
if( bWide )
{
if( m_vecDisplayMode[ i ].Height / ( float )m_vecDisplayMode[ i ].Width < 0.7f )
{
vecSuitableDisplayMode.push_back( i );
}
}
else
{
if( m_vecDisplayMode[ i ].Height / ( float )m_vecDisplayMode[ i ].Width > 0.7f )
{
vecSuitableDisplayMode.push_back( i );
}
}
}
if( vecSuitableDisplayMode.empty() )
{
for( i = 0; i < ( int )m_vecDisplayMode.size(); i++ )
{
vecSuitableDisplayMode.push_back( i );
}
}
for( i = ( int )vecSuitableDisplayMode.size() - 1; i >= 0; i-- )
{
if( ( m_vecDisplayMode[ vecSuitableDisplayMode[ i ] ].Width == nWidth ) && ( m_vecDisplayMode[ vecSuitableDisplayMode[ i ] ].Height == nHeight ) )
{
return;
}
}
int nNearIndex, nMinValue;
nMinValue = INT_MAX;
nNearIndex = -1;
for( i = ( int )vecSuitableDisplayMode.size() - 1; i >= 0; i-- )
{
if( m_vecDisplayMode[ vecSuitableDisplayMode[ i ] ].Width == nWidth )
{
if( abs( ( int )( m_vecDisplayMode[ vecSuitableDisplayMode[ i ] ].Height - nHeight ) ) < nMinValue )
{
nNearIndex = i;
nMinValue = abs( ( int )( m_vecDisplayMode[ vecSuitableDisplayMode[ i ] ].Height - nHeight ) );
}
}
}
if( nNearIndex == -1 )
{
for( i = ( int )vecSuitableDisplayMode.size() - 1; i >= 0; i-- )
{
if( m_vecDisplayMode[ vecSuitableDisplayMode[ i ] ].Height == nHeight )
{
if( abs( ( int )( m_vecDisplayMode[ vecSuitableDisplayMode[ i ] ].Width - nWidth ) ) < nMinValue )
{
nNearIndex = i;
nMinValue = abs( ( int )( m_vecDisplayMode[ vecSuitableDisplayMode[ i ] ].Width - nWidth ) );
}
}
}
}
if( nNearIndex == -1 )
{
nWidth = MIN_RES_WIDTH;
for( i = 0; i < ( int )vecSuitableDisplayMode.size(); i++ )
{
if( ( int )( m_vecDisplayMode[ vecSuitableDisplayMode[ i ] ].Width * m_vecDisplayMode[ vecSuitableDisplayMode[ i ] ].Height ) >= nWidth * nHeight )
{
nNearIndex = i;
break;
}
}
}
if( nNearIndex == -1 )
{
nNearIndex = ( int )vecSuitableDisplayMode.size() - 1;
}
if( nNearIndex == -1 ) {
nWidth = MIN_RES_WIDTH;
nHeight = MIN_RES_HEIGHT;
}
else {
nWidth = m_vecDisplayMode[ vecSuitableDisplayMode [ nNearIndex ] ].Width;
nHeight = m_vecDisplayMode[ vecSuitableDisplayMode[ nNearIndex ] ].Height;
}
}
int CEtDevice::FindSuitableRefreshRate( int nWidth, int nHeight )
{
int nResultRefreshRate = 0;
const int nTargetRefreshRate = 60;
for( int i = 0; i < ( int )m_vecDisplayMode.size(); i++ )
{
if( m_vecDisplayMode[i].Width == nWidth && m_vecDisplayMode[i].Height == nHeight ) {
if( abs((int)m_vecDisplayMode[i].RefreshRate - nTargetRefreshRate) < abs(nResultRefreshRate - nTargetRefreshRate) ) {
nResultRefreshRate = m_vecDisplayMode[i].RefreshRate;
}
}
}
return nResultRefreshRate;
}
int CEtDevice::Initialize( HWND hWnd, int nWidth, int nHeight, bool bWindow, bool bEnableMultiThread, bool bVSync, bool bEnableShaderDebug )
{
LabelRetry:
m_hWnd = hWnd;
m_pD3D = Direct3DCreate9( D3D_SDK_VERSION );
m_pD3D->GetDeviceCaps( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &m_Caps);
ADD_D3D_RES( m_pD3D );
EnumDisplayMode();
if( bWindow == false )
{
FindSuitableDisplayMode( nWidth, nHeight );
}
m_AdapterFormat = D3DFMT_X8R8G8B8;
memset( &m_Param, 0, sizeof( D3DPRESENT_PARAMETERS ) );
m_Param.BackBufferWidth = nWidth;
m_Param.BackBufferHeight = nHeight;
m_Param.BackBufferFormat = m_AdapterFormat;
m_Param.BackBufferCount = 1;
m_Param.EnableAutoDepthStencil = true;
m_Param.AutoDepthStencilFormat = D3DFMT_D24S8;
m_Param.SwapEffect = D3DSWAPEFFECT_DISCARD;
m_Param.Windowed = bWindow;
if( bWindow )
{
m_Param.FullScreen_RefreshRateInHz = 0;
}
else
{
m_Param.FullScreen_RefreshRateInHz = FindSuitableRefreshRate( nWidth, nHeight);
}
SetVSync( bVSync );
m_Param.Flags = D3DPRESENTFLAG_LOCKABLE_BACKBUFFER;
DWORD dwFlags;
m_DevType = D3DDEVTYPE_HAL;
dwFlags = D3DCREATE_HARDWARE_VERTEXPROCESSING;
if( (m_Caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) == 0 || m_Caps.VertexShaderVersion < D3DVS_VERSION(1,1) )
{
dwFlags = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
}
if( bEnableMultiThread )
{
dwFlags |= D3DCREATE_MULTITHREADED;
}
if( bEnableShaderDebug )
{
m_bShaderDebug = true;
m_DevType = D3DDEVTYPE_REF;
dwFlags = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
}
bool bProfileMode = false;
#ifndef _FINAL_BUILD
char* lpCommandLine = ::GetCommandLine();
if(strstr(lpCommandLine, "/perf"))
{
bProfileMode = true;
}
#endif
#ifdef USE_PERF_TEST
bProfileMode = true;
#endif
if( bProfileMode )
{
m_nAdapter = D3DADAPTER_DEFAULT;
m_DevType = D3DDEVTYPE_HAL;
// Look for 'NVIDIA PerfHUD' adapter
// If it is present, override default settings
for (UINT Adapter=0;Adapter<m_pD3D->GetAdapterCount();Adapter++)
{
D3DADAPTER_IDENTIFIER9 Identifier;
HRESULT Res;
Res = m_pD3D->GetAdapterIdentifier(Adapter,0,&Identifier);
if (strstr(Identifier.Description,"PerfHUD") != 0)
{
m_nAdapter = Adapter;
m_DevType = D3DDEVTYPE_REF;
break;
}
}
if( FAILED( m_pD3D->CreateDevice( m_nAdapter, m_DevType, hWnd, dwFlags, &m_Param, &m_pDevice ) ) )
{
ASSERT( 0 && "CreateDevice() Failed!!" );
return ETERR_CREATEDEVICEFAIL;
}
ADD_D3D_RES( m_pDevice );
}
else
{
m_nAdapter = D3DADAPTER_DEFAULT;
HRESULT hr;
if( FAILED( hr = m_pD3D->CreateDevice( m_nAdapter, m_DevType, hWnd, dwFlags, &m_Param, &m_pDevice ) ) )
{
static int nRetryStep = 5; // <20><><EFBFBD><EFBFBD><EFBFBD>̽<EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD>н<EFBFBD> <20>ټ<EFBFBD><D9BC><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD>õ<EFBFBD><C3B5>Ѵ<EFBFBD>...
if( nRetryStep-- > 0 ) {
SAFE_RELEASE( m_pD3D );
Sleep( 100 );
goto LabelRetry;
}
//if( hr == D3DERR_DEVICELOST ) {
ASSERT( 0 && "CreateDevice() Failed!!" );
return ETERR_CREATEDEVICEFAIL;
//}
}
ADD_D3D_RES( m_pDevice );
}
m_pDevice->GetDeviceCaps( &m_Caps );
m_pDevice->GetBackBuffer( 0, 0, D3DBACKBUFFER_TYPE_MONO, &m_pBackBufferSurface );
m_pDevice->GetDepthStencilSurface( &m_pDepthStencilSurface );
GetEtStateManager()->Initialize( this );
ADD_D3D_RES( m_pBackBufferSurface );
ADD_D3D_RES( m_pDepthStencilSurface );
EtMultiSampleType SampleTypes[] = { MULTISAMPLE_8_SAMPLES, MULTISAMPLE_4_SAMPLES, MULTISAMPLE_2_SAMPLES};
for ( int i = 0; i < _countof(SampleTypes); i++) {
HRESULT resultFullScreen = m_pD3D->CheckDeviceMultiSampleType( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_A8R8G8B8, FALSE, (D3DMULTISAMPLE_TYPE)SampleTypes[i], NULL);
HRESULT resultWindowed = m_pD3D->CheckDeviceMultiSampleType( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_A8R8G8B8, TRUE, (D3DMULTISAMPLE_TYPE)SampleTypes[i], NULL);
HRESULT resultDepthFullScreen = m_pD3D->CheckDeviceMultiSampleType( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_D24S8, FALSE, (D3DMULTISAMPLE_TYPE)SampleTypes[i], NULL);
HRESULT resultDepthWindowed = m_pD3D->CheckDeviceMultiSampleType( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_D24S8, TRUE, (D3DMULTISAMPLE_TYPE)SampleTypes[i], NULL);
if( resultFullScreen == D3D_OK && resultWindowed == D3D_OK &&
resultDepthFullScreen == D3D_OK && resultDepthWindowed == D3D_OK ) {
m_SupportedAntiAliasType = SampleTypes[i];
break;
}
}
SetClipCursor( !m_Param.Windowed );
CreateDDraw();
GetEtStateManager()->Reset();
SetDefaultState();
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>ʷ<EFBFBD> <20>ѹ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ش<EFBFBD>.
ClearBuffer( 0x00000000 );
ShowFrame();
#ifdef PRE_MOD_MEMORY_CHECK
CheckTotalLocalVideoMemory();
#else
m_dwTotalAvailTextureMemory = m_pDevice->GetAvailableTextureMem( );
#endif
return ET_OK;
}
void CEtDevice::SetVSync( bool bVSync )
{
m_Param.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
if( bVSync && m_Caps.PresentationIntervals & D3DPRESENT_INTERVAL_ONE )
{
m_Param.PresentationInterval = D3DPRESENT_INTERVAL_ONE;
}
}
bool CEtDevice::IsOnlyLowShaderAvailable( void )
{
if( NULL == m_pD3D )
return false;
// <20><><EFBFBD><EFBFBD> G31/G33 ī<><EFBFBD><E5B0B0> <20><><EFBFBD><EFBFBD> <20>͵<EFBFBD><CDB5><EFBFBD><EFBFBD><EFBFBD> Ȯ<><C8AE>
// GMA X3000 <20>̻<EFBFBD><CCBB><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><>.
bool bIsOnlyLowShaderAvailable = false;
D3DCAPS9 Caps; // Device CAPs structure
D3DADAPTER_IDENTIFIER9 AdapterID; // Used to store device info
// Retrieve device capabilities
if( m_pD3D->GetDeviceCaps( 0, D3DDEVTYPE_HAL, &Caps ) != D3D_OK )
{
return true; // caps <20><> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>..
}
// Check vendor and device ID and enable software vertex
// processing for Intel(R) Graphics...
// Gather the primary adapter's information...
if( m_pD3D->GetAdapterIdentifier(0,0,&AdapterID ) != D3D_OK )
{
return true; // <20>ƴ<EFBFBD><C6B4><EFBFBD> <20>ĺ<EFBFBD><C4BA>ڵ<EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>..
}
// 915, 945, G31/G33, Q35 <20>̳<EFBFBD><CCB3><EFBFBD><EFBFBD><EFBFBD> <20>Ͽ<EFBFBD><CFBF><EFBFBD> <20><><EFBFBD><EFBFBD>¥<EFBFBD><C2A5> <20><><EFBFBD>÷<EFBFBD><C3B7><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD>̴<EFBFBD> <20><><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.
// Intel Architecture
if( AdapterID.VendorId == 0x8086 )
{
if( //( AdapterID.DeviceId == 0x2A02 ) || // GM965 Device 0
//( AdapterID.DeviceId == 0x2A03 ) || // GM965 Device 1
//( AdapterID.DeviceId == 0x29A2 ) || // G965 Device 0
//( AdapterID.DeviceId == 0x29A3 ) || // G965 Device 1
( AdapterID.DeviceId == 0x27A2 ) || // 945GM Device 0
( AdapterID.DeviceId == 0x27A6 ) || // 945GM Device 1
( AdapterID.DeviceId == 0x2772 ) || // 945G Device 0
( AdapterID.DeviceId == 0x2776 ) || // 945G Device 1
( AdapterID.DeviceId == 0x2592 ) || // 915GM Device 0
( AdapterID.DeviceId == 0x2792 ) || // 915GM Device 1
( AdapterID.DeviceId == 0x2582 ) || // 915G Device 0
( AdapterID.DeviceId == 0x2782 ) || // 915G Device 1
( AdapterID.DeviceId == 0x2972 ) || // 946GZ Device 0
( AdapterID.DeviceId == 0x2973 ) || // 946GZ Device 1
//( AdapterID.DeviceId == 0x2992 ) || // Q965/Q963 Device 0
//( AdapterID.DeviceId == 0x2993 ) || // Q965/Q963 Device 1
( AdapterID.DeviceId == 0x29b2 ) || // Q35 Device 0
( AdapterID.DeviceId == 0x29b3 ) || // Q35 Device 1
( AdapterID.DeviceId == 0x29c2 ) || // G33/G31 Device 0
( AdapterID.DeviceId == 0x29c3 ) || // G33/G31 Device 1
( AdapterID.DeviceId == 0x29d2 ) || // Q33 Device 0
( AdapterID.DeviceId == 0x29d3 ) // Q33 Device 1
)
{
bIsOnlyLowShaderAvailable = true;
}
}
else
{
// #42934 <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><EFBFBD><E8BFAD> <20>ƴѰ<C6B4><D1B0><EFBFBD> <20>ȼ<EFBFBD> <20><><EFBFBD>̴<EFBFBD><CCB4><EFBFBD> StaticFlowControlDepth <20><><EFBFBD><EFBFBD> <20>ִ<EFBFBD> <20><><EFBFBD>
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>÷<EFBFBD><C3B7><EFBFBD> <20><><EFBFBD>̴<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.
if( 0 == Caps.PS20Caps.StaticFlowControlDepth )
bIsOnlyLowShaderAvailable = true;
}
return bIsOnlyLowShaderAvailable;
}
void CEtDevice::Reinitialize( int nWidth, int nHeight )
{
if( m_pDevice )
{
SAFE_RELEASE( m_pBackBufferSurface );
SAFE_RELEASE( m_pDepthStencilSurface );
m_Param.BackBufferWidth = nWidth;
m_Param.BackBufferHeight = nHeight;
if( m_Param.Windowed ) {
m_Param.FullScreen_RefreshRateInHz = 0;
}
else {
m_Param.FullScreen_RefreshRateInHz = FindSuitableRefreshRate( nWidth, nHeight);
}
HRESULT hr = m_pDevice->Reset( &m_Param );
if( FAILED(hr) ) {
MessageBox( 0 ,"Device cannot be reset.", "DragonNest", MB_OK);
PostQuitMessage( 0 );
}
m_pDevice->GetBackBuffer( 0, 0, D3DBACKBUFFER_TYPE_MONO, &m_pBackBufferSurface );
m_pDevice->GetDepthStencilSurface( &m_pDepthStencilSurface );
ADD_D3D_RES( m_pBackBufferSurface );
ADD_D3D_RES( m_pDepthStencilSurface );
GetEtStateManager()->Reset();
SetDefaultState();
}
CreateDDraw();
SetClipCursor( !m_Param.Windowed );
}
void CEtDevice::SetDefaultState()
{
GetEtStateManager()->SetDefaultState();
m_pCurSetRenderTarget = m_pBackBufferSurface;
m_pCurSetDepthStencil = m_pDepthStencilSurface;
}
void CEtDevice::ClearBuffer( D3DCOLOR COLOR, float fZ, DWORD dwStencil, bool bClearColor, bool bClearZ, bool bClearStencil )
{
DWORD dwFlags = 0;
if( bClearColor )
{
dwFlags |= D3DCLEAR_TARGET;
}
if( IsEnableZTest() )
{
if( bClearZ )
{
dwFlags |= D3DCLEAR_ZBUFFER;
}
if( bClearStencil )
{
dwFlags |= D3DCLEAR_STENCIL;
}
}
ScopeLock< CSyncLock > Lock( m_DeviceLock );
m_pDevice->Clear( 0, NULL, dwFlags, COLOR, fZ, dwStencil );
}
EtDeviceCheck CEtDevice::DeviceValidCheck()
{
HRESULT hr;
//if( m_Param.Windowed )
{
ScopeLock< CSyncLock > Lock( m_DeviceLock );
hr = m_pDevice->TestCooperativeLevel();
if( FAILED( hr ) )
{
if( hr == D3DERR_DEVICENOTRESET )
{
// <20><><EFBFBD><EFBFBD><EFBFBD>̽<EFBFBD><CCBD><EFBFBD> <20>ҽ<EFBFBD><D2BD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>Ѱ<EFBFBD><D1B0><EFBFBD>.
return DC_CAN_RESET;
}
else if ( hr == D3DERR_DEVICELOST )
{
// <20><><EFBFBD><EFBFBD><EFBFBD>̽<EFBFBD><CCBD><EFBFBD> <20>ҽ<EFBFBD><D2BD>߰<EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>Ұ<EFBFBD><D2B0><EFBFBD> <20><><EFBFBD><EFBFBD>
return DC_CANNOT_RESET;
}
else
{
// <20>׿<EFBFBD><D7BF><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20>Ұ<EFBFBD><D2B0><EFBFBD><EFBFBD>̴<EFBFBD>.
return DC_CANNOT_RESET;
}
}
}
return DC_OK;
}
void CEtDevice::SetRenderTarget( EtSurface *pSurface )
{
if( pSurface == m_pCurSetRenderTarget ) {
return;
}
ScopeLock< CSyncLock > Lock( m_DeviceLock );
m_pDevice->SetRenderTarget( 0 , pSurface ); // MRT <20><> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ѵ<EFBFBD>.
m_pCurSetRenderTarget = pSurface;
}
void CEtDevice::SetDepthStencilSurface( EtSurface *pSurface )
{
ScopeLock< CSyncLock > Lock( m_DeviceLock );
m_pDevice->SetDepthStencilSurface( pSurface );
m_pCurSetDepthStencil = pSurface;
}
void CEtDevice::DumpBackBuffer( LPDIRECT3DSURFACE9 pSurface, LPDIRECT3DSURFACE9 pSourceSurface )
{
ScopeLock< CSyncLock > Lock( m_DeviceLock );
m_pDevice->StretchRect( (pSourceSurface == NULL) ? m_pBackBufferSurface : pSourceSurface ,
NULL, pSurface, NULL, D3DTEXF_POINT );
}
void CEtDevice::SaveBackbuffer( const char *pFileName, D3DXIMAGE_FILEFORMAT Format )
{
D3DXSaveSurfaceToFile( pFileName, Format, m_pBackBufferSurface, NULL, NULL );
}
void CEtDevice::SaveBackbuffer( WCHAR *pFileName, D3DXIMAGE_FILEFORMAT Format )
{
D3DXSaveSurfaceToFileW( pFileName, Format, m_pBackBufferSurface, NULL, NULL );
}
int CEtDevice::FindVertexDeclaration( D3DVERTEXELEMENT9* pVertexElements )
{
int i, j, nElementCount, nSrcCount;
D3DVERTEXELEMENT9 *Decl;
nSrcCount = 0;
while( 1 )
{
if( pVertexElements[ nSrcCount ].Stream == 0xff )
{
break;
}
nSrcCount++;
}
nElementCount = 32;
for( i = 0; i < ( int )m_vecVertexDecl.size(); i++ )
{
Decl = m_vecVertexDecl[ i ].Elem;
nElementCount = m_vecVertexDecl[ i ].nElemCount;
if( nSrcCount != nElementCount - 1 )
{
continue;
}
for( j = 0; j < nSrcCount; j++)
{
if( ( Decl[ j ].Method != pVertexElements[ j ].Method ) ||
( Decl[ j ].Offset != pVertexElements[ j ].Offset ) ||
( Decl[ j ].Stream != pVertexElements[ j ].Stream ) ||
( Decl[ j ].Type != pVertexElements[ j ].Type ) ||
( Decl[ j ].UsageIndex != pVertexElements[ j ].UsageIndex ) )
{
break;
}
}
if( j >= nSrcCount )
{
return i;
}
}
return -1;
}
int CEtDevice::CreateVertexDeclaration( D3DVERTEXELEMENT9* pVertexElements )
{
int nFindIndex;
nFindIndex = FindVertexDeclaration( pVertexElements );
if( nFindIndex != -1 )
{
return nFindIndex;
}
EtVertexDecl *pDecl = NULL;
ScopeLock< CSyncLock > Lock( m_DeviceLock );
m_pDevice->CreateVertexDeclaration( pVertexElements, &pDecl );
ADD_D3D_RES( pDecl );
VertexDecl Decl;
Decl.pDecl = pDecl;
pDecl->GetDeclaration( Decl.Elem, ( UINT * )&Decl.nElemCount );
m_vecVertexDecl.push_back( Decl );
return ( int )( m_vecVertexDecl.size() - 1 );
}
EtVertexDecl *CEtDevice::GetVertexDeclaration( int nIndex )
{
if( ( nIndex < 0 ) || ( nIndex >= ( int )m_vecVertexDecl.size() ) )
{
ASSERT( 0 && "Invalid Vertex Declaration Index" );
return NULL;
}
return m_vecVertexDecl[ nIndex ].pDecl;
}
// Device <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ϴ<EFBFBD> <20>Լ<EFBFBD><D4BC><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>𸣹Ƿ<F0B8A3B9>,
// <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ϴ°<CFB4><C2B0><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20>ִ<EFBFBD>.
void CEtDevice::GetVertexElement( int nIndex, D3DVERTEXELEMENT9* pElement, UINT* pNumElements )
{
if( ( nIndex < 0 ) || ( nIndex >= ( int )m_vecVertexDecl.size() ) )
{
ASSERT( 0 && "Invalid Vertex Declaration Index" );
return ;
}
VertexDecl &decl = m_vecVertexDecl[ nIndex ];
for( UINT i = 0; i < decl.nElemCount; i++ ) {
pElement[ i ] = decl.Elem[ i ];
}
if( pNumElements ) {
*pNumElements = decl.nElemCount;
}
}
void CEtDevice::SetVertexDeclaration( int nIndex )
{
if( ( nIndex < 0 ) || ( nIndex >= ( int )m_vecVertexDecl.size() ) )
{
ASSERT( 0 && "Invalid Vertex Declaration Index" );
return;
}
ScopeLock< CSyncLock > Lock( m_DeviceLock );
m_pDevice->SetVertexDeclaration( m_vecVertexDecl[ nIndex ].pDecl );
}
#ifdef PRE_FIX_CLIENT_MEMOPTIMIZE
bool CEtDevice::CheckFlushWaitDelete()
{
bool bResult[2] = { true, true };
if( m_pFlushWaitDeleteCallback ) {
bResult[1] = m_pFlushWaitDeleteCallback();
}
else bResult[1] = false;
if( CEtResource::IsEmptyWaitDelete() ) bResult[0] = false;
else CEtResource::FlushWaitDelete();
if( bResult[0] == true || bResult[1] == true ) return true;
return false;
}
#endif
EtVertexBuffer *CEtDevice::CreateVertexBuffer( int nLength, DWORD dwFVF, EtUsage Usage, EtPool Pool )
{
EtVertexBuffer *pBuffer = NULL;
ScopeLock< CSyncLock > Lock( m_DeviceLock );
HRESULT hr = m_pDevice->CreateVertexBuffer( nLength, Usage, dwFVF, ( D3DPOOL )Pool, &pBuffer, NULL );
if( hr == E_OUTOFMEMORY ) {
#ifdef PRE_FIX_CLIENT_MEMOPTIMIZE
if( CheckFlushWaitDelete() ) {
return CreateVertexBuffer( nLength, dwFVF, Usage, Pool );
}
else {
m_szLastErrorMsg = "CreateVertexBuffer";
OnOutOfMemory();
return NULL;
}
#else
if( CEtResource::IsEmptyWaitDelete() ) {
m_szLastErrorMsg = "CreateVertexBuffer";
OnOutOfMemory();
return NULL;
}
else {
CEtResource::FlushWaitDelete();
return CreateVertexBuffer( nLength, dwFVF, Usage, Pool );
}
#endif
}
ADD_D3D_RES( pBuffer );
return pBuffer;
}
EtIndexBuffer *CEtDevice::CreateIndexBuffer( int nLength, EtUsage Usage, EtPool Pool )
{
EtIndexBuffer *pBuffer = NULL;
ScopeLock< CSyncLock > Lock( m_DeviceLock );
HRESULT hr = m_pDevice->CreateIndexBuffer( nLength, Usage, D3DFMT_INDEX16, ( D3DPOOL )Pool, &pBuffer, NULL );
if( hr == E_OUTOFMEMORY ) {
#ifdef PRE_FIX_CLIENT_MEMOPTIMIZE
if( CheckFlushWaitDelete() ) {
return CreateIndexBuffer( nLength, Usage, Pool );
}
else {
m_szLastErrorMsg = "CreateIndexBuffer";
OnOutOfMemory();
return NULL;
}
#else
if( CEtResource::IsEmptyWaitDelete() ) {
m_szLastErrorMsg = "CreateIndexBuffer";
OnOutOfMemory();
return NULL;
}
else {
CEtResource::FlushWaitDelete();
return CreateIndexBuffer( nLength, Usage, Pool );
}
#endif
}
ADD_D3D_RES( pBuffer );
return pBuffer;
}
void CEtDevice::SetStreamSource( int nStreamNum, EtVertexBuffer *pBuffer, int nStride, int nStartIndex )
{
if( pBuffer == NULL )
{
ASSERT( 0 && "Invalid VertexBuffer" );
}
ScopeLock< CSyncLock > Lock( m_DeviceLock );
m_pDevice->SetStreamSource( nStreamNum, pBuffer, nStartIndex, nStride );
}
void CEtDevice::SetIndexBuffer( EtIndexBuffer *pBuffer )
{
if( pBuffer == NULL )
{
ASSERT( 0 && "Invalid IndexBuffer" );
}
ScopeLock< CSyncLock > Lock( m_DeviceLock );
m_pDevice->SetIndices( pBuffer );
}
EtBaseTexture *CEtDevice::CreateTexture( int nWidth, int nHeight, EtFormat Format, EtUsage Usage, EtPool Pool, int nLevel )
{
LPDIRECT3DTEXTURE9 pTexture = NULL;
if( nWidth < 0 )
{
nWidth = Width() / abs( nWidth );
}
if( nHeight < 0 )
{
nHeight = Height() / abs( nHeight );
}
ScopeLock< CSyncLock > Lock( m_DeviceLock );
HRESULT hr = D3DXCreateTexture( m_pDevice, nWidth, nHeight, nLevel, Usage, ( D3DFORMAT )Format, ( D3DPOOL )Pool, &pTexture );
if( hr == E_OUTOFMEMORY ) {
#ifdef PRE_FIX_CLIENT_MEMOPTIMIZE
if( CheckFlushWaitDelete() ) {
return CreateTexture( nWidth, nHeight, Format, Usage, Pool, nLevel );
}
else {
m_szLastErrorMsg = "CreateTexture";
OnOutOfMemory();
return NULL;
}
#else
if( CEtResource::IsEmptyWaitDelete() ) {
m_szLastErrorMsg = "CreateTexture";
OnOutOfMemory();
return NULL;
}
else {
CEtResource::FlushWaitDelete();
return CreateTexture( nWidth, nHeight, Format, Usage, Pool, nLevel );
}
#endif
}
ADD_D3D_RES( pTexture );
return pTexture;
}
EtBaseTexture *CEtDevice::CreateRenderTargetTexture( int nWidth, int nHeight, EtFormat Format, EtUsage Usage, EtPool Pool )
{
LPDIRECT3DTEXTURE9 pTexture = NULL;
if( nWidth < 0 )
{
nWidth = Width() / abs( nWidth );
}
if( nHeight < 0 )
{
nHeight = Height() / abs( nHeight );
}
ScopeLock< CSyncLock > Lock( m_DeviceLock );
HRESULT hr = D3DXCreateTexture( m_pDevice, nWidth, nHeight, 1, D3DUSAGE_RENDERTARGET | Usage, ( D3DFORMAT )Format, ( D3DPOOL )Pool, &pTexture );
if( hr == E_OUTOFMEMORY ) {
#ifdef PRE_FIX_CLIENT_MEMOPTIMIZE
if( CheckFlushWaitDelete() ) {
return CreateRenderTargetTexture( nWidth, nHeight, Format, Usage, Pool );
}
else {
m_szLastErrorMsg = "CreateRenderTargetTexture";
OnOutOfMemory();
return NULL;
}
#else
if( CEtResource::IsEmptyWaitDelete() ) {
m_szLastErrorMsg = "CreateRenderTargetTexture";
OnOutOfMemory();
return NULL;
}
else {
CEtResource::FlushWaitDelete();
return CreateRenderTargetTexture( nWidth, nHeight, Format, Usage, Pool );
}
#endif
}
ADD_D3D_RES( pTexture );
return pTexture;
}
EtSurface *CEtDevice::CreateRenderTarget( int nWidth, int nHeight, EtFormat Format, EtPool Pool, EtMultiSampleType MultiSampleType )
{
if( nWidth < 0 )
{
nWidth = Width() / abs( nWidth );
}
if( nHeight < 0 )
{
nHeight = Height() / abs( nHeight );
}
EtSurface *pSurface = NULL;
ScopeLock< CSyncLock > Lock( m_DeviceLock );
HRESULT hr = m_pDevice->CreateRenderTarget( nWidth, nHeight, (D3DFORMAT)Format, (D3DMULTISAMPLE_TYPE)MultiSampleType, 0, FALSE, &pSurface, NULL);
if( hr == E_OUTOFMEMORY ) {
#ifdef PRE_FIX_CLIENT_MEMOPTIMIZE
if( CheckFlushWaitDelete() ) {
return CreateRenderTarget( nWidth, nHeight, Format, Pool, MultiSampleType );
}
else {
m_szLastErrorMsg = "CreateRenderTarget";
OnOutOfMemory();
return NULL;
}
#else
if( CEtResource::IsEmptyWaitDelete() ) {
m_szLastErrorMsg = "CreateRenderTarget";
OnOutOfMemory();
return NULL;
}
else {
CEtResource::FlushWaitDelete();
return CreateRenderTarget( nWidth, nHeight, Format, Pool, MultiSampleType );
}
#endif
}
if( !pSurface && MultiSampleType != MULTISAMPLE_NONE ) { // <20><>Ƽ<EFBFBD>˸<EFBFBD><CBB8>ƽ<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ϴ<EFBFBD> <20><><EFBFBD><EFBFBD>...
OutputDebug(" Fail Create MultiSample RenderTarget\n");
m_pDevice->CreateRenderTarget( nWidth, nHeight, (D3DFORMAT)Format, D3DMULTISAMPLE_NONE, 0, FALSE, &pSurface, NULL);
}
ADD_D3D_RES( pSurface );
return pSurface;
}
EtSurface *CEtDevice::CreateDepthStencil( int nWidth, int nHeight, EtFormat Format, EtMultiSampleType MultiSampleType )
{
EtSurface *pSurface = NULL;
if( nWidth < 0 )
{
nWidth = Width() / abs( nWidth );
}
if( nHeight < 0 )
{
nHeight = Height() / abs( nHeight );
}
ScopeLock< CSyncLock > Lock( m_DeviceLock );
HRESULT hr = m_pDevice->CreateDepthStencilSurface( nWidth, nHeight, ( D3DFORMAT )Format, (D3DMULTISAMPLE_TYPE) MultiSampleType, 0,
TRUE, &pSurface, NULL );
if( hr == E_OUTOFMEMORY ) {
#ifdef PRE_FIX_CLIENT_MEMOPTIMIZE
if( CheckFlushWaitDelete() ) {
return CreateDepthStencil( nWidth, nHeight, Format, MultiSampleType );
}
else {
m_szLastErrorMsg = "CreateDepthStencil";
OnOutOfMemory();
return NULL;
}
#else
if( CEtResource::IsEmptyWaitDelete() ) {
m_szLastErrorMsg = "CreateDepthStencil";
OnOutOfMemory();
return NULL;
}
else {
CEtResource::FlushWaitDelete();
return CreateDepthStencil( nWidth, nHeight, Format, MultiSampleType );
}
#endif
}
ADD_D3D_RES( pSurface );
return pSurface;
}
EtBaseTexture *CEtDevice::LoadTextureFromMemory( char *pSource, int nSrcSize, bool bPow2, UINT nWidth, UINT nHeight, int nMipLevel )
{
LPDIRECT3DTEXTURE9 pTexture = NULL;
if( nWidth == 0 && nHeight == 0 )
{
if( bPow2 )
{
nWidth = D3DX_DEFAULT;
nHeight = D3DX_DEFAULT;
}
else
{
nWidth = D3DX_DEFAULT_NONPOW2;
nHeight = D3DX_DEFAULT_NONPOW2;
}
}
ScopeLock< CSyncLock > Lock( m_DeviceLock );
HRESULT hr = D3DXCreateTextureFromFileInMemoryEx( m_pDevice, pSource, nSrcSize, nWidth, nHeight, nMipLevel, 0,
D3DFMT_UNKNOWN, D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, g_dwTextureColorKey, NULL, NULL, &pTexture );
if( hr == E_OUTOFMEMORY ) {
#ifdef PRE_FIX_CLIENT_MEMOPTIMIZE
if( CheckFlushWaitDelete() ) {
return LoadTextureFromMemory( pSource, nSrcSize, bPow2 );
}
else {
m_szLastErrorMsg = "LoadTextureFromMemory";
OnOutOfMemory();
return NULL;
}
#else
if( CEtResource::IsEmptyWaitDelete() ) {
m_szLastErrorMsg = "LoadTextureFromMemory";
OnOutOfMemory();
return NULL;
}
else {
CEtResource::FlushWaitDelete();
return LoadTextureFromMemory( pSource, nSrcSize, bPow2 );
}
#endif
}
ADD_D3D_RES( pTexture );
return pTexture;
}
EtBaseTexture *CEtDevice::LoadVolumeTextureFromMemory( char *pSource, int nSrcSize, bool bPow2, UINT nWidth, UINT nHeight )
{
LPDIRECT3DVOLUMETEXTURE9 pTexture = NULL;
if( nWidth == 0 && nHeight == 0 )
{
if( bPow2 )
{
nWidth = D3DX_DEFAULT;
nHeight = D3DX_DEFAULT;
}
else
{
nWidth = D3DX_DEFAULT_NONPOW2;
nHeight = D3DX_DEFAULT_NONPOW2;
}
}
ScopeLock< CSyncLock > Lock( m_DeviceLock );
HRESULT hr = D3DXCreateVolumeTextureFromFileInMemoryEx( m_pDevice, pSource, nSrcSize, nWidth, nHeight, D3DX_DEFAULT,
1, 0, D3DFMT_UNKNOWN, D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, g_dwTextureColorKey, NULL, NULL, &pTexture );
if( hr == E_OUTOFMEMORY ) {
#ifdef PRE_FIX_CLIENT_MEMOPTIMIZE
if( CheckFlushWaitDelete() ) {
return LoadVolumeTextureFromMemory( pSource, nSrcSize, bPow2 );
}
else {
m_szLastErrorMsg = "LoadVolumeTextureFromMemory";
OnOutOfMemory();
return NULL;
}
#else
if( CEtResource::IsEmptyWaitDelete() ) {
m_szLastErrorMsg = "LoadVolumeTextureFromMemory";
OnOutOfMemory();
return NULL;
}
else {
CEtResource::FlushWaitDelete();
return LoadVolumeTextureFromMemory( pSource, nSrcSize, bPow2 );
}
#endif
}
ADD_D3D_RES( pTexture );
return pTexture;
}
EtBaseTexture *CEtDevice::LoadCubeTextureFromMemory( char *pSource, int nSrcSize, bool bPow2, UINT nWidth, UINT nHeight )
{
LPDIRECT3DCUBETEXTURE9 pTexture = NULL;
if( nWidth == 0 && nHeight == 0 )
{
if( bPow2 )
{
nWidth = D3DX_DEFAULT;
nHeight = D3DX_DEFAULT;
}
else
{
nWidth = D3DX_DEFAULT_NONPOW2;
nHeight = D3DX_DEFAULT_NONPOW2;
}
}
ScopeLock< CSyncLock > Lock( m_DeviceLock );
HRESULT hr = D3DXCreateCubeTextureFromFileInMemoryEx( m_pDevice, pSource, nSrcSize, nWidth, nHeight, 0, D3DFMT_UNKNOWN,
D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, g_dwTextureColorKey, NULL, NULL, &pTexture );
if( hr == E_OUTOFMEMORY ) {
#ifdef PRE_FIX_CLIENT_MEMOPTIMIZE
if( CheckFlushWaitDelete() ) {
return LoadCubeTextureFromMemory( pSource, nSrcSize, bPow2 );
}
else {
m_szLastErrorMsg = "LoadCubeTextureFromMemory";
OnOutOfMemory();
return NULL;
}
#else
if( CEtResource::IsEmptyWaitDelete() ) {
m_szLastErrorMsg = "LoadCubeTextureFromMemory";
OnOutOfMemory();
return NULL;
}
else {
CEtResource::FlushWaitDelete();
return LoadCubeTextureFromMemory( pSource, nSrcSize, bPow2 );
}
#endif
}
ADD_D3D_RES( pTexture );
return pTexture;
}
EtBaseTexture *CEtDevice::LoadTextureFromFile( const char *pFileName, bool bPow2 )
{
LPDIRECT3DTEXTURE9 pTexture = NULL;
UINT nSize;
if( bPow2 )
{
nSize = D3DX_DEFAULT;
}
else
{
nSize = D3DX_DEFAULT_NONPOW2;
}
ScopeLock< CSyncLock > Lock( m_DeviceLock );
HRESULT hr = D3DXCreateTextureFromFileEx( m_pDevice, pFileName, nSize, nSize, nSize, 0, D3DFMT_UNKNOWN,
D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, g_dwTextureColorKey, NULL, NULL, &pTexture );
if( hr == E_OUTOFMEMORY ) {
#ifdef PRE_FIX_CLIENT_MEMOPTIMIZE
if( CheckFlushWaitDelete() ) {
return LoadTextureFromFile( pFileName, bPow2 );
}
else {
m_szLastErrorMsg = "LoadTextureFromFile";
OnOutOfMemory();
return NULL;
}
#else
if( CEtResource::IsEmptyWaitDelete() ) {
m_szLastErrorMsg = "LoadTextureFromFile";
OnOutOfMemory();
return NULL;
}
else {
CEtResource::FlushWaitDelete();
return LoadTextureFromFile( pFileName, bPow2 );
}
#endif
}
ADD_D3D_RES( pTexture );
return pTexture;
}
EtBaseTexture *CEtDevice::LoadVolumeTextureFromFile( const char *pFileName, bool bPow2 )
{
LPDIRECT3DVOLUMETEXTURE9 pTexture = NULL;
UINT nSize;
if( bPow2 )
{
nSize = D3DX_DEFAULT;
}
else
{
nSize = D3DX_DEFAULT_NONPOW2;
}
ScopeLock< CSyncLock > Lock( m_DeviceLock );
HRESULT hr = D3DXCreateVolumeTextureFromFileEx( m_pDevice, pFileName, nSize, nSize, D3DX_DEFAULT, 1, 0,
D3DFMT_UNKNOWN, D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, g_dwTextureColorKey, NULL, NULL, &pTexture );
if( hr == E_OUTOFMEMORY ) {
#ifdef PRE_FIX_CLIENT_MEMOPTIMIZE
if( CheckFlushWaitDelete() ) {
return LoadVolumeTextureFromFile( pFileName, bPow2 );
}
else {
m_szLastErrorMsg = "LoadVolumeTextureFromFile";
OnOutOfMemory();
return NULL;
}
#else
if( CEtResource::IsEmptyWaitDelete() ) {
m_szLastErrorMsg = "LoadVolumeTextureFromFile";
OnOutOfMemory();
return NULL;
}
else {
CEtResource::FlushWaitDelete();
return LoadVolumeTextureFromFile( pFileName, bPow2 );
}
#endif
}
ADD_D3D_RES( pTexture );
return pTexture;
}
EtBaseTexture *CEtDevice::LoadCubeTextureFromFile( const char *pFileName, bool bPow2 )
{
LPDIRECT3DCUBETEXTURE9 pTexture = NULL;
UINT nSize;
if( bPow2 )
{
nSize = D3DX_DEFAULT;
}
else
{
nSize = D3DX_DEFAULT_NONPOW2;
}
ScopeLock< CSyncLock > Lock( m_DeviceLock );
HRESULT hr = D3DXCreateCubeTextureFromFileEx( m_pDevice, pFileName, nSize, nSize, 0, D3DFMT_UNKNOWN, D3DPOOL_MANAGED,
D3DX_DEFAULT, D3DX_DEFAULT, g_dwTextureColorKey, NULL, NULL, &pTexture );
if( hr == E_OUTOFMEMORY ) {
#ifdef PRE_FIX_CLIENT_MEMOPTIMIZE
if( CheckFlushWaitDelete() ) {
return LoadCubeTextureFromFile( pFileName, bPow2 );
}
else {
m_szLastErrorMsg = "LoadCubeTextureFromFile";
OnOutOfMemory();
return NULL;
}
#else
if( CEtResource::IsEmptyWaitDelete() ) {
m_szLastErrorMsg = "LoadCubeTextureFromFile";
OnOutOfMemory();
return NULL;
}
else {
CEtResource::FlushWaitDelete();
return LoadCubeTextureFromFile( pFileName, bPow2 );
}
#endif
}
ADD_D3D_RES( pTexture );
return pTexture;
}
void CEtDevice::SetTexture( int nSampler, EtBaseTexture *pTexture )
{
if( GetEtStateManager()->IsEnable() ) {
GetEtStateManager()->SetTexture( nSampler, pTexture );
}
else {
ScopeLock< CSyncLock > Lock( m_DeviceLock );
m_pDevice->SetTexture( nSampler, pTexture );
}
}
void CEtDevice::ClearEffectMacro()
{
D3DXMACRO Macro;
int i;
for( i = 0; i < ( int )m_EffectMacroString.size(); i++ )
{
if( m_EffectMacroString[ i ] )
{
delete [] m_EffectMacroString[ i ];
}
}
m_EffectMacroString.clear();
m_EffectMacro.clear();
memset( &Macro, 0, sizeof( D3DXMACRO ) );
m_EffectMacro.push_back( Macro );
}
void CEtDevice::AddEffectMacro( char *szName, char *szDefinition )
{
D3DXMACRO Macro;
char *pString;
pString = new char[ strlen( szName ) + 1 ];
strcpy( pString, szName );
m_EffectMacroString.push_back( pString );
Macro.Name = pString;
pString = new char[ strlen( szDefinition ) + 1 ];
strcpy( pString, szDefinition );
m_EffectMacroString.push_back( pString );
Macro.Definition = pString;
m_EffectMacro[ m_EffectMacro.size() - 1 ] = Macro;
memset( &Macro, 0, sizeof( D3DXMACRO ) );
m_EffectMacro.push_back( Macro );
}
#ifdef PRE_CRASH_CHECK_BACKUP
float g_fMemoryPercent;
#endif
EtEffect *CEtDevice::LoadEffectFromMemory( char *pSource, int nSrcSize, void *pSharedEffectPool, ID3DXInclude *pInclude )
{
EtEffect *pEffect = NULL;
DWORD dwFlags = 0;//D3DXFX_LARGEADDRESSAWARE;
LPD3DXBUFFER pCompileError = NULL;
#ifdef PRE_CRASH_CHECK_BACKUP
g_fMemoryPercent = GetMemoryUsePercent();
#endif
ScopeLock< CSyncLock > Lock( m_DeviceLock );
D3DXCreateEffect( m_pDevice, pSource, nSrcSize, &m_EffectMacro[ 0 ], pInclude, dwFlags, ( LPD3DXEFFECTPOOL )pSharedEffectPool, &pEffect, &pCompileError );
if( pCompileError ) {
OutputDebug("%s\n", pCompileError->GetBufferPointer());
}
ADD_D3D_RES( pEffect );
return pEffect;
}
EtEffect *CEtDevice::LoadEffectFromFile( const char *pFileName, void *pSharedEffectPool )
{
EtEffect *pEffect = NULL;
DWORD dwFlags;
dwFlags = 0;
if( m_bShaderDebug )
{
dwFlags |= D3DXSHADER_DEBUG;
dwFlags |= D3DXSHADER_SKIPOPTIMIZATION;
dwFlags |= D3DXSHADER_FORCE_VS_SOFTWARE_NOOPT;
}
char szPath[ _MAX_PATH ], szCurDir[ _MAX_PATH ];
GetCurrentDirectory( _MAX_PATH, szCurDir );
_GetPath( szPath, _countof(szPath), pFileName );
_chdir( szPath );
LPD3DXBUFFER pCompileError = NULL;
ScopeLock< CSyncLock > Lock( m_DeviceLock );
D3DXCreateEffectFromFile( m_pDevice, pFileName, &m_EffectMacro[ 0 ], NULL, dwFlags, ( LPD3DXEFFECTPOOL )pSharedEffectPool, &pEffect, &pCompileError );
if( pCompileError ) {
OutputDebug("%s\n", pCompileError->GetBufferPointer());
}
SetCurrentDirectory( szCurDir );
ADD_D3D_RES( pEffect );
return pEffect;
}
void* CEtDevice::CreateFont( const char *pFontName )
{
ID3DXFont *pFont = NULL;
ScopeLock< CSyncLock > Lock( m_DeviceLock );
D3DXCreateFont( m_pDevice, 12, 0, 0, 1, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, DEFAULT_QUALITY,
DEFAULT_PITCH | FF_DONTCARE, pFontName, &pFont ) ;
ADD_D3D_RES( pFont );
return pFont;
}
void* CEtDevice::CreateSystemFont( const char *pFontName )
{
CEtSystemFont *pFont = CEtSystemFont::Create( 12 , pFontName );
return pFont;
}
void *CEtDevice::CreateSprite()
{
ID3DXSprite *pSprite = NULL;
ScopeLock< CSyncLock > Lock( m_DeviceLock );
D3DXCreateSprite( m_pDevice, &pSprite );
ADD_D3D_RES( pSprite );
return pSprite;
}
void CEtDevice::SetCullMode( CullMode Mode )
{
SetRenderState( D3DRS_CULLMODE, Mode );
}
void CEtDevice::SetWireframe( bool bEnable )
{
SetRenderState( D3DRS_FILLMODE, bEnable ? D3DFILL_WIREFRAME : D3DFILL_SOLID );
}
bool CEtDevice::EnableAlphaBlend( bool bEnable )
{
DWORD dwValue;
bool bRet = false;
GetRenderState( D3DRS_ALPHABLENDENABLE, &dwValue );
if( dwValue )
{
bRet = true;
}
SetRenderState( D3DRS_ALPHABLENDENABLE, bEnable );
if( bEnable )
{
SetRenderState( D3DRS_ALPHAREF, 0x0 );
SetRenderState( D3DRS_BLENDOP, D3DBLENDOP_ADD );
SetRenderState( D3DRS_SRCBLEND, D3DBLEND_SRCALPHA );
SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA );
}
else
{
SetRenderState( D3DRS_ALPHAREF, ALPHA_TEST_VALUE );
}
return bRet;
}
bool CEtDevice::EnableAlphaTest( bool bEnable )
{
DWORD dwValue;
bool bRet = false;
GetRenderState( D3DRS_ALPHATESTENABLE, &dwValue );
if( dwValue )
{
bRet = true;
}
SetRenderState( D3DRS_ALPHATESTENABLE, bEnable );
return bRet;
}
bool CEtDevice::IsEnableAlphaTest()
{
DWORD dwValue;
GetRenderState( D3DRS_ALPHATESTENABLE, &dwValue );
return dwValue != FALSE;
}
DWORD CEtDevice::SetAlphaRef( DWORD dwAlphaRef )
{
DWORD dwRet = GetAlphaRef();
SetRenderState( D3DRS_ALPHAREF, dwAlphaRef );
return dwRet;
}
DWORD CEtDevice::GetAlphaRef()
{
DWORD dwAlphaRef;
GetRenderState( D3DRS_ALPHAREF, &dwAlphaRef );
return dwAlphaRef;
}
bool CEtDevice::IsEnableAlphaBlend()
{
DWORD dwValue;
GetRenderState( D3DRS_ALPHABLENDENABLE, &dwValue );
return dwValue != FALSE;
}
bool CEtDevice::EnableZ( bool bEnable )
{
DWORD bRet = TRUE;
GetRenderState( D3DRS_ZENABLE, &bRet );
SetRenderState( D3DRS_ZWRITEENABLE, bEnable );
SetRenderState( D3DRS_ZENABLE, bEnable ? D3DZB_TRUE : D3DZB_FALSE );
return (bRet != FALSE);
}
bool CEtDevice::EnableZTest( bool bZTest )
{
bool bRet = IsEnableZTest();
SetRenderState( D3DRS_ZENABLE, bZTest ? D3DZB_TRUE : D3DZB_FALSE );
return bRet;
}
bool CEtDevice::IsEnableZTest()
{
DWORD dwValue;
GetRenderState( D3DRS_ZENABLE, &dwValue );
if( dwValue )
{
return true;
}
else
{
return false;
}
}
float CEtDevice::SetDepthBias( float fBias )
{
float fRet;
GetRenderState( D3DRS_DEPTHBIAS, (DWORD*)&fRet );
SetRenderState( D3DRS_DEPTHBIAS, *(DWORD*)&fBias );
return fRet;
}
bool CEtDevice::EnableZWrite( bool bEnable )
{
bool bRet = IsEnableZWrite();
SetRenderState( D3DRS_ZWRITEENABLE, bEnable );
return bRet;
}
EtCmpFunc CEtDevice::SetZFunc( EtCmpFunc ZFunc )
{
DWORD dwRet;
GetRenderState( D3DRS_ZFUNC, &dwRet );
SetRenderState( D3DRS_ZFUNC, ZFunc );
return ( EtCmpFunc )dwRet;
}
bool CEtDevice::IsEnableZWrite()
{
DWORD dwValue;
GetRenderState( D3DRS_ZWRITEENABLE, &dwValue );
if( dwValue )
{
return true;
}
else
{
return false;
}
}
EtBlendOP CEtDevice::SetBlendOP( EtBlendOP BlendOP )
{
DWORD dwOldBlendOP;
GetRenderState( D3DRS_BLENDOP, &dwOldBlendOP );
SetRenderState( D3DRS_BLENDOP, BlendOP );
return ( EtBlendOP )dwOldBlendOP;
}
EtBlendMode CEtDevice::SetSrcBlend( EtBlendMode BlendMode )
{
DWORD dwOldBlend;
GetRenderState( D3DRS_SRCBLEND, &dwOldBlend );
SetRenderState( D3DRS_SRCBLEND, BlendMode );
return ( EtBlendMode )dwOldBlend;
}
EtBlendMode CEtDevice::SetDestBlend( EtBlendMode BlendMode )
{
DWORD dwOldBlend;
GetRenderState( D3DRS_DESTBLEND, &dwOldBlend );
SetRenderState( D3DRS_DESTBLEND, BlendMode );
return ( EtBlendMode )dwOldBlend;
}
void CEtDevice::SetWorldTransform( EtMatrix *pWorldMat )
{
ScopeLock< CSyncLock > Lock( m_DeviceLock );
m_pDevice->SetTransform( D3DTS_WORLD, pWorldMat );
}
void CEtDevice::SetViewTransform( EtMatrix *pViewMat )
{
ScopeLock< CSyncLock > Lock( m_DeviceLock );
m_pDevice->SetTransform( D3DTS_VIEW, pViewMat );
}
void CEtDevice::SetProjTransform( EtMatrix *pProjMat )
{
ScopeLock< CSyncLock > Lock( m_DeviceLock );
m_pDevice->SetTransform( D3DTS_PROJECTION, pProjMat );
}
void CEtDevice::GetFVF( DWORD *dwFVF )
{
ScopeLock< CSyncLock > Lock( m_DeviceLock );
m_pDevice->GetFVF( dwFVF );
}
void CEtDevice::SetFVF( DWORD dwFVF )
{
ScopeLock< CSyncLock > Lock( m_DeviceLock );
m_pDevice->SetFVF( dwFVF );
}
void CEtDevice::SetVertexShader( LPDIRECT3DVERTEXSHADER9 pShader )
{
if( GetEtStateManager()->IsEnable() ) {
GetEtStateManager()->SetVertexShader( (LPDIRECT3DVERTEXSHADER9)pShader );
}
else {
ScopeLock< CSyncLock > Lock( m_DeviceLock );
m_pDevice->SetVertexShader( pShader );
}
}
void CEtDevice::SetPixelShader( LPDIRECT3DPIXELSHADER9 pShader )
{
if( GetEtStateManager()->IsEnable() ) {
GetEtStateManager()->SetPixelShader( (LPDIRECT3DPIXELSHADER9)pShader );
}
else {
ScopeLock< CSyncLock > Lock( m_DeviceLock );
m_pDevice->SetPixelShader( pShader );
}
}
//void CEtDevice::EnableLight( bool bEnable )
//{
// SetRenderState( D3DRS_LIGHTING, bEnable );
//}
void CEtDevice::SetCursorProperties( EtSurface *pSurface, UINT nXHotSpot, UINT nYHotSpot )
{
ScopeLock< CSyncLock > Lock( m_DeviceLock );
m_pDevice->SetCursorProperties( nXHotSpot, nYHotSpot, pSurface );
}
void CEtDevice::ShowCursor( bool bShow )
{
ScopeLock< CSyncLock > Lock( m_DeviceLock );
m_pDevice->ShowCursor( bShow );
}
void CEtDevice::SetCursorPos( int nX, int nY )
{
ScopeLock< CSyncLock > Lock( m_DeviceLock );
m_pDevice->SetCursorPosition( nX, nY, D3DCURSOR_IMMEDIATE_UPDATE );
}
void CEtDevice::SetGammaRamp( float fGamma, int nBright )
{
if( !m_pDevice ) return;
int i;
D3DGAMMARAMP GammaRamp;
ScopeLock< CSyncLock > Lock( m_DeviceLock );
m_pDevice->GetGammaRamp( 0, &GammaRamp );
for ( i = 0; i < 256; i++ )
{
float fValue = ( float )( 255 * pow( ( float ) i / 256, 1 / fGamma ) ) + nBright;
if( fValue < 0 )
{
fValue = 0;
}
if( fValue > 255 )
{
fValue = 255;
}
GammaRamp.red[ i ] = ( ( WORD )fValue ) << 8;
GammaRamp.green[ i ] = GammaRamp.red[ i ];
GammaRamp.blue[ i ] = GammaRamp.red[ i ];
}
m_pDevice->SetGammaRamp( 0, D3DSGR_CALIBRATE, &GammaRamp );
}
#ifdef PRE_MOD_MEMORY_CHECK
void CEtDevice::CheckTotalLocalVideoMemory()
{
ScopeLock<CSyncLock> Lock(m_DeviceLostLock);
// DDraw GetAvailableVidMem <20>Լ<EFBFBD><D4BC><EFBFBD> <20><EFBFBD><E1BAB8>,
// D3D GetAvailableTextureMem <20>Լ<EFBFBD><D4BC><EFBFBD> <20><EFBFBD><E1BAB8>,
// Windows WMI<4D><49><EFBFBD><EFBFBD> <20><><EFBFBD>ϴ<EFBFBD> <20>͵<EFBFBD> <20>غôµ<C3B4>,
// <20><><EFBFBD><EFBFBD> <20><>Ȯ<EFBFBD>Ѱ<EFBFBD>, <20><>Ż<EFBFBD><C5BB> DDraw<61><77> <20><><EFBFBD>ϰ<EFBFBD>, <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EBB7AE> D3D<33><44> üũ<C3BC>ϴ°Ŵ<C2B0>.
// WMI<4D><49> AvailMemory<72><79> <20>ƴ϶<C6B4>, <20><>¥ <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ī<EFBFBD><C4AB> <20>޸𸮸<DEB8> <20><><EFBFBD><EFBFBD><EFBFBD>ؼ<EFBFBD>, <20>Դٰ<D4B4> <20>Ϻ<EFBFBD> <20>Ŀ<EFBFBD><C4BF><EFBFBD><EFBFBD><EFBFBD> <20>ȸԾ <20>Ⱦ<EFBFBD><C8BE><EFBFBD><EFBFBD><EFBFBD> <20>Ѵ<EFBFBD>.
if( m_pDD != NULL )
{
DDSCAPS2 ddsCaps2;
DWORD dwTotal, dwFree;
memset( &ddsCaps2, 0, sizeof( DDSCAPS2 ) );
ddsCaps2.dwCaps = DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM;
if( m_pDD->GetAvailableVidMem( &ddsCaps2, &dwTotal, &dwFree ) == DD_OK )
m_dwLocalVideoMemory = dwTotal;
}
if( m_pDevice )
{
m_dwTotalAvailTextureMemory = m_pDevice->GetAvailableTextureMem();
}
m_dwMaxLocalVideoMemory = m_dwLocalVideoMemory / 1024 / 1024;
}
#endif
float CEtDevice::GetMemoryUsePercent()
{
ScopeLock<CSyncLock> Lock(m_DeviceLostLock);
#ifdef PRE_MOD_MEMORY_CHECK
m_dwUsingLocalVideoMemory = (m_dwTotalAvailTextureMemory - m_pDevice->GetAvailableTextureMem()) / 1024 / 1024;
return (m_dwTotalAvailTextureMemory - m_pDevice->GetAvailableTextureMem() ) / ( float )m_dwLocalVideoMemory;
#else
if( m_bUseDDrawMemCheck ) {
if( m_pDD == NULL ) {
return 0.0f;
}
DDSCAPS2 ddsCaps2;
DWORD dwTotal, dwFree;
memset( &ddsCaps2, 0, sizeof( DDSCAPS2 ) );
ddsCaps2.dwCaps = DDSCAPS_VIDEOMEMORY | DDSCAPS_LOCALVIDMEM;
m_pDD->GetAvailableVidMem( &ddsCaps2, &dwTotal, &dwFree );
if( dwTotal == 0 ) {
return 0.0f;
}
return ( dwTotal - dwFree ) / ( float )dwTotal;
}
else {
if( m_pDevice == NULL ) {
return 0.0f;
}
return (m_dwTotalAvailTextureMemory - m_pDevice->GetAvailableTextureMem() ) / ( float )m_dwTotalAvailTextureMemory ;
}
#endif
}
bool CEtDevice::CheckDeviceFormat( EtFormat CheckFormat, EtUsage Usage )
{
if( FAILED( m_pD3D->CheckDeviceFormat( m_nAdapter, m_DevType, m_AdapterFormat, Usage, D3DRTYPE_SURFACE, ( D3DFORMAT )CheckFormat ) ) )
{
return false;
}
return true;
}
void CEtDevice::SetClipCursor( bool bClip )
{
#if !defined(_DEBUG) && !defined(_RDEBUG) // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ÿ<EFBFBD><C3BF><EFBFBD> <20>ʿ<EFBFBD><CABF><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>Ƿ<EFBFBD> Ŭ<><C5AC> <20><><EFBFBD><EFBFBD>
if( bClip ) {
RECT rcWindow;
::GetWindowRect( m_hWnd, &rcWindow );
::ClipCursor( &rcWindow );
}
else {
::ClipCursor( NULL );
}
#endif
}
void CEtDevice::OnOutOfMemory()
{
if( m_pOutOfMemoryCallBack ) {
m_bCallOutOfMemory = true;
m_pOutOfMemoryCallBack->Run();
}
}
void CEtDevice::ShowFrame( RECT *pTargetRect )
{
if( m_pPrePresentCallback ) m_pPrePresentCallback();
ScopeLock< CSyncLock > Lock( m_DeviceLock );
m_pDevice->Present( NULL, pTargetRect, NULL, NULL );
m_nPolyCountPerFrame = m_nCurrentPolyCount;
m_nCurrentPolyCount = 0;
}
void CEtDevice::GetRenderState( D3DRENDERSTATETYPE State, DWORD *pdwValue )
{
GetEtStateManager()->GetRenderStateDefered( State, pdwValue);
}
void CEtDevice::SetRenderState( D3DRENDERSTATETYPE State, DWORD dwValue )
{
GetEtStateManager()->SetRenderStateDefered( State, dwValue);
}
void CEtDevice::GetSamplerState( DWORD Sampler, D3DSAMPLERSTATETYPE State, DWORD *pdwValue )
{
GetEtStateManager()->GetSamplerStateDefered( Sampler, State, pdwValue);
}
void CEtDevice::SetSamplerState( DWORD Sampler, D3DSAMPLERSTATETYPE State, DWORD Value )
{
GetEtStateManager()->SetSamplerStateDefered( Sampler, State, Value);
}
void CEtDevice::GetTextureStageState( DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD* pValue)
{
GetEtStateManager()->GetTextureStageStateDefered( Stage, Type, pValue);
}
void CEtDevice::SetTextureStageState( DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD Value)
{
GetEtStateManager()->SetTextureStageStateDefered( Stage, Type, Value);
}
DWORD CEtDevice::SetColorWriteEnable( DWORD dwEnable )
{
DWORD dwCur;
GetRenderState( D3DRS_COLORWRITEENABLE, &dwCur );
SetRenderState( D3DRS_COLORWRITEENABLE, dwEnable );
return dwCur;
}
void CEtDevice::DrawPrimitive( PrimitiveType nPrimitiveType, int nStartVertex, int nPrimitiveCount )
{
GetEtStateManager()->FlushDeferedStates();
ScopeLock< CSyncLock > Lock( m_DeviceLock );
m_pDevice->DrawPrimitive( ( D3DPRIMITIVETYPE )nPrimitiveType, nStartVertex, nPrimitiveCount );
m_nCurrentPolyCount += nPrimitiveCount;
}
void CEtDevice::DrawIndexedPrimitive( PrimitiveType nPrimitiveType, int nStartVertex, int nVertexCount, int nStartIndex, int nPrimitiveCount )
{
GetEtStateManager()->FlushDeferedStates();
ScopeLock< CSyncLock > Lock( m_DeviceLock );
m_pDevice->DrawIndexedPrimitive( ( D3DPRIMITIVETYPE )nPrimitiveType, nStartVertex, 0, nVertexCount, nStartIndex, nPrimitiveCount );
m_nCurrentPolyCount += nPrimitiveCount;
}
void CEtDevice::DrawPrimitiveUP( PrimitiveType nPrimitiveType, int nPrimitiveCount, void *pVertexData, int nStride )
{
GetEtStateManager()->FlushDeferedStates();
ScopeLock< CSyncLock > Lock( m_DeviceLock );
m_pDevice->DrawPrimitiveUP( ( D3DPRIMITIVETYPE )nPrimitiveType, nPrimitiveCount, pVertexData, nStride );
m_nCurrentPolyCount += nPrimitiveCount;
}
void CEtDevice::DrawIndexedPrimitiveUP( PrimitiveType nPrimitiveType, int nMinVertexIndex, int nNumVertices, int nPrimitiveCount, void *pIndexData, EtFormat IndexDataFormat, void *pVertexData, int nStride )
{
GetEtStateManager()->FlushDeferedStates();
ScopeLock< CSyncLock > Lock( m_DeviceLock );
m_pDevice->DrawIndexedPrimitiveUP( ( D3DPRIMITIVETYPE )nPrimitiveType, nMinVertexIndex, nNumVertices, nPrimitiveCount, pIndexData, (D3DFORMAT)IndexDataFormat, pVertexData, nStride);
m_nCurrentPolyCount += nPrimitiveCount;
}