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.

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