Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

488 lines
17 KiB

  1. ///////////////////////////////////////////////////////////////////////////////
  2. // Copyright (C) Microsoft Corporation, 1998.
  3. //
  4. // pixproc.cpp
  5. //
  6. // Direct3D Reference Rasterizer - Pixel Processor
  7. //
  8. ///////////////////////////////////////////////////////////////////////////////
  9. #include "pch.cpp"
  10. #pragma hdrstop
  11. //-----------------------------------------------------------------------------
  12. //
  13. // DoPixel - Invoked for each pixel by the scan converter, applies texture,
  14. // specular, fog, alpha blend, and writes result to surface. Also implements
  15. // depth, alpha, and stencil tests.
  16. //
  17. //-----------------------------------------------------------------------------
  18. void
  19. ReferenceRasterizer::DoPixel( RRPixel& Pixel )
  20. {
  21. // apply texture (includes lookup&filter and blending)
  22. if ( m_cActiveTextureStages > 0 )
  23. {
  24. RRColor TexturedColor = Pixel.Color;
  25. DoTexture( Pixel, TexturedColor );
  26. Pixel.Color = TexturedColor;
  27. // check colorkey
  28. for (INT32 i = 0; i < m_cActiveTextureStages; i++)
  29. {
  30. if ( NULL != m_pTexture[i] )
  31. {
  32. // kill pixel if colorkey killing and any samples matched
  33. if ( m_pTexture[i]->m_bDoColorKeyKill &&
  34. m_pTexture[i]->m_bColorKeyMatched )
  35. {
  36. return;
  37. }
  38. }
  39. }
  40. }
  41. // do alpha test - bail out if failed
  42. if ( m_dwRenderState[D3DRENDERSTATE_ALPHATESTENABLE] &&
  43. !AlphaTest( Pixel.Color.A ) )
  44. {
  45. return;
  46. }
  47. // add specular and saturate
  48. if ( m_dwRenderState[D3DRENDERSTATE_SPECULARENABLE] )
  49. {
  50. Pixel.Color.R += Pixel.Specular.R;
  51. Pixel.Color.G += Pixel.Specular.G;
  52. Pixel.Color.B += Pixel.Specular.B;
  53. Pixel.Color.R = minimum( 1.f, Pixel.Color.R );
  54. Pixel.Color.G = minimum( 1.f, Pixel.Color.G );
  55. Pixel.Color.B = minimum( 1.f, Pixel.Color.B );
  56. }
  57. // apply fog
  58. if ( m_dwRenderState[D3DRENDERSTATE_FOGENABLE] )
  59. {
  60. // get RRColor version of fog color
  61. RRColor FogColor = m_dwRenderState[D3DRENDERSTATE_FOGCOLOR];
  62. // do fog blend
  63. // (TODO: account for pre-multiplied alpha here??)
  64. RRColorComp ObjColorFrac = Pixel.FogIntensity; // f
  65. RRColorComp FogColorFrac = ~Pixel.FogIntensity; // 1. - f
  66. Pixel.Color.R = (ObjColorFrac * Pixel.Color.R) + (FogColorFrac * FogColor.R);
  67. Pixel.Color.G = (ObjColorFrac * Pixel.Color.G) + (FogColorFrac * FogColor.G);
  68. Pixel.Color.B = (ObjColorFrac * Pixel.Color.B) + (FogColorFrac * FogColor.B);
  69. // NOTE: this can be done with a single (signed) multiply as
  70. // (f)*Cp + (1-f)*Cf = f*(Cp-Cf) + Cf
  71. }
  72. //
  73. // read current depth for this pixel and do depth test - cannot
  74. // bail out if failed because stencil may need to be updated
  75. //
  76. RRDepth BufferDepth(Pixel.Depth.GetSType());
  77. BOOL bDepthTestPassed = TRUE;
  78. if ( m_dwRenderState[D3DRENDERSTATE_ZENABLE] )
  79. {
  80. m_pRenderTarget->ReadPixelDepth( Pixel.iX, Pixel.iY, BufferDepth );
  81. bDepthTestPassed = DepthCloser( Pixel.Depth, BufferDepth );
  82. }
  83. //
  84. // do stencil operation
  85. //
  86. BOOL bStencilTestPassed = TRUE;
  87. if ( m_dwRenderState[D3DRENDERSTATE_STENCILENABLE] )
  88. {
  89. // read stencil buffer and do stencil operation
  90. UINT8 uStncBuf = 0x0;
  91. m_pRenderTarget->ReadPixelStencil( Pixel.iX, Pixel.iY, uStncBuf );
  92. UINT8 uStncNew;
  93. bStencilTestPassed = DoStencil( uStncBuf, bDepthTestPassed, Pixel.Depth.GetSType(), uStncNew );
  94. // update stencil only if changed
  95. if ( uStncNew != uStncBuf )
  96. {
  97. // compute new buffer value based on write mask
  98. UINT8 uStncWMask = m_dwRenderState[D3DRENDERSTATE_STENCILWRITEMASK];
  99. UINT8 uStncBufNew = (uStncBuf & ~uStncWMask) | (uStncNew & uStncWMask);
  100. m_pRenderTarget->WritePixelStencil( Pixel.iX, Pixel.iY, uStncBufNew );
  101. }
  102. }
  103. if ( !(bDepthTestPassed && bStencilTestPassed) )
  104. {
  105. return;
  106. }
  107. //
  108. // do fragment generation processing - this is done prior to alpha blend
  109. // somewhat arbitrarily because fragment generation and incremental alpha
  110. // blending are mutually exclusive (blending of fragments requires multipass
  111. // and fragment matching to get the correct result - fragment matching is
  112. // not implemented here yet) (TODO: fragment matching)
  113. //
  114. // this may or may not complete the processing of this pixel
  115. //
  116. if ( m_bFragmentProcessingEnabled )
  117. {
  118. if ( DoFragmentGenerationProcessing( Pixel ) ) { return; }
  119. }
  120. //
  121. // do alpha blend
  122. //
  123. if ( m_dwRenderState[D3DRENDERSTATE_ALPHABLENDENABLE] )
  124. {
  125. RRColor BufferColor;
  126. m_pRenderTarget->ReadPixelColor( Pixel.iX, Pixel.iY, BufferColor );
  127. DoAlphaBlend( Pixel.Color, BufferColor, Pixel.Color );
  128. }
  129. //
  130. // update color and depth buffers
  131. //
  132. WritePixel( Pixel.iX, Pixel.iY, Pixel.Color, Pixel.Depth );
  133. // additional fragment processing associated with buffer write
  134. if ( m_bFragmentProcessingEnabled ) { DoFragmentBufferFixup( Pixel ); }
  135. }
  136. ///////////////////////////////////////////////////////////////////////////////
  137. // //
  138. // Pixel Processing Utility Functions //
  139. // //
  140. ///////////////////////////////////////////////////////////////////////////////
  141. //-----------------------------------------------------------------------------
  142. //
  143. // Depth compare method used for Z buffering and fragment processing.
  144. //
  145. // Returns TRUE if DepthVal is closer than DepthBuf. DepthA is the generated
  146. // value and DepthB
  147. //
  148. //-----------------------------------------------------------------------------
  149. BOOL
  150. ReferenceRasterizer::DepthCloser(
  151. const RRDepth& DepthVal,
  152. const RRDepth& DepthBuf )
  153. {
  154. if ( !m_dwRenderState[D3DRENDERSTATE_ZENABLE] ) { return TRUE; }
  155. switch ( m_dwRenderState[D3DRENDERSTATE_ZFUNC] )
  156. {
  157. case D3DCMP_NEVER: return FALSE;
  158. case D3DCMP_LESS: return ( DOUBLE(DepthVal) < DOUBLE(DepthBuf) );
  159. case D3DCMP_EQUAL: return ( DOUBLE(DepthVal) == DOUBLE(DepthBuf) );
  160. case D3DCMP_LESSEQUAL: return ( DOUBLE(DepthVal) <= DOUBLE(DepthBuf) );
  161. case D3DCMP_GREATER: return ( DOUBLE(DepthVal) > DOUBLE(DepthBuf) );
  162. case D3DCMP_NOTEQUAL: return ( DOUBLE(DepthVal) != DOUBLE(DepthBuf) );
  163. case D3DCMP_GREATEREQUAL: return ( DOUBLE(DepthVal) >= DOUBLE(DepthBuf) );
  164. case D3DCMP_ALWAYS: return TRUE;
  165. }
  166. return TRUE;
  167. }
  168. //-----------------------------------------------------------------------------
  169. //
  170. // Alpha test method for pixel processing.
  171. //
  172. // Returns TRUE if alpha test passes.
  173. //
  174. //-----------------------------------------------------------------------------
  175. BOOL
  176. ReferenceRasterizer::AlphaTest( const RRColorComp& Alpha )
  177. {
  178. // grab 8 bit unsigned alpha value
  179. UINT8 uAlpha = UINT8( Alpha );
  180. // form 8 bit alpha reference value
  181. UINT8 uAlphaRef8 = m_dwRenderState[D3DRENDERSTATE_ALPHAREF];
  182. // do alpha test and either return directly or pass through
  183. switch ( m_dwRenderState[D3DRENDERSTATE_ALPHAFUNC] )
  184. {
  185. case D3DCMP_NEVER: return FALSE;
  186. case D3DCMP_LESS: return (uAlpha < uAlphaRef8);
  187. case D3DCMP_EQUAL: return (uAlpha == uAlphaRef8);
  188. case D3DCMP_LESSEQUAL: return (uAlpha <= uAlphaRef8);
  189. case D3DCMP_GREATER: return (uAlpha > uAlphaRef8);
  190. case D3DCMP_NOTEQUAL: return (uAlpha != uAlphaRef8);
  191. case D3DCMP_GREATEREQUAL: return (uAlpha >= uAlphaRef8);
  192. case D3DCMP_ALWAYS: return TRUE;
  193. }
  194. return TRUE;
  195. }
  196. //-----------------------------------------------------------------------------
  197. //
  198. // DoStencil - Performs stencil test. Returns TRUE if stencil test passed.
  199. // Also computes stencil result value (to be written back to stencil planes
  200. // if test passes, subject to stencil write mask).
  201. //
  202. //-----------------------------------------------------------------------------
  203. BOOL
  204. ReferenceRasterizer::DoStencil(
  205. UINT8 uStncBuf, // in: stencil buffer value
  206. BOOL bDepthTest, // in: boolean result of depth test
  207. RRSurfaceType DepthSType, // in: surface type of Z buffer
  208. UINT8& uStncRet) // out: stencil value result
  209. {
  210. // support 8 bit stencil only, so do everything as UINT8's
  211. // get reference from renderstate
  212. UINT8 uStncRef = (UINT8)(m_dwRenderState[D3DRENDERSTATE_STENCILREF]);
  213. // form masked values for test
  214. UINT8 uStncMask = (UINT8)(m_dwRenderState[D3DRENDERSTATE_STENCILMASK]);
  215. UINT8 uStncBufM = uStncBuf & uStncMask;
  216. UINT8 uStncRefM = uStncRef & uStncMask;
  217. // max value for saturation ops
  218. UINT8 uStncMax;
  219. switch(DepthSType)
  220. {
  221. case RR_STYPE_Z24S8:
  222. case RR_STYPE_S8Z24: uStncMax = 0xff; break;
  223. case RR_STYPE_Z15S1:
  224. case RR_STYPE_S1Z15: uStncMax = 0x1; break;
  225. case RR_STYPE_Z24S4:
  226. case RR_STYPE_S4Z24: uStncMax = 0xf; break;
  227. default: uStncMax = 0; break; // don't let stencil become non 0
  228. }
  229. // do stencil compare function
  230. BOOL bStncTest = FALSE;
  231. switch ( m_dwRenderState[D3DRENDERSTATE_STENCILFUNC] )
  232. {
  233. case D3DCMP_NEVER: bStncTest = FALSE; break;
  234. case D3DCMP_LESS: bStncTest = (uStncRefM < uStncBufM); break;
  235. case D3DCMP_EQUAL: bStncTest = (uStncRefM == uStncBufM); break;
  236. case D3DCMP_LESSEQUAL: bStncTest = (uStncRefM <= uStncBufM); break;
  237. case D3DCMP_GREATER: bStncTest = (uStncRefM > uStncBufM); break;
  238. case D3DCMP_NOTEQUAL: bStncTest = (uStncRefM != uStncBufM); break;
  239. case D3DCMP_GREATEREQUAL: bStncTest = (uStncRefM >= uStncBufM); break;
  240. case D3DCMP_ALWAYS: bStncTest = TRUE; break;
  241. }
  242. // determine which stencil operation to perform
  243. DWORD dwStencilOp;
  244. if ( !bStncTest )
  245. {
  246. // stencil test failed - depth test does not matter
  247. dwStencilOp = m_dwRenderState[D3DRENDERSTATE_STENCILFAIL];
  248. }
  249. else
  250. {
  251. // stencil test passed - select based on depth pass/fail
  252. dwStencilOp = ( !bDepthTest )
  253. ? ( m_dwRenderState[D3DRENDERSTATE_STENCILZFAIL] )
  254. : ( m_dwRenderState[D3DRENDERSTATE_STENCILPASS] );
  255. }
  256. uStncRet = 0x0;
  257. switch ( dwStencilOp )
  258. {
  259. case D3DSTENCILOP_KEEP: uStncRet = uStncBuf; break;
  260. case D3DSTENCILOP_ZERO: uStncRet = 0x00; break;
  261. case D3DSTENCILOP_REPLACE: uStncRet = uStncRef; break;
  262. case D3DSTENCILOP_INCRSAT:
  263. uStncRet = (uStncBuf==uStncMax)?(uStncMax):(uStncBuf+1); break;
  264. case D3DSTENCILOP_DECRSAT:
  265. uStncRet = (uStncBuf==0x00)?(0x00):(uStncBuf-1); break;
  266. case D3DSTENCILOP_INVERT: uStncRet = ~uStncBuf; break;
  267. case D3DSTENCILOP_INCR: uStncRet = uStncBuf+1; break;
  268. case D3DSTENCILOP_DECR: uStncRet = uStncBuf-1; break;
  269. }
  270. return bStncTest;
  271. }
  272. //-----------------------------------------------------------------------------
  273. //
  274. // DoAlphaBlend - Performs color blending of source and destination colors
  275. // producing a result color.
  276. //
  277. //-----------------------------------------------------------------------------
  278. void
  279. ReferenceRasterizer::DoAlphaBlend(
  280. const RRColor& SrcColor, // in: source pixel color
  281. const RRColor& DstColor, // in: destination (buffer) color
  282. RRColor& ResColor) // out: result (blended) color
  283. {
  284. RRColor SrcColorFactor;
  285. RRColor DstColorFactor;
  286. BOOL bDestBlendOverride = FALSE;
  287. // compute source blend factors
  288. switch ( m_dwRenderState[D3DRENDERSTATE_SRCBLEND] )
  289. {
  290. default:
  291. case D3DBLEND_ZERO:
  292. SrcColorFactor.SetAllChannels( 0.F );
  293. break;
  294. case D3DBLEND_ONE:
  295. SrcColorFactor.SetAllChannels( 1.F );
  296. break;
  297. case D3DBLEND_SRCCOLOR:
  298. SrcColorFactor.R = SrcColor.R;
  299. SrcColorFactor.G = SrcColor.G;
  300. SrcColorFactor.B = SrcColor.B;
  301. SrcColorFactor.A = SrcColor.A;
  302. break;
  303. case D3DBLEND_INVSRCCOLOR:
  304. SrcColorFactor.R = ~SrcColor.R;
  305. SrcColorFactor.G = ~SrcColor.G;
  306. SrcColorFactor.B = ~SrcColor.B;
  307. SrcColorFactor.A = ~SrcColor.A;
  308. break;
  309. case D3DBLEND_SRCALPHA:
  310. SrcColorFactor.SetAllChannels( SrcColor.A );
  311. break;
  312. case D3DBLEND_INVSRCALPHA:
  313. SrcColorFactor.SetAllChannels( ~SrcColor.A );
  314. break;
  315. case D3DBLEND_DESTALPHA:
  316. SrcColorFactor.SetAllChannels( DstColor.A );
  317. break;
  318. case D3DBLEND_INVDESTALPHA:
  319. SrcColorFactor.SetAllChannels( ~DstColor.A );
  320. break;
  321. case D3DBLEND_DESTCOLOR:
  322. SrcColorFactor.R = DstColor.R;
  323. SrcColorFactor.G = DstColor.G;
  324. SrcColorFactor.B = DstColor.B;
  325. SrcColorFactor.A = DstColor.A;
  326. break;
  327. case D3DBLEND_INVDESTCOLOR:
  328. SrcColorFactor.R = ~DstColor.R;
  329. SrcColorFactor.G = ~DstColor.G;
  330. SrcColorFactor.B = ~DstColor.B;
  331. SrcColorFactor.A = ~DstColor.A;
  332. break;
  333. case D3DBLEND_SRCALPHASAT:
  334. {
  335. RRColorComp F = minimum( SrcColor.A, ~DstColor.A );
  336. SrcColorFactor.R = F;
  337. SrcColorFactor.G = F;
  338. SrcColorFactor.B = F;
  339. }
  340. SrcColorFactor.A = 1.F;
  341. break;
  342. // these are for SRCBLEND only and override DESTBLEND
  343. case D3DBLEND_BOTHSRCALPHA:
  344. bDestBlendOverride = TRUE;
  345. SrcColorFactor.SetAllChannels( SrcColor.A );
  346. DstColorFactor.SetAllChannels( ~SrcColor.A );
  347. break;
  348. case D3DBLEND_BOTHINVSRCALPHA:
  349. bDestBlendOverride = TRUE;
  350. SrcColorFactor.SetAllChannels( ~SrcColor.A );
  351. DstColorFactor.SetAllChannels( SrcColor.A );
  352. break;
  353. }
  354. // compute destination blend factors
  355. if ( !bDestBlendOverride )
  356. {
  357. switch ( m_dwRenderState[D3DRENDERSTATE_DESTBLEND] )
  358. {
  359. default:
  360. case D3DBLEND_ZERO:
  361. DstColorFactor.SetAllChannels( 0.F );
  362. break;
  363. case D3DBLEND_ONE:
  364. DstColorFactor.SetAllChannels( 1.F );
  365. break;
  366. case D3DBLEND_SRCCOLOR:
  367. DstColorFactor.R = SrcColor.R;
  368. DstColorFactor.G = SrcColor.G;
  369. DstColorFactor.B = SrcColor.B;
  370. DstColorFactor.A = SrcColor.A;
  371. break;
  372. case D3DBLEND_INVSRCCOLOR:
  373. DstColorFactor.R = ~SrcColor.R;
  374. DstColorFactor.G = ~SrcColor.G;
  375. DstColorFactor.B = ~SrcColor.B;
  376. DstColorFactor.A = ~SrcColor.A;
  377. break;
  378. case D3DBLEND_SRCALPHA:
  379. DstColorFactor.SetAllChannels( SrcColor.A );
  380. break;
  381. case D3DBLEND_INVSRCALPHA:
  382. DstColorFactor.SetAllChannels( ~SrcColor.A );
  383. break;
  384. case D3DBLEND_DESTALPHA:
  385. DstColorFactor.SetAllChannels( DstColor.A );
  386. break;
  387. case D3DBLEND_INVDESTALPHA:
  388. DstColorFactor.SetAllChannels( ~DstColor.A );
  389. break;
  390. case D3DBLEND_DESTCOLOR:
  391. DstColorFactor.R = DstColor.R;
  392. DstColorFactor.G = DstColor.G;
  393. DstColorFactor.B = DstColor.B;
  394. DstColorFactor.A = DstColor.A;
  395. break;
  396. case D3DBLEND_INVDESTCOLOR:
  397. DstColorFactor.R = ~DstColor.R;
  398. DstColorFactor.G = ~DstColor.G;
  399. DstColorFactor.B = ~DstColor.B;
  400. DstColorFactor.A = ~DstColor.A;
  401. break;
  402. case D3DBLEND_SRCALPHASAT:
  403. {
  404. RRColorComp F = minimum( SrcColor.A, ~DstColor.A );
  405. DstColorFactor.R = F;
  406. DstColorFactor.G = F;
  407. DstColorFactor.B = F;
  408. }
  409. DstColorFactor.A = 1.F;
  410. break;
  411. }
  412. }
  413. // apply blend factors to update pixel color
  414. ResColor.R = (SrcColorFactor.R * SrcColor.R) + (DstColorFactor.R * DstColor.R);
  415. ResColor.G = (SrcColorFactor.G * SrcColor.G) + (DstColorFactor.G * DstColor.G);
  416. ResColor.B = (SrcColorFactor.B * SrcColor.B) + (DstColorFactor.B * DstColor.B);
  417. ResColor.A = (SrcColorFactor.A * SrcColor.A) + (DstColorFactor.A * DstColor.A);
  418. // clamp result
  419. ResColor.R = minimum( 1.f, maximum( 0.f, ResColor.R ) );
  420. ResColor.G = minimum( 1.f, maximum( 0.f, ResColor.G ) );
  421. ResColor.B = minimum( 1.f, maximum( 0.f, ResColor.B ) );
  422. ResColor.A = minimum( 1.f, maximum( 0.f, ResColor.A ) );
  423. }
  424. ///////////////////////////////////////////////////////////////////////////////
  425. // end