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.

544 lines
18 KiB

  1. //----------------------------------------------------------------------------
  2. //
  3. // walk.cpp
  4. //
  5. // TriProcessor edge walking methods.
  6. //
  7. // Copyright (C) Microsoft Corporation, 1997.
  8. //
  9. //----------------------------------------------------------------------------
  10. #include "pch.cpp"
  11. #pragma hdrstop
  12. DBG_DECLARE_FILE();
  13. //----------------------------------------------------------------------------
  14. //
  15. // WalkTrapEitherSpans_Any_Clip
  16. //
  17. // Walks the given number of spans, using edge 0 - 2 as the attribute
  18. // edge and the given X and DXDY for the other edge.
  19. // Spans are clipped in X against the current clip rect.
  20. //
  21. // The spans can be split into subspans if required. cPixSplit indicates
  22. // the maximum length span that should be recorded. Any longer spans will
  23. // be cut into multiple span segments.
  24. //
  25. // Calls attribute handler functions so all attributes are supported.
  26. // Attributes are never touched directly so both fixed and float are supported.
  27. //
  28. //----------------------------------------------------------------------------
  29. HRESULT FASTCALL
  30. WalkTrapEitherSpans_Any_Clip(UINT uSpans, PINTCARRYVAL pXOther,
  31. PSETUPCTX pStpCtx, BOOL bAdvanceLast)
  32. {
  33. PD3DI_RASTSPAN pSpan;
  34. HRESULT hr;
  35. INT cTotalPix;
  36. INT cPix;
  37. INT uX, uXO;
  38. BOOL b20Valid;
  39. UINT uSpansAvail;
  40. RSASSERT(uSpans > 0);
  41. hr = D3D_OK;
  42. uSpansAvail = 0;
  43. for (;;)
  44. {
  45. //
  46. // Clip span and compute length. No attributes need to be
  47. // updated here because attributes have already been moved
  48. // inside the clip boundary.
  49. //
  50. uX = pStpCtx->X20.iV;
  51. uXO = pXOther->iV;
  52. b20Valid = TRUE;
  53. RSDPFM((RSM_WALK, "Full span at Y %d, %d - %d\n",
  54. pStpCtx->iY, uX,
  55. (pStpCtx->uFlags & TRIF_X_DEC) ? uXO + 1 : uXO - 1));
  56. if (pStpCtx->uFlags & TRIF_X_DEC)
  57. {
  58. if (uX >= pStpCtx->pCtx->Clip.right)
  59. {
  60. b20Valid = FALSE;
  61. uX = pStpCtx->pCtx->Clip.right - 1;
  62. }
  63. else if (uX < pStpCtx->pCtx->Clip.left &&
  64. pStpCtx->X20.iCY <= 0)
  65. {
  66. // Right edge has crossed the left clip boundary
  67. // travelling left so the remainder of the triangle
  68. // will not be visible.
  69. goto EH_Exit;
  70. }
  71. // -1 because this edge is displaced by one.
  72. if (uXO < pStpCtx->pCtx->Clip.left - 1)
  73. {
  74. uXO = pStpCtx->pCtx->Clip.left - 1;
  75. }
  76. cTotalPix = uX - uXO;
  77. }
  78. else
  79. {
  80. if (uX < pStpCtx->pCtx->Clip.left)
  81. {
  82. b20Valid = FALSE;
  83. uX = pStpCtx->pCtx->Clip.left;
  84. }
  85. else if (uX >= pStpCtx->pCtx->Clip.right &&
  86. pStpCtx->X20.iCY >= 0)
  87. {
  88. // Left edge has crossed the right clip boundary
  89. // travelling right so the remainder of the triangle
  90. // will not be visible.
  91. goto EH_Exit;
  92. }
  93. if (uXO > pStpCtx->pCtx->Clip.right)
  94. {
  95. uXO = pStpCtx->pCtx->Clip.right;
  96. }
  97. cTotalPix = uXO - uX;
  98. }
  99. if (cTotalPix > 0)
  100. {
  101. ATTRSET Attr;
  102. PATTRSET pAttr;
  103. // Start without PWL support since the first iteration doesn't
  104. // have precomputed values.
  105. pStpCtx->uPwlFlags = 0;
  106. pAttr = &pStpCtx->Attr;
  107. for (;;)
  108. {
  109. if (uSpansAvail == 0)
  110. {
  111. // We don't really have a good number to request
  112. // since uSpans could result in any number of span
  113. // fragments after dicing. Using uSpans is OK
  114. // as long as uSpans is relatively large, but if
  115. // uSpans gets small and there's a lot of dicing then
  116. // it would result in excessive AllocSpans calls.
  117. // Try to avoid this problem by lower-bounding the
  118. // request. Any excess spans will be given back
  119. // at the end.
  120. uSpansAvail = min(8, uSpans);
  121. hr = ALLOC_SPANS(pStpCtx, &uSpansAvail, &pSpan);
  122. if (hr != D3D_OK)
  123. {
  124. // uSpansAvail is set to zero on failure.
  125. goto EH_Exit;
  126. }
  127. }
  128. else
  129. {
  130. pSpan++;
  131. }
  132. uSpansAvail--;
  133. pStpCtx->pPrim->uSpans++;
  134. // Split up remaining pixels if necessary.
  135. cPix = min(cTotalPix, pStpCtx->cMaxSpan);
  136. pSpan->uPix = (UINT16)cPix;
  137. pSpan->uX = (UINT16)uX;
  138. pSpan->uY = (UINT16)pStpCtx->iY;
  139. RSDPFM((RSM_WALK, " Seg at Y %d, X %d, %c%d pix (%d, %d)\n",
  140. pStpCtx->iY, uX,
  141. (pStpCtx->uFlags & TRIF_X_DEC) ? '-' : '+',
  142. cPix, cTotalPix, pStpCtx->cMaxSpan));
  143. pStpCtx->pfnFillSpanAttrs(pAttr, pSpan, pStpCtx, cPix);
  144. cTotalPix -= cPix;
  145. if (cTotalPix <= 0)
  146. {
  147. break;
  148. }
  149. // There are still pixels left in the span so the loop's
  150. // going to go around again. Update all the attribute
  151. // values by cPix dX steps.
  152. //
  153. // We don't want to update the real edge attributes so we
  154. // need to work with a copy. We do this lazily to
  155. // avoid the data movement for the normal case where
  156. // the span isn't split.
  157. if (pAttr == &pStpCtx->Attr)
  158. {
  159. Attr = pStpCtx->Attr;
  160. pAttr = &Attr;
  161. }
  162. if (pStpCtx->uFlags & TRIF_X_DEC)
  163. {
  164. uX -= cPix;
  165. }
  166. else
  167. {
  168. uX += cPix;
  169. }
  170. pStpCtx->pfnAddScaledAttrs(pAttr, &pStpCtx->DAttrDX,
  171. pStpCtx, cPix);
  172. }
  173. }
  174. uSpans--;
  175. // If this is truly the last span of the triangle then we can stop,
  176. // but if it's just the last span of the top trapezoid then we
  177. // still need to advance the attributes on the long edge so
  178. // they're correct for the next trapzoid's first span.
  179. if (!bAdvanceLast && uSpans == 0)
  180. {
  181. break;
  182. }
  183. //
  184. // Advance long edge and all attributes.
  185. //
  186. pStpCtx->iY++;
  187. PATTRSET pDelta;
  188. pStpCtx->X20.iFrac += pStpCtx->X20.iDFrac;
  189. if (pStpCtx->X20.iFrac < 0)
  190. {
  191. // Carry step.
  192. pStpCtx->X20.iV += pStpCtx->X20.iCY;
  193. pStpCtx->X20.iFrac &= 0x7fffffff;
  194. pDelta = &pStpCtx->DAttrCY;
  195. }
  196. else
  197. {
  198. // No-carry step.
  199. pStpCtx->X20.iV += pStpCtx->X20.iNC;
  200. pDelta = &pStpCtx->DAttrNC;
  201. }
  202. // See if the edge has crossed a clip boundary.
  203. cPix = 0;
  204. if (b20Valid)
  205. {
  206. // Always take a normal step.
  207. pStpCtx->pfnAddAttrs(&pStpCtx->Attr, pDelta, pStpCtx);
  208. // See if the edge crossed out of the clip rect and if so,
  209. // how far.
  210. if (pStpCtx->uFlags & TRIF_X_DEC)
  211. {
  212. if (pStpCtx->X20.iV >= pStpCtx->pCtx->Clip.right)
  213. {
  214. cPix = pStpCtx->X20.iV - (pStpCtx->pCtx->Clip.right - 1);
  215. }
  216. }
  217. else
  218. {
  219. if (pStpCtx->X20.iV < pStpCtx->pCtx->Clip.left)
  220. {
  221. cPix = pStpCtx->pCtx->Clip.left - pStpCtx->X20.iV;
  222. }
  223. }
  224. }
  225. else
  226. {
  227. // Always step in Y.
  228. pStpCtx->pfnAddAttrs(&pStpCtx->Attr, &pStpCtx->DAttrDY, pStpCtx);
  229. // See if the edge crossed into validity and if so,
  230. // how far.
  231. if (pStpCtx->uFlags & TRIF_X_DEC)
  232. {
  233. if (pStpCtx->X20.iV < pStpCtx->pCtx->Clip.right - 1)
  234. {
  235. cPix = (pStpCtx->pCtx->Clip.right - 1) - pStpCtx->X20.iV;
  236. }
  237. }
  238. else
  239. {
  240. if (pStpCtx->X20.iV > pStpCtx->pCtx->Clip.left)
  241. {
  242. cPix = pStpCtx->X20.iV - pStpCtx->pCtx->Clip.left;
  243. }
  244. }
  245. }
  246. if (cPix > 0)
  247. {
  248. // The edge made a validity transition. Either the
  249. // attributes are sitting back at the edge of validity and
  250. // need to move forward or they've left the clip rect and
  251. // need to move back. Either way, cPix has the
  252. // number of pixels to move in X.
  253. // No precomputed values.
  254. pStpCtx->uPwlFlags = 0;
  255. pStpCtx->pfnAddScaledAttrs(&pStpCtx->Attr, &pStpCtx->DAttrDX,
  256. pStpCtx, cPix);
  257. }
  258. // Long edge updating is done so we can always stop here if we're out
  259. // of spans.
  260. if (uSpans == 0)
  261. {
  262. break;
  263. }
  264. // Advance other edge.
  265. pXOther->iFrac += pXOther->iDFrac;
  266. if (pXOther->iFrac < 0)
  267. {
  268. // Carry step.
  269. pXOther->iV += pXOther->iCY;
  270. pXOther->iFrac &= 0x7fffffff;
  271. }
  272. else
  273. {
  274. // No-carry step.
  275. pXOther->iV += pXOther->iNC;
  276. }
  277. }
  278. EH_Exit:
  279. if (uSpansAvail > 0)
  280. {
  281. FREE_SPANS(pStpCtx, uSpansAvail);
  282. }
  283. return hr;
  284. }
  285. //----------------------------------------------------------------------------
  286. //
  287. // WalkTrapEitherSpans_Any_NoClip
  288. //
  289. // WalkTrapSpans specialized for the trivial-accept clipping case.
  290. // Span dicing is also unsupported.
  291. // Calls attribute handler functions so all attributes are supported.
  292. // Attributes are never touched directly so both fixed and float are supported.
  293. //
  294. //----------------------------------------------------------------------------
  295. HRESULT FASTCALL
  296. WalkTrapEitherSpans_Any_NoClip(UINT uSpans, PINTCARRYVAL pXOther,
  297. PSETUPCTX pStpCtx, BOOL bAdvanceLast)
  298. {
  299. PD3DI_RASTSPAN pSpan;
  300. HRESULT hr;
  301. PINTCARRYVAL pXLeft, pXRight;
  302. UINT uSpansAvail;
  303. RSASSERT(uSpans > 0);
  304. hr = D3D_OK;
  305. if (pStpCtx->uFlags & TRIF_X_DEC)
  306. {
  307. pXLeft = pXOther;
  308. pXRight = &pStpCtx->X20;
  309. }
  310. else
  311. {
  312. pXLeft = &pStpCtx->X20;
  313. pXRight = pXOther;
  314. }
  315. uSpansAvail = 0;
  316. for (;;)
  317. {
  318. if (pXRight->iV > pXLeft->iV)
  319. {
  320. if (uSpansAvail == 0)
  321. {
  322. uSpansAvail = uSpans;
  323. hr = ALLOC_SPANS(pStpCtx, &uSpansAvail, &pSpan);
  324. if (hr != D3D_OK)
  325. {
  326. // uSpansAvail is set to zero on failure.
  327. goto EH_Exit;
  328. }
  329. }
  330. else
  331. {
  332. pSpan++;
  333. }
  334. uSpansAvail--;
  335. pStpCtx->pPrim->uSpans++;
  336. pSpan->uPix = (UINT16)(pXRight->iV - pXLeft->iV);
  337. pSpan->uX = (UINT16)pStpCtx->X20.iV;
  338. pSpan->uY = (UINT16)pStpCtx->iY;
  339. RSDPFM((RSM_WALK, "Span at Y %d, X %d, %c%d pix\n",
  340. pStpCtx->iY, pSpan->uX,
  341. (pStpCtx->uFlags & TRIF_X_DEC) ? '-' : '+',
  342. pSpan->uPix));
  343. pStpCtx->uPwlFlags = 0;
  344. pStpCtx->pfnFillSpanAttrs(&pStpCtx->Attr, pSpan, pStpCtx, 1);
  345. }
  346. uSpans--;
  347. // If this is truly the last span of the triangle then we can stop,
  348. // but if it's just the last span of the top trapezoid then we
  349. // still need to advance the attributes on the long edge so
  350. // they're correct for the next trapzoid's first span.
  351. if (!bAdvanceLast && uSpans == 0)
  352. {
  353. break;
  354. }
  355. //
  356. // Advance long edge and all attributes.
  357. //
  358. pStpCtx->iY++;
  359. PATTRSET pDelta;
  360. pStpCtx->X20.iFrac += pStpCtx->X20.iDFrac;
  361. if (pStpCtx->X20.iFrac < 0)
  362. {
  363. // Carry step.
  364. pStpCtx->X20.iV += pStpCtx->X20.iCY;
  365. pStpCtx->X20.iFrac &= 0x7fffffff;
  366. pDelta = &pStpCtx->DAttrCY;
  367. }
  368. else
  369. {
  370. // No-carry step.
  371. pStpCtx->X20.iV += pStpCtx->X20.iNC;
  372. pDelta = &pStpCtx->DAttrNC;
  373. }
  374. pStpCtx->pfnAddAttrs(&pStpCtx->Attr, pDelta, pStpCtx);
  375. // Long edge updating is done so we can always stop here if we're out
  376. // of spans.
  377. if (uSpans == 0)
  378. {
  379. break;
  380. }
  381. // Advance other edge.
  382. pXOther->iFrac += pXOther->iDFrac;
  383. if (pXOther->iFrac < 0)
  384. {
  385. // Carry step.
  386. pXOther->iV += pXOther->iCY;
  387. pXOther->iFrac &= 0x7fffffff;
  388. }
  389. else
  390. {
  391. // No-carry step.
  392. pXOther->iV += pXOther->iNC;
  393. }
  394. }
  395. EH_Exit:
  396. if (uSpansAvail > 0)
  397. {
  398. FREE_SPANS(pStpCtx, uSpansAvail);
  399. }
  400. return hr;
  401. }
  402. //
  403. // Tables of edge walkers.
  404. // Indexing is with the low four TRISF_*_USED bits.
  405. //
  406. #if !defined(_X86_) || defined(X86_CPP_WALKTRAPSPANS)
  407. #define WalkTrapFloatSpans_Z_Diff_NoClip WalkTrapEitherSpans_Any_NoClip
  408. #define WalkTrapFloatSpans_Z_Diff_Spec_NoClip WalkTrapEitherSpans_Any_NoClip
  409. #define WalkTrapFloatSpans_Z_Diff_Tex1_NoClip WalkTrapEitherSpans_Any_NoClip
  410. #define WalkTrapFloatSpans_Z_Diff_Spec_Tex1_NoClip \
  411. WalkTrapEitherSpans_Any_NoClip
  412. #define WalkTrapFloatSpans_Z_Tex1_Tex2_NoClip WalkTrapEitherSpans_Any_NoClip
  413. #define WalkTrapFloatSpans_Z_DIdx_NoClip WalkTrapEitherSpans_Any_NoClip
  414. #define WalkTrapFloatSpans_Z_DIdx_Tex1_NoClip WalkTrapEitherSpans_Any_NoClip
  415. #define WalkTrapFloatSpans_Z_Tex1_NoClip WalkTrapEitherSpans_Any_NoClip
  416. #define WalkTrapFixedSpans_Z_Diff_NoClip WalkTrapEitherSpans_Any_NoClip
  417. #define WalkTrapFixedSpans_Z_Diff_Spec_NoClip WalkTrapEitherSpans_Any_NoClip
  418. #define WalkTrapFixedSpans_Z_Diff_Tex1_NoClip WalkTrapEitherSpans_Any_NoClip
  419. #define WalkTrapFixedSpans_Z_Diff_Spec_Tex1_NoClip \
  420. WalkTrapEitherSpans_Any_NoClip
  421. #define WalkTrapFixedSpans_Z_Tex1_Tex2_NoClip WalkTrapEitherSpans_Any_NoClip
  422. #define WalkTrapFixedSpans_Z_DIdx_NoClip WalkTrapEitherSpans_Any_NoClip
  423. #define WalkTrapFixedSpans_Z_DIdx_Tex1_NoClip WalkTrapEitherSpans_Any_NoClip
  424. #define WalkTrapFixedSpans_Z_Tex1_NoClip WalkTrapEitherSpans_Any_NoClip
  425. #endif
  426. // Trivial accept walkers.
  427. PFN_WALKTRAPSPANS g_pfnWalkTrapFloatSpansNoClipTable[] =
  428. {
  429. (PFN_WALKTRAPSPANS)DebugBreakFn, /* 0: -2 -1 -S -D */
  430. WalkTrapFloatSpans_Z_Diff_NoClip, /* 1: -2 -1 -S +D */
  431. (PFN_WALKTRAPSPANS)DebugBreakFn, /* 2: -2 -1 +S -D */
  432. WalkTrapFloatSpans_Z_Diff_Spec_NoClip, /* 3: -2 -1 +S +D */
  433. (PFN_WALKTRAPSPANS)DebugBreakFn, /* 4: -2 +1 -S -D */
  434. WalkTrapFloatSpans_Z_Diff_Tex1_NoClip, /* 5: -2 +1 -S +D */
  435. (PFN_WALKTRAPSPANS)DebugBreakFn, /* 6: -2 +1 +S -D */
  436. WalkTrapFloatSpans_Z_Diff_Spec_Tex1_NoClip, /* 7: -2 +1 +S +D */
  437. (PFN_WALKTRAPSPANS)DebugBreakFn, /* 8: +2 -1 -S -D */
  438. (PFN_WALKTRAPSPANS)DebugBreakFn, /* 9: +2 -1 -S +D */
  439. (PFN_WALKTRAPSPANS)DebugBreakFn, /* A: +2 -1 +S -D */
  440. (PFN_WALKTRAPSPANS)DebugBreakFn, /* B: +2 -1 +S +D */
  441. WalkTrapFloatSpans_Z_Tex1_Tex2_NoClip, /* C: +2 +1 -S -D */
  442. (PFN_WALKTRAPSPANS)DebugBreakFn, /* D: +2 +1 -S +D */
  443. (PFN_WALKTRAPSPANS)DebugBreakFn, /* E: +2 +1 +S -D */
  444. (PFN_WALKTRAPSPANS)DebugBreakFn, /* F: +2 +1 +S +D */
  445. };
  446. #ifdef STEP_FIXED
  447. PFN_WALKTRAPSPANS g_pfnWalkTrapFixedSpansNoClipTable[] =
  448. {
  449. (PFN_WALKTRAPSPANS)DebugBreakFn, /* 0: -2 -1 -S -D */
  450. WalkTrapFixedSpans_Z_Diff_NoClip, /* 1: -2 -1 -S +D */
  451. (PFN_WALKTRAPSPANS)DebugBreakFn, /* 2: -2 -1 +S -D */
  452. WalkTrapFixedSpans_Z_Diff_Spec_NoClip, /* 3: -2 -1 +S +D */
  453. (PFN_WALKTRAPSPANS)DebugBreakFn, /* 4: -2 +1 -S -D */
  454. WalkTrapFixedSpans_Z_Diff_Tex1_NoClip, /* 5: -2 +1 -S +D */
  455. (PFN_WALKTRAPSPANS)DebugBreakFn, /* 6: -2 +1 +S -D */
  456. WalkTrapFixedSpans_Z_Diff_Spec_Tex1_NoClip, /* 7: -2 +1 +S +D */
  457. (PFN_WALKTRAPSPANS)DebugBreakFn, /* 8: +2 -1 -S -D */
  458. (PFN_WALKTRAPSPANS)DebugBreakFn, /* 9: +2 -1 -S +D */
  459. (PFN_WALKTRAPSPANS)DebugBreakFn, /* A: +2 -1 +S -D */
  460. (PFN_WALKTRAPSPANS)DebugBreakFn, /* B: +2 -1 +S +D */
  461. WalkTrapFixedSpans_Z_Tex1_Tex2_NoClip, /* C: +2 +1 -S -D */
  462. (PFN_WALKTRAPSPANS)DebugBreakFn, /* D: +2 +1 -S +D */
  463. (PFN_WALKTRAPSPANS)DebugBreakFn, /* E: +2 +1 +S -D */
  464. (PFN_WALKTRAPSPANS)DebugBreakFn, /* F: +2 +1 +S +D */
  465. };
  466. #endif
  467. // Ramp mode trivial accept walkers.
  468. PFN_WALKTRAPSPANS g_pfnRampWalkTrapFloatSpansNoClipTable[] =
  469. {
  470. (PFN_WALKTRAPSPANS)DebugBreakFn, /* 0: -I -1 */
  471. WalkTrapFloatSpans_Z_Tex1_NoClip, /* 1: -I +1 */
  472. WalkTrapFloatSpans_Z_DIdx_NoClip, /* 2: +I -1 */
  473. WalkTrapFloatSpans_Z_DIdx_Tex1_NoClip, /* 3: +I +1 */
  474. };