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.

1904 lines
68 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(`rampbead.mh')
  12. #include "BdStr_mh.h"
  13. #include "RastCap.h"
  14. #include "RastColl.h"
  15. #include "RampOld.h"
  16. static CRastCollection g_RastCollection;
  17. UINT16 g_uDitherTable[16] =
  18. {
  19. 0x00, 0x80, 0x20, 0xa0,
  20. 0xc0, 0x40, 0xe0, 0x60,
  21. 0x30, 0xb0, 0x10, 0x90,
  22. 0xf0, 0x70, 0xd0, 0x50
  23. };
  24. //-----------------------------------------------------------------------------
  25. //
  26. // DoZCompareSetup
  27. //
  28. // Initializes arithmetic Z compare state based on the Z test function.
  29. //
  30. //-----------------------------------------------------------------------------
  31. void DoZCompareSetup(PD3DI_RASTCTX pCtx, BOOL bIsMMX)
  32. {
  33. INT32 iXorMask;
  34. if (bIsMMX)
  35. {
  36. iXorMask = -1;
  37. }
  38. else
  39. {
  40. iXorMask = 1;
  41. }
  42. D3DCMPFUNC ZFunc = (D3DCMPFUNC)pCtx->pdwRenderState[D3DRENDERSTATE_ZFUNC];
  43. if (!pCtx->pdwRenderState[D3DRENDERSTATE_ZENABLE])
  44. {
  45. // setup ALWAYS if Z is not enabled, since we may be going into
  46. // the test beads for other reasons (like stencil)
  47. ZFunc = D3DCMP_ALWAYS;
  48. }
  49. switch (ZFunc)
  50. {
  51. case D3DCMP_NEVER:
  52. pCtx->iZAndMask = 0; pCtx->iZNeg = 0; pCtx->iZXorMask = iXorMask;
  53. break;
  54. case D3DCMP_ALWAYS:
  55. pCtx->iZAndMask = 0; pCtx->iZNeg = 0; pCtx->iZXorMask = 0;
  56. break;
  57. case D3DCMP_LESS:
  58. pCtx->iZAndMask = ~0; pCtx->iZNeg = 0; pCtx->iZXorMask = iXorMask;
  59. break;
  60. case D3DCMP_GREATEREQUAL:
  61. pCtx->iZAndMask = ~0; pCtx->iZNeg = 0; pCtx->iZXorMask = 0;
  62. break;
  63. case D3DCMP_EQUAL:
  64. pCtx->iZAndMask = 0x7fffffff; pCtx->iZNeg = 1; pCtx->iZXorMask =
  65. iXorMask;
  66. break;
  67. case D3DCMP_NOTEQUAL:
  68. pCtx->iZAndMask = 0x7fffffff; pCtx->iZNeg = 1; pCtx->iZXorMask = 0;
  69. break;
  70. default:
  71. case D3DCMP_LESSEQUAL:
  72. pCtx->iZAndMask = ~0; pCtx->iZNeg = 1; pCtx->iZXorMask = iXorMask;
  73. break;
  74. case D3DCMP_GREATER:
  75. pCtx->iZAndMask = ~0; pCtx->iZNeg = 1; pCtx->iZXorMask = 0;
  76. break;
  77. }
  78. if (bIsMMX)
  79. {
  80. pCtx->iZXorMask = ~pCtx->iZXorMask;
  81. }
  82. }
  83. //-----------------------------------------------------------------------------
  84. //
  85. // DoACompareSetup
  86. //
  87. // Initializes arithmetic alpha compare state based on the alpha test function.
  88. //
  89. //-----------------------------------------------------------------------------
  90. void DoACompareSetup(PD3DI_RASTCTX pCtx, BOOL bIsMMX)
  91. {
  92. INT32 iXorMask;
  93. if (bIsMMX)
  94. {
  95. iXorMask = -1;
  96. }
  97. else
  98. {
  99. iXorMask = 1;
  100. }
  101. switch ((D3DCMPFUNC)pCtx->pdwRenderState[D3DRENDERSTATE_ALPHAFUNC])
  102. {
  103. case D3DCMP_NEVER:
  104. pCtx->iAAndMask = 0; pCtx->iANeg = 0; pCtx->iAXorMask = iXorMask;
  105. break;
  106. default:
  107. case D3DCMP_ALWAYS:
  108. pCtx->iAAndMask = 0; pCtx->iANeg = 0; pCtx->iAXorMask = 0;
  109. break;
  110. case D3DCMP_LESS:
  111. pCtx->iAAndMask = ~0; pCtx->iANeg = 0; pCtx->iAXorMask = iXorMask;
  112. break;
  113. case D3DCMP_GREATEREQUAL:
  114. pCtx->iAAndMask = ~0; pCtx->iANeg = 0; pCtx->iAXorMask = 0;
  115. break;
  116. case D3DCMP_EQUAL:
  117. pCtx->iAAndMask = 0x7fffffff; pCtx->iANeg = 1; pCtx->iAXorMask =
  118. iXorMask;
  119. break;
  120. case D3DCMP_NOTEQUAL:
  121. pCtx->iAAndMask = 0x7fffffff; pCtx->iANeg = 1; pCtx->iAXorMask = 0;
  122. break;
  123. case D3DCMP_LESSEQUAL:
  124. pCtx->iAAndMask = ~0; pCtx->iANeg = 1; pCtx->iAXorMask = iXorMask;
  125. break;
  126. case D3DCMP_GREATER:
  127. pCtx->iAAndMask = ~0; pCtx->iANeg = 1; pCtx->iAXorMask = 0;
  128. break;
  129. }
  130. if (bIsMMX)
  131. {
  132. pCtx->iAXorMask = ~pCtx->iAXorMask;
  133. }
  134. // iARef is an 8.8 ALPHAREF value for use by RGB and MMX.
  135. // D3DRENDERSTATE_ALPHAREF is now an 8 bit (0xff max) value.
  136. pCtx->iARef = pCtx->pdwRenderState[D3DRENDERSTATE_ALPHAREF] << 8;
  137. }
  138. //-----------------------------------------------------------------------------
  139. //
  140. // DoSCompareSetup
  141. //
  142. // Initializes arithmetic stencil compare state based on the stencil function.
  143. //
  144. //-----------------------------------------------------------------------------
  145. void DoSCompareSetup(PD3DI_RASTCTX pCtx, BOOL bIsMMX)
  146. {
  147. INT32 iXorMask;
  148. if (bIsMMX)
  149. {
  150. iXorMask = -1;
  151. }
  152. else
  153. {
  154. iXorMask = 1;
  155. }
  156. switch ((D3DCMPFUNC)pCtx->pdwRenderState[D3DRENDERSTATE_STENCILFUNC])
  157. {
  158. case D3DCMP_NEVER:
  159. pCtx->iSAndMask = 0; pCtx->iSNeg = 0; pCtx->iSXorMask = iXorMask;
  160. break;
  161. default:
  162. case D3DCMP_ALWAYS:
  163. pCtx->iSAndMask = 0; pCtx->iSNeg = 0; pCtx->iSXorMask = 0;
  164. break;
  165. case D3DCMP_LESS:
  166. pCtx->iSAndMask = ~0; pCtx->iSNeg = 0; pCtx->iSXorMask = iXorMask;
  167. break;
  168. case D3DCMP_GREATEREQUAL:
  169. pCtx->iSAndMask = ~0; pCtx->iSNeg = 0; pCtx->iSXorMask = 0;
  170. break;
  171. case D3DCMP_EQUAL:
  172. pCtx->iSAndMask = 0x7fffffff; pCtx->iSNeg = 1; pCtx->iSXorMask =
  173. iXorMask;
  174. break;
  175. case D3DCMP_NOTEQUAL:
  176. pCtx->iSAndMask = 0x7fffffff; pCtx->iSNeg = 1; pCtx->iSXorMask = 0;
  177. break;
  178. case D3DCMP_LESSEQUAL:
  179. pCtx->iSAndMask = ~0; pCtx->iSNeg = 1; pCtx->iSXorMask = iXorMask;
  180. break;
  181. case D3DCMP_GREATER:
  182. pCtx->iSAndMask = ~0; pCtx->iSNeg = 1; pCtx->iSXorMask = 0;
  183. break;
  184. }
  185. if (bIsMMX)
  186. {
  187. pCtx->iSXorMask = ~pCtx->iSXorMask;
  188. }
  189. }
  190. //-----------------------------------------------------------------------------
  191. //
  192. // DoTexAddrSetup
  193. //
  194. // Initializes arithmetic texture address state state based on the texture
  195. // address function. iTex is the texure to setup.
  196. //
  197. //-----------------------------------------------------------------------------
  198. void DoTexAddrSetup(PD3DI_RASTCTX pCtx, INT32 iTex)
  199. {
  200. PD3DI_SPANTEX pTex = pCtx->pTexture[iTex];
  201. // Note that it is essential to turn on mirroring when in CLAMP/BORDER mode
  202. // to avoid filtering artifacts at the edge of the texture
  203. switch (pTex->TexAddrU)
  204. {
  205. default:
  206. case D3DTADDRESS_WRAP:
  207. pTex->iFlipMaskU = 0; pTex->iClampMinU = 0;
  208. pTex->iClampMaxU = 0; pTex->iClampEnU = 0; break;
  209. case D3DTADDRESS_MIRROR:
  210. pTex->iFlipMaskU = pTex->uMaskU+1; pTex->iClampMinU = 0;
  211. pTex->iClampMaxU = 0; pTex->iClampEnU = 0; break;
  212. case D3DTADDRESS_CLAMP:
  213. pTex->iFlipMaskU = pTex->uMaskU+1; pTex->iClampMinU = 0;
  214. pTex->iClampMaxU = pTex->uMaskU; pTex->iClampEnU = -1; break;
  215. case D3DTADDRESS_BORDER:
  216. pTex->iFlipMaskU = pTex->uMaskU+1; pTex->iClampMinU = -1;
  217. pTex->iClampMaxU = -1; pTex->iClampEnU = -1; break;
  218. }
  219. switch (pTex->TexAddrV)
  220. {
  221. default:
  222. case D3DTADDRESS_WRAP:
  223. pTex->iFlipMaskV = 0; pTex->iClampMinV = 0;
  224. pTex->iClampMaxV = 0; pTex->iClampEnV = 0; break;
  225. case D3DTADDRESS_MIRROR:
  226. pTex->iFlipMaskV = pTex->uMaskV+1; pTex->iClampMinV = 0;
  227. pTex->iClampMaxV = 0; pTex->iClampEnV = 0; break;
  228. case D3DTADDRESS_CLAMP:
  229. pTex->iFlipMaskV = pTex->uMaskV+1; pTex->iClampMinV = 0;
  230. pTex->iClampMaxV = pTex->uMaskV; pTex->iClampEnV = -1; break;
  231. case D3DTADDRESS_BORDER:
  232. pTex->iFlipMaskV = pTex->uMaskV+1; pTex->iClampMinV = -1;
  233. pTex->iClampMaxV = -1; pTex->iClampEnV = -1; break;
  234. }
  235. }
  236. // CMMX is no longer linked in
  237. // extern BEADTABLE g_CMMX_BeadTbl;
  238. extern BEADTABLE g_C_BeadTbl;
  239. #ifdef _X86_
  240. extern BEADTABLE g_MMX_BeadTbl;
  241. #else
  242. BEADTABLE g_MMX_BeadTbl = g_C_BeadTbl;
  243. #endif
  244. extern RAMPBEADTABLE g_Ramp_BeadTbl;
  245. HRESULT RampSpanInit(PD3DI_RASTCTX pCtx, PRAMPBEADTABLE pRBT);
  246. extern void Ramp_InitBeadTbl(void);
  247. #if DBG
  248. #define RANGE_CHECK(val,max) DDASSERT(((val) >= 0) && ((val) < (max)))
  249. #else
  250. #define RANGE_CHECK(val,max)
  251. #endif
  252. #undef DPF_MODNAME
  253. #define DPF_MODNAME "SpanInit"
  254. //-----------------------------------------------------------------------------
  255. //
  256. // SpanInit
  257. //
  258. // Initializes derived state (function pointers and arithmetic compare values)
  259. // based on the render state, surface type, etc.
  260. //
  261. //-----------------------------------------------------------------------------
  262. HRESULT SpanInit(PD3DI_RASTCTX pCtx)
  263. {
  264. int iZTest,
  265. iZFormat,
  266. iZWrite,
  267. iZFunc,
  268. iZDeferred,
  269. iStencil,
  270. iAlphaTest,
  271. iShadeMode,
  272. iSpecular,
  273. iVertexFog,
  274. iTexture,
  275. iTextureAddr[2],
  276. iTextureBorder[2],
  277. iTexturePerspective,
  278. iTextureFilter[2],
  279. iTextureMip[2],
  280. iTextureLOD[2],
  281. iTextureFormat[2],
  282. iTextureColorKey[2],
  283. iTextureBlend,
  284. iTextureAlphaOverride[2],
  285. iMono,
  286. iAlphaBlend,
  287. iAlphaDither[2],
  288. iBlend,
  289. iROP,
  290. iSrcBlend,
  291. iDestBlend,
  292. iTargetPixelFormat,
  293. iDither;
  294. PFNRENDERSPANS pfnRenderSpans;
  295. PFNSPANLAYER pfnTex1Addr,
  296. pfnTex2Addr,
  297. pfnColorBlend,
  298. pfnColorGen;
  299. PBEADTABLE pBeadTable;
  300. CRastCapRecord RastCapRec;
  301. #if DBG
  302. if (SPIGETFLAGS(DBG_USER_FLAGS) & SPIU_BREAK_ON_SPANINIT)
  303. {
  304. DebugBreak();
  305. }
  306. #endif
  307. // make sure this is always NULL unless it is valid
  308. pCtx->pfnRampOld = NULL;
  309. switch (pCtx->BeadSet)
  310. {
  311. #ifdef _X86_
  312. // Uncomment these (and comment out cases below) to test MMX on legacy code
  313. // case D3DIBS_CMMX:
  314. // case D3DIBS_C:
  315. case D3DIBS_MMXASRGB: // this is only different in pCtx->BeadSet for identification
  316. case D3DIBS_MMX:
  317. pBeadTable = &g_MMX_BeadTbl;
  318. break;
  319. #endif
  320. default:
  321. SPIDPFM((SPIM_INVALID,"Invalid BeadSet %d\n",
  322. pCtx->BeadSet));
  323. // fall through
  324. case D3DIBS_CMMX: // CMMX code is no longer used, make this behave the same as C
  325. case D3DIBS_C:
  326. pBeadTable = &g_C_BeadTbl;
  327. break;
  328. case D3DIBS_RAMP:
  329. return RampSpanInit(pCtx, &g_Ramp_BeadTbl);
  330. break;
  331. }
  332. DoZCompareSetup(pCtx, (pBeadTable == &g_MMX_BeadTbl));
  333. DoACompareSetup(pCtx, (pBeadTable == &g_MMX_BeadTbl));
  334. DoSCompareSetup(pCtx, (pBeadTable == &g_MMX_BeadTbl));
  335. // The function pointers that point to various beads are stored in
  336. // multi-dimensional arrays. In order to access the correct bead, we
  337. // use numerical indices into these arrays. The indices are either
  338. // the exact value of the renderstate used to choose the bead, or are
  339. // values chosen by looking at the value of the renderstate.
  340. // values needed to choose Test and AlphaTest beads
  341. iZTest = (pCtx->pdwRenderState[D3DRENDERSTATE_ZENABLE] ||
  342. pCtx->pdwRenderState[D3DRENDERSTATE_STENCILENABLE]) ? 1 : 0;
  343. RastCapRec.Set_ZTest(iZTest);
  344. switch (pCtx->iZBitCount)
  345. {
  346. default :
  347. SPIDPFM((SPIM_INVALID,"Invalid Z surface bit count, iZBitCount == 0x%x\n",
  348. pCtx->iZBitCount));
  349. case 0 :
  350. case 16 :
  351. iZFormat = 0;
  352. break;
  353. case 32 :
  354. iZFormat = 1;
  355. break;
  356. }
  357. RastCapRec.Set_ZFormat(iZFormat);
  358. iZWrite = pCtx->pdwRenderState[D3DRENDERSTATE_ZWRITEENABLE] ? 1 : 0;
  359. RastCapRec.Set_ZWrite(iZWrite);
  360. switch (pCtx->pdwRenderState[D3DRENDERSTATE_ZFUNC])
  361. {
  362. case D3DCMP_NEVER :
  363. case D3DCMP_ALWAYS :
  364. iZFunc = 0;
  365. break;
  366. case D3DCMP_LESS :
  367. case D3DCMP_GREATEREQUAL :
  368. iZFunc = 1;
  369. break;
  370. case D3DCMP_EQUAL :
  371. case D3DCMP_NOTEQUAL :
  372. iZFunc = 2;
  373. break;
  374. default :
  375. SPIDPFM((SPIM_INVALID,"Invalid renderstate value, D3DRENDERSTATE_ZFUNC == 0x%x\n",
  376. pCtx->pdwRenderState[D3DRENDERSTATE_ZFUNC]));
  377. case D3DCMP_LESSEQUAL :
  378. case D3DCMP_GREATER :
  379. iZFunc = 3;
  380. break;
  381. }
  382. if (!pCtx->pdwRenderState[D3DRENDERSTATE_ZENABLE])
  383. {
  384. // setup ALWAYS if Z is not enabled, since we may be going into
  385. // the test beads for other reasons (like stencil)
  386. iZFunc = 0;
  387. iZWrite = 0; // do not write iterated Z, but stencil will be written if needed
  388. }
  389. RastCapRec.Set_ZFunc(iZFunc);
  390. // Ignore stipple (D3DRENDERSTATE_STIPPLEENABLE), since no software rasterizers do it.
  391. RastCapRec.Set_Stipple(0);
  392. iAlphaTest = pCtx->pdwRenderState[D3DRENDERSTATE_ALPHATESTENABLE] ? 1 : 0;
  393. RastCapRec.Set_AlphaTest(iAlphaTest);
  394. iStencil = pCtx->pdwRenderState[D3DRENDERSTATE_STENCILENABLE] ? 1 : 0;
  395. RastCapRec.Set_Stencil(iStencil);
  396. // values needed for TestFail, TexAddr1 and ColorGen beads
  397. switch (pCtx->pdwRenderState[D3DRENDERSTATE_SHADEMODE])
  398. {
  399. case D3DSHADE_FLAT :
  400. iShadeMode = 0;
  401. break;
  402. default :
  403. SPIDPFM((SPIM_INVALID,"Invalid renderstate value, D3DRENDERSTATE_SHADEMODE == 0x%x\n",
  404. pCtx->pdwRenderState[D3DRENDERSTATE_SHADEMODE]));
  405. case D3DSHADE_GOURAUD :
  406. case D3DSHADE_PHONG :
  407. iShadeMode = 1;
  408. break;
  409. }
  410. RastCapRec.Set_ShadeMode(iShadeMode);
  411. iSpecular = pCtx->pdwRenderState[D3DRENDERSTATE_SPECULARENABLE] ? 1 : 0;
  412. RastCapRec.Set_Specular(iSpecular);
  413. iVertexFog = pCtx->pdwRenderState[D3DRENDERSTATE_FOGENABLE] ? 1 : 0;
  414. RastCapRec.Set_VertexFog(iVertexFog);
  415. // are we texturing at all?
  416. if (pCtx->cActTex == 0) {
  417. iTexture = 0;
  418. RastCapRec.Set_Texture(iTexture);
  419. iTextureBlend = 0;
  420. RastCapRec.Set_TextureBlend(iTextureBlend);
  421. iTexturePerspective = 0;
  422. RastCapRec.Set_TexturePersp(iTexturePerspective);
  423. iTextureAlphaOverride[0] = 0;
  424. RastCapRec.Set_TextureAlphaOverride(0, iTextureAlphaOverride[0]);
  425. iTextureColorKey[0] = 0;
  426. RastCapRec.Set_TextureColorKey(0, iTextureColorKey[0]);
  427. if (pCtx->uDevVer >= 1)
  428. {
  429. // DX6, DX5 required legacy behavior
  430. iAlphaDither[0] = pCtx->pdwRenderState[D3DRENDERSTATE_COLORKEYENABLE] ? 1 : 0;
  431. }
  432. else
  433. {
  434. // DX3, required legacy behavior
  435. iAlphaDither[0] =
  436. (pCtx->pdwRenderState[D3DRENDERSTATE_ALPHABLENDENABLE] ? 1 : 0) ||
  437. (pCtx->pdwRenderState[D3DRENDERSTATE_COLORKEYENABLE] ? 1 : 0);
  438. }
  439. } else {
  440. iTexturePerspective =
  441. pCtx->pdwRenderState[D3DRENDERSTATE_TEXTUREPERSPECTIVE] ? 1 : 0;
  442. RastCapRec.Set_TexturePersp(iTexturePerspective);
  443. if (iTexturePerspective) {
  444. iTexture = 2;
  445. } else {
  446. iTexture = 1;
  447. }
  448. // If Multi-texture then iTexture must be incremented by two. This only effects fail cases.
  449. if (!(pCtx->pdwRenderState[D3DHAL_TSS_OFFSET(1,D3DTSS_COLOROP)] == D3DTOP_DISABLE))
  450. {
  451. iTexture += 2;
  452. }
  453. RastCapRec.Set_Texture(iTexture);
  454. for (INT32 i = 0; i < (INT32)pCtx->cActTex; i++)
  455. {
  456. DoTexAddrSetup(pCtx, i);
  457. // values needed to choose TexAddr1 bead, TexRead routine
  458. // easiest to deal with border separately
  459. if ((pCtx->pTexture[i]->TexAddrU == D3DTADDRESS_BORDER) ||
  460. (pCtx->pTexture[i]->TexAddrV == D3DTADDRESS_BORDER)) {
  461. iTextureBorder[i] = 1;
  462. } else {
  463. iTextureBorder[i] = 0;
  464. }
  465. RastCapRec.Set_TextureBorder(i, iTextureBorder[i]);
  466. switch (pCtx->pTexture[i]->TexAddrU)
  467. {
  468. default :
  469. SPIDPFM((SPIM_INVALID,"Invalid texture address mode, TexAddrU == 0x%x\n",
  470. pCtx->pTexture[i]->TexAddrU));
  471. case D3DTADDRESS_WRAP :
  472. if ((pCtx->pTexture[i]->TexAddrV == D3DTADDRESS_WRAP) ||
  473. (pCtx->pTexture[i]->TexAddrV == D3DTADDRESS_MIRROR)) {
  474. iTextureAddr[i] = 0;
  475. } else {
  476. iTextureAddr[i] = 1;
  477. }
  478. break;
  479. case D3DTADDRESS_MIRROR :
  480. if ((pCtx->pTexture[i]->TexAddrV == D3DTADDRESS_WRAP) ||
  481. (pCtx->pTexture[i]->TexAddrV == D3DTADDRESS_MIRROR)) {
  482. iTextureAddr[i] = 0;
  483. } else {
  484. iTextureAddr[i] = 1;
  485. }
  486. break;
  487. case D3DTADDRESS_CLAMP :
  488. iTextureAddr[i] = 1;
  489. break;
  490. case D3DTADDRESS_BORDER :
  491. iTextureAddr[i] = 1;
  492. break;
  493. }
  494. RastCapRec.Set_TextureAddr(i, iTextureAddr[i]);
  495. if (i >= 1)
  496. {
  497. // no LOD info for second texture, just use uMagFilter
  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. iTextureFilter[i] = 0;
  505. break;
  506. case D3DTFG_LINEAR :
  507. case D3DTFG_FLATCUBIC:
  508. case D3DTFG_GAUSSIANCUBIC:
  509. case D3DTFG_ANISOTROPIC:
  510. iTextureFilter[i] = 1;
  511. break;
  512. }
  513. iTextureMip[i] = 0;
  514. iTextureLOD[i] = 0;
  515. }
  516. else
  517. {
  518. switch (pCtx->pTexture[i]->uMagFilter)
  519. {
  520. default :
  521. SPIDPFM((SPIM_INVALID,"Invalid texture filter mode, uMagFilter == 0x%x\n",
  522. pCtx->pTexture[i]->uMagFilter));
  523. case D3DTFG_POINT :
  524. if (pCtx->pTexture[i]->uMinFilter == D3DTFN_POINT)
  525. {
  526. iTextureFilter[i] = 0;
  527. }
  528. else
  529. {
  530. iTextureFilter[i] = 2;
  531. }
  532. break;
  533. case D3DTFG_LINEAR :
  534. case D3DTFG_FLATCUBIC:
  535. case D3DTFG_GAUSSIANCUBIC:
  536. case D3DTFG_ANISOTROPIC:
  537. if (pCtx->pTexture[i]->uMinFilter == D3DTFN_LINEAR)
  538. {
  539. iTextureFilter[i] = 1;
  540. }
  541. else
  542. {
  543. iTextureFilter[i] = 2;
  544. }
  545. break;
  546. }
  547. iTextureLOD[i] = 1;
  548. if ( (i == 0) && (pCtx->pTexture[i]->uMipFilter == D3DTFP_LINEAR) )
  549. {
  550. iTextureMip[i] = 1;
  551. }
  552. else
  553. {
  554. iTextureMip[i] = 0;
  555. // only set LOD to 0 if not mip filtering AND it is NOT the maybe
  556. // bilinear filter case
  557. if ( (pCtx->pTexture[i]->uMipFilter == D3DTFP_NONE) && (iTextureFilter[i] != 2) )
  558. {
  559. iTextureLOD[i] = 0;
  560. }
  561. }
  562. }
  563. RastCapRec.Set_TextureFilter(i, iTextureFilter[i]);
  564. RastCapRec.Set_TextureMip(i, iTextureMip[i]);
  565. RastCapRec.Set_TextureLOD(i, iTextureLOD[i]);
  566. // set iTextureAlphaOverride if texture doesn't have an alpha and should use
  567. // iterated alpha
  568. iTextureAlphaOverride[i] = 0;
  569. RastCapRec.Set_TextureAlphaOverride(i, iTextureAlphaOverride[i]);
  570. // values needed to chose TexRead routine
  571. switch(pCtx->pTexture[i]->Format)
  572. {
  573. default :
  574. SPIDPFM((SPIM_INVALID,"Invalid texture surface bit count, "
  575. "Format == 0x%x\n",(DWORD) pCtx->pTexture[i]->Format));
  576. return DDERR_INVALIDPARAMS;
  577. case D3DI_SPTFMT_B8G8R8 :
  578. iTextureFormat[i] = 0;
  579. iTextureAlphaOverride[i] = 1;
  580. break;
  581. case D3DI_SPTFMT_B8G8R8A8 :
  582. iTextureFormat[i] = 1;
  583. break;
  584. case D3DI_SPTFMT_B8G8R8X8 :
  585. // still necessary to select texture read that sets alpha to 0xff
  586. // for alpha dither
  587. iTextureFormat[i] = 0;
  588. iTextureAlphaOverride[i] = 1;
  589. break;
  590. case D3DI_SPTFMT_B5G6R5 :
  591. iTextureFormat[i] = 2;
  592. iTextureAlphaOverride[i] = 1;
  593. break;
  594. case D3DI_SPTFMT_B5G5R5 :
  595. iTextureFormat[i] = 3;
  596. iTextureAlphaOverride[i] = 1;
  597. break;
  598. case D3DI_SPTFMT_PALETTE4 :
  599. if (pCtx->pTexture[i]->pPalette == NULL)
  600. {
  601. D3D_ERR("(Rast) NULL palette in paletted texture");
  602. return DDERR_INVALIDPARAMS;
  603. }
  604. if (pCtx->pTexture[i]->uFlags & D3DI_SPANTEX_ALPHAPALETTE)
  605. {
  606. iTextureFormat[i] = 11;
  607. }
  608. else
  609. {
  610. iTextureFormat[i] = 4;
  611. iTextureAlphaOverride[i] = 1;
  612. }
  613. break;
  614. case D3DI_SPTFMT_PALETTE8 :
  615. if (pCtx->pTexture[i]->pPalette == NULL)
  616. {
  617. D3D_ERR("(Rast) NULL palette in paletted texture");
  618. return DDERR_INVALIDPARAMS;
  619. }
  620. if (pCtx->pTexture[i]->uFlags & D3DI_SPANTEX_ALPHAPALETTE)
  621. {
  622. iTextureFormat[i] = 12;
  623. }
  624. else
  625. {
  626. iTextureFormat[i] = 5;
  627. iTextureAlphaOverride[i] = 1;
  628. }
  629. break;
  630. case D3DI_SPTFMT_B5G5R5A1 :
  631. iTextureFormat[i] = 6;
  632. break;
  633. case D3DI_SPTFMT_B4G4R4 :
  634. iTextureFormat[i] = 7;
  635. iTextureAlphaOverride[i] = 1;
  636. break;
  637. case D3DI_SPTFMT_B4G4R4A4 :
  638. iTextureFormat[i] = 8;
  639. break;
  640. case D3DI_SPTFMT_L8 :
  641. iTextureFormat[i] = 9;
  642. iTextureAlphaOverride[i] = 1;
  643. break;
  644. case D3DI_SPTFMT_L8A8 :
  645. iTextureFormat[i] = 10;
  646. break;
  647. }
  648. RastCapRec.Set_TextureFormat(i, iTextureFormat[i]);
  649. if (pCtx->uDevVer >= 1)
  650. {
  651. // DX6, DX5 required legacy behavior
  652. iTextureColorKey[i] =
  653. pCtx->pdwRenderState[D3DRENDERSTATE_COLORKEYENABLE] ?
  654. ((pCtx->pTexture[i]->uFlags & D3DI_SPANTEX_HAS_TRANSPARENT) != 0) : 0;
  655. // DX5 required. Only alpha dither only when color keying
  656. iAlphaDither[i] = iTextureColorKey[i];
  657. }
  658. else
  659. {
  660. // Pre-DX5 Enable ColorKey for COLORKEY OR BLENDENABLE
  661. iTextureColorKey[i] = (pCtx->pdwRenderState[D3DRENDERSTATE_COLORKEYENABLE] ||
  662. pCtx->pdwRenderState[D3DRENDERSTATE_ALPHABLENDENABLE]) ?
  663. ((pCtx->pTexture[i]->uFlags & D3DI_SPANTEX_HAS_TRANSPARENT) != 0) : 0;
  664. // Alpha dither if Color Key OR Alpha Blend
  665. iAlphaDither[i] = iTextureColorKey[i] ||
  666. (pCtx->pdwRenderState[D3DRENDERSTATE_ALPHABLENDENABLE] != 0);
  667. }
  668. RastCapRec.Set_TextureColorKey(i, iTextureColorKey[i]);
  669. }
  670. // choose TexBlend bead
  671. iTextureBlend = -1;
  672. if ( (pCtx->uDevVer <= 1) && (pCtx->uFlags & RASTCTXFLAGS_APPHACK_MSGOLF)
  673. && (D3DTBLEND_DECAL == pCtx->pdwRenderState[D3DRENDERSTATE_TEXTUREMAPBLEND]) )
  674. {
  675. // MSGolf98 App Hack - use modulate for decal, but also make sure that alpha
  676. // gets set to 0 on 555 rendertargets so colorkey works
  677. iTextureBlend = 2;
  678. }
  679. else if ((pCtx->pdwRenderState[D3DHAL_TSS_OFFSET(1,D3DTSS_COLOROP)] == D3DTOP_DISABLE) &&
  680. (pCtx->pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_COLORARG1)] == pCtx->pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_ALPHAARG1)]) &&
  681. (pCtx->pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_COLORARG2)] == pCtx->pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_ALPHAARG2)]))
  682. {
  683. // might be legacy texture blend mode
  684. if ((pCtx->pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_COLOROP)] == D3DTOP_SELECTARG1) &&
  685. (pCtx->pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_ALPHAOP)] == D3DTOP_SELECTARG1) &&
  686. (pCtx->pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_COLORARG1)] == D3DTA_TEXTURE))
  687. {
  688. // copy, decal, decalmask
  689. iTextureBlend = 1;
  690. }
  691. if ((pCtx->pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_COLOROP)] == D3DTOP_MODULATE) &&
  692. (pCtx->pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_ALPHAOP)] == D3DTOP_SELECTARG1) &&
  693. (pCtx->pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_COLORARG1)] == D3DTA_TEXTURE) &&
  694. (pCtx->pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_COLORARG2)] == D3DTA_DIFFUSE))
  695. {
  696. // modulate, modulatemask
  697. if (iTextureAlphaOverride[0])
  698. {
  699. iTextureBlend = 3;
  700. }
  701. else
  702. {
  703. iTextureBlend = 2;
  704. }
  705. }
  706. }
  707. if (iTextureBlend == -1)
  708. {
  709. INT iCOp = 0;
  710. INT iCArg1 = 0;
  711. INT iCArg2 = 0;
  712. INT iAOp = 0;
  713. INT iAArg1 = 0;
  714. INT iAArg2 = 0;
  715. switch(pCtx->pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_COLOROP)])
  716. {
  717. default:
  718. SPIDPFM((SPIM_INVALID,"Invalid COLOROP0[0] == 0x%x\n",
  719. (DWORD) pCtx->pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_COLOROP)]));
  720. case D3DTOP_DISABLE: iCOp = 0; break;
  721. case D3DTOP_SELECTARG1: iCOp = 1; break;
  722. case D3DTOP_SELECTARG2: iCOp = 2; break;
  723. case D3DTOP_MODULATE: iCOp = 3; break;
  724. case D3DTOP_MODULATE2X: iCOp = 4; break;
  725. case D3DTOP_MODULATE4X: iCOp = 5; break;
  726. case D3DTOP_ADD: iCOp = 6; break;
  727. case D3DTOP_ADDSIGNED: iCOp = 7; break;
  728. case D3DTOP_BLENDDIFFUSEALPHA: iCOp = 8; break;
  729. case D3DTOP_BLENDTEXTUREALPHA: iCOp = 9; break;
  730. case D3DTOP_BLENDFACTORALPHA: iCOp = 10; break;
  731. case D3DTOP_BLENDTEXTUREALPHAPM: iCOp = 11; break;
  732. }
  733. switch(pCtx->pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_COLORARG1)])
  734. {
  735. default:
  736. SPIDPFM((SPIM_INVALID,"Invalid COLORARG1[0] == 0x%x\n",
  737. (DWORD) pCtx->pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_COLORARG1)]));
  738. case (D3DTA_TEXTURE):
  739. iCArg1 = 0; break;
  740. case (D3DTA_TEXTURE|D3DTA_COMPLEMENT):
  741. iCArg1 = 1; break;
  742. case (D3DTA_ALPHAREPLICATE|D3DTA_TEXTURE):
  743. iCArg1 = 2; break;
  744. case (D3DTA_ALPHAREPLICATE|D3DTA_TEXTURE|D3DTA_COMPLEMENT):
  745. iCArg1 = 3; break;
  746. }
  747. switch(pCtx->pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_COLORARG2)])
  748. {
  749. default:
  750. SPIDPFM((SPIM_INVALID,"Invalid COLORARG2[0] == 0x%x\n",
  751. (DWORD) pCtx->pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_COLORARG2)]));
  752. case (D3DTA_DIFFUSE):
  753. iCArg2 = 0; break;
  754. case (D3DTA_CURRENT):
  755. iCArg2 = 1; break;
  756. case (D3DTA_TFACTOR):
  757. iCArg2 = 2; break;
  758. case (D3DTA_COMPLEMENT|D3DTA_DIFFUSE):
  759. iCArg2 = 3; break;
  760. case (D3DTA_COMPLEMENT|D3DTA_CURRENT):
  761. iCArg2 = 4; break;
  762. case (D3DTA_COMPLEMENT|D3DTA_TFACTOR):
  763. iCArg2 = 5; break;
  764. case (D3DTA_ALPHAREPLICATE|D3DTA_DIFFUSE):
  765. iCArg2 = 6; break;
  766. case (D3DTA_ALPHAREPLICATE|D3DTA_CURRENT):
  767. iCArg2 = 7; break;
  768. case (D3DTA_ALPHAREPLICATE|D3DTA_TFACTOR):
  769. iCArg2 = 8; break;
  770. case (D3DTA_ALPHAREPLICATE|D3DTA_COMPLEMENT|D3DTA_DIFFUSE):
  771. iCArg2 = 9; break;
  772. case (D3DTA_ALPHAREPLICATE|D3DTA_COMPLEMENT|D3DTA_CURRENT):
  773. iCArg2 = 10; break;
  774. case (D3DTA_ALPHAREPLICATE|D3DTA_COMPLEMENT|D3DTA_TFACTOR):
  775. iCArg2 = 11; break;
  776. }
  777. switch(pCtx->pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_ALPHAOP)])
  778. {
  779. default:
  780. SPIDPFM((SPIM_INVALID,"Invalid ALPHAOP[0] == 0x%x\n",
  781. (DWORD) pCtx->pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_ALPHAOP)]));
  782. case D3DTOP_DISABLE: iAOp = 0; break;
  783. case D3DTOP_SELECTARG1: iAOp = 1; break;
  784. case D3DTOP_SELECTARG2: iAOp = 2; break;
  785. case D3DTOP_MODULATE: iAOp = 3; break;
  786. case D3DTOP_MODULATE2X: iAOp = 4; break;
  787. case D3DTOP_MODULATE4X: iAOp = 5; break;
  788. case D3DTOP_ADD: iAOp = 6; break;
  789. case D3DTOP_ADDSIGNED: iAOp = 7; break;
  790. case D3DTOP_BLENDDIFFUSEALPHA: iAOp = 8; break;
  791. case D3DTOP_BLENDTEXTUREALPHA: iAOp = 9; break;
  792. case D3DTOP_BLENDFACTORALPHA: iAOp = 10; break;
  793. case D3DTOP_BLENDTEXTUREALPHAPM: iAOp = 11; break;
  794. }
  795. switch(pCtx->pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_ALPHAARG1)])
  796. {
  797. default:
  798. SPIDPFM((SPIM_INVALID,"Invalid ALPHAARG1[0] == 0x%x\n",
  799. (DWORD) pCtx->pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_ALPHAARG1)]));
  800. case (D3DTA_TEXTURE):
  801. case (D3DTA_ALPHAREPLICATE|D3DTA_TEXTURE):
  802. iAArg1 = 0; break;
  803. case (D3DTA_TEXTURE|D3DTA_COMPLEMENT):
  804. case (D3DTA_ALPHAREPLICATE|D3DTA_TEXTURE|D3DTA_COMPLEMENT):
  805. iAArg1 = 1; break;
  806. }
  807. switch(pCtx->pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_ALPHAARG2)])
  808. {
  809. default:
  810. SPIDPFM((SPIM_INVALID,"Invalid ALPHAARG2[0] == 0x%x\n",
  811. (DWORD) pCtx->pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_ALPHAARG2)]));
  812. case (D3DTA_DIFFUSE):
  813. case (D3DTA_ALPHAREPLICATE|D3DTA_DIFFUSE):
  814. iAArg2 = 0; break;
  815. case (D3DTA_CURRENT):
  816. case (D3DTA_ALPHAREPLICATE|D3DTA_CURRENT):
  817. iAArg2 = 1; break;
  818. case (D3DTA_TFACTOR):
  819. case (D3DTA_ALPHAREPLICATE|D3DTA_TFACTOR):
  820. iAArg2 = 2; break;
  821. case (D3DTA_COMPLEMENT|D3DTA_DIFFUSE):
  822. case (D3DTA_ALPHAREPLICATE|D3DTA_COMPLEMENT|D3DTA_DIFFUSE):
  823. iAArg2 = 3; break;
  824. case (D3DTA_COMPLEMENT|D3DTA_CURRENT):
  825. case (D3DTA_ALPHAREPLICATE|D3DTA_COMPLEMENT|D3DTA_CURRENT):
  826. iAArg2 = 4; break;
  827. case (D3DTA_COMPLEMENT|D3DTA_TFACTOR):
  828. case (D3DTA_ALPHAREPLICATE|D3DTA_COMPLEMENT|D3DTA_TFACTOR):
  829. iAArg2 = 5; break;
  830. }
  831. pCtx->pfnTexBlendOpColor[0] = pBeadTable->pTexBlendOpColorBeads->pfnTexBlendOpColor[iCOp];
  832. pCtx->pfnTexBlendGetColor[0] = pBeadTable->pTexBlendGetColorBeads->pfnTexBlendGetColor[iCArg2][iCArg1];
  833. pCtx->pfnTexBlendOpAlpha[0] = pBeadTable->pTexBlendOpAlphaBeads->pfnTexBlendOpAlpha[iAOp];
  834. pCtx->pfnTexBlendGetAlpha[0] = pBeadTable->pTexBlendGetAlphaBeads->pfnTexBlendGetAlpha[iAArg2][iAArg1];
  835. // general TexBlend
  836. if (pCtx->pdwRenderState[D3DHAL_TSS_OFFSET(1,D3DTSS_COLOROP)] == D3DTOP_DISABLE)
  837. { \
  838. // Tex1_Gen
  839. iTextureBlend = 4;
  840. }
  841. else
  842. {
  843. // TexM_Gen
  844. iTextureBlend = 5;
  845. switch(pCtx->pdwRenderState[D3DHAL_TSS_OFFSET(1,D3DTSS_COLOROP)])
  846. {
  847. default:
  848. SPIDPFM((SPIM_INVALID,"Invalid COLOROP1[1] == 0x%x\n",
  849. (DWORD) pCtx->pdwRenderState[D3DHAL_TSS_OFFSET(1,D3DTSS_COLOROP)]));
  850. case D3DTOP_DISABLE: iCOp = 0; break;
  851. case D3DTOP_SELECTARG1: iCOp = 1; break;
  852. case D3DTOP_SELECTARG2: iCOp = 2; break;
  853. case D3DTOP_MODULATE: iCOp = 3; break;
  854. case D3DTOP_MODULATE2X: iCOp = 4; break;
  855. case D3DTOP_MODULATE4X: iCOp = 5; break;
  856. case D3DTOP_ADD: iCOp = 6; break;
  857. case D3DTOP_ADDSIGNED: iCOp = 7; break;
  858. case D3DTOP_BLENDDIFFUSEALPHA: iCOp = 8; break;
  859. case D3DTOP_BLENDTEXTUREALPHA: iCOp = 9; break;
  860. case D3DTOP_BLENDFACTORALPHA: iCOp = 10; break;
  861. case D3DTOP_BLENDTEXTUREALPHAPM: iCOp = 11; break;
  862. }
  863. switch(pCtx->pdwRenderState[D3DHAL_TSS_OFFSET(1,D3DTSS_COLORARG1)])
  864. {
  865. default:
  866. SPIDPFM((SPIM_INVALID,"Invalid COLORARG1[1] == 0x%x\n",
  867. (DWORD) pCtx->pdwRenderState[D3DHAL_TSS_OFFSET(1,D3DTSS_COLORARG1)]));
  868. case (D3DTA_TEXTURE):
  869. iCArg1 = 0; break;
  870. case (D3DTA_TEXTURE|D3DTA_COMPLEMENT):
  871. iCArg1 = 1; break;
  872. case (D3DTA_ALPHAREPLICATE|D3DTA_TEXTURE):
  873. iCArg1 = 2; break;
  874. case (D3DTA_ALPHAREPLICATE|D3DTA_TEXTURE|D3DTA_COMPLEMENT):
  875. iCArg1 = 3; break;
  876. }
  877. switch(pCtx->pdwRenderState[D3DHAL_TSS_OFFSET(1,D3DTSS_COLORARG2)])
  878. {
  879. case (D3DTA_DIFFUSE):
  880. iCArg2 = 0; break;
  881. default:
  882. SPIDPFM((SPIM_INVALID,"Invalid COLORARG2[1] == 0x%x\n",
  883. (DWORD) pCtx->pdwRenderState[D3DHAL_TSS_OFFSET(1,D3DTSS_COLORARG2)]));
  884. case (D3DTA_CURRENT):
  885. iCArg2 = 1; break;
  886. case (D3DTA_TFACTOR):
  887. iCArg2 = 2; break;
  888. case (D3DTA_COMPLEMENT|D3DTA_DIFFUSE):
  889. iCArg2 = 3; break;
  890. case (D3DTA_COMPLEMENT|D3DTA_CURRENT):
  891. iCArg2 = 4; break;
  892. case (D3DTA_COMPLEMENT|D3DTA_TFACTOR):
  893. iCArg2 = 5; break;
  894. case (D3DTA_ALPHAREPLICATE|D3DTA_DIFFUSE):
  895. iCArg2 = 6; break;
  896. case (D3DTA_ALPHAREPLICATE|D3DTA_CURRENT):
  897. iCArg2 = 7; break;
  898. case (D3DTA_ALPHAREPLICATE|D3DTA_TFACTOR):
  899. iCArg2 = 8; break;
  900. case (D3DTA_ALPHAREPLICATE|D3DTA_COMPLEMENT|D3DTA_DIFFUSE):
  901. iCArg2 = 9; break;
  902. case (D3DTA_ALPHAREPLICATE|D3DTA_COMPLEMENT|D3DTA_CURRENT):
  903. iCArg2 = 10; break;
  904. case (D3DTA_ALPHAREPLICATE|D3DTA_COMPLEMENT|D3DTA_TFACTOR):
  905. iCArg2 = 11; break;
  906. }
  907. switch(pCtx->pdwRenderState[D3DHAL_TSS_OFFSET(1,D3DTSS_ALPHAOP)])
  908. {
  909. default:
  910. SPIDPFM((SPIM_INVALID,"Invalid ALPHAOP[1] == 0x%x\n",
  911. (DWORD) pCtx->pdwRenderState[D3DHAL_TSS_OFFSET(1,D3DTSS_ALPHAOP)]));
  912. case D3DTOP_DISABLE: iAOp = 0; break;
  913. case D3DTOP_SELECTARG1: iAOp = 1; break;
  914. case D3DTOP_SELECTARG2: iAOp = 2; break;
  915. case D3DTOP_MODULATE: iAOp = 3; break;
  916. case D3DTOP_MODULATE2X: iAOp = 4; break;
  917. case D3DTOP_MODULATE4X: iAOp = 5; break;
  918. case D3DTOP_ADD: iAOp = 6; break;
  919. case D3DTOP_ADDSIGNED: iAOp = 7; break;
  920. case D3DTOP_BLENDDIFFUSEALPHA: iAOp = 8; break;
  921. case D3DTOP_BLENDTEXTUREALPHA: iAOp = 9; break;
  922. case D3DTOP_BLENDFACTORALPHA: iAOp = 10; break;
  923. case D3DTOP_BLENDTEXTUREALPHAPM: iAOp = 11; break;
  924. }
  925. switch(pCtx->pdwRenderState[D3DHAL_TSS_OFFSET(1,D3DTSS_ALPHAARG1)])
  926. {
  927. default:
  928. SPIDPFM((SPIM_INVALID,"Invalid ALPHAARG1[1] == 0x%x\n",
  929. (DWORD) pCtx->pdwRenderState[D3DHAL_TSS_OFFSET(1,D3DTSS_ALPHAARG1)]));
  930. case (D3DTA_TEXTURE):
  931. case (D3DTA_ALPHAREPLICATE|D3DTA_TEXTURE):
  932. iAArg1 = 0; break;
  933. case (D3DTA_TEXTURE|D3DTA_COMPLEMENT):
  934. case (D3DTA_ALPHAREPLICATE|D3DTA_TEXTURE|D3DTA_COMPLEMENT):
  935. iAArg1 = 1; break;
  936. }
  937. switch(pCtx->pdwRenderState[D3DHAL_TSS_OFFSET(1,D3DTSS_ALPHAARG2)])
  938. {
  939. case (D3DTA_DIFFUSE):
  940. case (D3DTA_ALPHAREPLICATE|D3DTA_DIFFUSE):
  941. iAArg2 = 0; break;
  942. default:
  943. SPIDPFM((SPIM_INVALID,"Invalid ALPHAARG2[1] == 0x%x\n",
  944. (DWORD) pCtx->pdwRenderState[D3DHAL_TSS_OFFSET(1,D3DTSS_ALPHAARG2)]));
  945. case (D3DTA_CURRENT):
  946. case (D3DTA_ALPHAREPLICATE|D3DTA_CURRENT):
  947. iAArg2 = 1; break;
  948. case (D3DTA_TFACTOR):
  949. case (D3DTA_ALPHAREPLICATE|D3DTA_TFACTOR):
  950. iAArg2 = 2; break;
  951. case (D3DTA_COMPLEMENT|D3DTA_DIFFUSE):
  952. case (D3DTA_ALPHAREPLICATE|D3DTA_COMPLEMENT|D3DTA_DIFFUSE):
  953. iAArg2 = 3; break;
  954. case (D3DTA_COMPLEMENT|D3DTA_CURRENT):
  955. case (D3DTA_ALPHAREPLICATE|D3DTA_COMPLEMENT|D3DTA_CURRENT):
  956. iAArg2 = 4; break;
  957. case (D3DTA_COMPLEMENT|D3DTA_TFACTOR):
  958. case (D3DTA_ALPHAREPLICATE|D3DTA_COMPLEMENT|D3DTA_TFACTOR):
  959. iAArg2 = 5; break;
  960. }
  961. pCtx->pfnTexBlendOpColor[1] = pBeadTable->pTexBlendOpColorBeads->pfnTexBlendOpColor[iCOp];
  962. pCtx->pfnTexBlendGetColor[1] = pBeadTable->pTexBlendGetColorBeads->pfnTexBlendGetColor[iCArg2][iCArg1];
  963. pCtx->pfnTexBlendOpAlpha[1] = pBeadTable->pTexBlendOpAlphaBeads->pfnTexBlendOpAlpha[iAOp];
  964. pCtx->pfnTexBlendGetAlpha[1] = pBeadTable->pTexBlendGetAlphaBeads->pfnTexBlendGetAlpha[iAArg2][iAArg1];
  965. }
  966. }
  967. RastCapRec.Set_TextureBlend(iTextureBlend);
  968. }
  969. // Ignore mono (D3DRENDERSTATE_MONOENABLE), since no software rasterizers do anything with it.
  970. iMono = 0;
  971. RastCapRec.Set_Mono(iMono);
  972. // values needed to choose ColorBlend bead
  973. iAlphaBlend =
  974. pCtx->pdwRenderState[D3DRENDERSTATE_ALPHABLENDENABLE] ? 1 : 0;
  975. RastCapRec.Set_AlphaBlend(iAlphaBlend);
  976. if (!iAlphaBlend ||
  977. ((pCtx->pdwRenderState[D3DRENDERSTATE_SRCBLEND] == D3DBLEND_ONE) &&
  978. (pCtx->pdwRenderState[D3DRENDERSTATE_DESTBLEND] == D3DBLEND_ZERO))) {
  979. iBlend = 0;
  980. } else {
  981. iBlend = 1;
  982. }
  983. RastCapRec.Set_Blend(iBlend);
  984. if (pCtx->pdwRenderState[D3DRENDERSTATE_ROP2] == R2_COPYPEN) {
  985. iROP = 0;
  986. } else {
  987. iROP = 1;
  988. }
  989. RastCapRec.Set_ROP(iROP);
  990. // value needed to choose DestBlend routine
  991. switch (pCtx->pdwRenderState[D3DRENDERSTATE_DESTBLEND])
  992. {
  993. default :
  994. SPIDPFM((SPIM_INVALID,"Invalid renderstate value, D3DRENDERSTATE_DESTBLEND == 0x%x\n",
  995. pCtx->pdwRenderState[D3DRENDERSTATE_DESTBLEND]));
  996. case D3DBLEND_ZERO :
  997. iDestBlend = 0;
  998. break;
  999. case D3DBLEND_ONE :
  1000. iDestBlend = 1;
  1001. break;
  1002. case D3DBLEND_SRCCOLOR :
  1003. iDestBlend = 2;
  1004. break;
  1005. case D3DBLEND_INVSRCCOLOR :
  1006. iDestBlend = 3;
  1007. break;
  1008. case D3DBLEND_SRCALPHA :
  1009. iDestBlend = 4;
  1010. break;
  1011. case D3DBLEND_INVSRCALPHA :
  1012. iDestBlend = 5;
  1013. break;
  1014. case D3DBLEND_DESTALPHA :
  1015. iDestBlend = 6;
  1016. break;
  1017. case D3DBLEND_INVDESTALPHA :
  1018. iDestBlend = 7;
  1019. break;
  1020. case D3DBLEND_DESTCOLOR :
  1021. iDestBlend = 8;
  1022. break;
  1023. case D3DBLEND_INVDESTCOLOR :
  1024. iDestBlend = 9;
  1025. break;
  1026. case D3DBLEND_SRCALPHASAT :
  1027. iDestBlend = 10;
  1028. break;
  1029. }
  1030. // set iSrcBlend after iDestBlend so BOTHSRCALPHA can override iDestBlend
  1031. // value needed to choose SrcBlend routine
  1032. switch (pCtx->pdwRenderState[D3DRENDERSTATE_SRCBLEND])
  1033. {
  1034. case D3DBLEND_ZERO :
  1035. iSrcBlend = 0;
  1036. break;
  1037. default :
  1038. SPIDPFM((SPIM_INVALID,"Invalid renderstate value, D3DRENDERSTATE_SRCBLEND == 0x%x\n",
  1039. pCtx->pdwRenderState[D3DRENDERSTATE_SRCBLEND]));
  1040. case D3DBLEND_ONE :
  1041. iSrcBlend = 1;
  1042. break;
  1043. case D3DBLEND_SRCCOLOR :
  1044. iSrcBlend = 2;
  1045. break;
  1046. case D3DBLEND_INVSRCCOLOR :
  1047. iSrcBlend = 3;
  1048. break;
  1049. case D3DBLEND_SRCALPHA :
  1050. iSrcBlend = 4;
  1051. break;
  1052. case D3DBLEND_INVSRCALPHA :
  1053. iSrcBlend = 5;
  1054. break;
  1055. case D3DBLEND_DESTALPHA :
  1056. iSrcBlend = 6;
  1057. break;
  1058. case D3DBLEND_INVDESTALPHA :
  1059. iSrcBlend = 7;
  1060. break;
  1061. case D3DBLEND_DESTCOLOR :
  1062. iSrcBlend = 8;
  1063. break;
  1064. case D3DBLEND_INVDESTCOLOR :
  1065. iSrcBlend = 9;
  1066. break;
  1067. case D3DBLEND_SRCALPHASAT :
  1068. iSrcBlend = 10;
  1069. break;
  1070. // these are special and set both source and dest
  1071. case D3DBLEND_BOTHSRCALPHA :
  1072. iSrcBlend = 4;
  1073. iDestBlend = 5;
  1074. break;
  1075. case D3DBLEND_BOTHINVSRCALPHA :
  1076. iSrcBlend = 5;
  1077. iDestBlend = 4;
  1078. break;
  1079. }
  1080. RastCapRec.Set_SrcBlend(iSrcBlend);
  1081. RastCapRec.Set_DestBlend(iDestBlend);
  1082. // values needed to choose BufWrite bead and BufRead routine
  1083. switch (pCtx->iSurfaceType)
  1084. {
  1085. default :
  1086. SPIDPFM((SPIM_INVALID,"Invalid target surface type, iSurfaceType == 0x%x\n",
  1087. pCtx->iSurfaceType));
  1088. case RR_STYPE_B8G8R8X8:
  1089. iTargetPixelFormat = 0;
  1090. break;
  1091. case RR_STYPE_B8G8R8A8:
  1092. iTargetPixelFormat = 1;
  1093. break;
  1094. case RR_STYPE_B5G6R5:
  1095. iTargetPixelFormat = 2;
  1096. break;
  1097. case RR_STYPE_B5G5R5:
  1098. iTargetPixelFormat = 3;
  1099. break;
  1100. case RR_STYPE_B5G5R5A1:
  1101. iTargetPixelFormat = 4;
  1102. break;
  1103. case RR_STYPE_B8G8R8:
  1104. iTargetPixelFormat = 5;
  1105. break;
  1106. case RR_STYPE_PALETTE8:
  1107. iTargetPixelFormat = 6;
  1108. break;
  1109. }
  1110. RastCapRec.Set_TargetPixelFormat(iTargetPixelFormat);
  1111. iDither = pCtx->pdwRenderState[D3DRENDERSTATE_DITHERENABLE] ? 1 : 0;
  1112. RastCapRec.Set_Dither(iDither);
  1113. iZDeferred = iAlphaTest || iAlphaDither[0];
  1114. // Set optional postprocessing beads first so that their addresses
  1115. // can be referenced later.
  1116. pCtx->pfnPixelEnd = pBeadTable->pPixelEndBeads->pfnPixelEnd[0];
  1117. pCtx->pfnSpanEnd = pBeadTable->pSpanEndBeads->pfnSpanEnd[0];
  1118. // start stringing beads together, back to front order avoids a lot of
  1119. // conditional logic
  1120. #if DBG
  1121. // null out all bead ptrs
  1122. pCtx->pfnBegin = NULL;
  1123. pCtx->pfnLoopEnd = NULL;
  1124. pCtx->pfnTestPassEnd = NULL;
  1125. pCtx->pfnTestFailEnd = NULL;
  1126. pCtx->pfnTex1AddrEnd = NULL;
  1127. pCtx->pfnTexRead[0] = NULL;
  1128. pCtx->pfnTexRead[1] = NULL;
  1129. pCtx->pfnTex2AddrEnd = NULL;
  1130. pCtx->pfnTexBlendEnd = NULL;
  1131. pCtx->pfnColorGenEnd = NULL;
  1132. pCtx->pfnAlphaTestPassEnd = NULL;
  1133. pCtx->pfnAlphaTestFailEnd = NULL;
  1134. pCtx->pfnSrcBlend = NULL;
  1135. pCtx->pfnDestBlend = NULL;
  1136. pCtx->pfnBufRead = NULL;
  1137. pCtx->pfnColorBlendEnd = NULL;
  1138. pCtx->pfnPixelEnd = NULL;
  1139. pCtx->pfnSpanEnd = NULL;
  1140. #endif
  1141. // range check indices used to select BufWrite bead
  1142. RANGE_CHECK(iDither,DITHERING_NUM);
  1143. RANGE_CHECK(iTargetPixelFormat,TARGETPIXELFORMAT_NUM);
  1144. // select BufWrite bead, which can be called through pfnColorBlendEnd,
  1145. // pfnAlphaTestPassEnd, pfnColorGenEnd, pfnTexBlendEnd
  1146. pCtx->pfnTexBlendEnd =
  1147. pCtx->pfnColorGenEnd =
  1148. pCtx->pfnAlphaTestPassEnd =
  1149. pCtx->pfnColorBlendEnd = pBeadTable->pBufWriteBeads->pfnBufWrite[iDither][iTargetPixelFormat];
  1150. #if DBG
  1151. strcpy(pCtx->szBufWrite,rgszBufWrite[iDither][iTargetPixelFormat]);
  1152. #endif
  1153. // range check indices used to select ColorBlend bead
  1154. RANGE_CHECK(iROP,ROP_NUM);
  1155. RANGE_CHECK(iBlend,BLEND_NUM);
  1156. // select ColorBlend bead, which can be called through
  1157. // pfnATextEnd, pfnColorGenEnd, or pfnTexBlendEnd
  1158. if ((pfnColorBlend = pBeadTable->pColorBlendBeads->pfnColorBlend[iROP][iBlend]) == NULL) {
  1159. pCtx->pfnColorBlendEnd = NULL;
  1160. } else {
  1161. pCtx->pfnTexBlendEnd =
  1162. pCtx->pfnColorGenEnd =
  1163. pCtx->pfnAlphaTestPassEnd = pfnColorBlend;
  1164. }
  1165. #if DBG
  1166. strcpy(pCtx->szColorBlend,rgszColorBlend[iROP][iBlend]);
  1167. #endif
  1168. // range check index used to select BufRead bead
  1169. RANGE_CHECK(iTargetPixelFormat,TARGETPIXELFORMAT_NUM);
  1170. // select Buf Read routine
  1171. pCtx->pfnBufRead = pBeadTable->pBufReadBeads->pfnBufRead[iTargetPixelFormat];
  1172. #if DBG
  1173. strcpy(pCtx->szBufRead,rgszBufRead[iTargetPixelFormat]);
  1174. #endif
  1175. if (iBlend) {
  1176. // range check index used to select DestBlend bead
  1177. RANGE_CHECK(iDestBlend,DESTBLEND_NUM);
  1178. // select DestBlend routine
  1179. pCtx->pfnDestBlend = pBeadTable->pDestBlendBeads->pfnDestBlend[iDestBlend];
  1180. #if DBG
  1181. strcpy(pCtx->szDestBlend,rgszDestBlend[iDestBlend]);
  1182. #endif
  1183. // range check index used to select SrcBlend bead
  1184. RANGE_CHECK(iSrcBlend,SRCBLEND_NUM);
  1185. // select SrcBlend routine
  1186. pCtx->pfnSrcBlend = pBeadTable->pSrcBlendBeads->pfnSrcBlend[iSrcBlend];
  1187. #if DBG
  1188. strcpy(pCtx->szSrcBlend,rgszSrcBlend[iSrcBlend]);
  1189. #endif
  1190. } else {
  1191. pCtx->pfnDestBlend = NULL;
  1192. pCtx->pfnSrcBlend = NULL;
  1193. #if DBG
  1194. strcpy(pCtx->szDestBlend,"NULL");
  1195. strcpy(pCtx->szSrcBlend,"NULL");
  1196. #endif
  1197. }
  1198. // select AlphaTest/AlphaDitheringTest bead, which can be called through
  1199. // pfnColorBlendEnd, pfnColorGenEnd, or pfnTexBlendEnd
  1200. // range check indices used to select AlphaTest bead
  1201. RANGE_CHECK(iStencil,STENCIL_NUM);
  1202. RANGE_CHECK(iZFormat,ZFORMAT_NUM);
  1203. RANGE_CHECK(iZWrite,ZWRITE_NUM);
  1204. RANGE_CHECK(iAlphaDither[0],COLORKEY_NUM);
  1205. RANGE_CHECK(iAlphaTest,ALPHATEST_NUM);
  1206. if (iAlphaTest || iAlphaDither[0])
  1207. {
  1208. pCtx->pfnTexBlendEnd =
  1209. pCtx->pfnColorGenEnd =
  1210. pBeadTable->pAlphaTestBeads->pfnAlphaTest[iStencil]
  1211. [iZFormat]
  1212. [iZWrite || iStencil]
  1213. [iAlphaDither[0]]
  1214. [iAlphaTest];
  1215. // If AlphaTest fails, it goes to where the BufWrite bead ends
  1216. pCtx->pfnAlphaTestFailEnd = pCtx->pfnPixelEnd;
  1217. #if DBG
  1218. strcpy(pCtx->szAlphaTest,rgszAlphaTest[iStencil][iZFormat][iZWrite]
  1219. [iAlphaDither[0]][iAlphaTest]);
  1220. #endif
  1221. }
  1222. else
  1223. {
  1224. pCtx->pfnAlphaTestPassEnd = NULL;
  1225. pCtx->pfnAlphaTestFailEnd = NULL;
  1226. #if DBG
  1227. strcpy(pCtx->szAlphaTest, "NULL");
  1228. #endif
  1229. }
  1230. // range check indices used to select ColorGen bead
  1231. RANGE_CHECK(iMono,MONO_NUM);
  1232. RANGE_CHECK(iVertexFog,VERTEXFOG_NUM);
  1233. RANGE_CHECK(iSpecular,SPECULAR_NUM);
  1234. RANGE_CHECK(iShadeMode,SHADEMODE_NUM);
  1235. // select ColorGen bead, which can be called through pfnTexBlendEnd
  1236. if ((pfnColorGen =
  1237. pBeadTable->pColorGenBeads->pfnColorGen[iMono][iVertexFog][iSpecular][iShadeMode]) == NULL) {
  1238. pCtx->pfnColorGenEnd = NULL;
  1239. } else {
  1240. pCtx->pfnTexBlendEnd = pfnColorGen;
  1241. }
  1242. #if DBG
  1243. strcpy(pCtx->szColorGen,
  1244. rgszColorGen[iMono][iVertexFog][iSpecular][iShadeMode]);
  1245. #endif
  1246. // range check indices used to select TexBlend bead
  1247. RANGE_CHECK(iTextureBlend,TEXTUREBLEND_NUM);
  1248. // select TexBlend bead, which can be called through pfnTexAddr2End,
  1249. // pfnTexAddr1End, pfnTestPassEnd, or pfnLoopEnd
  1250. pCtx->pfnLoopEnd =
  1251. pCtx->pfnTestPassEnd =
  1252. pCtx->pfnTex1AddrEnd =
  1253. pCtx->pfnTex2AddrEnd = pBeadTable->pTexBlendBeads->pfnTexBlend[iTextureBlend];
  1254. #if DBG
  1255. strcpy(pCtx->szTexBlend,rgszTexBlend[iTextureBlend]);
  1256. #endif
  1257. if (iTexture) {
  1258. if (pCtx->cActTex >= 2)
  1259. {
  1260. // range check indices used to select TexRead bead
  1261. RANGE_CHECK(iTextureColorKey[1],COLORKEY_NUM);
  1262. RANGE_CHECK(iTextureBorder[1],TEXTUREBORDER_NUM);
  1263. RANGE_CHECK(iTextureFormat[1],TEXTUREFORMAT_NUM);
  1264. // select TexAddr2 bead, which can be called through pfnTexAddr1
  1265. // select TexRead routine
  1266. pCtx->pfnTexRead[1] =
  1267. pBeadTable->pTexReadBeads->pfnTexRead[iTextureColorKey[1]][iTextureBorder[1]][iTextureFormat[1]];
  1268. #if DBG
  1269. strcpy(pCtx->szTexRead[1],
  1270. rgszTexRead[iTextureColorKey[1]][iTextureBorder[1]][iTextureFormat[1]]);
  1271. #endif
  1272. // range check indices used to select Tex1Addr bead
  1273. RANGE_CHECK(iTextureLOD[1],TEXTURELOD_NUM);
  1274. RANGE_CHECK(iTextureFilter[1],TEXTUREFILTER_NUM);
  1275. RANGE_CHECK(iTexturePerspective,TEXTUREPERSPECTIVE_NUM);
  1276. RANGE_CHECK(iTextureAddr[1],TEXTUREADDRESS_NUM);
  1277. // select TexAddr1 bead, which can be called through pfnTestPassEnd or
  1278. // pfnLoopEnd
  1279. if ((pfnTex2Addr = (pBeadTable->pTex2AddrBeads->pfnTex2Addr[iTextureFilter[1]]
  1280. [iTexturePerspective][iTextureAddr[1]])) == NULL) {
  1281. pCtx->pfnTex2AddrEnd = NULL;
  1282. } else {
  1283. pCtx->pfnLoopEnd =
  1284. pCtx->pfnTex1AddrEnd = pfnTex2Addr;
  1285. }
  1286. #if DBG
  1287. strcpy(pCtx->szTex2Addr,rgszTex2Addr[iTextureFilter[1]]
  1288. [iTexturePerspective][iTextureAddr[1]]);
  1289. #endif
  1290. } else {
  1291. pCtx->pfnTex2AddrEnd = NULL;
  1292. pCtx->pfnTexRead[1] = NULL;
  1293. #if DBG
  1294. strcpy(pCtx->szTex2Addr,"NULL");
  1295. strcpy(pCtx->szTexRead[1],"NULL");
  1296. #endif
  1297. }
  1298. // range check indices used to select TexRead bead
  1299. RANGE_CHECK(iTextureColorKey[0],COLORKEY_NUM);
  1300. RANGE_CHECK(iTextureBorder[0],TEXTUREBORDER_NUM);
  1301. RANGE_CHECK(iTextureFormat[0],TEXTUREFORMAT_NUM);
  1302. // select TexRead routine
  1303. pCtx->pfnTexRead[0] =
  1304. pBeadTable->pTexReadBeads->pfnTexRead[iTextureColorKey[0]][iTextureBorder[0]][iTextureFormat[0]];
  1305. #if DBG
  1306. strcpy(pCtx->szTexRead[0],
  1307. rgszTexRead[iTextureColorKey[0]][iTextureBorder[0]][iTextureFormat[0]]);
  1308. #endif
  1309. // range check indices used to select Tex1Addr bead
  1310. RANGE_CHECK(iTextureLOD[0],TEXTURELOD_NUM);
  1311. RANGE_CHECK(iTextureFilter[0],TEXTUREFILTER_NUM);
  1312. RANGE_CHECK(iTexturePerspective,TEXTUREPERSPECTIVE_NUM);
  1313. RANGE_CHECK(iTextureAddr[0],TEXTUREADDRESS_NUM);
  1314. // select TexAddr1 bead, which can be called through pfnTestPassEnd or
  1315. // pfnLoopEnd
  1316. if ((pfnTex1Addr = ((iTextureMip[0]) ?
  1317. (pBeadTable->pTex1AddrMipBeads->pfnTex1AddrMip[0]) :
  1318. (pBeadTable->pTex1AddrBeads->pfnTex1Addr[iTextureLOD[0]][iTextureFilter[0]]
  1319. [iTexturePerspective][iTextureAddr[0]]))) == NULL) {
  1320. pCtx->pfnTex1AddrEnd = NULL;
  1321. } else {
  1322. pCtx->pfnLoopEnd =
  1323. pCtx->pfnTestPassEnd = pfnTex1Addr;
  1324. }
  1325. #if DBG
  1326. if (iTextureMip[0])
  1327. {
  1328. strcpy(pCtx->szTex1Addr,rgszTex1AddrMip[0]);
  1329. }
  1330. else
  1331. {
  1332. strcpy(pCtx->szTex1Addr,rgszTex1Addr[iTextureLOD[0]][iTextureFilter[0]]
  1333. [iTexturePerspective][iTextureAddr[0]]);
  1334. }
  1335. #endif
  1336. } else {
  1337. pCtx->pfnTex2AddrEnd = NULL;
  1338. pCtx->pfnTexRead[0] = NULL;
  1339. pCtx->pfnTex1AddrEnd = NULL;
  1340. #if DBG
  1341. strcpy(pCtx->szTex2Addr,"NULL");
  1342. strcpy(pCtx->szTexRead[0],"NULL");
  1343. strcpy(pCtx->szTex1Addr,"NULL");
  1344. #endif
  1345. }
  1346. // select Test bead, which can be called through pfnLoopEnd
  1347. if (iZTest) {
  1348. // range check indices used to select Test bead
  1349. RANGE_CHECK(iStencil,STENCIL_NUM);
  1350. RANGE_CHECK(iZFunc,ZFUNC_NUM);
  1351. RANGE_CHECK(iZWrite,ZWRITE_NUM);
  1352. // ATTENTION range check this
  1353. // RANGE_CHECK(iAlphaTest,ALPHATEST_NUM);
  1354. RANGE_CHECK(iZFormat,ZFORMAT_NUM);
  1355. RANGE_CHECK(iSpecular,SPECULAR_NUM);
  1356. RANGE_CHECK(iVertexFog,VERTEXFOG_NUM);
  1357. RANGE_CHECK(iTexture,TEXTURE_NUM);
  1358. RANGE_CHECK(iShadeMode,SHADEMODE_NUM);
  1359. // if alpha testing, defer Z write
  1360. pCtx->pfnLoopEnd = pBeadTable->pTestBeads->pfnTest[iStencil][iZFunc]
  1361. [iZDeferred][iZWrite][iZFormat];
  1362. // select where this bead is going to go if the test fails
  1363. pCtx->pfnTestFailEnd =
  1364. pBeadTable->pTestFailBeads->pfnTestFail[iSpecular | iVertexFog][iTexture][iShadeMode];
  1365. if (iZDeferred && iStencil)
  1366. {
  1367. // If alpha testing and stenciling, need to
  1368. // defer stencil update until after the alpha test.
  1369. //
  1370. // This is not an issue for Z, since we never want to write Z
  1371. // if the Z test fails (hence we do not care about the outcome of
  1372. // the alpha test.
  1373. pCtx->pfnTestFailEnd = pCtx->pfnTestPassEnd;
  1374. }
  1375. #if DBG
  1376. strcpy(pCtx->szTest,rgszTest[iStencil][iZFunc][iZDeferred][iZWrite][iZFormat]);
  1377. strcpy(pCtx->szTestFail,
  1378. rgszTestFail[iSpecular | iVertexFog][iTexture][iShadeMode]);
  1379. #endif
  1380. } else {
  1381. pCtx->pfnTestPassEnd = NULL;
  1382. pCtx->pfnTestFailEnd = NULL;
  1383. #if DBG
  1384. strcpy(pCtx->szTest,"NULL");
  1385. strcpy(pCtx->szTestFail,"NULL");
  1386. #endif
  1387. }
  1388. // select Loop bead
  1389. pCtx->pfnBegin = pBeadTable->pBeginBeads->pfnBegin[0];
  1390. pCtx->pfnRenderSpans = pBeadTable->pRenderSpansBeads->pfnRenderSpans[0];
  1391. #if DBG
  1392. SPIDPFM((SPIM_REPORT,"Test = %s\n",pCtx->szTest));
  1393. SPIDPFM((SPIM_REPORT,"TestFail = %s\n",pCtx->szTestFail));
  1394. SPIDPFM((SPIM_REPORT,"Tex1Addr = %s\n",pCtx->szTex1Addr));
  1395. SPIDPFM((SPIM_REPORT,"TexRead1 = %s\n",pCtx->szTexRead[0]));
  1396. SPIDPFM((SPIM_REPORT,"TexRead2 = %s\n",pCtx->szTexRead[1]));
  1397. SPIDPFM((SPIM_REPORT,"Tex2Addr = %s\n",pCtx->szTex2Addr));
  1398. SPIDPFM((SPIM_REPORT,"TexBlend = %s\n",pCtx->szTexBlend));
  1399. SPIDPFM((SPIM_REPORT,"ColorGen = %s\n",pCtx->szColorGen));
  1400. SPIDPFM((SPIM_REPORT,"ColorBlend = %s\n",pCtx->szColorBlend));
  1401. SPIDPFM((SPIM_REPORT,"SrcBlend = %s\n",pCtx->szSrcBlend));
  1402. SPIDPFM((SPIM_REPORT,"DestBlend = %s\n",pCtx->szDestBlend));
  1403. SPIDPFM((SPIM_REPORT,"BufRead = %s\n",pCtx->szBufRead));
  1404. SPIDPFM((SPIM_REPORT,"AlphaTest = %s\n",pCtx->szAlphaTest));
  1405. SPIDPFM((SPIM_REPORT,"BufWrite = %s\n",pCtx->szBufWrite));
  1406. SPIDPFM((SPIM_REPORT,"RastCap = 0x%x 0x%x 0x%x\n",
  1407. RastCapRec.GetCapDWord(0),
  1408. RastCapRec.GetCapDWord(1),
  1409. RastCapRec.GetCapDWord(2)));
  1410. #if 0
  1411. DWORD dwCheckSum = RastCapRec.GetCapDWord(0) ^ RastCapRec.GetCapDWord(1) ^ RastCapRec.GetCapDWord(2);
  1412. static DWORD dwCheckSumLast;
  1413. if (dwCheckSum != dwCheckSumLast)
  1414. {
  1415. dwCheckSumLast = dwCheckSum;
  1416. DPF(0, "Spaninit");
  1417. DPF(0, "Test = %s",pCtx->szTest);
  1418. DPF(0, "TestFail = %s",pCtx->szTestFail);
  1419. DPF(0, "Tex1Addr = %s",pCtx->szTex1Addr);
  1420. DPF(0, "TexRead1 = %s",pCtx->szTexRead[0]);
  1421. DPF(0, "TexRead2 = %s",pCtx->szTexRead[1]);
  1422. DPF(0, "Tex2Addr = %s",pCtx->szTex2Addr);
  1423. DPF(0, "TexBlend = %s",pCtx->szTexBlend);
  1424. DPF(0, "ColorGen = %s",pCtx->szColorGen);
  1425. DPF(0, "ColorBlend = %s",pCtx->szColorBlend);
  1426. DPF(0, "SrcBlend = %s",pCtx->szSrcBlend);
  1427. DPF(0, "DestBlend = %s",pCtx->szDestBlend);
  1428. DPF(0, "BufRead = %s",pCtx->szBufRead);
  1429. DPF(0, "AlphaTest = %s",pCtx->szAlphaTest);
  1430. DPF(0, "BufWrite = %s",pCtx->szBufWrite);
  1431. DPF(0, "RastCap = 0x%x 0x%x 0x%x",
  1432. RastCapRec.GetCapDWord(0),
  1433. RastCapRec.GetCapDWord(1),
  1434. RastCapRec.GetCapDWord(2));
  1435. }
  1436. #endif
  1437. #endif
  1438. // is there a monolithic rasterizer that can do exactly
  1439. // what is needed?
  1440. RASTFNREC* pfnRastFnRec;
  1441. if ((pfnRastFnRec = g_RastCollection.Search(pCtx, &RastCapRec)) != NULL)
  1442. {
  1443. // yes, then replace beaded rasterizer with monolithic
  1444. DDASSERT(pfnRastFnRec->pfnRastFunc != 0);
  1445. pCtx->pfnRenderSpans = pfnRastFnRec->pfnRastFunc;
  1446. #if DBG
  1447. // null out all the others
  1448. pCtx->pfnBegin =
  1449. pCtx->pfnLoopEnd =
  1450. pCtx->pfnTestPassEnd =
  1451. pCtx->pfnTestFailEnd =
  1452. pCtx->pfnTex1AddrEnd =
  1453. pCtx->pfnTex2AddrEnd =
  1454. pCtx->pfnTexBlendEnd =
  1455. pCtx->pfnColorGenEnd =
  1456. pCtx->pfnAlphaTestPassEnd =
  1457. pCtx->pfnAlphaTestFailEnd =
  1458. pCtx->pfnColorBlendEnd =
  1459. pCtx->pfnPixelEnd = NULL;
  1460. #endif
  1461. }
  1462. #if DBG
  1463. static RASTFNREC* pfnLastRastFnRec = (RASTFNREC*)-1;
  1464. if (pfnLastRastFnRec != pfnRastFnRec)
  1465. {
  1466. if (pfnRastFnRec)
  1467. {
  1468. D3D_INFO(1, "SpanInit: Fast path rasterizer %s chosen", pfnRastFnRec->pszRastDesc);
  1469. }
  1470. else
  1471. {
  1472. D3D_WARN(1, "SpanInit: No fast path rasterizer chosen");
  1473. }
  1474. pfnLastRastFnRec = pfnRastFnRec;
  1475. }
  1476. #endif
  1477. return S_OK;
  1478. }
  1479. //-----------------------------------------------------------------------------
  1480. //
  1481. // RampSpanInit
  1482. //
  1483. // Initializes derived state (function pointers and arithmetic compare values)
  1484. // based on the render state, surface type, etc. for Ramp. This is independent of
  1485. // and quite different from the non-ramp beads.
  1486. //
  1487. //-----------------------------------------------------------------------------
  1488. HRESULT RampSpanInit(PD3DI_RASTCTX pCtx, PRAMPBEADTABLE pBeadTable)
  1489. {
  1490. int iTargetPixelFormat,
  1491. iZTest,
  1492. iZWrite,
  1493. iDither,
  1494. iTexture,
  1495. iTrans,
  1496. iTextureCopy = 0,
  1497. iTextureMonoCopy = 0,
  1498. iTextureFormat,
  1499. iTextureColorKey,
  1500. iShadeMode;
  1501. static BOOL bInitRampBeadTbl = FALSE;
  1502. static RAMPOLDBEADS* pRampOld_BeadTbl = NULL;
  1503. static PFNRAMPOLDTRI pfnRampOldTri = NULL;
  1504. if (!bInitRampBeadTbl)
  1505. {
  1506. bInitRampBeadTbl = TRUE;
  1507. Ramp_InitBeadTbl();
  1508. #if _X86_
  1509. // also see if there are fast DX5 based ramp routines
  1510. HINSTANCE hRampOldDLL = LoadLibrary("d3dramp.dll");
  1511. if (hRampOldDLL)
  1512. {
  1513. pRampOld_BeadTbl = (RAMPOLDBEADS*) GetProcAddress(hRampOldDLL, "g_RampOld_BeadTbl");
  1514. pfnRampOldTri = (PFNRAMPOLDTRI) GetProcAddress(hRampOldDLL, "RampOldTri");
  1515. }
  1516. #endif
  1517. }
  1518. DoZCompareSetup(pCtx, FALSE);
  1519. switch (pCtx->iSurfaceType)
  1520. {
  1521. default :
  1522. SPIDPFM((SPIM_INVALID,"Invalid target surface type, "
  1523. "iSurfaceType == 0x%x\n",
  1524. pCtx->iSurfaceType));
  1525. return DDERR_INVALIDPARAMS;
  1526. case RR_STYPE_PALETTE8:
  1527. iTargetPixelFormat = 0;
  1528. break;
  1529. case RR_STYPE_B5G6R5:
  1530. case RR_STYPE_B5G5R5:
  1531. case RR_STYPE_B5G5R5A1:
  1532. iTargetPixelFormat = 1;
  1533. break;
  1534. case RR_STYPE_B8G8R8X8:
  1535. case RR_STYPE_B8G8R8A8:
  1536. case RR_STYPE_B8G8R8:
  1537. iTargetPixelFormat = 2;
  1538. break;
  1539. }
  1540. iZTest = pCtx->pdwRenderState[D3DRENDERSTATE_ZENABLE] ? 1 : 0;
  1541. iZWrite = pCtx->pdwRenderState[D3DRENDERSTATE_ZWRITEENABLE] ? 1 : 0;
  1542. iDither = pCtx->pdwRenderState[D3DRENDERSTATE_DITHERENABLE] ? 1 : 0;
  1543. // are we texturing at all?
  1544. if (pCtx->cActTex == 0)
  1545. {
  1546. iTexture = 0;
  1547. iTextureFormat = 0;
  1548. iTextureColorKey = pCtx->pdwRenderState[D3DRENDERSTATE_COLORKEYENABLE];
  1549. }
  1550. else
  1551. {
  1552. iTexture =
  1553. pCtx->pdwRenderState[D3DRENDERSTATE_TEXTUREPERSPECTIVE] ? 9 : 1;
  1554. // values needed to chose TexRead routine
  1555. switch(pCtx->pTexture[0]->Format)
  1556. {
  1557. case D3DI_SPTFMT_PALETTE4 :
  1558. if (pCtx->pTexture[0]->pPalette == NULL)
  1559. {
  1560. D3D_ERR("(Rast) NULL palette in paletted texture");
  1561. return DDERR_INVALIDPARAMS;
  1562. }
  1563. iTextureFormat = 0;
  1564. break;
  1565. case D3DI_SPTFMT_B5G6R5:
  1566. case D3DI_SPTFMT_B5G5R5:
  1567. case D3DI_SPTFMT_B5G5R5A1:
  1568. if (pCtx->pdwRenderState[D3DRENDERSTATE_TEXTUREMAPBLEND]
  1569. == D3DTBLEND_COPY)
  1570. {
  1571. iTextureFormat = 2;
  1572. break;
  1573. }
  1574. default :
  1575. SPIDPFM((SPIM_INVALID,"Invalid texture surface bit count, "
  1576. "Format == 0x%x\n",(DWORD) pCtx->pTexture[0]->Format));
  1577. return DDERR_INVALIDPARAMS;
  1578. case D3DI_SPTFMT_PALETTE8 :
  1579. if (pCtx->pTexture[0]->pPalette == NULL)
  1580. {
  1581. D3D_ERR("(Rast) NULL palette in paletted texture");
  1582. return DDERR_INVALIDPARAMS;
  1583. }
  1584. iTextureFormat = 1;
  1585. break;
  1586. }
  1587. iTexture += iTextureFormat;
  1588. if ((pCtx->pdwRenderState[D3DRENDERSTATE_COLORKEYENABLE] ||
  1589. pCtx->pdwRenderState[D3DRENDERSTATE_ALPHABLENDENABLE]) &&
  1590. ((pCtx->pTexture[0]->uFlags & D3DI_SPANTEX_HAS_TRANSPARENT) != 0))
  1591. {
  1592. iTextureColorKey = 1;
  1593. iTexture += 2;
  1594. }
  1595. else
  1596. {
  1597. iTextureColorKey = 0;
  1598. }
  1599. if (pCtx->pdwRenderState[D3DRENDERSTATE_TEXTUREMAPBLEND] ==
  1600. D3DTBLEND_COPY)
  1601. {
  1602. iTextureCopy = 1;
  1603. if ( (D3DI_SPTFMT_PALETTE4 == pCtx->pTexture[0]->Format) ||
  1604. (D3DI_SPTFMT_PALETTE8 == pCtx->pTexture[0]->Format) )
  1605. {
  1606. iTextureMonoCopy = 1;
  1607. }
  1608. else
  1609. {
  1610. iTextureMonoCopy = 2;
  1611. }
  1612. iTexture += 4;
  1613. }
  1614. }
  1615. iTrans = pCtx->pdwRenderState[D3DRENDERSTATE_ALPHABLENDENABLE] ||
  1616. iTextureColorKey;
  1617. switch (pCtx->pdwRenderState[D3DRENDERSTATE_SHADEMODE])
  1618. {
  1619. case D3DSHADE_FLAT :
  1620. iShadeMode = 0;
  1621. break;
  1622. default :
  1623. SPIDPFM((SPIM_INVALID,"Invalid renderstate value, "
  1624. "D3DRENDERSTATE_SHADEMODE == 0x%x\n",
  1625. pCtx->pdwRenderState[D3DRENDERSTATE_SHADEMODE]));
  1626. case D3DSHADE_GOURAUD :
  1627. case D3DSHADE_PHONG :
  1628. iShadeMode = 1;
  1629. break;
  1630. }
  1631. #if DBG
  1632. static PFNRAMPOLD pfnRampOldOld = NULL;
  1633. #endif
  1634. // see if we can use an old DX5 ramp assembly routine
  1635. if ( (pRampOld_BeadTbl) &&
  1636. (iTargetPixelFormat <= 1) && (iDither == 0) &&
  1637. ((iTexture == 0) || ((iTextureFormat == 1) && (iTextureCopy == 0))) )
  1638. {
  1639. int iRampOldTexture = 0;
  1640. if (iTexture)
  1641. {
  1642. if (iTexture >= 9)
  1643. {
  1644. iRampOldTexture = 2;
  1645. }
  1646. else
  1647. {
  1648. iRampOldTexture = 1;
  1649. }
  1650. }
  1651. int iRampOldTrans = iTrans;
  1652. if (iRampOldTexture)
  1653. {
  1654. iRampOldTrans = iTextureColorKey;
  1655. }
  1656. pCtx->pfnRampOld = pRampOld_BeadTbl->pfnRampOld[iTargetPixelFormat][iZTest][iShadeMode][iRampOldTexture][iRampOldTrans];
  1657. if (pCtx->pfnRampOld)
  1658. {
  1659. pCtx->pfnRampOldTri = pfnRampOldTri;
  1660. }
  1661. }
  1662. #if DBG
  1663. if ((pfnRampOldOld == NULL) && (pCtx->pfnRampOld != NULL))
  1664. {
  1665. D3D_INFO(1, "Starting to use DX5 Ramp routines.");
  1666. pfnRampOldOld = pCtx->pfnRampOld;
  1667. }
  1668. if ((pfnRampOldOld != NULL) && (pCtx->pfnRampOld == NULL))
  1669. {
  1670. D3D_INFO(1, "Starting to use DX6 Ramp routines.");
  1671. // Uncomment this to see why DX5 rasterizer was not chosen
  1672. //#define WHY_IS_RAMP_SLOW_DEBUG 1
  1673. //
  1674. #if WHY_IS_RAMP_SLOW_DEBUG
  1675. D3D_INFO(1, "Not using DX5 Ramp routines because:");
  1676. D3D_INFO(1, " pRampOld_BeadTbl 0x%x, iTargetPixelFormat %d, iDither %d",
  1677. pRampOld_BeadTbl, iTargetPixelFormat, iDither);
  1678. D3D_INFO(1, " iTexture %d, iTextureFormat %d, iTextureCopy %d",
  1679. iTexture, iTextureFormat, iTextureCopy);
  1680. D3D_INFO(1, " pCtx->pfnRampOld 0x%x, iZTest %d, iShadeMode %d, iTrans %d",
  1681. pCtx->pfnRampOld, iZTest, iShadeMode, iTrans);
  1682. #endif
  1683. pfnRampOldOld = pCtx->pfnRampOld;
  1684. }
  1685. #endif
  1686. // Select TexRead routine.
  1687. pCtx->pfnTexRead[0] =
  1688. pBeadTable->pTexReadBeads->pfnTexRead[iTextureCopy][iTextureColorKey]
  1689. [iTextureFormat];
  1690. // Select Mono routine.
  1691. pCtx->pfnLoopEnd = pBeadTable->pMonoBeads->pfnMono[iTextureMonoCopy];
  1692. // Select Begin routine.
  1693. pCtx->pfnBegin = pBeadTable->pBeginBeads->pfnBegin[0];
  1694. // Select RenderSpans routine.
  1695. // Specialized beads can only be used when:
  1696. // Z compare is less-equal.
  1697. // Target surface is 8 or 16 bit.
  1698. // When in COPY mode, target surface is 8.
  1699. if ((iZTest &&
  1700. pCtx->pdwRenderState[D3DRENDERSTATE_ZFUNC] != D3DCMP_LESSEQUAL) ||
  1701. iTargetPixelFormat > 1 ||
  1702. iTextureMonoCopy > 1)
  1703. {
  1704. pCtx->pfnRenderSpans = pBeadTable->pfnRenderSpansAny;
  1705. }
  1706. else
  1707. {
  1708. pCtx->pfnRenderSpans = pBeadTable->pRenderSpansBeads->pfnRenderSpans
  1709. [iTexture][iShadeMode][iTrans][iDither][iZWrite][iZTest]
  1710. [iTargetPixelFormat];
  1711. }
  1712. #define DBG_RAMPCHOICE
  1713. // #define DBG_RAMPCHOICE_ALL
  1714. #ifdef DBG_RAMPCHOICE
  1715. #ifndef DBG_RAMPCHOICE_ALL
  1716. static BOOL bShowedChoice = FALSE;
  1717. #endif
  1718. char msg[80];
  1719. static UINT32 iOldRampRsIndex = 0xffffffff;
  1720. UINT32 iRampRsIndex;
  1721. iRampRsIndex =
  1722. iTargetPixelFormat +
  1723. iZTest * RAMPFORMAT_NUM +
  1724. iZWrite * (RAMPZTEST_NUM * RAMPFORMAT_NUM) +
  1725. iDither * (RAMPZWRITE_NUM * RAMPZTEST_NUM * RAMPFORMAT_NUM) +
  1726. iTrans * (RAMPDITHER_NUM * RAMPZWRITE_NUM * RAMPZTEST_NUM *
  1727. RAMPFORMAT_NUM) +
  1728. iShadeMode * (RAMPTRANS_NUM * RAMPDITHER_NUM * RAMPZWRITE_NUM *
  1729. RAMPZTEST_NUM * RAMPFORMAT_NUM) +
  1730. iTexture * (RAMPSHADEMODE_NUM * RAMPTRANS_NUM * RAMPDITHER_NUM *
  1731. RAMPZWRITE_NUM * RAMPZTEST_NUM * RAMPFORMAT_NUM);
  1732. #ifndef DBG_RAMPCHOICE_ALL
  1733. if (!bShowedChoice)
  1734. #endif
  1735. {
  1736. if (iRampRsIndex != iOldRampRsIndex)
  1737. {
  1738. if (pCtx->pfnRenderSpans == pBeadTable->pfnRenderSpansAny)
  1739. {
  1740. OutputDebugStringA("!! GENERIC RAMP !!: ");
  1741. #ifndef DBG_RAMPCHOICE_ALL
  1742. bShowedChoice = TRUE;
  1743. #else
  1744. }
  1745. #endif
  1746. sprintf(msg, "Ramp %d:%d:%d:%d:%d:%d:%d = %d\n",
  1747. iTexture, iShadeMode, iTrans, iDither, iZWrite, iZTest,
  1748. iTargetPixelFormat, iRampRsIndex);
  1749. OutputDebugStringA(msg);
  1750. iOldRampRsIndex = iRampRsIndex;
  1751. #ifndef DBG_RAMPCHOICE_ALL
  1752. }
  1753. #endif
  1754. }
  1755. }
  1756. #endif
  1757. return S_OK;
  1758. }