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.

335 lines
10 KiB

  1. //----------------------------------------------------------------------------
  2. //
  3. // tri.cpp
  4. //
  5. // PrimProcessor top-level triangle methods.
  6. //
  7. // Copyright (C) Microsoft Corporation, 1997.
  8. //
  9. //----------------------------------------------------------------------------
  10. #include "pch.cpp"
  11. #pragma hdrstop
  12. DBG_DECLARE_FILE();
  13. // Disallow fixed-point edge walkers to be chosen or not.
  14. #if 0
  15. #define DISALLOW_FIXED
  16. #endif
  17. // Maximum length of a PWL span. Short to make piecewise-linear
  18. // approximation more accurate.
  19. #define MAX_PWL_SPAN_LEN 16
  20. // Maximum normal span length.
  21. #define MAX_SPAN_LEN 256
  22. //----------------------------------------------------------------------------
  23. //
  24. // PrimProcessor::SetTriFunctions
  25. //
  26. // Set up function pointers for triangle processing.
  27. //
  28. //----------------------------------------------------------------------------
  29. inline void
  30. PrimProcessor::SetTriFunctions(void)
  31. {
  32. #if DBG
  33. if ((RSGETFLAGS(DBG_USER_FLAGS) & RSU_FORCE_PIXEL_SPANS) == 0)
  34. #else
  35. if ((m_StpCtx.uFlags & TRIF_RASTPRIM_OVERFLOW) == 0)
  36. #endif
  37. {
  38. // Valid deltas. If mipmapping or global fog is on then
  39. // only allow short subspans so that they can be done
  40. // reasonably accurately via piecewise linear interpolation.
  41. #ifdef PWL_FOG
  42. if (m_StpCtx.uFlags & (PRIMSF_LOD_USED | PRIMSF_GLOBAL_FOG_USED))
  43. #else
  44. if (m_StpCtx.uFlags & PRIMSF_LOD_USED)
  45. #endif
  46. {
  47. m_StpCtx.cMaxSpan = MAX_PWL_SPAN_LEN;
  48. }
  49. else
  50. {
  51. // No mipmapping so we can handle much larger spans.
  52. // Color values only have 8 bits of fraction so
  53. // we still need to worry about error accumulation.
  54. // Cut long spans to cap accumulated error.
  55. m_StpCtx.cMaxSpan = MAX_SPAN_LEN;
  56. }
  57. }
  58. else
  59. {
  60. // Invalid deltas. There's no way to communicate deltas to
  61. // the span routines so chop spans into pixels.
  62. // This case can only occur with very narrow triangles so
  63. // this isn't as expensive as it might seem at first.
  64. m_StpCtx.cMaxSpan = 1;
  65. }
  66. BOOL bFixed = FALSE;
  67. #ifdef STEP_FIXED
  68. // No ramp support.
  69. RSASSERT(m_StpCtx.pCtx->BeadSet != D3DIBS_RAMP);
  70. #endif
  71. if ((m_StpCtx.uFlags & PRIMF_TRIVIAL_ACCEPT_X) &&
  72. #if DBG
  73. (RSGETFLAGS(DBG_USER_FLAGS) & RSU_FORCE_GENERAL_WALK) == 0 &&
  74. #endif
  75. m_iXWidth <= m_StpCtx.cMaxSpan)
  76. {
  77. if ((m_StpCtx.uFlags & PRIMSF_SLOW_USED) != PRIMSF_Z_USED)
  78. {
  79. // If any slow attrs are on or Z is off use the general
  80. // function.
  81. m_StpCtx.pfnWalkTrapSpans = WalkTrapEitherSpans_Any_NoClip;
  82. }
  83. #if defined(STEP_FIXED) && !defined(DISALLOW_FIXED)
  84. // Attribute conversion can be a dominant cost for
  85. // triangles with very few spans, so avoid using fixed point
  86. // edge walking for them.
  87. else if ((m_StpCtx.uFlags & PRIMF_FIXED_OVERFLOW) == 0 &&
  88. m_uHeight20 > 3)
  89. {
  90. m_StpCtx.pfnWalkTrapSpans =
  91. g_pfnWalkTrapFixedSpansNoClipTable[m_iAttrFnIdx];
  92. bFixed = TRUE;
  93. }
  94. #endif
  95. else if (m_StpCtx.pCtx->BeadSet == D3DIBS_RAMP)
  96. {
  97. m_StpCtx.pfnWalkTrapSpans =
  98. g_pfnRampWalkTrapFloatSpansNoClipTable[m_iAttrFnIdx];
  99. }
  100. else
  101. {
  102. m_StpCtx.pfnWalkTrapSpans =
  103. g_pfnWalkTrapFloatSpansNoClipTable[m_iAttrFnIdx];
  104. }
  105. }
  106. else
  107. {
  108. // No special cases, just a general function.
  109. m_StpCtx.pfnWalkTrapSpans = WalkTrapEitherSpans_Any_Clip;
  110. }
  111. #ifdef STEP_FIXED
  112. if (bFixed)
  113. {
  114. RSASSERT((m_StpCtx.uFlags & PRIMSF_SLOW_USED) == PRIMSF_Z_USED);
  115. m_StpCtx.pfnAddAttrs = g_pfnAddFixedAttrsTable[m_iAttrFnIdx];
  116. m_StpCtx.pfnFillSpanAttrs =
  117. g_pfnFillSpanFixedAttrsTable[m_iAttrFnIdx];
  118. PFN_FLOATATTRSTOFIXED pfnFloatAttrsToFixed;
  119. pfnFloatAttrsToFixed = g_pfnFloatAttrsToFixedTable[m_iAttrFnIdx];
  120. pfnFloatAttrsToFixed(&m_StpCtx.Attr, &m_StpCtx.Attr);
  121. pfnFloatAttrsToFixed(&m_StpCtx.DAttrNC, &m_StpCtx.DAttrNC);
  122. pfnFloatAttrsToFixed(&m_StpCtx.DAttrCY, &m_StpCtx.DAttrCY);
  123. }
  124. else
  125. {
  126. if ((m_StpCtx.uFlags & PRIMSF_SLOW_USED) != PRIMSF_Z_USED)
  127. {
  128. // If any slow attrs are on or Z is off use the general functions.
  129. m_StpCtx.pfnAddAttrs = AddFloatAttrs_Any;
  130. m_StpCtx.pfnFillSpanAttrs = FillSpanFloatAttrs_Any_Either;
  131. }
  132. else
  133. {
  134. m_StpCtx.pfnAddAttrs = g_pfnAddFloatAttrsTable[m_iAttrFnIdx];
  135. m_StpCtx.pfnFillSpanAttrs =
  136. g_pfnFillSpanFloatAttrsTable[m_iAttrFnIdx];
  137. }
  138. }
  139. // Scaled attr functions already set since they only depend on
  140. // m_iAttrFnIdx.
  141. #else // STEP_FIXED
  142. // All attr functions already set since they only depend on
  143. // m_iAttrFnIdx.
  144. #endif // STEP_FIXED
  145. }
  146. //----------------------------------------------------------------------------
  147. //
  148. // PrimProcessor::Tri
  149. //
  150. // Calls triangle setup. If a triangle is produced by setup
  151. // this routine walks edges, generating spans into the buffer.
  152. //
  153. //----------------------------------------------------------------------------
  154. HRESULT
  155. PrimProcessor::Tri(LPD3DTLVERTEX pV0,
  156. LPD3DTLVERTEX pV1,
  157. LPD3DTLVERTEX pV2)
  158. {
  159. HRESULT hr;
  160. hr = D3D_OK;
  161. #if DBG
  162. hr = ValidateVertex(pV0);
  163. if (hr != D3D_OK)
  164. {
  165. RSDPF(("PrimProcessor::Tri, Invalid V0\n"));
  166. return hr;
  167. }
  168. hr = ValidateVertex(pV1);
  169. if (hr != D3D_OK)
  170. {
  171. RSDPF(("PrimProcessor::Tri, Invalid V1\n"));
  172. return hr;
  173. }
  174. hr = ValidateVertex(pV2);
  175. if (hr != D3D_OK)
  176. {
  177. RSDPF(("PrimProcessor::Tri, Invalid V2\n"));
  178. return hr;
  179. }
  180. #endif
  181. // Clear per-triangle flags.
  182. m_StpCtx.uFlags &= ~(PRIMF_ALL | TRIF_ALL);
  183. RSDPFM((RSM_FLAGS, "m_uPpFlags: 0x%08X, m_StpCtx.uFlags: 0x%08X\n",
  184. m_uPpFlags, m_StpCtx.uFlags));
  185. RSDPFM((RSM_TRIS, "Tri\n"));
  186. RSDPFM((RSM_TRIS, " V0 (%f,%f,%f)\n",
  187. pV0->dvSX, pV0->dvSY, pV0->dvSZ));
  188. RSDPFM((RSM_TRIS, " V1 (%f,%f,%f)\n",
  189. pV1->dvSX, pV1->dvSY, pV1->dvSZ));
  190. RSDPFM((RSM_TRIS, " V2 (%f,%f,%f)\n",
  191. pV2->dvSX, pV2->dvSY, pV2->dvSZ));
  192. GET_PRIM();
  193. // Set up the triangle and see if anything was produced.
  194. // Triangles may not be produced due to:
  195. // Face culling.
  196. // Trivial rejection against the clip rect.
  197. // Zero pixel coverage.
  198. if (TriSetup(pV0, pV1, pV2))
  199. {
  200. // Compute initial buffer pointers for the scanline.
  201. m_StpCtx.Attr.pSurface = m_StpCtx.pCtx->pSurfaceBits +
  202. m_StpCtx.iX * m_StpCtx.pCtx->iSurfaceStep +
  203. m_StpCtx.iY * m_StpCtx.pCtx->iSurfaceStride;
  204. if (m_StpCtx.uFlags & PRIMSF_Z_USED)
  205. {
  206. m_StpCtx.Attr.pZ = m_StpCtx.pCtx->pZBits +
  207. m_StpCtx.iX * m_StpCtx.pCtx->iZStep +
  208. m_StpCtx.iY * m_StpCtx.pCtx->iZStride;
  209. }
  210. // uSpans and pNext have already been initialized.
  211. SetTriFunctions();
  212. COMMIT_PRIM(FALSE);
  213. if (m_uHeight10 > 0)
  214. {
  215. hr = m_StpCtx.pfnWalkTrapSpans(m_uHeight10, &m_StpCtx.X10,
  216. &m_StpCtx, m_uHeight21 > 0);
  217. if (hr != D3D_OK)
  218. {
  219. return hr;
  220. }
  221. }
  222. if (m_uHeight21 > 0)
  223. {
  224. hr = m_StpCtx.pfnWalkTrapSpans(m_uHeight21, &m_StpCtx.X21,
  225. &m_StpCtx, FALSE);
  226. if (hr != D3D_OK)
  227. {
  228. return hr;
  229. }
  230. }
  231. #if DBG
  232. if (RSGETFLAGS(DBG_USER_FLAGS) & RSU_FLUSH_AFTER_PRIM)
  233. {
  234. Flush();
  235. }
  236. #endif
  237. }
  238. return hr;
  239. }
  240. #if DBG
  241. //----------------------------------------------------------------------------
  242. //
  243. // PrimProcessor::ValidateVertex
  244. //
  245. // Checks the ranges of verifiable contents of vertex, to avoid setting up
  246. // garbage.
  247. //
  248. //----------------------------------------------------------------------------
  249. inline HRESULT PrimProcessor::ValidateVertex(LPD3DTLVERTEX pV)
  250. {
  251. // from the OptSwExtCaps.dvGuardBand caps.
  252. if ((pV->sx < -32768.f) || (pV->sx > 32767.f) ||
  253. (pV->sy < -32768.f) || (pV->sy > 32767.f))
  254. {
  255. RSDPF(("ValidateVertex: x,y out of guardband range (%f,%f)\n",pV->sx,pV->sy));
  256. return DDERR_INVALIDPARAMS;
  257. }
  258. if (m_StpCtx.pCtx->pdwRenderState[D3DRENDERSTATE_ZENABLE] ||
  259. m_StpCtx.pCtx->pdwRenderState[D3DRENDERSTATE_ZWRITEENABLE])
  260. {
  261. // Allow a little slack for those generating triangles exactly on the
  262. // depth limit. Needed for Quake.
  263. if ((pV->sz < -0.00015f) || (pV->sz > 1.00015f))
  264. {
  265. RSDPF(("ValidateVertex: z out of range (%f)\n",pV->sz));
  266. return DDERR_INVALIDPARAMS;
  267. }
  268. }
  269. if (m_StpCtx.pCtx->cActTex > 0)
  270. {
  271. if (m_StpCtx.pCtx->pdwRenderState[D3DRENDERSTATE_TEXTUREPERSPECTIVE])
  272. {
  273. if (pV->rhw <= 0 )
  274. {
  275. RSDPF(("ValidateVertex: rhw out of range (%f)\n",pV->rhw));
  276. return DDERR_INVALIDPARAMS;
  277. }
  278. }
  279. // from OptSwExtCaps.dwMaxTextureRepeat cap.
  280. if ((pV->tu > 256.0F) || (pV->tu < -256.0F) ||
  281. (pV->tv > 256.0F) || (pV->tv < -256.0F))
  282. {
  283. RSDPF(("ValidateVertex: tu,tv out of range (%f,%f)\n",pV->tu,pV->tv));
  284. return DDERR_INVALIDPARAMS;
  285. }
  286. if (m_StpCtx.pCtx->cActTex > 1)
  287. {
  288. PRAST_GENERIC_VERTEX pGV = (PRAST_GENERIC_VERTEX)pV;
  289. if ((pGV->texCoord[1].tu > 256.0F) || (pGV->texCoord[1].tu < -256.0F) ||
  290. (pGV->texCoord[1].tv > 256.0F) || (pGV->texCoord[1].tv < -256.0F))
  291. {
  292. RSDPF(("ValidateVertex: texCoord[1].tu,texCoord[1].tv out of range (%f,%f)\n",pGV->texCoord[1].tu,pGV->texCoord[1].tv));
  293. return DDERR_INVALIDPARAMS;
  294. }
  295. }
  296. }
  297. return D3D_OK;
  298. }
  299. #endif