|
|
//===== Copyright � 1996-2005, Valve Corporation, All rights reserved. ======//
//
// Purpose: API-independent render state declarations
//
// $NoKeywords: $
//
//===========================================================================//
#ifndef RENDERSTATE_H
#define RENDERSTATE_H
#ifdef _WIN32
#pragma once
#endif
#include "tier1/interface.h"
#include "tier1/generichash.h"
#include "basetypes.h"
#include "mathlib/mathlib.h"
//-----------------------------------------------------------------------------
// Handle to render state objects
//-----------------------------------------------------------------------------
DECLARE_POINTER_HANDLE( RsRasterizerStateHandle_t ); #define RENDER_RASTERIZER_STATE_HANDLE_INVALID ( (RsRasterizerStateHandle_t)0 )
DECLARE_POINTER_HANDLE( RsDepthStencilStateHandle_t ); #define RENDER_DEPTH_STENCIL_STATE_HANDLE_INVALID ( (RsDepthStencilStateHandle_t)0 )
DECLARE_POINTER_HANDLE( RsBlendStateHandle_t ); #define RENDER_BLEND_STATE_HANDLE_INVALID ( (RsBlendStateHandle_t)0 )
//-----------------------------------------------------------------------------
// Packs a float4 color to ARGB 8-bit int color compatible with D3D9
//-----------------------------------------------------------------------------
FORCEINLINE uint32 PackFloat4ColorToUInt32( float flR, float flG, float flB, float flA ) { uint32 nR, nG, nB, nA; nR = uint32( flR * 255.0f ); nG = uint32( flG * 255.0f ); nB = uint32( flB * 255.0f ); nA = uint32( flA * 255.0f ); return ( ( nA & 0xFF ) << 24 ) | ( ( nR & 0xFF ) << 16 ) | ( ( nG & 0xFF ) << 8 ) | ( ( nB & 0xFF ) ); }
//-----------------------------------------------------------------------------
// Packs a float4 color to ARGB 8-bit int color compatible with D3D9, clamping the floats to [0, 1]
//-----------------------------------------------------------------------------
FORCEINLINE uint32 ClampAndPackFloat4ColorToUInt32( float flR, float flG, float flB, float flA ) { uint32 nR, nG, nB, nA; nR = uint32( clamp( flR, 0.0f, 1.0f ) * 255.0f ); nG = uint32( clamp( flG, 0.0f, 1.0f ) * 255.0f ); nB = uint32( clamp( flB, 0.0f, 1.0f ) * 255.0f ); nA = uint32( clamp( flA, 0.0f, 1.0f ) * 255.0f ); return ( ( nA & 0xFF ) << 24 ) | ( ( nR & 0xFF ) << 16 ) | ( ( nG & 0xFF ) << 8 ) | ( ( nB & 0xFF ) ); }
//-----------------------------------------------------------------------------
// Unpacks an ARGB 8-bit int color to 4 floats
//-----------------------------------------------------------------------------
FORCEINLINE void UnpackUint32ColorToFloat4( uint32 nPackedColor, float* pflR, float* pflG, float* pflB, float* pflA ) { uint32 nR, nG, nB, nA;
nR = ( nPackedColor >> 16 ) & 0xFF; nG = ( nPackedColor >> 8 ) & 0xFF; nB = ( nPackedColor ) & 0xFF; nA = ( nPackedColor >> 24 ) & 0xFF;
*pflR = nR * 255.0f; *pflG = nG * 255.0f; *pflB = nB * 255.0f; *pflA = nA * 255.0f; }
enum RsCullMode_t { RS_CULL_NONE = 0, RS_CULL_BACK = 1, RS_CULL_FRONT = 2 };
enum RsFillMode_t { RS_FILL_SOLID = 0, RS_FILL_WIREFRAME = 1 };
enum RsComparison_t { RS_CMP_NEVER = 0, RS_CMP_LESS = 1, RS_CMP_EQUAL = 2, RS_CMP_LESS_EQUAL = 3, RS_CMP_GREATER = 4, RS_CMP_NOT_EQUAL = 5, RS_CMP_GREATER_EQUAL = 6, RS_CMP_ALWAYS = 7 };
enum RsStencilOp_t { RS_STENCIL_OP_KEEP = 0, RS_STENCIL_OP_ZERO = 1, RS_STENCIL_OP_REPLACE = 2, RS_STENCIL_OP_INCR_SAT = 3, RS_STENCIL_OP_DECR_SAT = 4, RS_STENCIL_OP_INVERT = 5, RS_STENCIL_OP_INCR = 6, RS_STENCIL_OP_DECR = 7 };
enum RsHiStencilComparison360_t { RS_HI_STENCIL_CMP_EQUAL = 0, RS_HI_STENCIL_CMP_NOT_EQUAL = 1 };
enum RsHiZMode360_t { RS_HI_Z_AUTOMATIC = 0, RS_HI_Z_DISABLE = 1, RS_HI_Z_ENABLE = 2 };
enum RsBlendOp_t { RS_BLEND_OP_ADD = 0, RS_BLEND_OP_SUBTRACT = 1, RS_BLEND_OP_REV_SUBTRACT = 2, RS_BLEND_OP_MIN = 3, RS_BLEND_OP_MAX = 4 };
enum RsBlendMode_t { RS_BLEND_MODE_ZERO = 0, RS_BLEND_MODE_ONE = 1, RS_BLEND_MODE_SRC_COLOR = 2, RS_BLEND_MODE_INV_SRC_COLOR = 3, RS_BLEND_MODE_SRC_ALPHA = 4, RS_BLEND_MODE_INV_SRC_ALPHA = 5, RS_BLEND_MODE_DEST_ALPHA = 6, RS_BLEND_MODE_INV_DEST_ALPHA = 7, RS_BLEND_MODE_DEST_COLOR = 8, RS_BLEND_MODE_INV_DEST_COLOR = 9, RS_BLEND_MODE_SRC_ALPHA_SAT = 10, RS_BLEND_MODE_BLEND_FACTOR = 11, RS_BLEND_MODE_INV_BLEND_FACTOR = 12 };
enum RsColorWriteEnableBits_t { RS_COLOR_WRITE_ENABLE_R = 0x1, RS_COLOR_WRITE_ENABLE_G = 0x2, RS_COLOR_WRITE_ENABLE_B = 0x4, RS_COLOR_WRITE_ENABLE_A = 0x8, RS_COLOR_WRITE_ENABLE_ALL = RS_COLOR_WRITE_ENABLE_R | RS_COLOR_WRITE_ENABLE_G | RS_COLOR_WRITE_ENABLE_B | RS_COLOR_WRITE_ENABLE_A };
enum { RS_MAX_RENDER_TARGETS = 8 };
//-----------------------------------------------------------------------------
struct RsRasterizerStateDesc_t { RsFillMode_t m_nFillMode; RsCullMode_t m_nCullMode; bool m_bDepthClipEnable; bool m_bMultisampleEnable; int32 m_nDepthBias; // TODO: make this a float?
float32 m_flDepthBiasClamp; float32 m_flSlopeScaledDepthBias;
/* Not exposing these DX11 states
BOOL FrontCounterClockwise; BOOL ScissorEnable; BOOL AntialiasedLineEnable;
This needs to be passed in explicitly when setting the blend state op: uint32 multisamplemask; */
FORCEINLINE uint32 HashValue() const { // TODO: Optimize this
return HashItem( *this ); }
FORCEINLINE bool operator==( RsRasterizerStateDesc_t const &state ) const { return memcmp( this, &state, sizeof( RsRasterizerStateDesc_t ) ) == 0; } };
//-----------------------------------------------------------------------------
struct RsDepthStencilStateDesc_t { bool m_bDepthTestEnable; bool m_bDepthWriteEnable; RsComparison_t m_depthFunc;
RsHiZMode360_t m_hiZEnable360; RsHiZMode360_t m_hiZWriteEnable360;
bool m_bStencilEnable; uint8 m_nStencilReadMask; uint8 m_nStencilWriteMask;
RsStencilOp_t m_frontStencilFailOp; RsStencilOp_t m_frontStencilDepthFailOp; RsStencilOp_t m_frontStencilPassOp; RsComparison_t m_frontStencilFunc;
RsStencilOp_t m_backStencilFailOp; RsStencilOp_t m_backStencilDepthFailOp; RsStencilOp_t m_backStencilPassOp; RsComparison_t m_backStencilFunc;
bool m_bHiStencilEnable360; bool m_bHiStencilWriteEnable360; RsHiStencilComparison360_t m_hiStencilFunc360; uint8 m_nHiStencilRef360;
// Stencil ref not part of this, it's set explicitly when binding DS state block
// TODO: Figure out if I should pull the 360 HiStencil ref out too.
FORCEINLINE uint32 HashValue() const { // TODO: Optimize this
return HashItem( *this ); }
FORCEINLINE bool operator==( RsDepthStencilStateDesc_t const &state ) const { return memcmp( this, &state, sizeof( RsDepthStencilStateDesc_t ) ) == 0; } };
//-----------------------------------------------------------------------------
struct RsBlendStateDesc_t { bool m_bAlphaToCoverageEnable; bool m_bIndependentBlendEnable; bool m_bHighPrecisionBlendEnable360;
bool m_bBlendEnable[RS_MAX_RENDER_TARGETS]; RsBlendMode_t m_srcBlend[RS_MAX_RENDER_TARGETS]; RsBlendMode_t m_destBlend[RS_MAX_RENDER_TARGETS]; RsBlendOp_t m_blendOp[RS_MAX_RENDER_TARGETS]; RsBlendMode_t m_srcBlendAlpha[RS_MAX_RENDER_TARGETS]; RsBlendMode_t m_destBlendAlpha[RS_MAX_RENDER_TARGETS]; RsBlendOp_t m_blendOpAlpha[RS_MAX_RENDER_TARGETS]; uint8 m_nRenderTargetWriteMask[RS_MAX_RENDER_TARGETS];
FORCEINLINE uint32 HashValue() const { // TODO: Optimize this
return HashItem( *this ); }
FORCEINLINE bool operator==( RsBlendStateDesc_t const &state ) const { return memcmp( this, &state, sizeof( RsBlendStateDesc_t ) ) == 0; } };
enum RsFilter_t { RS_FILTER_MIN_MAG_MIP_POINT = 0, RS_FILTER_MIN_MAG_POINT_MIP_LINEAR = 0x1, RS_FILTER_MIN_POINT_MAG_LINEAR_MIP_POINT = 0x4, RS_FILTER_MIN_POINT_MAG_MIP_LINEAR = 0x5, RS_FILTER_MIN_LINEAR_MAG_MIP_POINT = 0x10, RS_FILTER_MIN_LINEAR_MAG_POINT_MIP_LINEAR = 0x11, RS_FILTER_MIN_MAG_LINEAR_MIP_POINT = 0x14, RS_FILTER_MIN_MAG_MIP_LINEAR = 0x15, RS_FILTER_ANISOTROPIC = 0x55, RS_FILTER_COMPARISON_MIN_MAG_MIP_POINT = 0x80, RS_FILTER_COMPARISON_MIN_MAG_POINT_MIP_LINEAR = 0x81, RS_FILTER_COMPARISON_MIN_POINT_MAG_LINEAR_MIP_POINT = 0x84, RS_FILTER_COMPARISON_MIN_POINT_MAG_MIP_LINEAR = 0x85, RS_FILTER_COMPARISON_MIN_LINEAR_MAG_MIP_POINT = 0x90, RS_FILTER_COMPARISON_MIN_LINEAR_MAG_POINT_MIP_LINEAR = 0x91, RS_FILTER_COMPARISON_MIN_MAG_LINEAR_MIP_POINT = 0x94, RS_FILTER_COMPARISON_MIN_MAG_MIP_LINEAR = 0x95, RS_FILTER_COMPARISON_ANISOTROPIC = 0xd5 };
enum RsFilterType_t { RS_FILTER_TYPE_POINT = 0, RS_FILTER_TYPE_LINEAR = 1 };
FORCEINLINE RsFilter_t RsEncodeBasicTextureFilter( RsFilterType_t minFilter, RsFilterType_t magFilter, RsFilterType_t mipFilter, bool bComparison ) { return static_cast< RsFilter_t >( ( bComparison ? 0x80 : 0 ) | ( ( minFilter & 0x3 ) << 4 ) | ( ( magFilter & 0x3 ) << 2 ) | ( mipFilter & 0x3 ) ); }
FORCEINLINE RsFilter_t RsEncodeAnisoTextureFilter( bool bComparison ) { return RsEncodeBasicTextureFilter( RS_FILTER_TYPE_LINEAR, RS_FILTER_TYPE_LINEAR, RS_FILTER_TYPE_LINEAR, bComparison ); }
FORCEINLINE RsFilterType_t RsGetTextureMinFilterType( RsFilter_t filter ) { return static_cast< RsFilterType_t >( 0x3 & ( filter >> 4 ) ); }
FORCEINLINE RsFilterType_t RsGetTextureMagFilterType( RsFilter_t filter ) { return static_cast< RsFilterType_t >( 0x3 & ( filter >> 2 ) ); }
FORCEINLINE RsFilterType_t RsGetTextureMipFilterType( RsFilter_t filter ) { return static_cast< RsFilterType_t >( 0x3 & filter ); }
FORCEINLINE bool RsIsComparisonTextureFilter( RsFilter_t filter ) { return ( filter & 0x80 ) != 0; }
FORCEINLINE bool RsIsAnisoTextureFilter( RsFilter_t filter ) { return static_cast< RsFilter_t >( filter & ~0x80 ) == RS_FILTER_ANISOTROPIC; }
enum RsTextureAddressMode_t { RS_TEXTURE_ADDRESS_WRAP = 0, RS_TEXTURE_ADDRESS_MIRROR = 1, RS_TEXTURE_ADDRESS_CLAMP = 2, RS_TEXTURE_ADDRESS_BORDER = 3, RS_TEXTURE_ADDRESS_MIRROR_ONCE = 4 };
//-----------------------------------------------------------------------------
class CSamplerStateDesc { public: explicit CSamplerStateDesc( RsFilter_t filter = RS_FILTER_MIN_MAG_MIP_LINEAR, RsTextureAddressMode_t addressU = RS_TEXTURE_ADDRESS_WRAP, RsTextureAddressMode_t addressV = RS_TEXTURE_ADDRESS_WRAP, RsTextureAddressMode_t addressW = RS_TEXTURE_ADDRESS_WRAP, float32 flMipLodBias = 0.0f, uint32 nMaxAniso = 16, RsComparison_t comparisonFunc = RS_CMP_LESS, uint32 nMinLod = 0, uint32 nMaxLod = 16, bool bSrgbFetch = false, bool bFetch4 = false ) { SetFilterMode( filter ); SetTextureAddressModeU( addressU ); SetTextureAddressModeV( addressU ); SetTextureAddressModeW( addressU ); SetMipLodBias( flMipLodBias ); SetMaxAnisotropy( nMaxAniso ); SetComparisonFunc( comparisonFunc ); SetMinMaxLod( nMinLod, nMaxLod ); SetSrgbFetchEnabled( bSrgbFetch ); SetFetch4Enabled( bFetch4 ); float32 flZeros[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; SetBorderColor( flZeros ); m_nPad = 0; }
FORCEINLINE RsFilter_t GetFilterMode() const { return static_cast< RsFilter_t >( m_nFilterMode ); } FORCEINLINE void SetFilterMode( RsFilter_t filter ) { m_nFilterMode = filter; }
FORCEINLINE RsTextureAddressMode_t GetTextureAddressModeU() const { return static_cast< RsTextureAddressMode_t >( m_nAddressU ); } FORCEINLINE RsTextureAddressMode_t GetTextureAddressModeV() const { return static_cast< RsTextureAddressMode_t >( m_nAddressV ); } FORCEINLINE RsTextureAddressMode_t GetTextureAddressModeW() const { return static_cast< RsTextureAddressMode_t >( m_nAddressW ); }
FORCEINLINE void SetTextureAddressModeU( RsTextureAddressMode_t addressMode ) { m_nAddressU = addressMode; } FORCEINLINE void SetTextureAddressModeV( RsTextureAddressMode_t addressMode ) { m_nAddressV = addressMode; } FORCEINLINE void SetTextureAddressModeW( RsTextureAddressMode_t addressMode ) { m_nAddressW = addressMode; } FORCEINLINE float32 GetMipLodBias() const { return float32( m_nMipLodBias ) / 16.0f * ( m_nMipLodBiasSign ? -1.0f : 1.0f ); }
FORCEINLINE void SetMipLodBias( float32 flBias ) { m_nMipLodBias = int( fabsf( flBias ) * 16.0f ); m_nMipLodBiasSign = ( flBias >= 0.0f ) ? 0 : 1; }
FORCEINLINE uint32 GetMaxAnisotropy() const { return 1 << m_nAnisoExp; } FORCEINLINE void SetMaxAnisotropy( uint32 nMaxAniso ) { uint32 nAnisoExp = uint32( FastLog2( MAX( nMaxAniso, 1 ) ) ); m_nAnisoExp = MIN( nAnisoExp, 7 ); }
FORCEINLINE RsComparison_t GetComparisonFunc() const { return static_cast< RsComparison_t >( m_nComparisonFunc ); } FORCEINLINE void SetComparisonFunc( RsComparison_t compFunc ) { m_nComparisonFunc = compFunc; }
FORCEINLINE void SetBorderColor( const float32 *pBorderColor ) { m_nBorderColor8Bit = ClampAndPackFloat4ColorToUInt32( pBorderColor[0], pBorderColor[1], pBorderColor[2], pBorderColor[3] ); }
FORCEINLINE void GetBorderColor( float32 *pBorderColorOut ) const { UnpackUint32ColorToFloat4( m_nBorderColor8Bit, pBorderColorOut, pBorderColorOut + 1, pBorderColorOut + 2, pBorderColorOut + 3 ); }
FORCEINLINE uint32 GetBorderColor32Bit() const { return m_nBorderColor8Bit; }
FORCEINLINE void GetMinMaxLod( uint32 *pMinLodOut, uint32 *pMaxLodOut ) const { *pMinLodOut = m_nMinLod; *pMaxLodOut = m_nMaxLod; }
FORCEINLINE uint32 GetMinLod() const { return m_nMinLod; }
FORCEINLINE uint32 GetMaxLod() const { return m_nMaxLod; }
FORCEINLINE void SetMinMaxLod( uint32 nMinLod, uint32 nMaxLod ) { m_nMinLod = MIN( 15, nMinLod ); m_nMaxLod = MIN( 15, nMaxLod ); }
FORCEINLINE void SetMinLod( uint32 nMinLod ) { m_nMinLod = MIN( 15, nMinLod ); }
FORCEINLINE void SetMaxLod( uint32 nMaxLod ) { m_nMaxLod = MIN( 15, nMaxLod ); }
bool GetFetch4Enabled() const { return m_nFetch4Enable ? true : false; } void SetFetch4Enabled( bool bEnable ) { m_nFetch4Enable = bEnable; }
bool GetSrgbFetchEnabled() const { return m_nSrgbFetchEnable ? true : false; } void SetSrgbFetchEnabled( bool bEnable ) { m_nSrgbFetchEnable = bEnable; }
FORCEINLINE uint32 HashValue( void ) const { COMPILE_TIME_ASSERT( sizeof( CSamplerStateDesc ) == 12 ); return Hash12( this ); }
FORCEINLINE bool operator==( CSamplerStateDesc const &state ) const { return memcmp( this, &state, sizeof( CSamplerStateDesc ) ) == 0; }
private:
// 32 bits
uint32 m_nFilterMode : 8; uint32 m_nMipLodBias : 8; // 4.4 fixed point
uint32 m_nMipLodBiasSign : 1; uint32 m_nAddressU : 3; uint32 m_nAddressV : 3; uint32 m_nAddressW : 3; uint32 m_nAnisoExp : 3; uint32 m_nComparisonFunc : 3;
// 32 bits
uint32 m_nBorderColor8Bit;
// 32 bits (18 bits available for extension
uint32 m_nMinLod : 6; // TODO: Either make them fixed-point, or kick them out of the state block alltogether
uint32 m_nMaxLod : 6; uint32 m_nFetch4Enable : 1; uint32 m_nSrgbFetchEnable : 1; uint32 m_nPad : 18; };
//-----------------------------------------------------------------------------
// Enums for builtin state objects
//-----------------------------------------------------------------------------
enum RenderCullMode_t { RENDER_CULLMODE_CULL_BACKFACING = 0, // this culls polygons with clockwise winding
RENDER_CULLMODE_CULL_FRONTFACING = 1, // this culls polygons with counterclockwise winding
RENDER_CULLMODE_CULL_NONE = 2, // no culling
};
enum RenderZBufferMode_t { RENDER_ZBUFFER_NONE = 0, RENDER_ZBUFFER_ZTEST_AND_WRITE, RENDER_ZBUFFER_ZTEST_NO_WRITE, RENDER_ZBUFFER_ZTEST_GREATER_NO_WRITE, RENDER_ZBUFFER_ZTEST_EQUAL_NO_WRITE,
// Stencil modes
RENDER_ZBUFFER_NONE_STENCIL_TEST_NOTEQUAL, RENDER_ZBUFFER_ZTEST_AND_WRITE_STENCIL_SET1, RENDER_ZBUFFER_ZTEST_NO_WRITE_STENCIL_TEST_NOTEQUAL_SET0, RENDER_ZBUFFER_ZTEST_GREATER_NO_WRITE_STENCIL_TEST_NOTEQUAL_SET0,
RENDER_ZBUFFER_NUM_BUILTIN_MODES };
enum RenderBlendMode_t { RENDER_BLEND_NONE = 0, RENDER_BLEND_NOPIXELWRITE = 1, RENDER_BLEND_RGBAPIXELWRITE, RENDER_BLEND_ALPHABLENDING, RENDER_BLEND_ADDITIVE_ON_ALPHA,
RENDER_NUM_BUILTIN_BLENDSTATES };
#endif // RENDERSTATE_H
|