gfxD3D9StateBlock.cpp 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2012 GarageGames, LLC
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to
  6. // deal in the Software without restriction, including without limitation the
  7. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. // sell copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  20. // IN THE SOFTWARE.
  21. //-----------------------------------------------------------------------------
  22. #include "gfx/gfxDevice.h"
  23. #if defined(TORQUE_OS_XENON)
  24. # include <xtl.h>
  25. #else
  26. # include <d3d9.h>
  27. #endif
  28. #include "gfx/D3D9/gfxD3D9StateBlock.h"
  29. #include "gfx/D3D9/gfxD3D9EnumTranslate.h"
  30. GFXD3D9StateBlock::GFXD3D9StateBlock(const GFXStateBlockDesc& desc, LPDIRECT3DDEVICE9 d3dDevice)
  31. {
  32. AssertFatal(d3dDevice, "Invalid mD3DDevice!");
  33. mDesc = desc;
  34. mCachedHashValue = desc.getHashValue();
  35. mD3DDevice = d3dDevice;
  36. // Color writes
  37. mColorMask = 0;
  38. mColorMask |= ( mDesc.colorWriteRed ? GFXCOLORWRITEENABLE_RED : 0 );
  39. mColorMask |= ( mDesc.colorWriteGreen ? GFXCOLORWRITEENABLE_GREEN : 0 );
  40. mColorMask |= ( mDesc.colorWriteBlue ? GFXCOLORWRITEENABLE_BLUE : 0 );
  41. mColorMask |= ( mDesc.colorWriteAlpha ? GFXCOLORWRITEENABLE_ALPHA : 0 );
  42. // Z*bias
  43. mZBias = *((U32*)&mDesc.zBias);
  44. mZSlopeBias = *((U32*)&mDesc.zSlopeBias);
  45. }
  46. GFXD3D9StateBlock::~GFXD3D9StateBlock()
  47. {
  48. }
  49. /// Returns the hash value of the desc that created this block
  50. U32 GFXD3D9StateBlock::getHashValue() const
  51. {
  52. return mCachedHashValue;
  53. }
  54. /// Returns a GFXStateBlockDesc that this block represents
  55. const GFXStateBlockDesc& GFXD3D9StateBlock::getDesc() const
  56. {
  57. return mDesc;
  58. }
  59. /// Called by D3D9 device to active this state block.
  60. /// @param oldState The current state, used to make sure we don't set redundant states on the device. Pass NULL to reset all states.
  61. void GFXD3D9StateBlock::activate(GFXD3D9StateBlock* oldState)
  62. {
  63. PROFILE_SCOPE( GFXD3D9StateBlock_Activate );
  64. // Little macro to save some typing, SD = state diff, checks for null source state block, then
  65. // checks to see if the states differ
  66. #if defined(TORQUE_OS_XENON)
  67. #define SD(x, y) if (!oldState || oldState->mDesc.x != mDesc.x) \
  68. mD3DDevice->SetRenderState_Inline(y, mDesc.x)
  69. // Same as above, but allows you to set the data
  70. #define SDD(x, y, z) if (!oldState || oldState->mDesc.x != mDesc.x) \
  71. mD3DDevice->SetRenderState_Inline(y, z)
  72. #else
  73. #define SD(x, y) if (!oldState || oldState->mDesc.x != mDesc.x) \
  74. mD3DDevice->SetRenderState(y, mDesc.x)
  75. // Same as above, but allows you to set the data
  76. #define SDD(x, y, z) if (!oldState || oldState->mDesc.x != mDesc.x) \
  77. mD3DDevice->SetRenderState(y, z)
  78. #endif
  79. // Blending
  80. SD(blendEnable, D3DRS_ALPHABLENDENABLE);
  81. SDD(blendSrc, D3DRS_SRCBLEND, GFXD3D9Blend[mDesc.blendSrc]);
  82. SDD(blendDest, D3DRS_DESTBLEND, GFXD3D9Blend[mDesc.blendDest]);
  83. SDD(blendOp, D3DRS_BLENDOP, GFXD3D9BlendOp[mDesc.blendOp]);
  84. // Separate alpha blending
  85. SD(separateAlphaBlendEnable, D3DRS_SEPARATEALPHABLENDENABLE);
  86. SDD(separateAlphaBlendSrc, D3DRS_SRCBLENDALPHA, GFXD3D9Blend[mDesc.separateAlphaBlendSrc]);
  87. SDD(separateAlphaBlendDest, D3DRS_DESTBLENDALPHA, GFXD3D9Blend[mDesc.separateAlphaBlendDest]);
  88. SDD(separateAlphaBlendOp, D3DRS_BLENDOPALPHA, GFXD3D9BlendOp[mDesc.separateAlphaBlendOp]);
  89. // Alpha test
  90. SD(alphaTestEnable, D3DRS_ALPHATESTENABLE);
  91. SDD(alphaTestFunc, D3DRS_ALPHAFUNC, GFXD3D9CmpFunc[mDesc.alphaTestFunc]);
  92. SD(alphaTestRef, D3DRS_ALPHAREF);
  93. // Color writes
  94. if ((oldState == NULL) || (mColorMask != oldState->mColorMask))
  95. mD3DDevice->SetRenderState(D3DRS_COLORWRITEENABLE, mColorMask);
  96. // Culling
  97. SDD(cullMode, D3DRS_CULLMODE, GFXD3D9CullMode[mDesc.cullMode]);
  98. // Depth
  99. SD(zEnable, D3DRS_ZENABLE);
  100. SD(zWriteEnable, D3DRS_ZWRITEENABLE);
  101. SDD(zFunc, D3DRS_ZFUNC, GFXD3D9CmpFunc[mDesc.zFunc]);
  102. if ((!oldState) || (mZBias != oldState->mZBias))
  103. mD3DDevice->SetRenderState(D3DRS_DEPTHBIAS, mZBias);
  104. if ((!oldState) || (mZSlopeBias != oldState->mZSlopeBias))
  105. mD3DDevice->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, mZSlopeBias);
  106. // Stencil
  107. SD(stencilEnable, D3DRS_STENCILENABLE);
  108. SDD(stencilFailOp, D3DRS_STENCILFAIL, GFXD3D9StencilOp[mDesc.stencilFailOp]);
  109. SDD(stencilZFailOp, D3DRS_STENCILZFAIL, GFXD3D9StencilOp[mDesc.stencilZFailOp]);
  110. SDD(stencilPassOp, D3DRS_STENCILPASS, GFXD3D9StencilOp[mDesc.stencilPassOp]);
  111. SDD(stencilFunc, D3DRS_STENCILFUNC, GFXD3D9CmpFunc[mDesc.stencilFunc]);
  112. SD(stencilRef, D3DRS_STENCILREF);
  113. SD(stencilMask, D3DRS_STENCILMASK);
  114. SD(stencilWriteMask, D3DRS_STENCILWRITEMASK);
  115. SDD(fillMode, D3DRS_FILLMODE, GFXD3D9FillMode[mDesc.fillMode]);
  116. #if !defined(TORQUE_OS_XENON)
  117. SD(ffLighting, D3DRS_LIGHTING);
  118. SD(vertexColorEnable, D3DRS_COLORVERTEX);
  119. static DWORD swzTemp;
  120. getOwningDevice()->getDeviceSwizzle32()->ToBuffer( &swzTemp, &mDesc.textureFactor, sizeof(ColorI) );
  121. SDD(textureFactor, D3DRS_TEXTUREFACTOR, swzTemp);
  122. #endif
  123. #undef SD
  124. #undef SDD
  125. // NOTE: Samplers and Stages are different things.
  126. //
  127. // The Stages were for fixed function blending. When using shaders
  128. // calling SetTextureStageState() is a complete waste of time. In
  129. // fact if this function rises to the top of profiles we should
  130. // refactor stateblocks to seperate the two.
  131. //
  132. // Samplers are used by both fixed function and shaders, but the
  133. // number of samplers is limited by shader model.
  134. #if !defined(TORQUE_OS_XENON)
  135. #define TSS(x, y, z) if (!oldState || oldState->mDesc.samplers[i].x != mDesc.samplers[i].x) \
  136. mD3DDevice->SetTextureStageState(i, y, z)
  137. for ( U32 i = 0; i < 8; i++ )
  138. {
  139. TSS(textureColorOp, D3DTSS_COLOROP, GFXD3D9TextureOp[mDesc.samplers[i].textureColorOp]);
  140. TSS(colorArg1, D3DTSS_COLORARG1, mDesc.samplers[i].colorArg1);
  141. TSS(colorArg2, D3DTSS_COLORARG2, mDesc.samplers[i].colorArg2);
  142. TSS(colorArg3, D3DTSS_COLORARG0, mDesc.samplers[i].colorArg3);
  143. TSS(alphaOp, D3DTSS_ALPHAOP, GFXD3D9TextureOp[mDesc.samplers[i].alphaOp]);
  144. TSS(alphaArg1, D3DTSS_ALPHAARG1, mDesc.samplers[i].alphaArg1);
  145. TSS(alphaArg2, D3DTSS_ALPHAARG2, mDesc.samplers[i].alphaArg2);
  146. TSS(alphaArg3, D3DTSS_ALPHAARG0, mDesc.samplers[i].alphaArg3);
  147. TSS(textureTransform, D3DTSS_TEXTURETRANSFORMFLAGS, mDesc.samplers[i].textureTransform);
  148. TSS(resultArg, D3DTSS_RESULTARG, mDesc.samplers[i].resultArg);
  149. }
  150. #undef TSS
  151. #endif
  152. #if defined(TORQUE_OS_XENON)
  153. #define SS(x, y, z) if (!oldState || oldState->mDesc.samplers[i].x != mDesc.samplers[i].x) \
  154. mD3DDevice->SetSamplerState_Inline(i, y, z)
  155. #else
  156. #define SS(x, y, z) if (!oldState || oldState->mDesc.samplers[i].x != mDesc.samplers[i].x) \
  157. mD3DDevice->SetSamplerState(i, y, z)
  158. #endif
  159. for ( U32 i = 0; i < getOwningDevice()->getNumSamplers(); i++ )
  160. {
  161. SS(minFilter, D3DSAMP_MINFILTER, GFXD3D9TextureFilter[mDesc.samplers[i].minFilter]);
  162. SS(magFilter, D3DSAMP_MAGFILTER, GFXD3D9TextureFilter[mDesc.samplers[i].magFilter]);
  163. SS(mipFilter, D3DSAMP_MIPFILTER, GFXD3D9TextureFilter[mDesc.samplers[i].mipFilter]);
  164. F32 bias = mDesc.samplers[i].mipLODBias;
  165. DWORD dwBias = *( (LPDWORD)(&bias) );
  166. SS(mipLODBias, D3DSAMP_MIPMAPLODBIAS, dwBias);
  167. SS(maxAnisotropy, D3DSAMP_MAXANISOTROPY, mDesc.samplers[i].maxAnisotropy);
  168. SS(addressModeU, D3DSAMP_ADDRESSU, GFXD3D9TextureAddress[mDesc.samplers[i].addressModeU]);
  169. SS(addressModeV, D3DSAMP_ADDRESSV, GFXD3D9TextureAddress[mDesc.samplers[i].addressModeV]);
  170. SS(addressModeW, D3DSAMP_ADDRESSW, GFXD3D9TextureAddress[mDesc.samplers[i].addressModeW]);
  171. }
  172. #undef SS
  173. }