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