456 lines
14 KiB
C++
456 lines
14 KiB
C++
#include "StdAfx.h"
|
|
#include "EtDevice.h"
|
|
#include "EtStateManager.h"
|
|
|
|
#ifdef _DEBUG
|
|
#define new new(_NORMAL_BLOCK,__FILE__,__LINE__)
|
|
#endif
|
|
|
|
CEtStateBlockManager::CEtStateBlockManager() : m_pD3DDevice( NULL )
|
|
{
|
|
m_bEnable = true;
|
|
Reset();
|
|
}
|
|
|
|
CEtStateBlockManager::~CEtStateBlockManager()
|
|
{
|
|
}
|
|
|
|
void CEtStateBlockManager::Initialize( CEtDevice *pDevice )
|
|
{
|
|
m_pD3DDevice = (IDirect3DDevice9*)pDevice->GetDevicePtr();
|
|
}
|
|
|
|
int CEtStateBlockManager::CreateStateBlock( SStateBlock *StateBlock )
|
|
{
|
|
int i, nSize;
|
|
nSize = (int)m_stateBlocks.size();
|
|
for( i = 0; i < nSize; i++) {
|
|
if( m_stateBlocks[ i ] == *StateBlock ) {
|
|
return i;
|
|
}
|
|
}
|
|
m_stateBlocks.push_back( *StateBlock );
|
|
return (int)m_stateBlocks.size()-1;
|
|
|
|
}
|
|
|
|
//#define _DEBUG_VALID_STATE
|
|
void CEtStateBlockManager::SetDefaultState()
|
|
{
|
|
#if defined( _DEBUG_VALID_STATE )
|
|
DWORD dwVal;
|
|
for( int i = 1; i < RS_MAX; i++) {
|
|
if( i <= 6 ) continue;
|
|
if( i >= 10 && i <= 13 ) continue;
|
|
if( i == 17 || i == 18 || i == 21 || i == 30 || i == 31 || i == 32 || i == 33 || ( i >= 39 && i <= 47) || (i>=49&&i<=51) || ( i >= 61 && i <= 127) ) continue;
|
|
if( i == 138 || i == 149 || i == 150 || i == 153 || i == 164 || i == 169 || i == 177 || i == 197 || i == 198 ) continue;
|
|
m_pD3DDevice->GetRenderState( (D3DRENDERSTATETYPE)i, &dwVal);
|
|
SetRenderStateDefered( (D3DRENDERSTATETYPE)i, dwVal);
|
|
}
|
|
for( int j = 1; j < STAGE_MAX; j++) {
|
|
for( int i = 0; i < SS_MAX; i++) {
|
|
m_pD3DDevice->GetSamplerState( j, (D3DSAMPLERSTATETYPE)i, &dwVal);
|
|
SetSamplerStateDefered( j, (D3DSAMPLERSTATETYPE)i, dwVal);
|
|
}
|
|
for( int i = 1; i < TS_MAX; i++) {
|
|
if( (i >= 12 && i <= 21) || i == 25 || i == 29 || i == 30 || i == 31 ) continue;
|
|
m_pD3DDevice->GetTextureStageState( j, (D3DTEXTURESTAGESTATETYPE)i, &dwVal);
|
|
SetTextureStageStateDefered( j, (D3DTEXTURESTAGESTATETYPE)i, dwVal);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
SetRenderStateDefered( D3DRS_ZENABLE, D3DZB_TRUE );
|
|
SetRenderStateDefered( D3DRS_ZWRITEENABLE, TRUE );
|
|
SetRenderStateDefered( D3DRS_CULLMODE, D3DCULL_CCW );
|
|
SetRenderStateDefered( D3DRS_ALPHABLENDENABLE, FALSE );
|
|
SetRenderStateDefered( D3DRS_ALPHAREF, ALPHA_TEST_VALUE );
|
|
SetRenderStateDefered( D3DRS_ALPHATESTENABLE, TRUE );
|
|
SetRenderStateDefered( D3DRS_SCISSORTESTENABLE, FALSE);
|
|
|
|
SetRenderStateDefered( D3DRS_LIGHTING, FALSE );
|
|
SetRenderStateDefered( D3DRS_COLORWRITEENABLE, 0xf );
|
|
SetRenderStateDefered( D3DRS_ZFUNC, D3DCMP_LESSEQUAL );
|
|
SetRenderStateDefered( D3DRS_DEPTHBIAS, 0 );
|
|
|
|
SetRenderStateDefered( D3DRS_ALPHAFUNC, D3DCMP_GREATER );
|
|
|
|
SetRenderStateDefered( D3DRS_SRCBLEND, D3DBLEND_SRCALPHA );
|
|
SetRenderStateDefered( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA );
|
|
SetRenderStateDefered( D3DRS_BLENDOP, D3DBLENDOP_ADD );
|
|
|
|
// State For Sprite
|
|
GetEtDevice()->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );
|
|
GetEtDevice()->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE );
|
|
GetEtDevice()->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE );
|
|
GetEtDevice()->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
|
|
GetEtDevice()->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
|
|
GetEtDevice()->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE );
|
|
|
|
GetEtDevice()->SetSamplerState( 0, D3DSAMP_MAXANISOTROPY, 1 );
|
|
|
|
for( int i = 0; i < STAGE_MAX; i++) {
|
|
SetSamplerStateDefered( i, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR );
|
|
SetSamplerStateDefered( i, D3DSAMP_MINFILTER, D3DTEXF_LINEAR );
|
|
SetSamplerStateDefered( i, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR );
|
|
|
|
SetSamplerStateDefered( i, D3DSAMP_ADDRESSU, D3DTADDRESS_WRAP );
|
|
SetSamplerStateDefered( i, D3DSAMP_ADDRESSV, D3DTADDRESS_WRAP );
|
|
}
|
|
}
|
|
|
|
void CEtStateBlockManager::Reset()
|
|
{
|
|
for( int i = 0; i < RS_MAX; i++) {
|
|
m_RenderState[ 0 ][ i ] = RESET_MAGIC_NUMBER;
|
|
m_RenderState[ 1 ][ i ] = RESET_MAGIC_NUMBER;
|
|
m_RenderState[ 2 ][ i ] = RESET_MAGIC_NUMBER;
|
|
m_RenderState[ 3 ][ i ] = RESET_MAGIC_NUMBER;
|
|
}
|
|
|
|
for( int j = 0; j < STAGE_MAX; j++)
|
|
{
|
|
for( int i = 0; i < SS_MAX; i++) {
|
|
m_SamplerState[ 0 ][ j ][ i ] = RESET_MAGIC_NUMBER;
|
|
m_SamplerState[ 1 ][ j ][ i ] = RESET_MAGIC_NUMBER;
|
|
m_SamplerState[ 2 ][ j ][ i ] = RESET_MAGIC_NUMBER;
|
|
m_SamplerState[ 3 ][ j ][ i ] = RESET_MAGIC_NUMBER;
|
|
}
|
|
for( int i = 0; i < TS_MAX; i++) {
|
|
m_TextureStageState[ 0 ][ j ][ i ] = RESET_MAGIC_NUMBER;
|
|
m_TextureStageState[ 1 ][ j ][ i ] = RESET_MAGIC_NUMBER;
|
|
m_TextureStageState[ 2 ][ j ][ i ] = RESET_MAGIC_NUMBER;
|
|
m_TextureStageState[ 3 ][ j ][ i ] = RESET_MAGIC_NUMBER;
|
|
}
|
|
}
|
|
|
|
for( int i = 0; i < RS_MAX; i++) {
|
|
m_DirtyRenderFlag[ i ] = false;
|
|
}
|
|
for( int j = 0; j < STAGE_MAX; j++) {
|
|
for( int i = 0; i < SS_MAX; i++) {
|
|
m_DirtySamplerFlag[ j ][ i ] = false;
|
|
}
|
|
for( int i = 0; i < TS_MAX; i++) {
|
|
m_DirtyTextureStageFlag[ j ][ i ] = false;
|
|
}
|
|
}
|
|
|
|
m_nDirtyRenderCount = 0;
|
|
for( int i = 0; i < STAGE_MAX; i++) {
|
|
m_DirtySamplerCount[ i ] = 0;
|
|
m_DirtyTextureStageCount[ i ] = 0;
|
|
m_currTexture[ i ] = NULL;
|
|
}
|
|
|
|
m_currPixelShader = NULL;
|
|
m_currVertexShader = NULL;
|
|
|
|
#if defined( _CHECK_STATE_PERFORMANCE )
|
|
m_nStateSkip = 0;
|
|
m_nStateTotal = 0;
|
|
|
|
m_nShaderSkip = 0;
|
|
m_nShaderTotal = 0;
|
|
|
|
m_nTextureSkip = 0;
|
|
m_nTextureTotal = 0;
|
|
#endif
|
|
}
|
|
|
|
void CEtStateBlockManager::GetRenderStateDefered( D3DRENDERSTATETYPE State, DWORD *pdwValue )
|
|
{
|
|
if( m_bEnable ) {
|
|
ASSERT( m_RenderState[ 0 ][ State ] != RESET_MAGIC_NUMBER );
|
|
*pdwValue = m_RenderState[ 0 ][ State ];
|
|
}
|
|
else {
|
|
m_pD3DDevice->GetRenderState( State, pdwValue );
|
|
}
|
|
}
|
|
|
|
void CEtStateBlockManager::SetRenderStateDefered( D3DRENDERSTATETYPE State, DWORD dwValue )
|
|
{
|
|
if( m_bEnable ) {
|
|
|
|
ASSERT( m_nDirtyRenderCount < DIRTY_MAX );
|
|
if( m_nDirtyRenderCount >= DIRTY_MAX ) {
|
|
return;
|
|
}
|
|
|
|
if( m_DirtyRenderFlag[ State ] == false ) {
|
|
m_DirtyRenderFlag[ State ] = true;
|
|
m_DirtyRenderState[ m_nDirtyRenderCount++ ] = State;
|
|
}
|
|
m_RenderState[ 0 ][ State ] = dwValue;
|
|
}
|
|
else {
|
|
m_pD3DDevice->SetRenderState( State, dwValue );
|
|
}
|
|
}
|
|
|
|
void CEtStateBlockManager::GetSamplerStateDefered( DWORD Sampler, D3DSAMPLERSTATETYPE State, DWORD *pdwValue )
|
|
{
|
|
if( m_bEnable ) {
|
|
//ASSERT( Sampler <= 5 );
|
|
//ASSERT( m_SamplerState[ 0 ][ Sampler ][ State ] != RESET_MAGIC_NUMBER );
|
|
*pdwValue = m_SamplerState[ 0 ][ Sampler ][ State ];
|
|
}
|
|
else {
|
|
m_pD3DDevice->GetSamplerState( Sampler, State, pdwValue );
|
|
}
|
|
}
|
|
|
|
void CEtStateBlockManager::SetSamplerStateDefered( DWORD Sampler, D3DSAMPLERSTATETYPE State, DWORD Value )
|
|
{
|
|
if( m_bEnable )
|
|
{
|
|
if( Sampler >= STAGE_MAX || m_DirtySamplerCount[ Sampler ] >= DIRTY_MAX )
|
|
{
|
|
ASSERT( Sampler < STAGE_MAX );
|
|
ASSERT( m_DirtySamplerCount[ Sampler ] < DIRTY_MAX );
|
|
return;
|
|
}
|
|
|
|
if( m_DirtySamplerFlag[ Sampler ][ State ] == false ) {
|
|
m_DirtySamplerFlag[ Sampler ][ State ] = true;
|
|
m_DirtySamplerState[ Sampler ][ m_DirtySamplerCount[ Sampler ]++ ] = State;
|
|
}
|
|
m_SamplerState[ 0 ][ Sampler ][ State ] = Value;
|
|
}
|
|
else {
|
|
m_pD3DDevice->SetSamplerState( Sampler, State, Value );
|
|
}
|
|
}
|
|
|
|
void CEtStateBlockManager::GetTextureStageStateDefered( DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD *pdwValue)
|
|
{
|
|
if( m_bEnable ) {
|
|
//ASSERT( Stage < STAGE_MAX );
|
|
//ASSERT( m_TextureStageState[ 0 ][ Stage ][ Type ] != RESET_MAGIC_NUMBER );
|
|
*pdwValue = m_TextureStageState[ 0 ][ Stage ][ Type ];
|
|
}
|
|
else {
|
|
m_pD3DDevice->GetTextureStageState( Stage, Type, pdwValue );
|
|
}
|
|
}
|
|
|
|
void CEtStateBlockManager::SetTextureStageStateDefered( DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD Value)
|
|
{
|
|
if( m_bEnable )
|
|
{
|
|
if( Stage >= STAGE_MAX || m_DirtyTextureStageCount[ Stage ] >= DIRTY_MAX )
|
|
{
|
|
ASSERT( Stage < STAGE_MAX );
|
|
ASSERT( m_DirtyTextureStageCount[ Stage ] < DIRTY_MAX );
|
|
return;
|
|
}
|
|
|
|
if( m_DirtyTextureStageFlag[ Stage ][ Type ] == false ) {
|
|
m_DirtyTextureStageFlag[ Stage ][ Type ] = true;
|
|
m_DirtyTextureStageState[ Stage ][ m_DirtyTextureStageCount[ Stage ]++ ] = Type;
|
|
}
|
|
m_TextureStageState[ 0 ][ Stage ][ Type ] = Value;
|
|
}
|
|
else {
|
|
m_pD3DDevice->SetTextureStageState( Stage, Type, Value );
|
|
}
|
|
}
|
|
|
|
void CEtStateBlockManager::FlushDeferedStates()
|
|
{
|
|
#if defined( _CHECK_STATE_PERFORMANCE )
|
|
static bool bPressPrev = false;
|
|
bool bPress = GetAsyncKeyState(VK_HOME)<0;
|
|
if( !bPressPrev && bPress ) {
|
|
SetEnable( !IsEnable() );
|
|
OutputDebug("RenderState Optimize %s\n", IsEnable() ? "Enable" : "Disable");
|
|
}
|
|
bPressPrev = bPress;
|
|
#endif
|
|
|
|
if( !m_bEnable ) {
|
|
return;
|
|
}
|
|
|
|
#if defined( _DEBUG_VALID_STATE )
|
|
for( int i = 1; i < RS_MAX; i++) {
|
|
if( m_RenderState[ 1 ][ i ] != RESET_MAGIC_NUMBER )
|
|
{
|
|
DWORD dwVal=0;
|
|
m_pD3DDevice->GetRenderState( (D3DRENDERSTATETYPE)i, &dwVal);
|
|
ASSERT( m_RenderState[ 1 ][ i ] == dwVal );
|
|
}
|
|
}
|
|
for( int j = 0; j < STAGE_MAX; j++) {
|
|
for( int i = 1; i < SS_MAX; i++) {
|
|
if( RESET_MAGIC_NUMBER != m_SamplerState[ 1 ][ j ][ i ] ) {
|
|
DWORD dwVal=0;
|
|
m_pD3DDevice->GetSamplerState( j, (D3DSAMPLERSTATETYPE)i, &dwVal);
|
|
ASSERT( m_SamplerState[ 1 ][ j ][ i ] == dwVal );
|
|
}
|
|
}
|
|
for( int i = 1; i < TS_MAX; i++) {
|
|
if( m_TextureStageState[ 1 ][ j ][ i ] != RESET_MAGIC_NUMBER ) {
|
|
DWORD dwVal=0;
|
|
m_pD3DDevice->GetTextureStageState( j, (D3DTEXTURESTAGESTATETYPE)i, &dwVal);
|
|
ASSERT( m_TextureStageState[ 1 ][ j ][ i ] == dwVal );
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
|
|
#if defined( _CHECK_STATE_PERFORMANCE )
|
|
m_nStateTotal += m_nDirtyRenderCount;
|
|
#endif
|
|
for( int i = 0; i < m_nDirtyRenderCount; i++) {
|
|
D3DRENDERSTATETYPE State = (D3DRENDERSTATETYPE)m_DirtyRenderState[ i ];
|
|
m_DirtyRenderFlag[ State ] = false;
|
|
|
|
if( m_RenderState[ 0 ][ State ] != m_RenderState[ 1 ][ State ] ) {
|
|
m_pD3DDevice->SetRenderState( State, m_RenderState[ 0 ][ State ] );
|
|
m_RenderState[ 1 ][ State ] = m_RenderState[ 0 ][ State ];
|
|
}
|
|
#if defined( _CHECK_STATE_PERFORMANCE )
|
|
else {
|
|
m_nStateSkip++;
|
|
}
|
|
#endif
|
|
}
|
|
m_nDirtyRenderCount = 0;
|
|
|
|
for( int j = 0; j < STAGE_MAX; j++) {
|
|
#if defined( _CHECK_STATE_PERFORMANCE )
|
|
m_nStateTotal += m_DirtySamplerCount[ j ];
|
|
m_nStateTotal += m_DirtyTextureStageCount[ j ];
|
|
#endif
|
|
for( int i = 0; i < m_DirtySamplerCount[ j ]; i++) {
|
|
D3DSAMPLERSTATETYPE State = (D3DSAMPLERSTATETYPE)m_DirtySamplerState[ j ][ i ];
|
|
m_DirtySamplerFlag[ j ][ State ] = false;
|
|
|
|
|
|
|
|
if( m_SamplerState[ 0 ][ j ][ State ] != m_SamplerState[ 1 ][ j ][ State ] ) {
|
|
m_pD3DDevice->SetSamplerState( j, State, m_SamplerState[ 0 ][ j ][ State ] );
|
|
m_SamplerState[ 1 ][ j ][ State ] = m_SamplerState[ 0 ][ j ][ State ];
|
|
}
|
|
#if defined( _CHECK_STATE_PERFORMANCE )
|
|
else {
|
|
m_nStateSkip++;
|
|
}
|
|
#endif
|
|
}
|
|
m_DirtySamplerCount[ j ] = 0;
|
|
for( int i = 0; i < m_DirtyTextureStageCount[ j ]; i++) {
|
|
D3DTEXTURESTAGESTATETYPE State = (D3DTEXTURESTAGESTATETYPE)m_DirtyTextureStageState[ j ][ i ];
|
|
m_DirtyTextureStageFlag[ j ][ State ] = false;
|
|
|
|
if( m_TextureStageState[ 0 ][ j ][ State ] != m_TextureStageState[ 1 ][ j ][ State ] ) {
|
|
m_pD3DDevice->SetTextureStageState( j, State, m_TextureStageState[ 0 ][ j ][ State ] );
|
|
m_TextureStageState[ 1 ][ j ][ State ] = m_TextureStageState[ 0 ][ j ][ State ];
|
|
}
|
|
#if defined( _CHECK_STATE_PERFORMANCE )
|
|
else {
|
|
m_nStateSkip++;
|
|
}
|
|
#endif
|
|
}
|
|
m_DirtyTextureStageCount[ j ] = 0;
|
|
}
|
|
}
|
|
|
|
void CEtStateBlockManager::Capture()
|
|
{
|
|
for( int i = 0; i < RS_MAX; i++) {
|
|
m_RenderState[ 2 ][ i ] = m_RenderState[ 0 ][ i ];
|
|
}
|
|
for( int j = 0; j < STAGE_MAX; j++) {
|
|
for( int i = 0; i < SS_MAX; i++) {
|
|
m_SamplerState[ 2 ][ j ][ i ] = m_SamplerState[ 0 ][ j ][ i ];
|
|
}
|
|
for( int i = 0; i < TS_MAX; i++) {
|
|
m_TextureStageState[ 2 ][ j ][ i ] = m_TextureStageState[ 0 ][ j ][ i ];
|
|
}
|
|
}
|
|
}
|
|
|
|
void CEtStateBlockManager::Diff()
|
|
{
|
|
for( int i = 0; i < RS_MAX; i++) {
|
|
if( m_RenderState[ 3 ][ i ] != RESET_MAGIC_NUMBER && m_RenderState[ 3 ][ i ] != m_RenderState[ 0 ][ i ] )
|
|
{
|
|
int df = 3;
|
|
}
|
|
m_RenderState[ 3 ][ i ] = m_RenderState[ 0 ][ i ];
|
|
}
|
|
for( int j = 0; j < STAGE_MAX; j++) {
|
|
for( int i = 0; i < SS_MAX; i++) {
|
|
|
|
if( m_SamplerState[ 3 ][ j ][ i ] != RESET_MAGIC_NUMBER && m_SamplerState[ 3 ][ j ][ i ] != m_SamplerState[ 0 ][ j ][ i ] )
|
|
{
|
|
int df = 3;
|
|
}
|
|
m_SamplerState[ 3 ][ j ][ i ] = m_SamplerState[ 0 ][ j ][ i ];
|
|
|
|
}
|
|
for( int i = 0; i < TS_MAX; i++) {
|
|
|
|
if( m_TextureStageState[ 3 ][ j ][ i ] != RESET_MAGIC_NUMBER && m_TextureStageState[ 3 ][ j ][ i ] != m_TextureStageState[ 0 ][ j ][ i ] )
|
|
{
|
|
int df = 3;
|
|
}
|
|
m_TextureStageState[ 3 ][ j ][ i ] = m_TextureStageState[ 0 ][ j ][ i ];
|
|
}
|
|
}
|
|
}
|
|
|
|
void CEtStateBlockManager::Restore()
|
|
{
|
|
for( int i = 0; i < RS_MAX; i++) {
|
|
if( m_RenderState[ 2 ][ i ] != m_RenderState[ 0 ][ i ] ) {
|
|
ASSERT( m_RenderState[ 2 ][ i ] != RESET_MAGIC_NUMBER );
|
|
SetRenderStateDefered( (D3DRENDERSTATETYPE) i, m_RenderState[ 2 ][ i ]);
|
|
}
|
|
}
|
|
for( int j = 0; j < STAGE_MAX; j++) {
|
|
for( int i = 0; i < SS_MAX; i++) {
|
|
if( m_SamplerState[ 2 ][ j ][ i ] != m_SamplerState[ 0 ][ j ][ i ] ) {
|
|
ASSERT( m_SamplerState[ 2 ][ j ][ i ] != RESET_MAGIC_NUMBER );
|
|
SetSamplerStateDefered( j, (D3DSAMPLERSTATETYPE)i, m_SamplerState[ 2 ][ j ][ i ]);
|
|
}
|
|
}
|
|
for( int i = 0; i < TS_MAX; i++) {
|
|
if( m_TextureStageState[ 2 ][ j ][ i ] != m_TextureStageState[ 0 ][ j ][ i ] ) {
|
|
ASSERT( m_TextureStageState[ 2 ][ j ][ i ] != RESET_MAGIC_NUMBER );
|
|
SetTextureStageStateDefered( j, (D3DTEXTURESTAGESTATETYPE)i, m_TextureStageState[ 2 ][ j ][ i ]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void CEtStateBlockManager::DebugDumpState()
|
|
{
|
|
#if defined(_DEBUG) || defined(_RDEBUG)
|
|
FILE *fp = fopen( "d:\\RenderState.txt", "wt");
|
|
for( int i = 0; i < RS_MAX; i++) {
|
|
fprintf(fp, "RS %d = %d\n", i, m_RenderState[ 0 ][ i ] );
|
|
}
|
|
for( int j = 0; j < STAGE_MAX; j++) {
|
|
for( int i = 0; i < SS_MAX; i++) {
|
|
fprintf(fp, "SS %d:%d = %d\n", j, i, m_SamplerState[ 0 ][ j ][ i ] );
|
|
}
|
|
for( int i = 0; i < TS_MAX; i++) {
|
|
fprintf(fp, "TS %d:%d = %d\n", j, i, m_TextureStageState[ 0 ][ j ][ i ] );
|
|
}
|
|
}
|
|
fclose(fp);
|
|
#endif
|
|
}
|
|
|
|
static CEtStateBlockManager s_EtStateManager;
|
|
CEtStateBlockManager* GetEtStateManager()
|
|
{
|
|
return &s_EtStateManager;
|
|
}
|