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.

342 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 (m_StpCtx.pCtx->pfnRampOld)
  162. {
  163. m_StpCtx.pCtx->pfnRampOldTri(m_StpCtx.pCtx, pV0, pV1, pV2);
  164. return hr;
  165. }
  166. #if DBG
  167. hr = ValidateVertex(pV0);
  168. if (hr != D3D_OK)
  169. {
  170. RSDPF(("PrimProcessor::Tri, Invalid V0\n"));
  171. return hr;
  172. }
  173. hr = ValidateVertex(pV1);
  174. if (hr != D3D_OK)
  175. {
  176. RSDPF(("PrimProcessor::Tri, Invalid V1\n"));
  177. return hr;
  178. }
  179. hr = ValidateVertex(pV2);
  180. if (hr != D3D_OK)
  181. {
  182. RSDPF(("PrimProcessor::Tri, Invalid V2\n"));
  183. return hr;
  184. }
  185. #endif
  186. // Clear per-triangle flags.
  187. m_StpCtx.uFlags &= ~(PRIMF_ALL | TRIF_ALL);
  188. RSDPFM((RSM_FLAGS, "m_uPpFlags: 0x%08X, m_StpCtx.uFlags: 0x%08X\n",
  189. m_uPpFlags, m_StpCtx.uFlags));
  190. RSDPFM((RSM_TRIS, "Tri\n"));
  191. RSDPFM((RSM_TRIS, " V0 (%f,%f,%f)\n",
  192. pV0->dvSX, pV0->dvSY, pV0->dvSZ));
  193. RSDPFM((RSM_TRIS, " V1 (%f,%f,%f)\n",
  194. pV1->dvSX, pV1->dvSY, pV1->dvSZ));
  195. RSDPFM((RSM_TRIS, " V2 (%f,%f,%f)\n",
  196. pV2->dvSX, pV2->dvSY, pV2->dvSZ));
  197. GET_PRIM();
  198. // Set up the triangle and see if anything was produced.
  199. // Triangles may not be produced due to:
  200. // Face culling.
  201. // Trivial rejection against the clip rect.
  202. // Zero pixel coverage.
  203. if (TriSetup(pV0, pV1, pV2))
  204. {
  205. // Compute initial buffer pointers for the scanline.
  206. m_StpCtx.Attr.pSurface = m_StpCtx.pCtx->pSurfaceBits +
  207. m_StpCtx.iX * m_StpCtx.pCtx->iSurfaceStep +
  208. m_StpCtx.iY * m_StpCtx.pCtx->iSurfaceStride;
  209. if (m_StpCtx.uFlags & PRIMSF_Z_USED)
  210. {
  211. m_StpCtx.Attr.pZ = m_StpCtx.pCtx->pZBits +
  212. m_StpCtx.iX * m_StpCtx.pCtx->iZStep +
  213. m_StpCtx.iY * m_StpCtx.pCtx->iZStride;
  214. }
  215. // uSpans and pNext have already been initialized.
  216. SetTriFunctions();
  217. COMMIT_PRIM(FALSE);
  218. if (m_uHeight10 > 0)
  219. {
  220. hr = m_StpCtx.pfnWalkTrapSpans(m_uHeight10, &m_StpCtx.X10,
  221. &m_StpCtx, m_uHeight21 > 0);
  222. if (hr != D3D_OK)
  223. {
  224. return hr;
  225. }
  226. }
  227. if (m_uHeight21 > 0)
  228. {
  229. hr = m_StpCtx.pfnWalkTrapSpans(m_uHeight21, &m_StpCtx.X21,
  230. &m_StpCtx, FALSE);
  231. if (hr != D3D_OK)
  232. {
  233. return hr;
  234. }
  235. }
  236. #if DBG
  237. if (RSGETFLAGS(DBG_USER_FLAGS) & RSU_FLUSH_AFTER_PRIM)
  238. {
  239. Flush();
  240. }
  241. #endif
  242. }
  243. return hr;
  244. }
  245. #if DBG
  246. //----------------------------------------------------------------------------
  247. //
  248. // PrimProcessor::ValidateVertex
  249. //
  250. // Checks the ranges of verifiable contents of vertex, to avoid setting up
  251. // garbage.
  252. //
  253. //----------------------------------------------------------------------------
  254. inline HRESULT PrimProcessor::ValidateVertex(LPD3DTLVERTEX pV)
  255. {
  256. // from the OptSwExtCaps.dvGuardBand caps.
  257. if ((pV->sx < -32768.f) || (pV->sx > 32767.f) ||
  258. (pV->sy < -32768.f) || (pV->sy > 32767.f))
  259. {
  260. RSDPF(("ValidateVertex: x,y out of guardband range (%f,%f)\n",pV->sx,pV->sy));
  261. return DDERR_INVALIDPARAMS;
  262. }
  263. if (m_StpCtx.pCtx->pdwRenderState[D3DRENDERSTATE_ZENABLE] ||
  264. m_StpCtx.pCtx->pdwRenderState[D3DRENDERSTATE_ZWRITEENABLE])
  265. {
  266. // Allow a little slack for those generating triangles exactly on the
  267. // depth limit. Needed for Quake.
  268. if ((pV->sz < -0.00015f) || (pV->sz > 1.00015f))
  269. {
  270. RSDPF(("ValidateVertex: z out of range (%f)\n",pV->sz));
  271. return DDERR_INVALIDPARAMS;
  272. }
  273. }
  274. if (m_StpCtx.pCtx->cActTex > 0)
  275. {
  276. if (m_StpCtx.pCtx->pdwRenderState[D3DRENDERSTATE_TEXTUREPERSPECTIVE])
  277. {
  278. if (pV->rhw <= 0 )
  279. {
  280. RSDPF(("ValidateVertex: rhw out of range (%f)\n",pV->rhw));
  281. return DDERR_INVALIDPARAMS;
  282. }
  283. }
  284. // from OptSwExtCaps.dwMaxTextureRepeat cap.
  285. if ((pV->tu > 256.0F) || (pV->tu < -256.0F) ||
  286. (pV->tv > 256.0F) || (pV->tv < -256.0F))
  287. {
  288. RSDPF(("ValidateVertex: tu,tv out of range (%f,%f)\n",pV->tu,pV->tv));
  289. return DDERR_INVALIDPARAMS;
  290. }
  291. if (m_StpCtx.pCtx->cActTex > 1)
  292. {
  293. PRAST_GENERIC_VERTEX pGV = (PRAST_GENERIC_VERTEX)pV;
  294. if ((pGV->tu2 > 256.0F) || (pGV->tu2 < -256.0F) ||
  295. (pGV->tv2 > 256.0F) || (pGV->tv2 < -256.0F))
  296. {
  297. RSDPF(("ValidateVertex: tu2,tv2 out of range (%f,%f)\n",pGV->tu2,pGV->tv2));
  298. return DDERR_INVALIDPARAMS;
  299. }
  300. }
  301. }
  302. return D3D_OK;
  303. }
  304. #endif