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.

284 lines
8.0 KiB

  1. //----------------------------------------------------------------------------
  2. //
  3. // line.cpp
  4. //
  5. // Line processing.
  6. //
  7. // Copyright (C) Microsoft Corporation, 1997.
  8. //
  9. //----------------------------------------------------------------------------
  10. #include "rgb_pch.h"
  11. #pragma hdrstop
  12. #include "d3dutil.h"
  13. #include "setup.hpp"
  14. #include "attrs_mh.h"
  15. #include "tstp_mh.h"
  16. #include "walk_mh.h"
  17. #include "rsdbg.hpp"
  18. DBG_DECLARE_FILE();
  19. //----------------------------------------------------------------------------
  20. //
  21. // LinePatternStateMachine
  22. //
  23. // Runs the line pattern state machine and returns TRUE if the pixel is to be
  24. // drawn, false otherwise.
  25. //
  26. //----------------------------------------------------------------------------
  27. static inline BOOL LinePatternStateMachine(WORD wRepeatFactor, WORD wLinePattern, WORD& wRepeati, WORD& wPatterni)
  28. {
  29. if (wRepeatFactor == 0)
  30. {
  31. return TRUE;
  32. }
  33. WORD wBit = (wLinePattern >> wPatterni) & 1;
  34. if (++wRepeati >= wRepeatFactor)
  35. {
  36. wRepeati = 0;
  37. wPatterni = (wPatterni+1) & 0xf;
  38. }
  39. return (BOOL)wBit;
  40. }
  41. #define CLAMP_COLOR(fVal, uVal) \
  42. if (FLOAT_LTZ(fVal)) \
  43. { \
  44. uVal = 0; \
  45. } \
  46. else \
  47. { \
  48. if (uVal > 0xffff) \
  49. { \
  50. uVal = 0xffff; \
  51. } \
  52. } \
  53. #define CLAMP_Z(fVal, uVal) \
  54. if (FLOAT_LTZ(fVal)) \
  55. { \
  56. uVal = 0; \
  57. } \
  58. //----------------------------------------------------------------------------
  59. //
  60. // ClampPixel
  61. //
  62. // Clamp color, specular and z(if any) of a pixel. Right now, it's done for
  63. // first and last pixel of a line only.
  64. //
  65. //----------------------------------------------------------------------------
  66. inline void
  67. ClampPixel(PATTRSET pAttrs, PD3DI_RASTSPAN pSpan)
  68. {
  69. CLAMP_COLOR(pAttrs->fB, pSpan->uB);
  70. CLAMP_COLOR(pAttrs->fG, pSpan->uG);
  71. CLAMP_COLOR(pAttrs->fR, pSpan->uR);
  72. CLAMP_COLOR(pAttrs->fA, pSpan->uA);
  73. CLAMP_COLOR(pAttrs->fBS, pSpan->uBS);
  74. CLAMP_COLOR(pAttrs->fGS, pSpan->uGS);
  75. CLAMP_COLOR(pAttrs->fRS, pSpan->uRS);
  76. CLAMP_Z(pAttrs->fZ, pSpan->uZ);
  77. }
  78. //----------------------------------------------------------------------------
  79. //
  80. // WalkLinePattern
  81. //
  82. // Walks a line and generates the pixels touched according to the pattern.
  83. // If wRepeatFactor >= 1, we are patterning, otherwise, we are not
  84. //
  85. //----------------------------------------------------------------------------
  86. HRESULT
  87. WalkLinePattern(PSETUPCTX pStpCtx, WORD wRepeatFactor, WORD wLinePattern)
  88. {
  89. HRESULT hr;
  90. UINT uSpansAvail;
  91. PD3DI_RASTSPAN pSpan;
  92. WORD wRepeati = 0;
  93. WORD wPatterni = 0;
  94. BOOL bFirst = TRUE;
  95. RSASSERT(pStpCtx->cLinePix > 0);
  96. hr = DD_OK;
  97. uSpansAvail = 0;
  98. RSASSERT((pStpCtx->uFlags & PRIMSF_LOD_USED) == 0);
  99. #ifdef PWL_FOG
  100. pStpCtx->uPwlFlags = PWL_NO_NEXT_FOG;
  101. #endif
  102. for (;;)
  103. {
  104. if (pStpCtx->iX >= pStpCtx->pCtx->Clip.left &&
  105. pStpCtx->iX < pStpCtx->pCtx->Clip.right &&
  106. pStpCtx->iY >= pStpCtx->pCtx->Clip.top &&
  107. pStpCtx->iY < pStpCtx->pCtx->Clip.bottom)
  108. {
  109. if (LinePatternStateMachine(wRepeatFactor, wLinePattern, wRepeati, wPatterni))
  110. {
  111. if (uSpansAvail == 0)
  112. {
  113. uSpansAvail = pStpCtx->cLinePix;
  114. hr = ALLOC_SPANS(pStpCtx, &uSpansAvail, &pSpan);
  115. if (hr != DD_OK)
  116. {
  117. // uSpansAvail is set to zero on failure.
  118. goto EH_Exit;
  119. }
  120. }
  121. else
  122. {
  123. pSpan++;
  124. }
  125. uSpansAvail--;
  126. pStpCtx->pPrim->uSpans++;
  127. pSpan->uPix = 1;
  128. pSpan->uX = (UINT16)pStpCtx->iX;
  129. pSpan->uY = (UINT16)pStpCtx->iY;
  130. pStpCtx->pfnFillSpanAttrs(&pStpCtx->Attr, pSpan, pStpCtx, 1);
  131. // Clamp first/last pixel
  132. if (bFirst || pStpCtx->cLinePix == 1)
  133. {
  134. bFirst = FALSE;
  135. ClampPixel(&pStpCtx->Attr, pSpan);
  136. }
  137. }
  138. }
  139. if (--pStpCtx->cLinePix == 0)
  140. {
  141. break;
  142. }
  143. #ifdef VERBOSE_LINES
  144. RSDPF((" %4d,%4d: %10d %11d => ",
  145. pStpCtx->iX, pStpCtx->iY,
  146. pStpCtx->iLineFrac, pStpCtx->iLineFrac + pStpCtx->iDLineFrac));
  147. #endif
  148. pStpCtx->iLineFrac += pStpCtx->iDLineFrac;
  149. if (pStpCtx->iLineFrac < 0)
  150. {
  151. pStpCtx->iLineFrac &= 0x7fffffff;
  152. pStpCtx->iX += pStpCtx->iDXCY;
  153. pStpCtx->iY += pStpCtx->iDYCY;
  154. pStpCtx->DAttrDMajor.ipSurface = pStpCtx->DAttrCY.ipSurface;
  155. pStpCtx->DAttrDMajor.ipZ = pStpCtx->DAttrCY.ipZ;
  156. }
  157. else
  158. {
  159. pStpCtx->iX += pStpCtx->iDXNC;
  160. pStpCtx->iY += pStpCtx->iDYNC;
  161. pStpCtx->DAttrDMajor.ipSurface = pStpCtx->DAttrNC.ipSurface;
  162. pStpCtx->DAttrDMajor.ipZ = pStpCtx->DAttrNC.ipZ;
  163. }
  164. #ifdef VERBOSE_LINES
  165. RSDPFM((DBG_MASK_FORCE | DBG_MASK_NO_PREFIX, "%4d,%4d: %10d\n",
  166. pStpCtx->iX, pStpCtx->iY,
  167. pStpCtx->iLineFrac));
  168. #endif
  169. pStpCtx->pfnAddAttrs(&pStpCtx->Attr, &pStpCtx->DAttrDMajor, pStpCtx);
  170. }
  171. EH_Exit:
  172. if (uSpansAvail > 0)
  173. {
  174. FREE_SPANS(pStpCtx, uSpansAvail);
  175. }
  176. return hr;
  177. }
  178. //----------------------------------------------------------------------------
  179. //
  180. // PrimProcessor::Line
  181. //
  182. // Provides a line for processing.
  183. //
  184. //----------------------------------------------------------------------------
  185. HRESULT
  186. PrimProcessor::Line(LPD3DTLVERTEX pV0,
  187. LPD3DTLVERTEX pV1,
  188. LPD3DTLVERTEX pFlatVtx)
  189. {
  190. HRESULT hr;
  191. hr = DD_OK;
  192. #if DBG
  193. hr = ValidateVertex(pV0);
  194. if (hr != DD_OK)
  195. {
  196. return hr;
  197. }
  198. hr = ValidateVertex(pV1);
  199. if (hr != DD_OK)
  200. {
  201. return hr;
  202. }
  203. #endif
  204. // Clear per-line flags.
  205. m_StpCtx.uFlags &= ~(PRIMF_ALL | LNF_ALL);
  206. RSDPFM((RSM_FLAGS, "m_uPpFlags: 0x%08X, m_StpCtx.uFlags: 0x%08X\n",
  207. m_uPpFlags, m_StpCtx.uFlags));
  208. RSDPFM((RSM_LINES, "Line\n"));
  209. RSDPFM((RSM_LINES, " V0 (%f,%f,%f)\n",
  210. pV0->dvSX, pV0->dvSY, pV0->dvSZ));
  211. RSDPFM((RSM_LINES, " V1 (%f,%f,%f)\n",
  212. pV1->dvSX, pV1->dvSY, pV1->dvSZ));
  213. // Remember flat color controlling vertex for setup.
  214. m_StpCtx.pFlatVtx = pFlatVtx;
  215. if (LineSetup(pV0, pV1))
  216. {
  217. // Compute initial buffer pointers for the scanline.
  218. m_StpCtx.Attr.pSurface = m_StpCtx.pCtx->pSurfaceBits +
  219. m_StpCtx.iX * m_StpCtx.pCtx->iSurfaceStep +
  220. m_StpCtx.iY * m_StpCtx.pCtx->iSurfaceStride;
  221. if (m_StpCtx.uFlags & PRIMSF_Z_USED)
  222. {
  223. m_StpCtx.Attr.pZ = m_StpCtx.pCtx->pZBits +
  224. m_StpCtx.iX * m_StpCtx.pCtx->iZStep +
  225. m_StpCtx.iY * m_StpCtx.pCtx->iZStride;
  226. }
  227. // Line walking only generates single-pixel spans so
  228. // the prim deltas are unused. Therefore, line spans
  229. // are simply added to whatever primitive happens to
  230. // be sitting in the buffer.
  231. hr = AppendPrim();
  232. if (hr != DD_OK)
  233. {
  234. return hr;
  235. }
  236. union
  237. {
  238. D3DLINEPATTERN LPat;
  239. DWORD dwLPat;
  240. } LinePat;
  241. LinePat.dwLPat = m_StpCtx.pCtx->pdwRenderState[D3DRS_LINEPATTERN];
  242. hr = WalkLinePattern(&m_StpCtx, LinePat.LPat.wRepeatFactor, LinePat.LPat.wLinePattern);
  243. }
  244. return hr;
  245. }