//========= Copyright Valve Corporation, All rights reserved. ============// // // Purpose: // // $NoKeywords: $ // //=============================================================================// #ifndef TRANSITION_TABLE_H #define TRANSITION_TABLE_H #ifdef _WIN32 #pragma once #endif #include "utlvector.h" #include "shadershadowdx8.h" #include "UtlSortVector.h" #include "checksum_crc.h" #include "shaderapi/ishaderapi.h" // Required for DEBUG_BOARD_STATE #include "shaderapidx8_global.h" //----------------------------------------------------------------------------- // Forward declarations //----------------------------------------------------------------------------- struct IDirect3DStateBlock9; //----------------------------------------------------------------------------- // Enumeration for ApplyStateFunc_ts //----------------------------------------------------------------------------- // Any function that does not require a texture stage // NOTE: If you change this, change the function table s_pRenderFunctionTable[] below!! enum RenderStateFunc_t { RENDER_STATE_DepthTest = 0, RENDER_STATE_ZWriteEnable, RENDER_STATE_ColorWriteEnable, RENDER_STATE_AlphaTest, RENDER_STATE_FillMode, RENDER_STATE_Lighting, RENDER_STATE_SpecularEnable, RENDER_STATE_SRGBWriteEnable, RENDER_STATE_AlphaBlend, RENDER_STATE_SeparateAlphaBlend, RENDER_STATE_CullEnable, RENDER_STATE_VertexBlendEnable, RENDER_STATE_FogMode, RENDER_STATE_ActivateFixedFunction, RENDER_STATE_TextureEnable, RENDER_STATE_DiffuseMaterialSource, RENDER_STATE_DisableFogGammaCorrection, RENDER_STATE_EnableAlphaToCoverage, RENDER_STATE_COUNT, }; // Any function that requires a texture stage // NOTE: If you change this, change the function table s_pTextureFunctionTable[] below!! enum TextureStateFunc_t { TEXTURE_STATE_TexCoordIndex = 0, TEXTURE_STATE_SRGBReadEnable, TEXTURE_STATE_Fetch4Enable, #ifdef DX_TO_GL_ABSTRACTION TEXTURE_STATE_ShadowFilterEnable, #endif // Fixed function states TEXTURE_STATE_ColorTextureStage, TEXTURE_STATE_AlphaTextureStage, TEXTURE_STATE_COUNT }; //----------------------------------------------------------------------------- // Types related to transition table entries //----------------------------------------------------------------------------- typedef void (*ApplyStateFunc_t)( const ShadowState_t& shadowState, int arg ); //----------------------------------------------------------------------------- // The DX8 implementation of the transition table //----------------------------------------------------------------------------- class CTransitionTable { public: struct CurrentTextureStageState_t { D3DTEXTUREOP m_ColorOp; int m_ColorArg1; int m_ColorArg2; D3DTEXTUREOP m_AlphaOp; int m_AlphaArg1; int m_AlphaArg2; }; struct CurrentSamplerState_t { bool m_SRGBReadEnable; bool m_Fetch4Enable; bool m_ShadowFilterEnable; }; struct CurrentState_t { // Everything in this 'CurrentState' structure is a state whose value we don't care about // under certain circumstances, (which therefore can diverge from the shadow state), // or states which we override in the dynamic pass. // Alpha state bool m_AlphaBlendEnable; D3DBLEND m_SrcBlend; D3DBLEND m_DestBlend; D3DBLENDOP m_BlendOp; // GR - Separate alpha state bool m_SeparateAlphaBlendEnable; D3DBLEND m_SrcBlendAlpha; D3DBLEND m_DestBlendAlpha; D3DBLENDOP m_BlendOpAlpha; // Depth testing states D3DZBUFFERTYPE m_ZEnable; D3DCMPFUNC m_ZFunc; PolygonOffsetMode_t m_ZBias; // Alpha testing states bool m_AlphaTestEnable; D3DCMPFUNC m_AlphaFunc; int m_AlphaRef; bool m_ForceDepthFuncEquals; bool m_bOverrideDepthEnable; D3DZBUFFERTYPE m_OverrideZWriteEnable; bool m_bOverrideAlphaWriteEnable; bool m_bOverriddenAlphaWriteValue; bool m_bOverrideColorWriteEnable; bool m_bOverriddenColorWriteValue; DWORD m_ColorWriteEnable; bool m_bLinearColorSpaceFrameBufferEnable; bool m_StencilEnable; D3DCMPFUNC m_StencilFunc; int m_StencilRef; int m_StencilMask; DWORD m_StencilFail; DWORD m_StencilZFail; DWORD m_StencilPass; int m_StencilWriteMask; // Texture stage state CurrentTextureStageState_t m_TextureStage[MAX_TEXTURE_STAGES]; CurrentSamplerState_t m_SamplerState[MAX_SAMPLERS]; }; public: // constructor, destructor CTransitionTable( ); virtual ~CTransitionTable(); // Initialization, shutdown bool Init( ); void Shutdown( ); // Resets the snapshots... void Reset(); // Takes a snapshot StateSnapshot_t TakeSnapshot( ); // Take startup snapshot void TakeDefaultStateSnapshot( ); // Makes the board state match the snapshot void UseSnapshot( StateSnapshot_t snapshotId ); // Cause the board to match the default state snapshot void UseDefaultState(); // Snapshotted state overrides void ForceDepthFuncEquals( bool bEnable ); void OverrideDepthEnable( bool bEnable, bool bDepthEnable ); void OverrideAlphaWriteEnable( bool bOverrideEnable, bool bAlphaWriteEnable ); void OverrideColorWriteEnable( bool bOverrideEnable, bool bColorWriteEnable ); void EnableLinearColorSpaceFrameBuffer( bool bEnable ); // Returns a particular snapshot const ShadowState_t &GetSnapshot( StateSnapshot_t snapshotId ) const; const ShadowShaderState_t &GetSnapshotShader( StateSnapshot_t snapshotId ) const; // Gets the current shadow state const ShadowState_t *CurrentShadowState() const; const ShadowShaderState_t *CurrentShadowShaderState() const; // Return the current shapshot int CurrentSnapshot() const { return m_CurrentSnapshotId; } CurrentState_t& CurrentState() { return m_CurrentState; } #ifdef DEBUG_BOARD_STATE ShadowState_t& BoardState() { return m_BoardState; } ShadowShaderState_t& BoardShaderState() { return m_BoardShaderState; } #endif // The following are meant to be used by the transition table only public: // Applies alpha blending void ApplyAlphaBlend( const ShadowState_t& state ); // GR - separate alpha blend void ApplySeparateAlphaBlend( const ShadowState_t& state ); void ApplyAlphaTest( const ShadowState_t& state ); void ApplyDepthTest( const ShadowState_t& state ); // Applies alpha texture op void ApplyColorTextureStage( const ShadowState_t& state, int stage ); void ApplyAlphaTextureStage( const ShadowState_t& state, int stage ); void ApplySRGBWriteEnable( const ShadowState_t& state ); private: enum { INVALID_TRANSITION_OP = 0xFFFFFF }; typedef short ShadowStateId_t; // For the transition table struct TransitionList_t { unsigned int m_FirstOperation : 24; unsigned int m_NumOperations : 8; }; union TransitionOp_t { unsigned char m_nBits; struct { unsigned char m_nOpCode : 7; unsigned char m_bIsTextureCode : 1; } m_nInfo; }; struct SnapshotShaderState_t { ShadowShaderState_t m_ShaderState; ShadowStateId_t m_ShadowStateId; unsigned short m_nReserved; // Pad to 2 ints unsigned int m_nReserved2; }; struct ShadowStateDictEntry_t { CRC32_t m_nChecksum; ShadowStateId_t m_nShadowStateId; }; struct SnapshotDictEntry_t { CRC32_t m_nChecksum; StateSnapshot_t m_nSnapshot; }; class ShadowStateDictLessFunc { public: bool Less( const ShadowStateDictEntry_t &src1, const ShadowStateDictEntry_t &src2, void *pCtx ); }; class SnapshotDictLessFunc { public: bool Less( const SnapshotDictEntry_t &src1, const SnapshotDictEntry_t &src2, void *pCtx ); }; class UniqueSnapshotLessFunc { public: bool Less( const TransitionList_t &src1, const TransitionList_t &src2, void *pCtx ); }; CurrentTextureStageState_t &TextureStage( int stage ) { return m_CurrentState.m_TextureStage[stage]; } const CurrentTextureStageState_t &TextureStage( int stage ) const { return m_CurrentState.m_TextureStage[stage]; } CurrentSamplerState_t &SamplerState( int stage ) { return m_CurrentState.m_SamplerState[stage]; } const CurrentSamplerState_t &SamplerState( int stage ) const { return m_CurrentState.m_SamplerState[stage]; } // creates state snapshots ShadowStateId_t CreateShadowState( const ShadowState_t ¤tState ); StateSnapshot_t CreateStateSnapshot( ShadowStateId_t shadowStateId, const ShadowShaderState_t& currentShaderState ); // finds state snapshots ShadowStateId_t FindShadowState( const ShadowState_t& currentState ) const; StateSnapshot_t FindStateSnapshot( ShadowStateId_t id, const ShadowShaderState_t& currentState ) const; // Finds identical transition lists unsigned int FindIdenticalTransitionList( unsigned int firstElem, unsigned short numOps, unsigned int nFirstTest ) const; // Adds a transition void AddTransition( RenderStateFunc_t func ); void AddTextureTransition( TextureStateFunc_t func, int stage ); // Apply a transition void ApplyTransition( TransitionList_t& list, int snapshot ); // Creates an entry in the transition table void CreateTransitionTableEntry( int to, int from ); // Checks if a state is valid bool TestShadowState( const ShadowState_t& state, const ShadowShaderState_t &shaderState ); // Perform state block overrides void PerformShadowStateOverrides( ); // Applies the transition list void ApplyTransitionList( int snapshot, int nFirstOp, int nOpCount ); // Apply shader state (stuff that doesn't lie in the transition table) void ApplyShaderState( const ShadowState_t &shadowState, const ShadowShaderState_t &shaderState ); // Wrapper for the non-standard transitions for stateblock + non-stateblock cases int CreateNormalTransitions( const ShadowState_t& fromState, const ShadowState_t& toState, bool bForce ); // State setting methods void SetZEnable( D3DZBUFFERTYPE nEnable ); void SetZFunc( D3DCMPFUNC nCmpFunc ); private: // Sets up the default state StateSnapshot_t m_DefaultStateSnapshot; TransitionList_t m_DefaultTransition; ShadowState_t m_DefaultShadowState; // The current snapshot id ShadowStateId_t m_CurrentShadowId; StateSnapshot_t m_CurrentSnapshotId; // Maintains a list of all used snapshot transition states CUtlVector< ShadowState_t > m_ShadowStateList; // Lookup table for fast snapshot finding CUtlSortVector< ShadowStateDictEntry_t, ShadowStateDictLessFunc > m_ShadowStateDict; // The snapshot transition table CUtlVector< CUtlVector< TransitionList_t > > m_TransitionTable; // List of unique transitions CUtlSortVector< TransitionList_t, UniqueSnapshotLessFunc > m_UniqueTransitions; // Stores all state transition operations CUtlVector< TransitionOp_t > m_TransitionOps; // Stores all state for a particular snapshot CUtlVector< SnapshotShaderState_t > m_SnapshotList; // Lookup table for fast snapshot finding CUtlSortVector< SnapshotDictEntry_t, SnapshotDictLessFunc > m_SnapshotDict; // The current board state. CurrentState_t m_CurrentState; #ifdef DEBUG_BOARD_STATE // Maintains the total shadow state ShadowState_t m_BoardState; ShadowShaderState_t m_BoardShaderState; #endif }; //----------------------------------------------------------------------------- // Inline methods //----------------------------------------------------------------------------- inline const ShadowState_t &CTransitionTable::GetSnapshot( StateSnapshot_t snapshotId ) const { Assert( (snapshotId >= 0) && (snapshotId < m_SnapshotList.Count()) ); return m_ShadowStateList[m_SnapshotList[snapshotId].m_ShadowStateId]; } inline const ShadowShaderState_t &CTransitionTable::GetSnapshotShader( StateSnapshot_t snapshotId ) const { Assert( (snapshotId >= 0) && (snapshotId < m_SnapshotList.Count()) ); return m_SnapshotList[snapshotId].m_ShaderState; } inline const ShadowState_t *CTransitionTable::CurrentShadowState() const { if ( m_CurrentShadowId == -1 ) return NULL; Assert( (m_CurrentShadowId >= 0) && (m_CurrentShadowId < m_ShadowStateList.Count()) ); return &m_ShadowStateList[m_CurrentShadowId]; } inline const ShadowShaderState_t *CTransitionTable::CurrentShadowShaderState() const { if ( m_CurrentShadowId == -1 ) return NULL; Assert( (m_CurrentShadowId >= 0) && (m_CurrentShadowId < m_ShadowStateList.Count()) ); return &m_SnapshotList[m_CurrentShadowId].m_ShaderState; } #endif // TRANSITION_TABLE_H