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.

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