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.

1446 lines
52 KiB

  1. //-----------------------------------------------------------------------------
  2. //
  3. // This file contains the span state validation function.
  4. //
  5. // Copyright (C) Microsoft Corporation, 1997.
  6. //
  7. //-----------------------------------------------------------------------------
  8. #include "rgb_pch.h"
  9. #pragma hdrstop
  10. include(`bead.mh')
  11. #include "BdStr_mh.h"
  12. #include "RastCap.h"
  13. #include "RastColl.h"
  14. #include "spindbg.hpp"
  15. static CRastCollection g_RastCollection;
  16. UINT16 g_uDitherTable[16] =
  17. {
  18. 0x00, 0x80, 0x20, 0xa0,
  19. 0xc0, 0x40, 0xe0, 0x60,
  20. 0x30, 0xb0, 0x10, 0x90,
  21. 0xf0, 0x70, 0xd0, 0x50
  22. };
  23. //-----------------------------------------------------------------------------
  24. //
  25. // DoZCompareSetup
  26. //
  27. // Initializes arithmetic Z compare state based on the Z test function.
  28. //
  29. //-----------------------------------------------------------------------------
  30. void DoZCompareSetup(PD3DI_RASTCTX pCtx, BOOL bIsMMX)
  31. {
  32. INT32 iXorMask;
  33. if (bIsMMX)
  34. {
  35. iXorMask = -1;
  36. }
  37. else
  38. {
  39. iXorMask = 1;
  40. }
  41. D3DCMPFUNC ZFunc = (D3DCMPFUNC)pCtx->pdwRenderState[D3DRS_ZFUNC];
  42. if (!pCtx->pdwRenderState[D3DRS_ZENABLE])
  43. {
  44. // setup ALWAYS if Z is not enabled, since we may be going into
  45. // the test beads for other reasons (like stencil)
  46. ZFunc = D3DCMP_ALWAYS;
  47. }
  48. switch (ZFunc)
  49. {
  50. case D3DCMP_NEVER:
  51. pCtx->iZAndMask = 0; pCtx->iZNeg = 0; pCtx->iZXorMask = iXorMask;
  52. break;
  53. case D3DCMP_ALWAYS:
  54. pCtx->iZAndMask = 0; pCtx->iZNeg = 0; pCtx->iZXorMask = 0;
  55. break;
  56. case D3DCMP_LESS:
  57. pCtx->iZAndMask = ~0; pCtx->iZNeg = 0; pCtx->iZXorMask = iXorMask;
  58. break;
  59. case D3DCMP_GREATEREQUAL:
  60. pCtx->iZAndMask = ~0; pCtx->iZNeg = 0; pCtx->iZXorMask = 0;
  61. break;
  62. case D3DCMP_EQUAL:
  63. pCtx->iZAndMask = 0x7fffffff; pCtx->iZNeg = 1; pCtx->iZXorMask =
  64. iXorMask;
  65. break;
  66. case D3DCMP_NOTEQUAL:
  67. pCtx->iZAndMask = 0x7fffffff; pCtx->iZNeg = 1; pCtx->iZXorMask = 0;
  68. break;
  69. default:
  70. case D3DCMP_LESSEQUAL:
  71. pCtx->iZAndMask = ~0; pCtx->iZNeg = 1; pCtx->iZXorMask = iXorMask;
  72. break;
  73. case D3DCMP_GREATER:
  74. pCtx->iZAndMask = ~0; pCtx->iZNeg = 1; pCtx->iZXorMask = 0;
  75. break;
  76. }
  77. if (bIsMMX)
  78. {
  79. pCtx->iZXorMask = ~pCtx->iZXorMask;
  80. }
  81. }
  82. //-----------------------------------------------------------------------------
  83. //
  84. // DoACompareSetup
  85. //
  86. // Initializes arithmetic alpha compare state based on the alpha test function.
  87. //
  88. //-----------------------------------------------------------------------------
  89. void DoACompareSetup(PD3DI_RASTCTX pCtx, BOOL bIsMMX)
  90. {
  91. INT32 iXorMask;
  92. if (bIsMMX)
  93. {
  94. iXorMask = -1;
  95. }
  96. else
  97. {
  98. iXorMask = 1;
  99. }
  100. switch ((D3DCMPFUNC)pCtx->pdwRenderState[D3DRS_ALPHAFUNC])
  101. {
  102. case D3DCMP_NEVER:
  103. pCtx->iAAndMask = 0; pCtx->iANeg = 0; pCtx->iAXorMask = iXorMask;
  104. break;
  105. default:
  106. case D3DCMP_ALWAYS:
  107. pCtx->iAAndMask = 0; pCtx->iANeg = 0; pCtx->iAXorMask = 0;
  108. break;
  109. case D3DCMP_LESS:
  110. pCtx->iAAndMask = ~0; pCtx->iANeg = 0; pCtx->iAXorMask = iXorMask;
  111. break;
  112. case D3DCMP_GREATEREQUAL:
  113. pCtx->iAAndMask = ~0; pCtx->iANeg = 0; pCtx->iAXorMask = 0;
  114. break;
  115. case D3DCMP_EQUAL:
  116. pCtx->iAAndMask = 0x7fffffff; pCtx->iANeg = 1; pCtx->iAXorMask =
  117. iXorMask;
  118. break;
  119. case D3DCMP_NOTEQUAL:
  120. pCtx->iAAndMask = 0x7fffffff; pCtx->iANeg = 1; pCtx->iAXorMask = 0;
  121. break;
  122. case D3DCMP_LESSEQUAL:
  123. pCtx->iAAndMask = ~0; pCtx->iANeg = 1; pCtx->iAXorMask = iXorMask;
  124. break;
  125. case D3DCMP_GREATER:
  126. pCtx->iAAndMask = ~0; pCtx->iANeg = 1; pCtx->iAXorMask = 0;
  127. break;
  128. }
  129. if (bIsMMX)
  130. {
  131. pCtx->iAXorMask = ~pCtx->iAXorMask;
  132. }
  133. // iARef is an 8.8 ALPHAREF value for use by RGB and MMX.
  134. // D3DRS_ALPHAREF is now an 8 bit (0xff max) value.
  135. pCtx->iARef = pCtx->pdwRenderState[D3DRS_ALPHAREF] << 8;
  136. }
  137. //-----------------------------------------------------------------------------
  138. //
  139. // DoSCompareSetup
  140. //
  141. // Initializes arithmetic stencil compare state based on the stencil function.
  142. //
  143. //-----------------------------------------------------------------------------
  144. void DoSCompareSetup(PD3DI_RASTCTX pCtx, BOOL bIsMMX)
  145. {
  146. INT32 iXorMask;
  147. if (bIsMMX)
  148. {
  149. iXorMask = -1;
  150. }
  151. else
  152. {
  153. iXorMask = 1;
  154. }
  155. switch ((D3DCMPFUNC)pCtx->pdwRenderState[D3DRS_STENCILFUNC])
  156. {
  157. case D3DCMP_NEVER:
  158. pCtx->iSAndMask = 0; pCtx->iSNeg = 0; pCtx->iSXorMask = iXorMask;
  159. break;
  160. default:
  161. case D3DCMP_ALWAYS:
  162. pCtx->iSAndMask = 0; pCtx->iSNeg = 0; pCtx->iSXorMask = 0;
  163. break;
  164. case D3DCMP_LESS:
  165. pCtx->iSAndMask = ~0; pCtx->iSNeg = 0; pCtx->iSXorMask = iXorMask;
  166. break;
  167. case D3DCMP_GREATEREQUAL:
  168. pCtx->iSAndMask = ~0; pCtx->iSNeg = 0; pCtx->iSXorMask = 0;
  169. break;
  170. case D3DCMP_EQUAL:
  171. pCtx->iSAndMask = 0x7fffffff; pCtx->iSNeg = 1; pCtx->iSXorMask =
  172. iXorMask;
  173. break;
  174. case D3DCMP_NOTEQUAL:
  175. pCtx->iSAndMask = 0x7fffffff; pCtx->iSNeg = 1; pCtx->iSXorMask = 0;
  176. break;
  177. case D3DCMP_LESSEQUAL:
  178. pCtx->iSAndMask = ~0; pCtx->iSNeg = 1; pCtx->iSXorMask = iXorMask;
  179. break;
  180. case D3DCMP_GREATER:
  181. pCtx->iSAndMask = ~0; pCtx->iSNeg = 1; pCtx->iSXorMask = 0;
  182. break;
  183. }
  184. if (bIsMMX)
  185. {
  186. pCtx->iSXorMask = ~pCtx->iSXorMask;
  187. }
  188. }
  189. //-----------------------------------------------------------------------------
  190. //
  191. // DoTexAddrSetup
  192. //
  193. // Initializes arithmetic texture address state state based on the texture
  194. // address function. iTex is the texure to setup.
  195. //
  196. //-----------------------------------------------------------------------------
  197. void DoTexAddrSetup(PD3DI_RASTCTX pCtx, INT32 iTex)
  198. {
  199. PD3DI_SPANTEX pTex = pCtx->pTexture[iTex];
  200. // Note that it is essential to turn on mirroring when in CLAMP/BORDER mode
  201. // to avoid filtering artifacts at the edge of the texture
  202. switch (pTex->TexAddrU)
  203. {
  204. default:
  205. case D3DTADDRESS_WRAP:
  206. pTex->iFlipMaskU = 0; pTex->iClampMinU = 0;
  207. pTex->iClampMaxU = 0; pTex->iClampEnU = 0; break;
  208. case D3DTADDRESS_MIRROR:
  209. pTex->iFlipMaskU = pTex->uMaskU+1; pTex->iClampMinU = 0;
  210. pTex->iClampMaxU = 0; pTex->iClampEnU = 0; break;
  211. case D3DTADDRESS_CLAMP:
  212. pTex->iFlipMaskU = pTex->uMaskU+1; pTex->iClampMinU = 0;
  213. pTex->iClampMaxU = pTex->uMaskU; pTex->iClampEnU = -1; break;
  214. case D3DTADDRESS_BORDER:
  215. pTex->iFlipMaskU = pTex->uMaskU+1; pTex->iClampMinU = -1;
  216. pTex->iClampMaxU = -1; pTex->iClampEnU = -1; break;
  217. }
  218. switch (pTex->TexAddrV)
  219. {
  220. default:
  221. case D3DTADDRESS_WRAP:
  222. pTex->iFlipMaskV = 0; pTex->iClampMinV = 0;
  223. pTex->iClampMaxV = 0; pTex->iClampEnV = 0; break;
  224. case D3DTADDRESS_MIRROR:
  225. pTex->iFlipMaskV = pTex->uMaskV+1; pTex->iClampMinV = 0;
  226. pTex->iClampMaxV = 0; pTex->iClampEnV = 0; break;
  227. case D3DTADDRESS_CLAMP:
  228. pTex->iFlipMaskV = pTex->uMaskV+1; pTex->iClampMinV = 0;
  229. pTex->iClampMaxV = pTex->uMaskV; pTex->iClampEnV = -1; break;
  230. case D3DTADDRESS_BORDER:
  231. pTex->iFlipMaskV = pTex->uMaskV+1; pTex->iClampMinV = -1;
  232. pTex->iClampMaxV = -1; pTex->iClampEnV = -1; break;
  233. }
  234. }
  235. // CMMX is no longer linked in
  236. // extern BEADTABLE g_CMMX_BeadTbl;
  237. extern BEADTABLE g_C_BeadTbl;
  238. #ifdef _X86_
  239. extern BEADTABLE g_MMX_BeadTbl;
  240. #else
  241. BEADTABLE g_MMX_BeadTbl = g_C_BeadTbl;
  242. #endif
  243. #if 0 && DBG
  244. #define RANGE_CHECK(val,max) DDASSERT(((val) >= 0) && ((val) < (max)))
  245. #else
  246. #define RANGE_CHECK(val,max)
  247. #endif
  248. // #undef DPF_MODNAME
  249. // #define DPF_MODNAME "SpanInit"
  250. //-----------------------------------------------------------------------------
  251. //
  252. // SpanInit
  253. //
  254. // Initializes derived state (function pointers and arithmetic compare values)
  255. // based on the render state, surface type, etc.
  256. //
  257. //-----------------------------------------------------------------------------
  258. HRESULT SpanInit(PD3DI_RASTCTX pCtx)
  259. {
  260. int iZTest,
  261. iZFormat,
  262. iZWrite,
  263. iZFunc,
  264. iZDeferred,
  265. iStencil,
  266. iAlphaTest,
  267. iShadeMode,
  268. iSpecular,
  269. iVertexFog,
  270. iTexture,
  271. iTextureAddr[D3DHAL_TSS_MAXSTAGES],
  272. iTextureBorder[D3DHAL_TSS_MAXSTAGES],
  273. iTexturePerspective,
  274. iTextureFilter[D3DHAL_TSS_MAXSTAGES],
  275. iTextureMip[D3DHAL_TSS_MAXSTAGES],
  276. iTextureLOD[D3DHAL_TSS_MAXSTAGES],
  277. iTextureFormat[D3DHAL_TSS_MAXSTAGES],
  278. iTextureColorKey[D3DHAL_TSS_MAXSTAGES],
  279. iTextureBlend,
  280. iTextureAlphaOverride[D3DHAL_TSS_MAXSTAGES],
  281. iMono,
  282. iAlphaBlend,
  283. iAlphaDither,
  284. iBlend,
  285. iROP,
  286. iSrcBlend,
  287. iDestBlend,
  288. iTargetPixelFormat,
  289. iDither;
  290. PFNRENDERSPANS pfnRenderSpans;
  291. PFNSPANLAYER pfnTexAddr[D3DHAL_TSS_MAXSTAGES],
  292. pfnColorBlend,
  293. pfnColorGen;
  294. PBEADTABLE pBeadTable;
  295. CRastCapRecord RastCapRec;
  296. #if DBG
  297. if (SPIGETFLAGS(DBG_USER_FLAGS) & SPIU_BREAK_ON_SPANINIT)
  298. {
  299. DebugBreak();
  300. }
  301. #endif
  302. switch (pCtx->BeadSet)
  303. {
  304. #ifdef _X86_
  305. // Uncomment these (and comment out cases below) to test MMX on legacy code
  306. // case D3DIBS_CMMX:
  307. // case D3DIBS_C:
  308. case D3DIBS_MMXASRGB: // this is only different in pCtx->BeadSet for identification
  309. case D3DIBS_MMX:
  310. pBeadTable = &g_MMX_BeadTbl;
  311. break;
  312. #endif
  313. default:
  314. SPIDPFM((SPIM_INVALID,"Invalid BeadSet %d\n",
  315. pCtx->BeadSet));
  316. // fall through
  317. case D3DIBS_CMMX: // CMMX code is no longer used, make this behave the same as C
  318. case D3DIBS_C:
  319. pBeadTable = &g_C_BeadTbl;
  320. break;
  321. }
  322. DoZCompareSetup(pCtx, (pBeadTable == &g_MMX_BeadTbl));
  323. DoACompareSetup(pCtx, (pBeadTable == &g_MMX_BeadTbl));
  324. DoSCompareSetup(pCtx, (pBeadTable == &g_MMX_BeadTbl));
  325. // The function pointers that point to various beads are stored in
  326. // multi-dimensional arrays. In order to access the correct bead, we
  327. // use numerical indices into these arrays. The indices are either
  328. // the exact value of the renderstate used to choose the bead, or are
  329. // values chosen by looking at the value of the renderstate.
  330. // values needed to choose Test and AlphaTest beads
  331. iZTest = (pCtx->pdwRenderState[D3DRS_ZENABLE] ||
  332. pCtx->pdwRenderState[D3DRS_STENCILENABLE]) ? 1 : 0;
  333. RastCapRec.Set_ZTest(iZTest);
  334. switch (pCtx->iZBitCount)
  335. {
  336. default :
  337. SPIDPFM((SPIM_INVALID,"Invalid Z surface bit count, iZBitCount == 0x%x\n",
  338. pCtx->iZBitCount));
  339. case 0 :
  340. case 16 :
  341. iZFormat = 0;
  342. break;
  343. case 32 :
  344. iZFormat = 1;
  345. break;
  346. }
  347. RastCapRec.Set_ZFormat(iZFormat);
  348. iZWrite = pCtx->pdwRenderState[D3DRS_ZWRITEENABLE] ? 1 : 0;
  349. RastCapRec.Set_ZWrite(iZWrite);
  350. switch (pCtx->pdwRenderState[D3DRS_ZFUNC])
  351. {
  352. case D3DCMP_NEVER :
  353. case D3DCMP_ALWAYS :
  354. iZFunc = 0;
  355. break;
  356. case D3DCMP_LESS :
  357. case D3DCMP_GREATEREQUAL :
  358. iZFunc = 1;
  359. break;
  360. case D3DCMP_EQUAL :
  361. case D3DCMP_NOTEQUAL :
  362. iZFunc = 2;
  363. break;
  364. default :
  365. SPIDPFM((SPIM_INVALID,"Invalid renderstate value, D3DRS_ZFUNC == 0x%x\n",
  366. pCtx->pdwRenderState[D3DRS_ZFUNC]));
  367. case D3DCMP_LESSEQUAL :
  368. case D3DCMP_GREATER :
  369. iZFunc = 3;
  370. break;
  371. }
  372. if (!pCtx->pdwRenderState[D3DRS_ZENABLE])
  373. {
  374. // setup ALWAYS if Z is not enabled, since we may be going into
  375. // the test beads for other reasons (like stencil)
  376. iZFunc = 0;
  377. iZWrite = 0; // do not write iterated Z, but stencil will be written if needed
  378. }
  379. RastCapRec.Set_ZFunc(iZFunc);
  380. // Ignore stipple (D3DRENDERSTATE_STIPPLEENABLE), since no software rasterizers do it.
  381. RastCapRec.Set_Stipple(0);
  382. iAlphaTest = pCtx->pdwRenderState[D3DRS_ALPHATESTENABLE] ? 1 : 0;
  383. RastCapRec.Set_AlphaTest(iAlphaTest);
  384. iStencil = pCtx->pdwRenderState[D3DRS_STENCILENABLE] ? 1 : 0;
  385. RastCapRec.Set_Stencil(iStencil);
  386. // values needed for TestFail, TexAddr1 and ColorGen beads
  387. switch (pCtx->pdwRenderState[D3DRS_SHADEMODE])
  388. {
  389. case D3DSHADE_FLAT :
  390. iShadeMode = 0;
  391. break;
  392. default :
  393. SPIDPFM((SPIM_INVALID,"Invalid renderstate value, D3DRS_SHADEMODE == 0x%x\n",
  394. pCtx->pdwRenderState[D3DRS_SHADEMODE]));
  395. case D3DSHADE_GOURAUD :
  396. case D3DSHADE_PHONG :
  397. iShadeMode = 1;
  398. break;
  399. }
  400. RastCapRec.Set_ShadeMode(iShadeMode);
  401. iSpecular = pCtx->pdwRenderState[D3DRS_SPECULARENABLE] ? 1 : 0;
  402. RastCapRec.Set_Specular(iSpecular);
  403. iVertexFog = pCtx->pdwRenderState[D3DRS_FOGENABLE] ? 1 : 0;
  404. RastCapRec.Set_VertexFog(iVertexFog);
  405. // turn on alpha dither for color key so the pixels go away for
  406. // the software rasterizers
  407. iAlphaDither = (false&& pCtx->pdwRenderState[D3DRENDERSTATE_COLORKEYENABLE] ? 1 : 0);
  408. // are we texturing at all?
  409. if (pCtx->cActTex == 0) {
  410. iTexture = 0;
  411. RastCapRec.Set_Texture(iTexture);
  412. iTextureBlend = 0;
  413. RastCapRec.Set_TextureBlend(iTextureBlend);
  414. iTexturePerspective = 0;
  415. RastCapRec.Set_TexturePersp(iTexturePerspective);
  416. iTextureAlphaOverride[0] = 0;
  417. RastCapRec.Set_TextureAlphaOverride(0, iTextureAlphaOverride[0]);
  418. iTextureColorKey[0] = 0;
  419. RastCapRec.Set_TextureColorKey(0, iTextureColorKey[0]);
  420. } else {
  421. iTexturePerspective =
  422. (true|| pCtx->pdwRenderState[D3DRENDERSTATE_TEXTUREPERSPECTIVE] ? 1 : 0);
  423. RastCapRec.Set_TexturePersp(iTexturePerspective);
  424. if (iTexturePerspective) {
  425. iTexture = 2;
  426. } else {
  427. iTexture = 1;
  428. }
  429. // If Multi-texture then iTexture must be incremented by two. This only effects fail cases.
  430. if (!(pCtx->pdwTextureStageState[1][D3DTSS_COLOROP] == D3DTOP_DISABLE))
  431. {
  432. iTexture += 2;
  433. }
  434. RastCapRec.Set_Texture(iTexture);
  435. for (INT32 i = 0; i < (INT32)pCtx->cActTex; i++)
  436. {
  437. DoTexAddrSetup(pCtx, i);
  438. // values needed to choose TexAddr bead, TexRead routine
  439. // easiest to deal with border separately
  440. if ((pCtx->pTexture[i]->TexAddrU == D3DTADDRESS_BORDER) ||
  441. (pCtx->pTexture[i]->TexAddrV == D3DTADDRESS_BORDER)) {
  442. iTextureBorder[i] = 1;
  443. } else {
  444. iTextureBorder[i] = 0;
  445. }
  446. RastCapRec.Set_TextureBorder(i, iTextureBorder[i]);
  447. switch (pCtx->pTexture[i]->TexAddrU)
  448. {
  449. default :
  450. SPIDPFM((SPIM_INVALID,"Invalid texture address mode, TexAddrU == 0x%x\n",
  451. pCtx->pTexture[i]->TexAddrU));
  452. case D3DTADDRESS_WRAP :
  453. if ((pCtx->pTexture[i]->TexAddrV == D3DTADDRESS_WRAP) ||
  454. (pCtx->pTexture[i]->TexAddrV == D3DTADDRESS_MIRROR)) {
  455. iTextureAddr[i] = 0;
  456. } else {
  457. iTextureAddr[i] = 1;
  458. }
  459. break;
  460. case D3DTADDRESS_MIRROR :
  461. if ((pCtx->pTexture[i]->TexAddrV == D3DTADDRESS_WRAP) ||
  462. (pCtx->pTexture[i]->TexAddrV == D3DTADDRESS_MIRROR)) {
  463. iTextureAddr[i] = 0;
  464. } else {
  465. iTextureAddr[i] = 1;
  466. }
  467. break;
  468. case D3DTADDRESS_CLAMP :
  469. iTextureAddr[i] = 1;
  470. break;
  471. case D3DTADDRESS_BORDER :
  472. iTextureAddr[i] = 1;
  473. break;
  474. }
  475. RastCapRec.Set_TextureAddr(i, iTextureAddr[i]);
  476. if (i >= 1)
  477. {
  478. // no LOD info for second texture or later, just use uMagFilter
  479. switch (pCtx->pTexture[i]->uMagFilter)
  480. {
  481. default :
  482. SPIDPFM((SPIM_INVALID,"Invalid texture filter mode, uMagFilter == 0x%x\n",
  483. pCtx->pTexture[i]->uMagFilter));
  484. case D3DTFG_POINT :
  485. iTextureFilter[i] = 0;
  486. break;
  487. case D3DTFG_LINEAR :
  488. case D3DTFG_FLATCUBIC:
  489. case D3DTFG_GAUSSIANCUBIC:
  490. case D3DTFG_ANISOTROPIC:
  491. iTextureFilter[i] = 1;
  492. break;
  493. }
  494. iTextureMip[i] = 0;
  495. iTextureLOD[i] = 0;
  496. }
  497. else
  498. {
  499. switch (pCtx->pTexture[i]->uMagFilter)
  500. {
  501. default :
  502. SPIDPFM((SPIM_INVALID,"Invalid texture filter mode, uMagFilter == 0x%x\n",
  503. pCtx->pTexture[i]->uMagFilter));
  504. case D3DTFG_POINT :
  505. if (pCtx->pTexture[i]->uMinFilter == D3DTFN_POINT)
  506. {
  507. iTextureFilter[i] = 0;
  508. }
  509. else
  510. {
  511. iTextureFilter[i] = 2;
  512. }
  513. break;
  514. case D3DTFG_LINEAR :
  515. case D3DTFG_FLATCUBIC:
  516. case D3DTFG_GAUSSIANCUBIC:
  517. case D3DTFG_ANISOTROPIC:
  518. if (pCtx->pTexture[i]->uMinFilter == D3DTFN_LINEAR)
  519. {
  520. iTextureFilter[i] = 1;
  521. }
  522. else
  523. {
  524. iTextureFilter[i] = 2;
  525. }
  526. break;
  527. }
  528. iTextureLOD[i] = 1;
  529. if ( (i == 0) && (pCtx->pTexture[i]->uMipFilter == D3DTFP_LINEAR) )
  530. {
  531. iTextureMip[i] = 1;
  532. }
  533. else
  534. {
  535. iTextureMip[i] = 0;
  536. // only set LOD to 0 if not mip filtering AND it is NOT the maybe
  537. // bilinear filter case
  538. if ( (pCtx->pTexture[i]->uMipFilter == D3DTFP_NONE) && (iTextureFilter[i] != 2) )
  539. {
  540. iTextureLOD[i] = 0;
  541. }
  542. }
  543. }
  544. RastCapRec.Set_TextureFilter(i, iTextureFilter[i]);
  545. RastCapRec.Set_TextureMip(i, iTextureMip[i]);
  546. RastCapRec.Set_TextureLOD(i, iTextureLOD[i]);
  547. // set iTextureAlphaOverride if texture doesn't have an alpha and should use
  548. // iterated alpha
  549. iTextureAlphaOverride[i] = 0;
  550. RastCapRec.Set_TextureAlphaOverride(i, iTextureAlphaOverride[i]);
  551. // values needed to chose TexRead routine
  552. switch(pCtx->pTexture[i]->Format)
  553. {
  554. default :
  555. SPIDPFM((SPIM_INVALID,"Invalid texture surface bit count, "
  556. "Format == 0x%x\n",(DWORD) pCtx->pTexture[i]->Format));
  557. return DDERR_INVALIDPARAMS;
  558. case D3DI_SPTFMT_B8G8R8 :
  559. iTextureFormat[i] = 0;
  560. iTextureAlphaOverride[i] = 1;
  561. break;
  562. case D3DI_SPTFMT_B8G8R8A8 :
  563. iTextureFormat[i] = 1;
  564. break;
  565. case D3DI_SPTFMT_B8G8R8X8 :
  566. // still necessary to select texture read that sets alpha to 0xff
  567. // for alpha dither
  568. iTextureFormat[i] = 0;
  569. iTextureAlphaOverride[i] = 1;
  570. break;
  571. case D3DI_SPTFMT_B5G6R5 :
  572. iTextureFormat[i] = 2;
  573. iTextureAlphaOverride[i] = 1;
  574. break;
  575. case D3DI_SPTFMT_B5G5R5 :
  576. iTextureFormat[i] = 3;
  577. iTextureAlphaOverride[i] = 1;
  578. break;
  579. case D3DI_SPTFMT_PALETTE4 :
  580. if (pCtx->pTexture[i]->pPalette == NULL)
  581. {
  582. // D3D_ERR("(Rast) NULL palette in paletted texture");
  583. return DDERR_INVALIDPARAMS;
  584. }
  585. if (pCtx->pTexture[i]->uFlags & D3DI_SPANTEX_ALPHAPALETTE)
  586. {
  587. iTextureFormat[i] = 10;
  588. }
  589. else
  590. {
  591. iTextureFormat[i] = 4;
  592. iTextureAlphaOverride[i] = 1;
  593. }
  594. break;
  595. case D3DI_SPTFMT_PALETTE8 :
  596. if (pCtx->pTexture[i]->pPalette == NULL)
  597. {
  598. // D3D_ERR("(Rast) NULL palette in paletted texture");
  599. return DDERR_INVALIDPARAMS;
  600. }
  601. if (pCtx->pTexture[i]->uFlags & D3DI_SPANTEX_ALPHAPALETTE)
  602. {
  603. iTextureFormat[i] = 11;
  604. }
  605. else
  606. {
  607. iTextureFormat[i] = 5;
  608. iTextureAlphaOverride[i] = 1;
  609. }
  610. break;
  611. case D3DI_SPTFMT_B5G5R5A1 :
  612. iTextureFormat[i] = 6;
  613. break;
  614. case D3DI_SPTFMT_B4G4R4A4 :
  615. iTextureFormat[i] = 7;
  616. break;
  617. case D3DI_SPTFMT_L8 :
  618. iTextureFormat[i] = 8;
  619. iTextureAlphaOverride[i] = 1;
  620. break;
  621. case D3DI_SPTFMT_L8A8 :
  622. iTextureFormat[i] = 9;
  623. break;
  624. }
  625. RastCapRec.Set_TextureFormat(i, iTextureFormat[i]);
  626. iTextureColorKey[i] =
  627. (false&& pCtx->pdwRenderState[D3DRENDERSTATE_COLORKEYENABLE] ?
  628. ((pCtx->pTexture[i]->uFlags & D3DI_SPANTEX_HAS_TRANSPARENT) != 0) : 0);
  629. RastCapRec.Set_TextureColorKey(i, iTextureColorKey[i]);
  630. }
  631. // choose TexBlend bead
  632. iTextureBlend = -1;
  633. if ((pCtx->pdwTextureStageState[1][D3DTSS_COLOROP] == D3DTOP_DISABLE) &&
  634. (pCtx->pdwTextureStageState[0][D3DTSS_COLORARG1] == pCtx->pdwTextureStageState[0][D3DTSS_ALPHAARG1]) &&
  635. (pCtx->pdwTextureStageState[0][D3DTSS_COLORARG2] == pCtx->pdwTextureStageState[0][D3DTSS_ALPHAARG2]))
  636. {
  637. // might be legacy texture blend mode
  638. if ((pCtx->pdwTextureStageState[0][D3DTSS_COLOROP] == D3DTOP_SELECTARG1) &&
  639. (pCtx->pdwTextureStageState[0][D3DTSS_ALPHAOP] == D3DTOP_SELECTARG1) &&
  640. (pCtx->pdwTextureStageState[0][D3DTSS_COLORARG1] == D3DTA_TEXTURE))
  641. {
  642. // copy, decal, decalmask
  643. iTextureBlend = 1;
  644. }
  645. if ((pCtx->pdwTextureStageState[0][D3DTSS_COLOROP] == D3DTOP_MODULATE) &&
  646. (pCtx->pdwTextureStageState[0][D3DTSS_ALPHAOP] == D3DTOP_SELECTARG1) &&
  647. (pCtx->pdwTextureStageState[0][D3DTSS_COLORARG1] == D3DTA_TEXTURE) &&
  648. (pCtx->pdwTextureStageState[0][D3DTSS_COLORARG2] == D3DTA_DIFFUSE))
  649. {
  650. // modulate, modulatemask
  651. if (iTextureAlphaOverride[0])
  652. {
  653. iTextureBlend = 3;
  654. }
  655. else
  656. {
  657. iTextureBlend = 2;
  658. }
  659. }
  660. }
  661. if (iTextureBlend == -1)
  662. {
  663. INT iCOp = 0;
  664. INT iCArg1 = 0;
  665. INT iCArg2 = 0;
  666. INT iAOp = 0;
  667. INT iAArg1 = 0;
  668. INT iAArg2 = 0;
  669. pCtx->cActBldStage = 0;
  670. for (INT32 i = 0; i < (INT32)pCtx->cActTex; i++)
  671. {
  672. switch(pCtx->pdwTextureStageState[i][D3DTSS_COLOROP])
  673. {
  674. default:
  675. SPIDPFM((SPIM_INVALID,"Invalid COLOROP0[%d] == 0x%x\n", i,
  676. (DWORD) pCtx->pdwTextureStageState[i][D3DTSS_COLOROP]));
  677. case D3DTOP_DISABLE: iCOp = 0; break;
  678. case D3DTOP_SELECTARG1: iCOp = 1; break;
  679. case D3DTOP_SELECTARG2: iCOp = 2; break;
  680. case D3DTOP_MODULATE: iCOp = 3; break;
  681. case D3DTOP_MODULATE2X: iCOp = 4; break;
  682. case D3DTOP_MODULATE4X: iCOp = 5; break;
  683. case D3DTOP_ADD: iCOp = 6; break;
  684. case D3DTOP_ADDSIGNED: iCOp = 7; break;
  685. case D3DTOP_BLENDDIFFUSEALPHA: iCOp = 8; break;
  686. case D3DTOP_BLENDTEXTUREALPHA: iCOp = 9; break;
  687. case D3DTOP_BLENDFACTORALPHA: iCOp = 10; break;
  688. case D3DTOP_BLENDTEXTUREALPHAPM: iCOp = 11; break;
  689. case D3DTOP_ADDSIGNED2X: iCOp = 12; break;
  690. case D3DTOP_SUBTRACT: iCOp = 13; break;
  691. case D3DTOP_ADDSMOOTH: iCOp = 14; break;
  692. case D3DTOP_MODULATEALPHA_ADDCOLOR: iCOp = 15; break;
  693. case D3DTOP_MODULATECOLOR_ADDALPHA: iCOp = 16; break;
  694. }
  695. if (iCOp == 0 && i > 0)
  696. {
  697. break;
  698. }
  699. switch(pCtx->pdwTextureStageState[i][D3DTSS_COLORARG1])
  700. {
  701. default:
  702. SPIDPFM((SPIM_INVALID,"Invalid COLORARG1[%d] == 0x%x\n", i,
  703. (DWORD) pCtx->pdwTextureStageState[i][D3DTSS_COLORARG1]));
  704. case (D3DTA_TEXTURE):
  705. iCArg1 = 0; break;
  706. case (D3DTA_TEXTURE|D3DTA_COMPLEMENT):
  707. iCArg1 = 1; break;
  708. case (D3DTA_ALPHAREPLICATE|D3DTA_TEXTURE):
  709. iCArg1 = 2; break;
  710. case (D3DTA_ALPHAREPLICATE|D3DTA_TEXTURE|D3DTA_COMPLEMENT):
  711. iCArg1 = 3; break;
  712. }
  713. switch(pCtx->pdwTextureStageState[i][D3DTSS_COLORARG2])
  714. {
  715. default:
  716. SPIDPFM((SPIM_INVALID,"Invalid COLORARG2[%d] == 0x%x\n", i,
  717. (DWORD) pCtx->pdwTextureStageState[i][D3DTSS_COLORARG2]));
  718. case (D3DTA_DIFFUSE):
  719. iCArg2 = 0; break;
  720. case (D3DTA_CURRENT):
  721. iCArg2 = 1; break;
  722. case (D3DTA_TFACTOR):
  723. iCArg2 = 2; break;
  724. case (D3DTA_COMPLEMENT|D3DTA_DIFFUSE):
  725. iCArg2 = 3; break;
  726. case (D3DTA_COMPLEMENT|D3DTA_CURRENT):
  727. iCArg2 = 4; break;
  728. case (D3DTA_COMPLEMENT|D3DTA_TFACTOR):
  729. iCArg2 = 5; break;
  730. case (D3DTA_ALPHAREPLICATE|D3DTA_DIFFUSE):
  731. iCArg2 = 6; break;
  732. case (D3DTA_ALPHAREPLICATE|D3DTA_CURRENT):
  733. iCArg2 = 7; break;
  734. case (D3DTA_ALPHAREPLICATE|D3DTA_TFACTOR):
  735. iCArg2 = 8; break;
  736. case (D3DTA_ALPHAREPLICATE|D3DTA_COMPLEMENT|D3DTA_DIFFUSE):
  737. iCArg2 = 9; break;
  738. case (D3DTA_ALPHAREPLICATE|D3DTA_COMPLEMENT|D3DTA_CURRENT):
  739. iCArg2 = 10; break;
  740. case (D3DTA_ALPHAREPLICATE|D3DTA_COMPLEMENT|D3DTA_TFACTOR):
  741. iCArg2 = 11; break;
  742. case (D3DTA_SPECULAR):
  743. iCArg2 = 12; break;
  744. case (D3DTA_COMPLEMENT|D3DTA_SPECULAR):
  745. iCArg2 = 13; break;
  746. case (D3DTA_ALPHAREPLICATE|D3DTA_SPECULAR):
  747. iCArg2 = 14; break;
  748. case (D3DTA_ALPHAREPLICATE|D3DTA_COMPLEMENT|D3DTA_SPECULAR):
  749. iCArg2 = 15; break;
  750. }
  751. switch(pCtx->pdwTextureStageState[i][D3DTSS_ALPHAOP])
  752. {
  753. default:
  754. SPIDPFM((SPIM_INVALID,"Invalid ALPHAOP[%d] == 0x%x\n", i,
  755. (DWORD) pCtx->pdwTextureStageState[i][D3DTSS_ALPHAOP]));
  756. case D3DTOP_DISABLE: iAOp = 0; break;
  757. case D3DTOP_SELECTARG1: iAOp = 1; break;
  758. case D3DTOP_SELECTARG2: iAOp = 2; break;
  759. case D3DTOP_MODULATE: iAOp = 3; break;
  760. case D3DTOP_MODULATE2X: iAOp = 4; break;
  761. case D3DTOP_MODULATE4X: iAOp = 5; break;
  762. case D3DTOP_ADD: iAOp = 6; break;
  763. case D3DTOP_ADDSIGNED: iAOp = 7; break;
  764. case D3DTOP_BLENDDIFFUSEALPHA: iAOp = 8; break;
  765. case D3DTOP_BLENDTEXTUREALPHA: iAOp = 9; break;
  766. case D3DTOP_BLENDFACTORALPHA: iAOp = 10; break;
  767. case D3DTOP_BLENDTEXTUREALPHAPM: iAOp = 11; break;
  768. case D3DTOP_ADDSIGNED2X: iAOp = 12; break;
  769. case D3DTOP_SUBTRACT: iAOp = 13; break;
  770. case D3DTOP_ADDSMOOTH: iAOp = 14; break;
  771. }
  772. switch(pCtx->pdwTextureStageState[i][D3DTSS_ALPHAARG1])
  773. {
  774. default:
  775. SPIDPFM((SPIM_INVALID,"Invalid ALPHAARG1[%d] == 0x%x\n", i,
  776. (DWORD) pCtx->pdwTextureStageState[i][D3DTSS_ALPHAARG1]));
  777. case (D3DTA_TEXTURE):
  778. case (D3DTA_ALPHAREPLICATE|D3DTA_TEXTURE):
  779. iAArg1 = 0; break;
  780. case (D3DTA_TEXTURE|D3DTA_COMPLEMENT):
  781. case (D3DTA_ALPHAREPLICATE|D3DTA_TEXTURE|D3DTA_COMPLEMENT):
  782. iAArg1 = 1; break;
  783. }
  784. switch(pCtx->pdwTextureStageState[i][D3DTSS_ALPHAARG2])
  785. {
  786. default:
  787. SPIDPFM((SPIM_INVALID,"Invalid ALPHAARG2[%d] == 0x%x\n", i,
  788. (DWORD) pCtx->pdwTextureStageState[i][D3DTSS_ALPHAARG2]));
  789. case (D3DTA_DIFFUSE):
  790. case (D3DTA_ALPHAREPLICATE|D3DTA_DIFFUSE):
  791. iAArg2 = 0; break;
  792. case (D3DTA_CURRENT):
  793. case (D3DTA_ALPHAREPLICATE|D3DTA_CURRENT):
  794. iAArg2 = 1; break;
  795. case (D3DTA_TFACTOR):
  796. case (D3DTA_ALPHAREPLICATE|D3DTA_TFACTOR):
  797. iAArg2 = 2; break;
  798. case (D3DTA_COMPLEMENT|D3DTA_DIFFUSE):
  799. case (D3DTA_ALPHAREPLICATE|D3DTA_COMPLEMENT|D3DTA_DIFFUSE):
  800. iAArg2 = 3; break;
  801. case (D3DTA_COMPLEMENT|D3DTA_CURRENT):
  802. case (D3DTA_ALPHAREPLICATE|D3DTA_COMPLEMENT|D3DTA_CURRENT):
  803. iAArg2 = 4; break;
  804. case (D3DTA_COMPLEMENT|D3DTA_TFACTOR):
  805. case (D3DTA_ALPHAREPLICATE|D3DTA_COMPLEMENT|D3DTA_TFACTOR):
  806. iAArg2 = 5; break;
  807. case (D3DTA_SPECULAR):
  808. case (D3DTA_ALPHAREPLICATE|D3DTA_SPECULAR):
  809. iAArg2 = 6; break;
  810. case (D3DTA_COMPLEMENT|D3DTA_SPECULAR):
  811. case (D3DTA_ALPHAREPLICATE|D3DTA_COMPLEMENT|D3DTA_SPECULAR):
  812. iAArg2 = 7; break;
  813. }
  814. pCtx->pfnTexBlendOpColor[i] = pBeadTable->pTexBlendOpColorBeads->pfnTexBlendOpColor[iCOp];
  815. pCtx->pfnTexBlendGetColor[i] = pBeadTable->pTexBlendGetColorBeads->pfnTexBlendGetColor[iCArg2][iCArg1];
  816. pCtx->pfnTexBlendOpAlpha[i] = pBeadTable->pTexBlendOpAlphaBeads->pfnTexBlendOpAlpha[iAOp];
  817. pCtx->pfnTexBlendGetAlpha[i] = pBeadTable->pTexBlendGetAlphaBeads->pfnTexBlendGetAlpha[iAArg2][iAArg1];
  818. pCtx->cActBldStage += 1;
  819. }
  820. if ( pCtx->cActBldStage <= 1 ) {
  821. // Tex1_Gen
  822. iTextureBlend = 4;
  823. }
  824. else {
  825. // TexM_Gen
  826. iTextureBlend = 5;
  827. }
  828. }
  829. RastCapRec.Set_TextureBlend(iTextureBlend);
  830. }
  831. // Ignore mono (D3DRENDERSTATE_MONOENABLE), since no software rasterizers do anything with it.
  832. iMono = 0;
  833. RastCapRec.Set_Mono(iMono);
  834. // values needed to choose ColorBlend bead
  835. iAlphaBlend =
  836. pCtx->pdwRenderState[D3DRS_ALPHABLENDENABLE] ? 1 : 0;
  837. RastCapRec.Set_AlphaBlend(iAlphaBlend);
  838. if (!iAlphaBlend ||
  839. ((pCtx->pdwRenderState[D3DRS_SRCBLEND] == D3DBLEND_ONE) &&
  840. (pCtx->pdwRenderState[D3DRS_DESTBLEND] == D3DBLEND_ZERO))) {
  841. iBlend = 0;
  842. } else {
  843. iBlend = 1;
  844. }
  845. RastCapRec.Set_Blend(iBlend);
  846. if (true|| pCtx->pdwRenderState[D3DRENDERSTATE_ROP2] == R2_COPYPEN) {
  847. iROP = 0;
  848. } else {
  849. iROP = 1;
  850. }
  851. RastCapRec.Set_ROP(iROP);
  852. // value needed to choose DestBlend routine
  853. switch (pCtx->pdwRenderState[D3DRS_DESTBLEND])
  854. {
  855. default :
  856. SPIDPFM((SPIM_INVALID,"Invalid renderstate value, D3DRS_DESTBLEND == 0x%x\n",
  857. pCtx->pdwRenderState[D3DRS_DESTBLEND]));
  858. case D3DBLEND_ZERO :
  859. iDestBlend = 0;
  860. break;
  861. case D3DBLEND_ONE :
  862. iDestBlend = 1;
  863. break;
  864. case D3DBLEND_SRCCOLOR :
  865. iDestBlend = 2;
  866. break;
  867. case D3DBLEND_INVSRCCOLOR :
  868. iDestBlend = 3;
  869. break;
  870. case D3DBLEND_SRCALPHA :
  871. iDestBlend = 4;
  872. break;
  873. case D3DBLEND_INVSRCALPHA :
  874. iDestBlend = 5;
  875. break;
  876. case D3DBLEND_DESTALPHA :
  877. iDestBlend = 6;
  878. break;
  879. case D3DBLEND_INVDESTALPHA :
  880. iDestBlend = 7;
  881. break;
  882. case D3DBLEND_DESTCOLOR :
  883. iDestBlend = 8;
  884. break;
  885. case D3DBLEND_INVDESTCOLOR :
  886. iDestBlend = 9;
  887. break;
  888. case D3DBLEND_SRCALPHASAT :
  889. iDestBlend = 10;
  890. break;
  891. }
  892. // set iSrcBlend after iDestBlend so BOTHSRCALPHA can override iDestBlend
  893. // value needed to choose SrcBlend routine
  894. switch (pCtx->pdwRenderState[D3DRS_SRCBLEND])
  895. {
  896. case D3DBLEND_ZERO :
  897. iSrcBlend = 0;
  898. break;
  899. default :
  900. SPIDPFM((SPIM_INVALID,"Invalid renderstate value, D3DRS_SRCBLEND == 0x%x\n",
  901. pCtx->pdwRenderState[D3DRS_SRCBLEND]));
  902. case D3DBLEND_ONE :
  903. iSrcBlend = 1;
  904. break;
  905. case D3DBLEND_SRCCOLOR :
  906. iSrcBlend = 2;
  907. break;
  908. case D3DBLEND_INVSRCCOLOR :
  909. iSrcBlend = 3;
  910. break;
  911. case D3DBLEND_SRCALPHA :
  912. iSrcBlend = 4;
  913. break;
  914. case D3DBLEND_INVSRCALPHA :
  915. iSrcBlend = 5;
  916. break;
  917. case D3DBLEND_DESTALPHA :
  918. iSrcBlend = 6;
  919. break;
  920. case D3DBLEND_INVDESTALPHA :
  921. iSrcBlend = 7;
  922. break;
  923. case D3DBLEND_DESTCOLOR :
  924. iSrcBlend = 8;
  925. break;
  926. case D3DBLEND_INVDESTCOLOR :
  927. iSrcBlend = 9;
  928. break;
  929. case D3DBLEND_SRCALPHASAT :
  930. iSrcBlend = 10;
  931. break;
  932. // these are special and set both source and dest
  933. case D3DBLEND_BOTHSRCALPHA :
  934. iSrcBlend = 4;
  935. iDestBlend = 5;
  936. break;
  937. case D3DBLEND_BOTHINVSRCALPHA :
  938. iSrcBlend = 5;
  939. iDestBlend = 4;
  940. break;
  941. }
  942. RastCapRec.Set_SrcBlend(iSrcBlend);
  943. RastCapRec.Set_DestBlend(iDestBlend);
  944. // values needed to choose BufWrite bead and BufRead routine
  945. switch (pCtx->iSurfaceType)
  946. {
  947. default :
  948. SPIDPFM((SPIM_INVALID,"Invalid target surface type, iSurfaceType == 0x%x\n",
  949. pCtx->iSurfaceType));
  950. case RAST_STYPE_B8G8R8X8:
  951. iTargetPixelFormat = 0;
  952. break;
  953. case RAST_STYPE_B8G8R8A8:
  954. iTargetPixelFormat = 1;
  955. break;
  956. case RAST_STYPE_B5G6R5:
  957. iTargetPixelFormat = 2;
  958. break;
  959. case RAST_STYPE_B5G5R5:
  960. iTargetPixelFormat = 3;
  961. break;
  962. case RAST_STYPE_B5G5R5A1:
  963. iTargetPixelFormat = 4;
  964. break;
  965. case RAST_STYPE_B8G8R8:
  966. iTargetPixelFormat = 5;
  967. break;
  968. case RAST_STYPE_PALETTE8:
  969. iTargetPixelFormat = 6;
  970. break;
  971. }
  972. RastCapRec.Set_TargetPixelFormat(iTargetPixelFormat);
  973. iDither = pCtx->pdwRenderState[D3DRS_DITHERENABLE] ? 1 : 0;
  974. RastCapRec.Set_Dither(iDither);
  975. iZDeferred = iAlphaTest || iAlphaDither;
  976. // Set optional postprocessing beads first so that their addresses
  977. // can be referenced later.
  978. pCtx->pfnPixelEnd = pBeadTable->pPixelEndBeads->pfnPixelEnd[0];
  979. pCtx->pfnSpanEnd = pBeadTable->pSpanEndBeads->pfnSpanEnd[0];
  980. // start stringing beads together, back to front order avoids a lot of
  981. // conditional logic
  982. #if DBG
  983. // null out all bead ptrs
  984. pCtx->pfnBegin = NULL;
  985. pCtx->pfnLoopEnd = NULL;
  986. pCtx->pfnTestPassEnd = NULL;
  987. pCtx->pfnTestFailEnd = NULL;
  988. pCtx->pfnTexAddrEnd = NULL;
  989. pCtx->pfnTexRead[0] = NULL;
  990. pCtx->pfnTexRead[1] = NULL;
  991. pCtx->pfnTexAddr[0] = NULL;
  992. pCtx->pfnTexBlendEnd = NULL;
  993. pCtx->pfnColorGenEnd = NULL;
  994. pCtx->pfnAlphaTestPassEnd = NULL;
  995. pCtx->pfnAlphaTestFailEnd = NULL;
  996. pCtx->pfnSrcBlend = NULL;
  997. pCtx->pfnDestBlend = NULL;
  998. pCtx->pfnBufRead = NULL;
  999. pCtx->pfnColorBlendEnd = NULL;
  1000. pCtx->pfnPixelEnd = NULL;
  1001. pCtx->pfnSpanEnd = NULL;
  1002. #endif
  1003. // range check indices used to select BufWrite bead
  1004. RANGE_CHECK(iDither,DITHERING_NUM);
  1005. RANGE_CHECK(iTargetPixelFormat,TARGETPIXELFORMAT_NUM);
  1006. // select BufWrite bead, which can be called through pfnColorBlendEnd,
  1007. // pfnAlphaTestPassEnd, pfnColorGenEnd, pfnTexBlendEnd
  1008. pCtx->pfnTexBlendEnd =
  1009. pCtx->pfnColorGenEnd =
  1010. pCtx->pfnAlphaTestPassEnd =
  1011. pCtx->pfnColorBlendEnd = pBeadTable->pBufWriteBeads->pfnBufWrite[iDither][iTargetPixelFormat];
  1012. #if DBG
  1013. strcpy(pCtx->szBufWrite,rgszBufWrite[iDither][iTargetPixelFormat]);
  1014. #endif
  1015. // range check indices used to select ColorBlend bead
  1016. RANGE_CHECK(iROP,ROP_NUM);
  1017. RANGE_CHECK(iBlend,BLEND_NUM);
  1018. // select ColorBlend bead, which can be called through
  1019. // pfnATextEnd, pfnColorGenEnd, or pfnTexBlendEnd
  1020. if ((pfnColorBlend = pBeadTable->pColorBlendBeads->pfnColorBlend[iROP][iBlend]) == NULL) {
  1021. pCtx->pfnColorBlendEnd = NULL;
  1022. } else {
  1023. pCtx->pfnTexBlendEnd =
  1024. pCtx->pfnColorGenEnd =
  1025. pCtx->pfnAlphaTestPassEnd = pfnColorBlend;
  1026. }
  1027. #if DBG
  1028. strcpy(pCtx->szColorBlend,rgszColorBlend[iROP][iBlend]);
  1029. #endif
  1030. // range check index used to select BufRead bead
  1031. RANGE_CHECK(iTargetPixelFormat,TARGETPIXELFORMAT_NUM);
  1032. // select Buf Read routine
  1033. pCtx->pfnBufRead = pBeadTable->pBufReadBeads->pfnBufRead[iTargetPixelFormat];
  1034. #if DBG
  1035. strcpy(pCtx->szBufRead,rgszBufRead[iTargetPixelFormat]);
  1036. #endif
  1037. if (iBlend) {
  1038. // range check index used to select DestBlend bead
  1039. RANGE_CHECK(iDestBlend,DESTBLEND_NUM);
  1040. // select DestBlend routine
  1041. pCtx->pfnDestBlend = pBeadTable->pDestBlendBeads->pfnDestBlend[iDestBlend];
  1042. #if DBG
  1043. strcpy(pCtx->szDestBlend,rgszDestBlend[iDestBlend]);
  1044. #endif
  1045. // range check index used to select SrcBlend bead
  1046. RANGE_CHECK(iSrcBlend,SRCBLEND_NUM);
  1047. // select SrcBlend routine
  1048. pCtx->pfnSrcBlend = pBeadTable->pSrcBlendBeads->pfnSrcBlend[iSrcBlend];
  1049. #if DBG
  1050. strcpy(pCtx->szSrcBlend,rgszSrcBlend[iSrcBlend]);
  1051. #endif
  1052. } else {
  1053. pCtx->pfnDestBlend = NULL;
  1054. pCtx->pfnSrcBlend = NULL;
  1055. #if DBG
  1056. strcpy(pCtx->szDestBlend,"NULL");
  1057. strcpy(pCtx->szSrcBlend,"NULL");
  1058. #endif
  1059. }
  1060. // select AlphaTest/AlphaDitheringTest bead, which can be called through
  1061. // pfnColorBlendEnd, pfnColorGenEnd, or pfnTexBlendEnd
  1062. // range check indices used to select AlphaTest bead
  1063. RANGE_CHECK(iStencil,STENCIL_NUM);
  1064. RANGE_CHECK(iZFormat,ZFORMAT_NUM);
  1065. RANGE_CHECK(iZWrite,ZWRITE_NUM);
  1066. RANGE_CHECK(iAlphaDither,COLORKEY_NUM);
  1067. RANGE_CHECK(iAlphaTest,ALPHATEST_NUM);
  1068. if (iAlphaTest || iAlphaDither)
  1069. {
  1070. pCtx->pfnTexBlendEnd =
  1071. pCtx->pfnColorGenEnd =
  1072. pBeadTable->pAlphaTestBeads->pfnAlphaTest[iStencil]
  1073. [iZFormat]
  1074. [iZWrite || iStencil]
  1075. [iAlphaDither]
  1076. [iAlphaTest];
  1077. // If AlphaTest fails, it goes to where the BufWrite bead ends
  1078. pCtx->pfnAlphaTestFailEnd = pCtx->pfnPixelEnd;
  1079. #if DBG
  1080. strcpy(pCtx->szAlphaTest,rgszAlphaTest[iStencil][iZFormat][iZWrite]
  1081. [iAlphaDither][iAlphaTest]);
  1082. #endif
  1083. }
  1084. else
  1085. {
  1086. pCtx->pfnAlphaTestPassEnd = NULL;
  1087. pCtx->pfnAlphaTestFailEnd = NULL;
  1088. #if DBG
  1089. strcpy(pCtx->szAlphaTest, "NULL");
  1090. #endif
  1091. }
  1092. // range check indices used to select ColorGen bead
  1093. RANGE_CHECK(iMono,MONO_NUM);
  1094. RANGE_CHECK(iVertexFog,VERTEXFOG_NUM);
  1095. RANGE_CHECK(iSpecular,SPECULAR_NUM);
  1096. RANGE_CHECK(iShadeMode,SHADEMODE_NUM);
  1097. // select ColorGen bead, which can be called through pfnTexBlendEnd
  1098. if ((pfnColorGen =
  1099. pBeadTable->pColorGenBeads->pfnColorGen[iMono][iVertexFog][iSpecular][iShadeMode]) == NULL) {
  1100. pCtx->pfnColorGenEnd = NULL;
  1101. } else {
  1102. pCtx->pfnTexBlendEnd = pfnColorGen;
  1103. }
  1104. #if DBG
  1105. strcpy(pCtx->szColorGen,
  1106. rgszColorGen[iMono][iVertexFog][iSpecular][iShadeMode]);
  1107. #endif
  1108. // range check indices used to select TexBlend bead
  1109. RANGE_CHECK(iTextureBlend,TEXTUREBLEND_NUM);
  1110. // select TexBlend bead, which can be called through pfnTexAddr2End,
  1111. // pfnTexAddr1End, pfnTestPassEnd, or pfnLoopEnd
  1112. pCtx->pfnLoopEnd =
  1113. pCtx->pfnTestPassEnd =
  1114. pCtx->pfnTexAddrEnd = pBeadTable->pTexBlendBeads->pfnTexBlend[iTextureBlend];
  1115. #if DBG
  1116. strcpy(pCtx->szTexBlend,rgszTexBlend[iTextureBlend]);
  1117. #endif
  1118. if (iTexture) {
  1119. if (pCtx->cActTex >= 2)
  1120. {
  1121. for (INT32 i = 1; i < (INT32)pCtx->cActTex; i ++)
  1122. {
  1123. // range check indices used to select TexRead bead
  1124. RANGE_CHECK(iTextureColorKey[i],COLORKEY_NUM);
  1125. RANGE_CHECK(iTextureBorder[i],TEXTUREBORDER_NUM);
  1126. RANGE_CHECK(iTextureFormat[i],TEXTUREFORMAT_NUM);
  1127. // select TexAddr2 bead, which can be called through pfnTexAddr1
  1128. // select TexRead routine
  1129. pCtx->pfnTexRead[i] =
  1130. pBeadTable->pTexReadBeads->pfnTexRead[iTextureColorKey[i]][iTextureBorder[i]][iTextureFormat[i]];
  1131. #if DBG
  1132. strcpy(pCtx->szTexRead[i],
  1133. rgszTexRead[iTextureColorKey[i]][iTextureBorder[i]][iTextureFormat[i]]);
  1134. #endif
  1135. // range check indices used to select Tex1Addr bead
  1136. RANGE_CHECK(iTextureLOD[i],TEXTURELOD_NUM);
  1137. RANGE_CHECK(iTextureFilter[i],TEXTUREFILTER_NUM);
  1138. RANGE_CHECK(iTexturePerspective,TEXTUREPERSPECTIVE_NUM);
  1139. RANGE_CHECK(iTextureAddr[i],TEXTUREADDRESS_NUM);
  1140. // select TexAddr1 bead, which can be called through pfnTestPassEnd or
  1141. // pfnLoopEnd
  1142. pCtx->pfnTexAddr[i] = (pBeadTable->pTex2AddrBeads->pfnTex2Addr[iTextureFilter[i]]
  1143. [iTexturePerspective][iTextureAddr[i]]);
  1144. #if DBG
  1145. strcpy(pCtx->szTexAddr[i],rgszTex2Addr[iTextureFilter[i]]
  1146. [iTexturePerspective][iTextureAddr[i]]);
  1147. #endif
  1148. }
  1149. } else {
  1150. pCtx->pfnTexRead[1] = NULL;
  1151. pCtx->pfnTexAddr[1] = NULL;
  1152. #if DBG
  1153. strcpy(pCtx->szTexAddr[1],"NULL");
  1154. strcpy(pCtx->szTexRead[1],"NULL");
  1155. #endif
  1156. }
  1157. // range check indices used to select TexRead bead
  1158. RANGE_CHECK(iTextureColorKey[0],COLORKEY_NUM);
  1159. RANGE_CHECK(iTextureBorder[0],TEXTUREBORDER_NUM);
  1160. RANGE_CHECK(iTextureFormat[0],TEXTUREFORMAT_NUM);
  1161. // select TexRead routine
  1162. pCtx->pfnTexRead[0] =
  1163. pBeadTable->pTexReadBeads->pfnTexRead[iTextureColorKey[0]][iTextureBorder[0]][iTextureFormat[0]];
  1164. #if DBG
  1165. strcpy(pCtx->szTexRead[0],
  1166. rgszTexRead[iTextureColorKey[0]][iTextureBorder[0]][iTextureFormat[0]]);
  1167. #endif
  1168. // range check indices used to select Tex1Addr bead
  1169. RANGE_CHECK(iTextureLOD[0],TEXTURELOD_NUM);
  1170. RANGE_CHECK(iTextureFilter[0],TEXTUREFILTER_NUM);
  1171. RANGE_CHECK(iTexturePerspective,TEXTUREPERSPECTIVE_NUM);
  1172. RANGE_CHECK(iTextureAddr[0],TEXTUREADDRESS_NUM);
  1173. // select TexAddr1 bead, which can be called through pfnTestPassEnd or
  1174. // pfnLoopEnd
  1175. pCtx->pfnTexAddr[0] = (iTextureMip[0]) ?
  1176. (pBeadTable->pTex1AddrMipBeads->pfnTex1AddrMip[0]) :
  1177. (pBeadTable->pTex1AddrBeads->pfnTex1Addr[iTextureLOD[0]][iTextureFilter[0]]
  1178. [iTexturePerspective][iTextureAddr[0]]);
  1179. pCtx->pfnLoopEnd =
  1180. pCtx->pfnTestPassEnd = pBeadTable->pTexAddrWrapperBeads->pfnTexAddrWrapper[0];
  1181. #if DBG
  1182. if (iTextureMip[0])
  1183. {
  1184. strcpy(pCtx->szTexAddr[0],rgszTex1AddrMip[0]);
  1185. }
  1186. else
  1187. {
  1188. strcpy(pCtx->szTexAddr[0],rgszTex1Addr[iTextureLOD[0]][iTextureFilter[0]]
  1189. [iTexturePerspective][iTextureAddr[0]]);
  1190. }
  1191. #endif
  1192. } else {
  1193. pCtx->pfnTexAddrEnd = NULL;
  1194. pCtx->pfnTexRead[0] = NULL;
  1195. #if DBG
  1196. strcpy(pCtx->szTexRead[0],"NULL");
  1197. strcpy(pCtx->szTexAddr[0],"NULL");
  1198. strcpy(pCtx->szTexAddr[1],"NULL");
  1199. #endif
  1200. }
  1201. // select Test bead, which can be called through pfnLoopEnd
  1202. if (iZTest) {
  1203. // range check indices used to select Test bead
  1204. RANGE_CHECK(iStencil,STENCIL_NUM);
  1205. RANGE_CHECK(iZFunc,ZFUNC_NUM);
  1206. RANGE_CHECK(iZWrite,ZWRITE_NUM);
  1207. // ATTENTION range check this
  1208. // RANGE_CHECK(iAlphaTest,ALPHATEST_NUM);
  1209. RANGE_CHECK(iZFormat,ZFORMAT_NUM);
  1210. RANGE_CHECK(iSpecular,SPECULAR_NUM);
  1211. RANGE_CHECK(iVertexFog,VERTEXFOG_NUM);
  1212. RANGE_CHECK(iTexture,TEXTURE_NUM);
  1213. RANGE_CHECK(iShadeMode,SHADEMODE_NUM);
  1214. // if alpha testing, defer Z write
  1215. pCtx->pfnLoopEnd = pBeadTable->pTestBeads->pfnTest[iStencil][iZFunc]
  1216. [iZDeferred][iZWrite][iZFormat];
  1217. // select where this bead is going to go if the test fails
  1218. pCtx->pfnTestFailEnd =
  1219. pBeadTable->pTestFailBeads->pfnTestFail[iSpecular | iVertexFog][iTexture][iShadeMode];
  1220. if (iZDeferred && iStencil)
  1221. {
  1222. // If alpha testing and stenciling, need to
  1223. // defer stencil update until after the alpha test.
  1224. //
  1225. // This is not an issue for Z, since we never want to write Z
  1226. // if the Z test fails (hence we do not care about the outcome of
  1227. // the alpha test.
  1228. pCtx->pfnTestFailEnd = pCtx->pfnTestPassEnd;
  1229. }
  1230. #if DBG
  1231. strcpy(pCtx->szTest,rgszTest[iStencil][iZFunc][iZDeferred][iZWrite][iZFormat]);
  1232. strcpy(pCtx->szTestFail,
  1233. rgszTestFail[iSpecular | iVertexFog][iTexture][iShadeMode]);
  1234. #endif
  1235. } else {
  1236. pCtx->pfnTestPassEnd = NULL;
  1237. pCtx->pfnTestFailEnd = NULL;
  1238. #if DBG
  1239. strcpy(pCtx->szTest,"NULL");
  1240. strcpy(pCtx->szTestFail,"NULL");
  1241. #endif
  1242. }
  1243. // select Loop bead
  1244. pCtx->pfnBegin = pBeadTable->pBeginBeads->pfnBegin[0];
  1245. pCtx->pfnRenderSpans = pBeadTable->pRenderSpansBeads->pfnRenderSpans[0];
  1246. #if DBG
  1247. SPIDPFM((SPIM_REPORT,"Test = %s\n",pCtx->szTest));
  1248. SPIDPFM((SPIM_REPORT,"TestFail = %s\n",pCtx->szTestFail));
  1249. SPIDPFM((SPIM_REPORT,"TexAddr[0] = %s\n",pCtx->szTexAddr[0]));
  1250. SPIDPFM((SPIM_REPORT,"TexRead1 = %s\n",pCtx->szTexRead[0]));
  1251. SPIDPFM((SPIM_REPORT,"TexRead2 = %s\n",pCtx->szTexRead[1]));
  1252. SPIDPFM((SPIM_REPORT,"TexAddr[1] = %s\n",pCtx->szTexAddr[1]));
  1253. SPIDPFM((SPIM_REPORT,"TexBlend = %s\n",pCtx->szTexBlend));
  1254. SPIDPFM((SPIM_REPORT,"ColorGen = %s\n",pCtx->szColorGen));
  1255. SPIDPFM((SPIM_REPORT,"ColorBlend = %s\n",pCtx->szColorBlend));
  1256. SPIDPFM((SPIM_REPORT,"SrcBlend = %s\n",pCtx->szSrcBlend));
  1257. SPIDPFM((SPIM_REPORT,"DestBlend = %s\n",pCtx->szDestBlend));
  1258. SPIDPFM((SPIM_REPORT,"BufRead = %s\n",pCtx->szBufRead));
  1259. SPIDPFM((SPIM_REPORT,"AlphaTest = %s\n",pCtx->szAlphaTest));
  1260. SPIDPFM((SPIM_REPORT,"BufWrite = %s\n",pCtx->szBufWrite));
  1261. SPIDPFM((SPIM_REPORT,"RastCap = 0x%x 0x%x 0x%x\n",
  1262. RastCapRec.GetCapDWord(0),
  1263. RastCapRec.GetCapDWord(1),
  1264. RastCapRec.GetCapDWord(2)));
  1265. #if 0
  1266. DWORD dwCheckSum = RastCapRec.GetCapDWord(0) ^ RastCapRec.GetCapDWord(1) ^ RastCapRec.GetCapDWord(2);
  1267. static DWORD dwCheckSumLast;
  1268. if (dwCheckSum != dwCheckSumLast)
  1269. {
  1270. dwCheckSumLast = dwCheckSum;
  1271. DPF(0, "Spaninit");
  1272. DPF(0, "Test = %s",pCtx->szTest);
  1273. DPF(0, "TestFail = %s",pCtx->szTestFail);
  1274. DPF(0, "TexAddr[0] = %s",pCtx->szTexAddr[0]);
  1275. DPF(0, "TexRead1 = %s",pCtx->szTexRead[0]);
  1276. DPF(0, "TexRead2 = %s",pCtx->szTexRead[1]);
  1277. DPF(0, "TexAddr[1] = %s",pCtx->szTexAddr[1]);
  1278. DPF(0, "TexBlend = %s",pCtx->szTexBlend);
  1279. DPF(0, "ColorGen = %s",pCtx->szColorGen);
  1280. DPF(0, "ColorBlend = %s",pCtx->szColorBlend);
  1281. DPF(0, "SrcBlend = %s",pCtx->szSrcBlend);
  1282. DPF(0, "DestBlend = %s",pCtx->szDestBlend);
  1283. DPF(0, "BufRead = %s",pCtx->szBufRead);
  1284. DPF(0, "AlphaTest = %s",pCtx->szAlphaTest);
  1285. DPF(0, "BufWrite = %s",pCtx->szBufWrite);
  1286. DPF(0, "RastCap = 0x%x 0x%x 0x%x",
  1287. RastCapRec.GetCapDWord(0),
  1288. RastCapRec.GetCapDWord(1),
  1289. RastCapRec.GetCapDWord(2));
  1290. }
  1291. #endif
  1292. #endif
  1293. // is there a monolithic rasterizer that can do exactly
  1294. // what is needed?
  1295. RASTFNREC* pfnRastFnRec;
  1296. if ((pfnRastFnRec = g_RastCollection.Search(pCtx, &RastCapRec)) != NULL)
  1297. {
  1298. // yes, then replace beaded rasterizer with monolithic
  1299. // DDASSERT(pfnRastFnRec->pfnRastFunc != 0);
  1300. pCtx->pfnRenderSpans = pfnRastFnRec->pfnRastFunc;
  1301. #if DBG
  1302. // null out all the others
  1303. pCtx->pfnBegin =
  1304. pCtx->pfnLoopEnd =
  1305. pCtx->pfnTestPassEnd =
  1306. pCtx->pfnTestFailEnd =
  1307. pCtx->pfnTexAddrEnd =
  1308. pCtx->pfnTexBlendEnd =
  1309. pCtx->pfnColorGenEnd =
  1310. pCtx->pfnAlphaTestPassEnd =
  1311. pCtx->pfnAlphaTestFailEnd =
  1312. pCtx->pfnColorBlendEnd =
  1313. pCtx->pfnPixelEnd = NULL;
  1314. pCtx->pfnTexAddr[0] = NULL;
  1315. #endif
  1316. }
  1317. #if 0 && DBG
  1318. static RASTFNREC* pfnLastRastFnRec = (RASTFNREC*)-1;
  1319. if (pfnLastRastFnRec != pfnRastFnRec)
  1320. {
  1321. if (pfnRastFnRec)
  1322. {
  1323. D3D_INFO(0, "SpanInit: Fast path rasterizer %s chosen", pfnRastFnRec->pszRastDesc);
  1324. }
  1325. else
  1326. {
  1327. D3D_WARN(0, "SpanInit: No fast path rasterizer chosen");
  1328. }
  1329. pfnLastRastFnRec = pfnRastFnRec;
  1330. }
  1331. #endif
  1332. return S_OK;
  1333. }