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.

4723 lines
214 KiB

  1. /******************************Module*Header**********************************\
  2. *
  3. * *******************
  4. * * D3D SAMPLE CODE *
  5. * *******************
  6. *
  7. * Module Name: d3dtxt.c
  8. *
  9. * Content: D3D texture setup
  10. *
  11. * Copyright (c) 1994-1999 3Dlabs Inc. Ltd. All rights reserved.
  12. * Copyright (c) 1995-2003 Microsoft Corporation. All rights reserved.
  13. \*****************************************************************************/
  14. #include "glint.h"
  15. #include "dma.h"
  16. #include "chroma.h"
  17. #include "tag.h"
  18. //-----------------------------------------------------------------------------
  19. // Some variables shared through this module (not globals)
  20. // These are set up in _D3DChangeTextureP3RX.
  21. // P3 has 16 texture map base address slots, numbered 0 to 15 hence ...
  22. #define P3_TEX_MAP_MAX_LEVEL 15
  23. typedef struct
  24. {
  25. DWORD dwTex0MipBase;
  26. DWORD dwTex0MipMax;
  27. DWORD dwTex0ActMaxLevel; // Controlled by D3DTSS_MAXMIPLEVEL, default 0
  28. DWORD dwTex1MipBase;
  29. DWORD dwTex1MipMax;
  30. DWORD dwTex1ActMaxLevel; // Same for Texture 1
  31. } P3_MIP_BASES;
  32. #define TSSTATE(stageno,argno) \
  33. ( pContext->TextureStageState[stageno].m_dwVal[argno] )
  34. #define TSSTATESELECT(stageno,argno) \
  35. ( TSSTATE(stageno,argno) & D3DTA_SELECTMASK )
  36. #define TSSTATEINVMASK(stageno,argno) \
  37. ( TSSTATE(stageno,argno) & ~D3DTA_COMPLEMENT )
  38. #define TSSTATEALPHA(stageno,argno) \
  39. ( TSSTATE(stageno,argno) & ~D3DTA_ALPHAREPLICATE )
  40. #define IS_ALPHA_ARG 1
  41. #define IS_COLOR_ARG 0
  42. #if DX8_DDI
  43. //-----------------------------------------------------------------------------
  44. //
  45. // __TXT_MapDX8toDX6TexFilter
  46. //
  47. // map DX8 enums into DX6(&7) texture filtering enums
  48. //
  49. //-----------------------------------------------------------------------------
  50. DWORD
  51. __TXT_MapDX8toDX6TexFilter( DWORD dwStageState, DWORD dwValue )
  52. {
  53. switch (dwStageState)
  54. {
  55. case D3DTSS_MAGFILTER:
  56. switch (dwValue)
  57. {
  58. case D3DTEXF_POINT : return D3DTFG_POINT;
  59. case D3DTEXF_LINEAR : return D3DTFG_LINEAR;
  60. case D3DTEXF_FLATCUBIC : return D3DTFG_FLATCUBIC;
  61. case D3DTEXF_GAUSSIANCUBIC : return D3DTFG_GAUSSIANCUBIC;
  62. case D3DTEXF_ANISOTROPIC : return D3DTFG_ANISOTROPIC;
  63. }
  64. break;
  65. case D3DTSS_MINFILTER:
  66. switch (dwValue)
  67. {
  68. case D3DTEXF_POINT : return D3DTFN_POINT;
  69. case D3DTEXF_LINEAR : return D3DTFN_LINEAR;
  70. case D3DTEXF_FLATCUBIC : return D3DTFN_ANISOTROPIC;
  71. }
  72. break;
  73. case D3DTSS_MIPFILTER:
  74. switch (dwValue)
  75. {
  76. case D3DTEXF_NONE : return D3DTFP_NONE;
  77. case D3DTEXF_POINT : return D3DTFP_POINT;
  78. case D3DTEXF_LINEAR : return D3DTFP_LINEAR;
  79. }
  80. break;
  81. }
  82. return 0x0;
  83. } // __TXT_MapDX8toDX6TexFilter
  84. #endif // DX8_DDI
  85. //-----------------------------------------------------------------------------
  86. //
  87. // _D3D_TXT_ParseTextureStageStates
  88. //
  89. // Parse the texture state stages command token and update our context state
  90. //
  91. // Note : bTranslateDX8FilterValueToDX6 will only be FALSE when it is called
  92. // from _D3D_SB_ExecuteStateSet if that state set's value has been
  93. // changes by _D3D_SB_CaptureStateSet (Basically DX6 filter values are
  94. // stored in the state set directly, thus no need to translate them.)
  95. //
  96. //-----------------------------------------------------------------------------
  97. void
  98. _D3D_TXT_ParseTextureStageStates(
  99. P3_D3DCONTEXT* pContext,
  100. D3DHAL_DP2TEXTURESTAGESTATE *pState,
  101. DWORD dwCount,
  102. BOOL bTranslateDX8FilterValueToDX6)
  103. {
  104. DWORD i;
  105. DWORD dwStage, dwState, dwValue;
  106. DISPDBG((DBGLVL,"*** In _D3D_TXT_ParseTextureStageStates"));
  107. for (i = 0; i < dwCount; i++, pState++)
  108. {
  109. dwStage = pState->wStage;
  110. dwState = pState->TSState;
  111. dwValue = pState->dwValue;
  112. // check for range before continuing
  113. if ( (dwStage < D3DHAL_TSS_MAXSTAGES) &&
  114. (dwState < D3DTSS_MAX))
  115. {
  116. #if DX7_D3DSTATEBLOCKS
  117. if (pContext->bStateRecMode)
  118. {
  119. // Record this texture stage state into the
  120. //current state set being recorded
  121. _D3D_SB_RecordStateSetTSS(pContext, dwStage, dwState, dwValue);
  122. // skip any further processing and go to the next TSS
  123. continue;
  124. }
  125. #endif //DX7_D3DSTATEBLOCKS
  126. #if DX7_TEXMANAGEMENT
  127. if ((D3DTSS_TEXTUREMAP == dwState) && (0 != dwValue))
  128. {
  129. P3_SURF_INTERNAL* pTexture;
  130. pTexture = GetSurfaceFromHandle(pContext, dwValue);
  131. // If this is a valid managed texture
  132. if (CHECK_SURF_INTERNAL_AND_DDSURFACE_VALIDITY(pTexture) &&
  133. (pTexture->dwCaps2 & DDSCAPS2_TEXTUREMANAGE))
  134. {
  135. // Update stats
  136. _D3D_TM_STAT_Inc_NumTexturesUsed(pContext);
  137. _D3D_TM_STAT_Inc_NumUsedTexInVid(pContext, pTexture);
  138. }
  139. }
  140. #endif // DX7_TEXMANAGEMENT
  141. DISPDBG((DBGLVL," Stage = %d, State = 0x%x, Value = 0x%x",
  142. dwStage, dwState, dwValue));
  143. // Special case a texture handle change and the address update
  144. switch ( dwState )
  145. {
  146. case D3DTSS_TEXTUREMAP:
  147. DISPDBG((DBGLVL," D3DTSS_TEXTUREMAP: Handle=0x%x", dwValue));
  148. if (pContext->TextureStageState[dwStage].m_dwVal[dwState] !=
  149. dwValue)
  150. {
  151. pContext->TextureStageState[dwStage].m_dwVal[dwState] =
  152. dwValue;
  153. DIRTY_TEXTURE(pContext);
  154. }
  155. break;
  156. case D3DTSS_ADDRESS:
  157. DISPDBG((DBGLVL," D3DTSS_ADDRESS"));
  158. // map single set ADDRESS to both U and V controls
  159. pContext->TextureStageState[dwStage].m_dwVal[D3DTSS_ADDRESSU] =
  160. pContext->TextureStageState[dwStage].m_dwVal[D3DTSS_ADDRESSV] =
  161. pContext->TextureStageState[dwStage].m_dwVal[dwState] = dwValue;
  162. DIRTY_TEXTURE(pContext);
  163. break;
  164. case D3DTSS_COLOROP:
  165. case D3DTSS_ALPHAOP:
  166. case D3DTSS_COLORARG1:
  167. case D3DTSS_COLORARG2:
  168. case D3DTSS_ALPHAARG1:
  169. case D3DTSS_ALPHAARG2:
  170. pContext->TextureStageState[dwStage].m_dwVal[dwState] = dwValue;
  171. pContext->Flags &= ~SURFACE_MODULATE;
  172. DIRTY_TEXTURESTAGEBLEND(pContext);
  173. DIRTY_TEXTURE(pContext);
  174. break;
  175. case D3DTSS_TEXCOORDINDEX:
  176. DISPDBG((DBGLVL," D3DTSS_TEXCOORDINDEX: stage %d, value %d",
  177. dwStage, dwValue ));
  178. pContext->TextureStageState[dwStage].m_dwVal[dwState] = dwValue;
  179. // Update the offsets to the texture coordinates
  180. // NOTE: The texture coordinate index can contain various flags
  181. // in addition to the actual value. These flags are:
  182. // D3DTSS_TCI_PASSTHRU (default - resolves to zero)
  183. // D3DTSS_TCI_CAMERASPACENORMAL
  184. // D3DTSS_TCI_CAMERASPACEPOSITION
  185. // D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR
  186. // and are used for texture coordinate generation.
  187. //
  188. // These flags are not relevant when considering the offset of
  189. // texture coordinates in the vertex stream. These flags appear
  190. // in the high word of the index value DWORD. Only the low word
  191. // contains actual index data. Therefore, we will mask of the
  192. // low word when looking up the offset table for this texture
  193. // coordinate index.
  194. pContext->FVFData.dwTexOffset[dwStage] =
  195. pContext->FVFData.dwTexCoordOffset[dwValue & 0x0000FFFFul];
  196. DIRTY_TEXTURE(pContext);
  197. break;
  198. case D3DTSS_MIPMAPLODBIAS:
  199. DISPDBG((DBGLVL," D3DTSS_MIPMAPLODBIAS: stage %d, value %d",
  200. dwStage, dwValue ));
  201. pContext->TextureStageState[dwStage].m_dwVal[dwState] = dwValue;
  202. DIRTY_TEXTURE(pContext);
  203. break;
  204. case D3DTSS_MAGFILTER:
  205. case D3DTSS_MINFILTER:
  206. case D3DTSS_MIPFILTER:
  207. #if DX8_DDI
  208. if((!IS_DX7_OR_EARLIER_APP(pContext)) &&
  209. bTranslateDX8FilterValueToDX6)
  210. {
  211. // filtering values are somewhat different in DX8
  212. // so translate them before using them.
  213. dwValue = __TXT_MapDX8toDX6TexFilter(dwState, dwValue);
  214. }
  215. #endif DX8_DDI
  216. pContext->TextureStageState[dwStage].m_dwVal[dwState] = dwValue;
  217. DIRTY_TEXTURE(pContext);
  218. break;
  219. case D3DTSS_MAXMIPLEVEL:
  220. DISPDBG((DBGLVL," D3DTSS_MAXMIPLEVEL: stage %d, value %d",
  221. dwStage, dwValue ));
  222. pContext->TextureStageState[dwStage].m_dwVal[dwState] = dwValue;
  223. DIRTY_TEXTURE(pContext);
  224. break;
  225. default:
  226. pContext->TextureStageState[dwStage].m_dwVal[dwState] = dwValue;
  227. DIRTY_TEXTURE(pContext);
  228. break;
  229. } // switch
  230. }
  231. else
  232. {
  233. DISPDBG((WRNLVL,"Out of range stage/state %d %d",dwStage,dwState));
  234. }// if
  235. } // for
  236. } // _D3D_TXT_ParseTextureStageStates
  237. //-----------------------------------------------------------------------------
  238. //
  239. // SETARG
  240. //
  241. // dwArg = the argument.
  242. // num = argument number (1 or 2).
  243. // bIsAlpha = TRUE if this is the alpha channel,
  244. // FALSE if this is the colour channel.
  245. // iD3DStage = D3D stage number.
  246. // iChipStageNo = chip stage number (should only be 0 or 1 on P3)
  247. //
  248. //-----------------------------------------------------------------------------
  249. void
  250. SETARG(
  251. P3_D3DCONTEXT *pContext,
  252. struct TextureCompositeRGBAMode *pMode,
  253. DWORD dwArg,
  254. DWORD num,
  255. BOOL bIsAlpha,
  256. DWORD iD3DStage,
  257. DWORD iChipStageNo)
  258. {
  259. BOOL bSetArgToggleInvert;
  260. DWORD dwArgValue, dwInvertArgValue;
  261. BOOL bArgValueAssigned = FALSE,
  262. bInvertArgValueAssigned;
  263. bSetArgToggleInvert = FALSE;
  264. switch (dwArg & D3DTA_SELECTMASK)
  265. {
  266. case D3DTA_TEXTURE:
  267. if ((dwArg & D3DTA_ALPHAREPLICATE) || (bIsAlpha))
  268. {
  269. dwArgValue = ( pContext->iStageTex[iD3DStage] == 0 ) ?
  270. P3RX_TEXCOMP_T0A :
  271. P3RX_TEXCOMP_T1A;
  272. bArgValueAssigned = TRUE;
  273. DISPDBG((DBGLVL," Tex%dA", pContext->iStageTex[iD3DStage] ));
  274. }
  275. else
  276. {
  277. dwArgValue = ( pContext->iStageTex[iD3DStage] == 0 ) ?
  278. P3RX_TEXCOMP_T0C :
  279. P3RX_TEXCOMP_T1C;
  280. bArgValueAssigned = TRUE;
  281. DISPDBG((DBGLVL," Tex%dC", pContext->iStageTex[iD3DStage] ));
  282. }
  283. break;
  284. case D3DTA_DIFFUSE:
  285. if ((dwArg & D3DTA_ALPHAREPLICATE) || (bIsAlpha))
  286. {
  287. dwArgValue = P3RX_TEXCOMP_CA;
  288. bArgValueAssigned = TRUE;
  289. DISPDBG((DBGLVL," DiffA" ));
  290. }
  291. else
  292. {
  293. dwArgValue = P3RX_TEXCOMP_CC;
  294. bArgValueAssigned = TRUE;
  295. DISPDBG((DBGLVL," DiffC" ));
  296. }
  297. break;
  298. case D3DTA_CURRENT:
  299. // Cope with a "current" argument in texcomp0
  300. if ( iChipStageNo == 0 )
  301. {
  302. // This is texcomp0
  303. if ( pContext->bBumpmapEnabled )
  304. {
  305. // Emboss bumpmapping is on
  306. if ((dwArg & D3DTA_ALPHAREPLICATE) || (bIsAlpha))
  307. {
  308. // This is the alpha-channel, where the D3D stages 0 & 1
  309. // should have put the heightfield info.
  310. dwArgValue = P3RX_TEXCOMP_HEIGHTA;
  311. bArgValueAssigned = TRUE;
  312. DISPDBG((DBGLVL," BumpA" ));
  313. // And cope with inverted bumpmaps.
  314. bSetArgToggleInvert = pContext->bBumpmapInverted;
  315. }
  316. else
  317. {
  318. // Colour channel - this will hold the diffuse colour.
  319. dwArgValue = P3RX_TEXCOMP_CC;
  320. bArgValueAssigned = TRUE;
  321. DISPDBG((DBGLVL," DiffC" ));
  322. }
  323. }
  324. else
  325. {
  326. // Embossing is off - default to diffuse.
  327. if ((dwArg & D3DTA_ALPHAREPLICATE) || (bIsAlpha))
  328. {
  329. dwArgValue = P3RX_TEXCOMP_CA;
  330. bArgValueAssigned = TRUE;
  331. DISPDBG((DBGLVL," DiffA" ));
  332. }
  333. else
  334. {
  335. dwArgValue = P3RX_TEXCOMP_CC;
  336. bArgValueAssigned = TRUE;
  337. DISPDBG((DBGLVL," DiffC" ));
  338. }
  339. }
  340. }
  341. else
  342. {
  343. // texcomp stage 1
  344. if ( pContext->bStage0DotProduct )
  345. {
  346. // Need to take the dotproduct sum result,
  347. // even in the alpha channel, according to the docs.
  348. dwArgValue = P3RX_TEXCOMP_SUM;
  349. bArgValueAssigned = TRUE;
  350. }
  351. else
  352. {
  353. if ((dwArg & D3DTA_ALPHAREPLICATE) || (bIsAlpha))
  354. {
  355. dwArgValue = P3RX_TEXCOMP_OA;
  356. bArgValueAssigned = TRUE;
  357. DISPDBG((DBGLVL," CurrA" ));
  358. }
  359. else
  360. {
  361. dwArgValue = P3RX_TEXCOMP_OC;
  362. bArgValueAssigned = TRUE;
  363. DISPDBG((DBGLVL," CurrC" ));
  364. }
  365. }
  366. }
  367. break;
  368. case D3DTA_TFACTOR:
  369. if ((dwArg & D3DTA_ALPHAREPLICATE) || (bIsAlpha))
  370. {
  371. dwArgValue = P3RX_TEXCOMP_FA;
  372. bArgValueAssigned = TRUE;
  373. DISPDBG((DBGLVL," TfactA" ));
  374. }
  375. else
  376. {
  377. dwArgValue = P3RX_TEXCOMP_FC;
  378. bArgValueAssigned = TRUE;
  379. DISPDBG((DBGLVL," TfactC" ));
  380. }
  381. break;
  382. default:
  383. if ( bIsAlpha )
  384. {
  385. DISPDBG((ERRLVL,"ERROR: Invalid AlphaArgument"));
  386. SET_BLEND_ERROR ( pContext, BSF_UNDEFINED_ALPHA_ARG );
  387. }
  388. else
  389. {
  390. DISPDBG((ERRLVL,"ERROR: Invalid ColorArgument"));
  391. SET_BLEND_ERROR ( pContext, BSF_UNDEFINED_COLOR_ARG );
  392. }
  393. break;
  394. } // switch
  395. if ( ( (dwArg & D3DTA_COMPLEMENT) == 0 ) == bSetArgToggleInvert )
  396. {
  397. dwInvertArgValue= __PERMEDIA_ENABLE;
  398. bInvertArgValueAssigned = TRUE;
  399. DISPDBG((DBGLVL," inverted" ));
  400. }
  401. else
  402. {
  403. dwInvertArgValue = __PERMEDIA_DISABLE;
  404. bInvertArgValueAssigned = TRUE;
  405. }
  406. // Set up the I input for MODULATExxx_ADDxxx modes.
  407. if ( num == 1 )
  408. {
  409. switch (dwArg & D3DTA_SELECTMASK)
  410. {
  411. case D3DTA_TEXTURE:
  412. pMode->I = ( pContext->iStageTex[iD3DStage] == 0 ) ?
  413. P3RX_TEXCOMP_I_T0A :
  414. P3RX_TEXCOMP_I_T1A;
  415. DISPDBG((DBGLVL," I: Tex%dA", pContext->iStageTex[iD3DStage] ));
  416. break;
  417. case D3DTA_DIFFUSE:
  418. pMode->I = P3RX_TEXCOMP_I_CA;
  419. DISPDBG((DBGLVL," I: DiffA" ));
  420. break;
  421. case D3DTA_CURRENT:
  422. if ( iChipStageNo == 0 )
  423. {
  424. if ( pContext->bBumpmapEnabled )
  425. {
  426. // Bumpmapping mode.
  427. pMode->I = P3RX_TEXCOMP_I_HA;
  428. DISPDBG((DBGLVL," I: BumpA" ));
  429. }
  430. else
  431. {
  432. pMode->I = P3RX_TEXCOMP_I_CA;
  433. DISPDBG((DBGLVL," I: DiffA" ));
  434. }
  435. }
  436. else
  437. {
  438. pMode->I = P3RX_TEXCOMP_I_OA;
  439. DISPDBG((DBGLVL," I: CurrA" ));
  440. }
  441. break;
  442. case D3DTA_TFACTOR:
  443. pMode->I = P3RX_TEXCOMP_I_FA;
  444. DISPDBG((DBGLVL," I: TfactA" ));
  445. break;
  446. default:
  447. if ( bIsAlpha )
  448. {
  449. DISPDBG((ERRLVL,"ERROR: Invalid AlphaArgument"));
  450. SET_BLEND_ERROR ( pContext, BSF_UNDEFINED_ALPHA_ARG );
  451. }
  452. else
  453. {
  454. DISPDBG((ERRLVL,"ERROR: Invalid ColorArgument"));
  455. SET_BLEND_ERROR ( pContext, BSF_UNDEFINED_COLOR_ARG );
  456. }
  457. break;
  458. } // switch
  459. if ( ( (dwArg & D3DTA_COMPLEMENT) == 0 ) == bSetArgToggleInvert )
  460. {
  461. pMode->InvertI = __PERMEDIA_ENABLE;
  462. }
  463. else
  464. {
  465. pMode->InvertI = __PERMEDIA_DISABLE;
  466. }
  467. } // if ( num == 1 )
  468. if (bArgValueAssigned)
  469. {
  470. if (num == 1)
  471. {
  472. pMode->Arg1 = dwArgValue;
  473. }
  474. else
  475. {
  476. pMode->Arg2 = dwArgValue;
  477. }
  478. }
  479. if (bInvertArgValueAssigned)
  480. {
  481. if (num == 1)
  482. {
  483. pMode->InvertArg1 = dwInvertArgValue;
  484. }
  485. else
  486. {
  487. pMode->InvertArg2 = dwInvertArgValue;
  488. }
  489. }
  490. } // SETARG
  491. //-----------------------------------------------------------------------------
  492. //
  493. // SETTAARG_ALPHA
  494. //
  495. // TexApp blend mode for the alpha channel.
  496. //
  497. //-----------------------------------------------------------------------------
  498. void
  499. SETTAARG_ALPHA(
  500. P3_D3DCONTEXT *pContext,
  501. struct TextureApplicationMode *pMode,
  502. DWORD dwArg,
  503. DWORD num)
  504. {
  505. switch (dwArg & D3DTA_SELECTMASK)
  506. {
  507. case D3DTA_TEXTURE:
  508. DISPDBG((ERRLVL,"ERROR: Invalid TA AlphaArgument"));
  509. SET_BLEND_ERROR ( pContext, BSF_CANT_USE_ALPHA_ARG_HERE );
  510. break;
  511. case D3DTA_DIFFUSE:
  512. if ( (num) == 1 )
  513. {
  514. pMode->AlphaA = P3RX_TEXAPP_A_CA;
  515. DISPDBG((DBGLVL," DiffA" ));
  516. }
  517. else
  518. {
  519. DISPDBG((ERRLVL,"ERROR: Invalid TA AlphaArgument"));
  520. SET_BLEND_ERROR ( pContext, BSF_CANT_USE_ALPHA_ARG_HERE );
  521. }
  522. break;
  523. case D3DTA_CURRENT:
  524. if ( (num) == 2 )
  525. {
  526. pMode->AlphaB = P3RX_TEXAPP_B_TA;
  527. DISPDBG((DBGLVL," CurrA" ));
  528. }
  529. else
  530. {
  531. // Can't do
  532. DISPDBG((ERRLVL,"ERROR: Invalid TA AlphaArgument"));
  533. SET_BLEND_ERROR ( pContext, BSF_CANT_USE_ALPHA_ARG_HERE );
  534. }
  535. break;
  536. case D3DTA_TFACTOR:
  537. if ( (num) == 1 )
  538. {
  539. pMode->AlphaA = P3RX_TEXAPP_A_KA;
  540. DISPDBG((DBGLVL," TfactA" ));
  541. }
  542. else
  543. {
  544. if ( (num) != 2)
  545. {
  546. DISPDBG((ERRLVL," ** SETTAARG: num must be 1 or 2"));
  547. }
  548. pMode->AlphaB = P3RX_TEXAPP_B_KA;
  549. DISPDBG((DBGLVL," TfactA" ));
  550. }
  551. break;
  552. default:
  553. DISPDBG((ERRLVL,"ERROR: Unknown TA AlphaArgument"));
  554. SET_BLEND_ERROR ( pContext, BSF_UNDEFINED_ALPHA_ARG );
  555. break;
  556. }
  557. if ( (dwArg & D3DTA_COMPLEMENT) != 0 )
  558. {
  559. // Can't do COMPLEMENT on the args.
  560. DISPDBG((ERRLVL,"ERROR: Can't do COMPLEMENT in TA unit"));
  561. SET_BLEND_ERROR ( pContext, BSF_CANT_USE_ALPHA_ARG_HERE );
  562. }
  563. } // SETTAARG_ALPHA
  564. //-----------------------------------------------------------------------------
  565. //
  566. // SETTAARG_COLOR
  567. //
  568. // TexApp blend mode for the color channel.
  569. //
  570. //-----------------------------------------------------------------------------
  571. void
  572. SETTAARG_COLOR(
  573. P3_D3DCONTEXT *pContext,
  574. struct TextureApplicationMode *pMode,
  575. DWORD dwArg,
  576. DWORD num)
  577. {
  578. switch (dwArg & D3DTA_SELECTMASK)
  579. {
  580. DISPDBG((ERRLVL,"ERROR: Invalid TA ColorArgument"));
  581. SET_BLEND_ERROR ( pContext, BSF_CANT_USE_COLOR_ARG_HERE );
  582. break;
  583. case D3DTA_DIFFUSE:
  584. if ( (num) == 1 )
  585. {
  586. if ( (dwArg & D3DTA_ALPHAREPLICATE) != 0 )
  587. {
  588. pMode->ColorA = P3RX_TEXAPP_A_CA;
  589. DISPDBG((DBGLVL," DiffA" ));
  590. }
  591. else
  592. {
  593. pMode->ColorA = P3RX_TEXAPP_A_CC;
  594. DISPDBG((DBGLVL," DiffC" ));
  595. }
  596. // Set up the I input for MODULATExxx_ADDxxx modes
  597. pMode->ColorI = P3RX_TEXAPP_I_CA;
  598. DISPDBG((DBGLVL," I: DiffA" ));
  599. }
  600. else
  601. {
  602. DISPDBG((ERRLVL,"ERROR: Invalid TA ColorArgument"));
  603. SET_BLEND_ERROR ( pContext, BSF_CANT_USE_COLOR_ARG_HERE );
  604. }
  605. break;
  606. case D3DTA_CURRENT:
  607. if ( (num) == 2 )
  608. {
  609. if (dwArg & D3DTA_ALPHAREPLICATE)
  610. {
  611. pMode->ColorB = P3RX_TEXAPP_B_TA;
  612. DISPDBG((DBGLVL," CurrA" ));
  613. }
  614. else
  615. {
  616. pMode->ColorB = P3RX_TEXAPP_B_TC;
  617. DISPDBG((DBGLVL," CurrC" ));
  618. }
  619. }
  620. else
  621. {
  622. // Can't do.
  623. DISPDBG((ERRLVL,"ERROR: Invalid TA ColorArgument"));
  624. SET_BLEND_ERROR ( pContext, BSF_CANT_USE_COLOR_ARG_HERE );
  625. }
  626. break;
  627. case D3DTA_TFACTOR:
  628. if ( (num) == 1 )
  629. {
  630. if ( (dwArg & D3DTA_ALPHAREPLICATE) != 0 )
  631. {
  632. pMode->ColorA = P3RX_TEXAPP_A_KA;
  633. DISPDBG((DBGLVL," TfactA" ));
  634. }
  635. else
  636. {
  637. pMode->ColorA = P3RX_TEXAPP_A_KC;
  638. DISPDBG((DBGLVL," TfactC" ));
  639. }
  640. // Set up the I input for MODULATExxx_ADDxxx modes.
  641. pMode->ColorI = P3RX_TEXAPP_I_KA;
  642. DISPDBG((DBGLVL," I: TfactA" ));
  643. }
  644. else
  645. {
  646. if ( (num) != 2)
  647. {
  648. DISPDBG((ERRLVL," ** SETTAARG: num must be 1 or 2"));
  649. }
  650. if (dwArg & D3DTA_ALPHAREPLICATE)
  651. {
  652. pMode->ColorB = P3RX_TEXAPP_B_KA;
  653. DISPDBG((DBGLVL," TfactA" ));
  654. }
  655. else
  656. {
  657. pMode->ColorB = P3RX_TEXAPP_B_KC;
  658. DISPDBG((DBGLVL," TfactC" ));
  659. }
  660. }
  661. break;
  662. default:
  663. DISPDBG((ERRLVL,"ERROR: Unknown TA ColorArgument"));
  664. SET_BLEND_ERROR ( pContext, BSF_UNDEFINED_COLOR_ARG );
  665. break;
  666. }
  667. if ( (dwArg & D3DTA_COMPLEMENT) != 0 )
  668. {
  669. // Can't do COMPLEMENT on the args.
  670. DISPDBG((ERRLVL,"ERROR: Can't do COMPLEMENT in TA unit"));
  671. SET_BLEND_ERROR ( pContext, BSF_CANT_USE_COLOR_ARG_HERE );
  672. }
  673. } // SETTAARG_COLOR
  674. //-----------------------------------------------------------------------------
  675. //
  676. // SETOP
  677. //
  678. // Note - SETOP must be done after SETARG for DISABLE to work.
  679. //
  680. //-----------------------------------------------------------------------------
  681. void
  682. SETOP(
  683. P3_D3DCONTEXT *pContext,
  684. struct TextureCompositeRGBAMode* pMode,
  685. DWORD dwOperation,
  686. DWORD iD3DStage,
  687. DWORD iChipStageNo,
  688. BOOL bIsAlpha)
  689. {
  690. pMode->Enable = __PERMEDIA_ENABLE;
  691. pMode->Scale = P3RX_TEXCOMP_OPERATION_SCALE_ONE;
  692. pMode->InvertI = __PERMEDIA_DISABLE;
  693. pMode->A = P3RX_TEXCOMP_ARG1;
  694. pMode->B = P3RX_TEXCOMP_ARG2;
  695. switch (dwOperation)
  696. {
  697. case D3DTOP_DISABLE:
  698. if ( bIsAlpha )
  699. {
  700. // Just pass through "current"
  701. pMode->Operation = P3RX_TEXCOMP_OPERATION_PASS_A;
  702. if ( iChipStageNo == 0 )
  703. {
  704. if ( pContext->bBumpmapEnabled )
  705. {
  706. // Embossing is on.
  707. pMode->Arg1 = P3RX_TEXCOMP_HEIGHTA;
  708. }
  709. else
  710. {
  711. // Current = diffuse in stage0.
  712. pMode->Arg1 = P3RX_TEXCOMP_CA;
  713. }
  714. }
  715. else
  716. {
  717. if ( pContext->bStage0DotProduct )
  718. {
  719. pMode->Arg1 = P3RX_TEXCOMP_SUM;
  720. }
  721. else
  722. {
  723. pMode->Arg1 = P3RX_TEXCOMP_OA;
  724. }
  725. }
  726. }
  727. else
  728. {
  729. DISPDBG((ERRLVL,"SETOP: Colour op was DISABLE"
  730. " - should never have got here."));
  731. }
  732. break;
  733. case D3DTOP_SELECTARG1:
  734. DISPDBG((DBGLVL," D3DTOP_SELECTARG1"));
  735. pMode->Operation = P3RX_TEXCOMP_OPERATION_PASS_A;
  736. break;
  737. case D3DTOP_SELECTARG2:
  738. DISPDBG((DBGLVL," D3DTOP_SELECTARG2"));
  739. pMode->Operation = P3RX_TEXCOMP_OPERATION_PASS_A; // No Pass B
  740. pMode->A = P3RX_TEXCOMP_ARG2;
  741. break;
  742. case D3DTOP_MODULATE:
  743. DISPDBG((DBGLVL," D3DTOP_MODULATE"));
  744. pMode->Operation = P3RX_TEXCOMP_OPERATION_MODULATE_AB;
  745. break;
  746. case D3DTOP_MODULATE2X:
  747. DISPDBG((DBGLVL," D3DTOP_MODULATE2X"));
  748. pMode->Operation = P3RX_TEXCOMP_OPERATION_MODULATE_AB;
  749. pMode->Scale = P3RX_TEXCOMP_OPERATION_SCALE_TWO;
  750. break;
  751. case D3DTOP_MODULATE4X:
  752. DISPDBG((DBGLVL," D3DTOP_MODULATE4X"));
  753. pMode->Operation = P3RX_TEXCOMP_OPERATION_MODULATE_AB;
  754. pMode->Scale = P3RX_TEXCOMP_OPERATION_SCALE_FOUR;
  755. break;
  756. case D3DTOP_ADD:
  757. DISPDBG((DBGLVL," D3DTOP_ADD"));
  758. pMode->Operation = P3RX_TEXCOMP_OPERATION_ADD_AB;
  759. break;
  760. case D3DTOP_ADDSIGNED:
  761. DISPDBG((DBGLVL," D3DTOP_ADDSIGNED"));
  762. pMode->Operation = P3RX_TEXCOMP_OPERATION_ADDSIGNED_AB;
  763. break;
  764. case D3DTOP_ADDSIGNED2X:
  765. DISPDBG((DBGLVL," D3DTOP_ADDSIGNED2X"));
  766. pMode->Operation = P3RX_TEXCOMP_OPERATION_ADDSIGNED_AB;
  767. pMode->Scale = P3RX_TEXCOMP_OPERATION_SCALE_TWO;
  768. break;
  769. case D3DTOP_SUBTRACT:
  770. DISPDBG((DBGLVL," D3DTOP_SUBTRACT"));
  771. pMode->Operation = P3RX_TEXCOMP_OPERATION_SUBTRACT_AB;
  772. break;
  773. case D3DTOP_ADDSMOOTH:
  774. DISPDBG((DBGLVL," D3DTOP_ADDSMOOTH"));
  775. pMode->Operation = P3RX_TEXCOMP_OPERATION_ADD_AB_SUB_MODULATE_AB;
  776. break;
  777. case D3DTOP_BLENDDIFFUSEALPHA:
  778. DISPDBG((DBGLVL," D3DTOP_BLENDDIFFUSEALPHA"));
  779. pMode->Operation = P3RX_TEXCOMP_OPERATION_LERP_ABI;
  780. pMode->A = P3RX_TEXCOMP_ARG2;
  781. pMode->B = P3RX_TEXCOMP_ARG1;
  782. pMode->I = P3RX_TEXCOMP_I_CA;
  783. break;
  784. case D3DTOP_BLENDTEXTUREALPHA:
  785. DISPDBG((DBGLVL," D3DTOP_BLENDTEXTUREALPHA"));
  786. pMode->Operation = P3RX_TEXCOMP_OPERATION_LERP_ABI;
  787. pMode->A = P3RX_TEXCOMP_ARG2;
  788. pMode->B = P3RX_TEXCOMP_ARG1;
  789. pMode->I = ( pContext->iStageTex[iD3DStage] == 0 ) ?
  790. P3RX_TEXCOMP_I_T0A :
  791. P3RX_TEXCOMP_I_T1A;
  792. DISPDBG((DBGLVL," alpha: Tex%dA", pContext->iStageTex[iD3DStage] ));
  793. break;
  794. case D3DTOP_BLENDFACTORALPHA:
  795. DISPDBG((DBGLVL," D3DTOP_BLENDFACTORALPHA"));
  796. pMode->Operation = P3RX_TEXCOMP_OPERATION_LERP_ABI;
  797. pMode->A = P3RX_TEXCOMP_ARG2;
  798. pMode->B = P3RX_TEXCOMP_ARG1;
  799. pMode->I = P3RX_TEXCOMP_I_FA;
  800. break;
  801. case D3DTOP_BLENDCURRENTALPHA:
  802. DISPDBG((DBGLVL," D3DTOP_BLENDCURRENTALPHA"));
  803. pMode->Operation = P3RX_TEXCOMP_OPERATION_LERP_ABI;
  804. pMode->A = P3RX_TEXCOMP_ARG2;
  805. pMode->B = P3RX_TEXCOMP_ARG1;
  806. pMode->I = P3RX_TEXCOMP_I_OA;
  807. break;
  808. case D3DTOP_BLENDTEXTUREALPHAPM:
  809. DISPDBG((DBGLVL," D3DTOP_BLENDTEXTUREALPHAPM"));
  810. pMode->Operation = P3RX_TEXCOMP_OPERATION_MODULATE_AI_ADD_B;
  811. pMode->A = P3RX_TEXCOMP_ARG2;
  812. pMode->B = P3RX_TEXCOMP_ARG1;
  813. pMode->I = ( pContext->iStageTex[iD3DStage] == 0 ) ?
  814. P3RX_TEXCOMP_I_T0A :
  815. P3RX_TEXCOMP_I_T1A;
  816. DISPDBG((DBGLVL," alpha: Tex%dA", pContext->iStageTex[iD3DStage] ));
  817. pMode->InvertI = __PERMEDIA_ENABLE;
  818. break;
  819. case D3DTOP_PREMODULATE:
  820. DISPDBG((DBGLVL," D3DTOP_PREMODULATE"));
  821. // result = current_tex * next_stage_tex - ignore arguments.
  822. if ( ( pContext->iStageTex[iD3DStage] != -1 ) &&
  823. ( pContext->iStageTex[iD3DStage+1] != -1 ) )
  824. {
  825. pMode->Arg1 = ( pContext->iStageTex[iD3DStage] == 0 ) ?
  826. P3RX_TEXCOMP_T0C :
  827. P3RX_TEXCOMP_T1C;
  828. DISPDBG((DBGLVL," Arg1: Tex%d", pContext->iStageTex[iD3DStage] ));
  829. pMode->Arg2 = ( pContext->iStageTex[iD3DStage+1] == 0 ) ?
  830. P3RX_TEXCOMP_T0C :
  831. P3RX_TEXCOMP_T1C;
  832. DISPDBG((DBGLVL," Arg2: Tex%d", pContext->iStageTex[iD3DStage+1] ));
  833. }
  834. else
  835. {
  836. // Not enough textures
  837. DISPDBG((ERRLVL,"** SETOP: PREMODULATE didn't have two "
  838. "textures to play with."));
  839. if ( bIsAlpha )
  840. {
  841. SET_BLEND_ERROR ( pContext, BSF_CANT_USE_ALPHA_OP_HERE );
  842. }
  843. else
  844. {
  845. SET_BLEND_ERROR ( pContext, BSF_CANT_USE_COLOR_OP_HERE );
  846. }
  847. pMode->Arg1 = P3RX_TEXCOMP_CC;
  848. pMode->Arg2 = P3RX_TEXCOMP_CC;
  849. }
  850. pMode->Operation = P3RX_TEXCOMP_OPERATION_MODULATE_AB;
  851. pMode->A = P3RX_TEXCOMP_ARG2;
  852. pMode->B = P3RX_TEXCOMP_ARG1;
  853. break;
  854. case D3DTOP_MODULATEALPHA_ADDCOLOR:
  855. DISPDBG((DBGLVL," D3DTOP_MODULATEALPHA_ADDCOLOR"));
  856. pMode->Operation = P3RX_TEXCOMP_OPERATION_MODULATE_AI_ADD_B;
  857. pMode->A = P3RX_TEXCOMP_ARG2;
  858. pMode->B = P3RX_TEXCOMP_ARG1;
  859. // I input set up by SETARG
  860. break;
  861. case D3DTOP_MODULATECOLOR_ADDALPHA:
  862. DISPDBG((DBGLVL," D3DTOP_MODULATECOLOR_ADDALPHA"));
  863. pMode->Operation = P3RX_TEXCOMP_OPERATION_MODULATE_AB_ADD_I;
  864. pMode->A = P3RX_TEXCOMP_ARG2;
  865. pMode->B = P3RX_TEXCOMP_ARG1;
  866. // I input set up by SETARG
  867. break;
  868. case D3DTOP_MODULATEINVALPHA_ADDCOLOR:
  869. DISPDBG((DBGLVL," D3DTOP_MODULATEINVALPHA_ADDCOLOR"));
  870. pMode->Operation = P3RX_TEXCOMP_OPERATION_MODULATE_AI_ADD_B;
  871. pMode->A = P3RX_TEXCOMP_ARG2;
  872. pMode->B = P3RX_TEXCOMP_ARG1;
  873. // I input set up by SETARG
  874. pMode->InvertI = 1 - pMode->InvertI;
  875. break;
  876. case D3DTOP_MODULATEINVCOLOR_ADDALPHA:
  877. DISPDBG((DBGLVL," D3DTOP_MODULATEINVCOLOR_ADDALPHA"));
  878. pMode->Operation = P3RX_TEXCOMP_OPERATION_MODULATE_AB_ADD_I;
  879. pMode->A = P3RX_TEXCOMP_ARG2;
  880. pMode->B = P3RX_TEXCOMP_ARG1;
  881. pMode->InvertArg1 = 1 - pMode->InvertArg1;
  882. // I input set up by SETARG
  883. break;
  884. case D3DTOP_DOTPRODUCT3:
  885. DISPDBG((DBGLVL," D3DTOP_DOTPRODUCT3"));
  886. if ( iChipStageNo == 0 )
  887. {
  888. pMode->Operation = P3RX_TEXCOMP_OPERATION_MODULATE_SIGNED_AB;
  889. // Signal that the special input to stage 1 is needed.
  890. pContext->bStage0DotProduct = TRUE;
  891. }
  892. else
  893. {
  894. // Can't do stage 1 dotproduct. Fail.
  895. DISPDBG((ERRLVL,"** SETOP: Can't do DOTPRODUCT3 in second stage."));
  896. if ( bIsAlpha )
  897. {
  898. SET_BLEND_ERROR ( pContext, BSF_CANT_USE_ALPHA_OP_HERE );
  899. }
  900. else
  901. {
  902. SET_BLEND_ERROR ( pContext, BSF_CANT_USE_COLOR_OP_HERE );
  903. }
  904. pMode->Operation = P3RX_TEXCOMP_OPERATION_PASS_A;
  905. }
  906. break;
  907. case D3DTOP_BUMPENVMAP:
  908. case D3DTOP_BUMPENVMAPLUMINANCE:
  909. DISPDBG((ERRLVL,"** SETOP: Unsupported operation."));
  910. if ( bIsAlpha )
  911. {
  912. SET_BLEND_ERROR ( pContext, BSF_UNSUPPORTED_ALPHA_OP );
  913. }
  914. else
  915. {
  916. SET_BLEND_ERROR ( pContext, BSF_UNSUPPORTED_COLOR_OP );
  917. }
  918. break;
  919. default:
  920. DISPDBG((ERRLVL,"** SETOP: Unknown operation."));
  921. if ( bIsAlpha )
  922. {
  923. SET_BLEND_ERROR ( pContext, BSF_UNDEFINED_ALPHA_OP );
  924. }
  925. else
  926. {
  927. SET_BLEND_ERROR ( pContext, BSF_UNDEFINED_COLOR_OP );
  928. }
  929. break;
  930. } // switch
  931. } // SETOP
  932. //-----------------------------------------------------------------------------
  933. //
  934. // SETTAOP
  935. //
  936. // Must be done after SETTAARG to set up DISABLE properly.
  937. //
  938. //-----------------------------------------------------------------------------
  939. void
  940. SETTAOP(
  941. P3_D3DCONTEXT *pContext,
  942. struct TextureApplicationMode* pMode,
  943. DWORD dwOperand,
  944. BOOL bIsAlpha,
  945. DWORD iD3DStage,
  946. DWORD iChipStageNo)
  947. {
  948. DWORD dwInvertI, dwOperation, dwI = 0, dwA = 0;
  949. BOOL bOperation = FALSE,
  950. bI = FALSE,
  951. bA = FALSE;
  952. pMode->Enable = __PERMEDIA_ENABLE;
  953. dwInvertI = __PERMEDIA_DISABLE;
  954. switch (dwOperand)
  955. {
  956. case D3DTOP_DISABLE:
  957. if ( bIsAlpha )
  958. {
  959. // Just pass through "current"
  960. dwOperation = P3RX_TEXAPP_OPERATION_PASS_A;
  961. bOperation = TRUE;
  962. dwA = P3RX_TEXAPP_A_CA;
  963. bA = TRUE;
  964. }
  965. else
  966. {
  967. DISPDBG((ERRLVL,"SETTAOP: Colour op was DISABLE "
  968. " should never have got here."));
  969. }
  970. break;
  971. case D3DTOP_SELECTARG1:
  972. DISPDBG((DBGLVL," D3DTOP_SELECTARG1"));
  973. dwOperation = P3RX_TEXAPP_OPERATION_PASS_A;
  974. bOperation = TRUE;
  975. break;
  976. case D3DTOP_SELECTARG2:
  977. DISPDBG((DBGLVL," D3DTOP_SELECTARG2"));
  978. dwOperation = P3RX_TEXAPP_OPERATION_PASS_B;
  979. bOperation = TRUE;
  980. break;
  981. case D3DTOP_MODULATE:
  982. DISPDBG((DBGLVL," D3DTOP_MODULATE"));
  983. dwOperation = P3RX_TEXAPP_OPERATION_MODULATE_AB;
  984. bOperation = TRUE;
  985. break;
  986. case D3DTOP_ADD:
  987. DISPDBG((DBGLVL," D3DTOP_ADD"));
  988. dwOperation = P3RX_TEXAPP_OPERATION_ADD_AB;
  989. bOperation = TRUE;
  990. break;
  991. case D3DTOP_BLENDDIFFUSEALPHA:
  992. DISPDBG((DBGLVL," D3DTOP_BLENDDIFFUSEALPHA"));
  993. dwOperation = P3RX_TEXAPP_OPERATION_LERP_ABI;
  994. bOperation = TRUE;
  995. dwInvertI = 1 - dwInvertI;
  996. dwI = P3RX_TEXAPP_I_CA;
  997. bI = TRUE;
  998. break;
  999. case D3DTOP_BLENDFACTORALPHA:
  1000. DISPDBG((DBGLVL," D3DTOP_BLENDFACTORALPHA"));
  1001. dwOperation = P3RX_TEXAPP_OPERATION_LERP_ABI;
  1002. bOperation = TRUE;
  1003. dwInvertI = 1 - dwInvertI;
  1004. dwI = P3RX_TEXAPP_I_KA;
  1005. bI = TRUE;
  1006. break;
  1007. case D3DTOP_BLENDCURRENTALPHA:
  1008. DISPDBG((DBGLVL," D3DTOP_BLENDCURRENTALPHA"));
  1009. dwOperation = P3RX_TEXAPP_OPERATION_LERP_ABI;
  1010. bOperation = TRUE;
  1011. dwInvertI = 1 - dwInvertI;
  1012. dwI = P3RX_TEXAPP_I_TA;
  1013. bI = TRUE;
  1014. break;
  1015. case D3DTOP_MODULATEALPHA_ADDCOLOR:
  1016. DISPDBG((DBGLVL," D3DTOP_MODULATEALPHA_ADDCOLOR"));
  1017. dwOperation = P3RX_TEXAPP_OPERATION_MODULATE_BI_ADD_A;
  1018. bOperation = TRUE;
  1019. // I should have been set up by SETTAARG.
  1020. // dwI = P3RX_TEXAPP_I_TA;
  1021. break;
  1022. case D3DTOP_MODULATECOLOR_ADDALPHA:
  1023. DISPDBG((DBGLVL," D3DTOP_MODULATECOLOR_ADDALPHA"));
  1024. dwOperation = P3RX_TEXAPP_OPERATION_MODULATE_AB_ADD_I;
  1025. bOperation = TRUE;
  1026. // I should have been set up by SETTAARG.
  1027. // dwI = P3RX_TEXAPP_I_TA;
  1028. break;
  1029. case D3DTOP_MODULATEINVALPHA_ADDCOLOR:
  1030. DISPDBG((DBGLVL," D3DTOP_MODULATEINVALPHA_ADDCOLOR"));
  1031. dwOperation = P3RX_TEXAPP_OPERATION_MODULATE_BI_ADD_A;
  1032. bOperation = TRUE;
  1033. dwInvertI = 1 - dwInvertI;
  1034. // I should have been set up by SETTAARG.
  1035. // dwI = P3RX_TEXAPP_I_TA;
  1036. break;
  1037. case D3DTOP_MODULATE2X:
  1038. case D3DTOP_MODULATE4X:
  1039. case D3DTOP_ADDSIGNED:
  1040. case D3DTOP_ADDSIGNED2X:
  1041. case D3DTOP_SUBTRACT:
  1042. case D3DTOP_ADDSMOOTH:
  1043. case D3DTOP_BLENDTEXTUREALPHA:
  1044. case D3DTOP_BLENDTEXTUREALPHAPM:
  1045. case D3DTOP_PREMODULATE:
  1046. case D3DTOP_MODULATEINVCOLOR_ADDALPHA:
  1047. case D3DTOP_DOTPRODUCT3:
  1048. DISPDBG((ERRLVL,"** SETTAOP: Unsupported operation in TA unit."));
  1049. if ( bIsAlpha )
  1050. {
  1051. SET_BLEND_ERROR ( pContext, BSF_CANT_USE_ALPHA_OP_HERE );
  1052. }
  1053. else
  1054. {
  1055. SET_BLEND_ERROR ( pContext, BSF_CANT_USE_COLOR_OP_HERE );
  1056. }
  1057. break;
  1058. case D3DTOP_BUMPENVMAP:
  1059. case D3DTOP_BUMPENVMAPLUMINANCE:
  1060. DISPDBG((ERRLVL,"** SETTAOP: Unsupported operation."));
  1061. if ( bIsAlpha )
  1062. {
  1063. SET_BLEND_ERROR ( pContext, BSF_UNSUPPORTED_ALPHA_OP );
  1064. }
  1065. else
  1066. {
  1067. SET_BLEND_ERROR ( pContext, BSF_UNSUPPORTED_COLOR_OP );
  1068. }
  1069. break;
  1070. default:
  1071. // What is this?. //azn
  1072. DISPDBG((ERRLVL,"** SETTAOP: Unknown operation."));
  1073. if ( bIsAlpha )
  1074. {
  1075. SET_BLEND_ERROR ( pContext, BSF_UNDEFINED_ALPHA_OP );
  1076. }
  1077. else
  1078. {
  1079. SET_BLEND_ERROR ( pContext, BSF_UNDEFINED_COLOR_OP );
  1080. }
  1081. break;
  1082. }
  1083. if(bIsAlpha)
  1084. {
  1085. pMode->AlphaInvertI = dwInvertI;
  1086. if (bOperation)
  1087. {
  1088. pMode->AlphaOperation = dwOperation;
  1089. }
  1090. if (bI)
  1091. {
  1092. pMode->AlphaI = dwI;
  1093. }
  1094. if (bA)
  1095. {
  1096. pMode->AlphaA = dwA;
  1097. }
  1098. }
  1099. else
  1100. {
  1101. pMode->ColorInvertI = dwInvertI;
  1102. if (bOperation)
  1103. {
  1104. pMode->ColorOperation = dwOperation;
  1105. }
  1106. if (bI)
  1107. {
  1108. pMode->ColorI = dwI;
  1109. }
  1110. if (bA)
  1111. {
  1112. pMode->ColorA = dwA;
  1113. }
  1114. }
  1115. } // SETTAOP
  1116. //-----------------------------------------------------------------------------
  1117. //
  1118. // _D3DDisplayWholeTSSPipe
  1119. //
  1120. // Dumps the whole TSS pipe state out to the debug stream.
  1121. // Also dumps fog, specular and alpha-blend state out.
  1122. //
  1123. //-----------------------------------------------------------------------------
  1124. void _D3DDisplayWholeTSSPipe ( P3_D3DCONTEXT* pContext, int iDebugNumber )
  1125. {
  1126. #if DBG
  1127. int i;
  1128. char *pszTemp, *pszTempPre, *pszTempPost;
  1129. char *pszOp;
  1130. char *pszArg1Pre, *pszArg1, *pszArg1Post;
  1131. char *pszArg2Pre, *pszArg2, *pszArg2Post;
  1132. char *pszSrc, *pszDest;
  1133. P3_SURF_INTERNAL* pTexture;
  1134. P3_SURF_FORMAT* pFormatSurface;
  1135. DISPDBG((iDebugNumber,"TSS dump:"));
  1136. #define SWITCH_ARG(prefix,opname) \
  1137. case prefix##_##opname##: pszTemp = #opname; break
  1138. i = 0;
  1139. while ( ( i < 8 ) && ( TSSTATE ( i, D3DTSS_COLOROP ) != D3DTOP_DISABLE ) )
  1140. {
  1141. switch ( TSSTATE ( i, D3DTSS_COLOROP ) )
  1142. {
  1143. SWITCH_ARG ( D3DTOP,DISABLE );
  1144. SWITCH_ARG ( D3DTOP,SELECTARG1 );
  1145. SWITCH_ARG ( D3DTOP,SELECTARG2 );
  1146. SWITCH_ARG ( D3DTOP,MODULATE );
  1147. SWITCH_ARG ( D3DTOP,MODULATE2X );
  1148. SWITCH_ARG ( D3DTOP,MODULATE4X );
  1149. SWITCH_ARG ( D3DTOP,ADD );
  1150. SWITCH_ARG ( D3DTOP,ADDSIGNED );
  1151. SWITCH_ARG ( D3DTOP,ADDSIGNED2X );
  1152. SWITCH_ARG ( D3DTOP,SUBTRACT );
  1153. SWITCH_ARG ( D3DTOP,ADDSMOOTH );
  1154. SWITCH_ARG ( D3DTOP,BLENDDIFFUSEALPHA );
  1155. SWITCH_ARG ( D3DTOP,BLENDTEXTUREALPHA );
  1156. SWITCH_ARG ( D3DTOP,BLENDFACTORALPHA );
  1157. SWITCH_ARG ( D3DTOP,BLENDTEXTUREALPHAPM );
  1158. SWITCH_ARG ( D3DTOP,BLENDCURRENTALPHA );
  1159. SWITCH_ARG ( D3DTOP,PREMODULATE );
  1160. SWITCH_ARG ( D3DTOP,MODULATEALPHA_ADDCOLOR );
  1161. SWITCH_ARG ( D3DTOP,MODULATECOLOR_ADDALPHA );
  1162. SWITCH_ARG ( D3DTOP,MODULATEINVALPHA_ADDCOLOR );
  1163. SWITCH_ARG ( D3DTOP,MODULATEINVCOLOR_ADDALPHA );
  1164. SWITCH_ARG ( D3DTOP,BUMPENVMAP );
  1165. SWITCH_ARG ( D3DTOP,BUMPENVMAPLUMINANCE );
  1166. SWITCH_ARG ( D3DTOP,DOTPRODUCT3 );
  1167. default:
  1168. pszTemp = "Unknown";
  1169. break;
  1170. }
  1171. pszOp = pszTemp;
  1172. switch ( TSSTATESELECT ( i, D3DTSS_COLORARG1 ) )
  1173. {
  1174. SWITCH_ARG ( D3DTA,DIFFUSE );
  1175. SWITCH_ARG ( D3DTA,CURRENT );
  1176. SWITCH_ARG ( D3DTA,TEXTURE );
  1177. SWITCH_ARG ( D3DTA,TFACTOR );
  1178. default:
  1179. pszTemp = "Unknown";
  1180. break;
  1181. }
  1182. if ( ( TSSTATE ( i, D3DTSS_COLORARG1 ) & D3DTA_ALPHAREPLICATE ) != 0 )
  1183. {
  1184. pszTempPost = ".A";
  1185. }
  1186. else
  1187. {
  1188. pszTempPost = ".C";
  1189. }
  1190. if ( ( TSSTATE ( i, D3DTSS_COLORARG1 ) & D3DTA_COMPLEMENT ) != 0 )
  1191. {
  1192. pszTempPre = "1-";
  1193. }
  1194. else
  1195. {
  1196. pszTempPre = "";
  1197. }
  1198. pszArg1Pre = pszTempPre;
  1199. pszArg1Post = pszTempPost;
  1200. pszArg1 = pszTemp;
  1201. switch ( TSSTATESELECT ( i, D3DTSS_COLORARG2 ) )
  1202. {
  1203. SWITCH_ARG ( D3DTA,DIFFUSE );
  1204. SWITCH_ARG ( D3DTA,CURRENT );
  1205. SWITCH_ARG ( D3DTA,TEXTURE );
  1206. SWITCH_ARG ( D3DTA,TFACTOR );
  1207. default:
  1208. pszTemp = "Unknown";
  1209. break;
  1210. }
  1211. if ( ( TSSTATE ( i, D3DTSS_COLORARG2 ) & D3DTA_ALPHAREPLICATE ) != 0 )
  1212. {
  1213. pszTempPost = ".A";
  1214. }
  1215. else
  1216. {
  1217. pszTempPost = ".C";
  1218. }
  1219. if ( ( TSSTATE ( i, D3DTSS_COLORARG2 ) & D3DTA_COMPLEMENT ) != 0 )
  1220. {
  1221. pszTempPre = "1-";
  1222. }
  1223. else
  1224. {
  1225. pszTempPre = "";
  1226. }
  1227. pszArg2Pre = pszTempPre;
  1228. pszArg2Post = pszTempPost;
  1229. pszArg2 = pszTemp;
  1230. DISPDBG((iDebugNumber," C%i: %s: %s%s%s, %s%s%s",
  1231. i, pszOp, pszArg1Pre, pszArg1, pszArg1Post,
  1232. pszArg2Pre, pszArg2, pszArg2Post ));
  1233. switch ( TSSTATE ( i, D3DTSS_ALPHAOP ) )
  1234. {
  1235. SWITCH_ARG ( D3DTOP,DISABLE );
  1236. SWITCH_ARG ( D3DTOP,SELECTARG1 );
  1237. SWITCH_ARG ( D3DTOP,SELECTARG2 );
  1238. SWITCH_ARG ( D3DTOP,MODULATE );
  1239. SWITCH_ARG ( D3DTOP,MODULATE2X );
  1240. SWITCH_ARG ( D3DTOP,MODULATE4X );
  1241. SWITCH_ARG ( D3DTOP,ADD );
  1242. SWITCH_ARG ( D3DTOP,ADDSIGNED );
  1243. SWITCH_ARG ( D3DTOP,ADDSIGNED2X );
  1244. SWITCH_ARG ( D3DTOP,SUBTRACT );
  1245. SWITCH_ARG ( D3DTOP,ADDSMOOTH );
  1246. SWITCH_ARG ( D3DTOP,BLENDDIFFUSEALPHA );
  1247. SWITCH_ARG ( D3DTOP,BLENDTEXTUREALPHA );
  1248. SWITCH_ARG ( D3DTOP,BLENDFACTORALPHA );
  1249. SWITCH_ARG ( D3DTOP,BLENDTEXTUREALPHAPM );
  1250. SWITCH_ARG ( D3DTOP,BLENDCURRENTALPHA );
  1251. SWITCH_ARG ( D3DTOP,PREMODULATE );
  1252. SWITCH_ARG ( D3DTOP,MODULATEALPHA_ADDCOLOR );
  1253. SWITCH_ARG ( D3DTOP,MODULATECOLOR_ADDALPHA );
  1254. SWITCH_ARG ( D3DTOP,MODULATEINVALPHA_ADDCOLOR );
  1255. SWITCH_ARG ( D3DTOP,MODULATEINVCOLOR_ADDALPHA );
  1256. SWITCH_ARG ( D3DTOP,BUMPENVMAP );
  1257. SWITCH_ARG ( D3DTOP,BUMPENVMAPLUMINANCE );
  1258. SWITCH_ARG ( D3DTOP,DOTPRODUCT3 );
  1259. default:
  1260. pszTemp = "Unknown";
  1261. break;
  1262. }
  1263. pszOp = pszTemp;
  1264. switch ( TSSTATESELECT ( i, D3DTSS_ALPHAARG1 ) )
  1265. {
  1266. SWITCH_ARG ( D3DTA,DIFFUSE );
  1267. SWITCH_ARG ( D3DTA,CURRENT );
  1268. SWITCH_ARG ( D3DTA,TEXTURE );
  1269. SWITCH_ARG ( D3DTA,TFACTOR );
  1270. default:
  1271. pszTemp = "Unknown";
  1272. break;
  1273. }
  1274. if ( ( TSSTATE ( i, D3DTSS_ALPHAARG1 ) & D3DTA_ALPHAREPLICATE ) != 0 )
  1275. {
  1276. // Alpharep doesn't mean much in the alpha channel.
  1277. pszTempPost = ".AR???";
  1278. }
  1279. else
  1280. {
  1281. pszTempPost = ".A";
  1282. }
  1283. if ( ( TSSTATE ( i, D3DTSS_ALPHAARG1 ) & D3DTA_COMPLEMENT ) != 0 )
  1284. {
  1285. pszTempPre = "1-";
  1286. }
  1287. else
  1288. {
  1289. pszTempPre = "";
  1290. }
  1291. pszArg1Pre = pszTempPre;
  1292. pszArg1Post = pszTempPost;
  1293. pszArg1 = pszTemp;
  1294. switch ( TSSTATESELECT ( i, D3DTSS_ALPHAARG2 ) )
  1295. {
  1296. SWITCH_ARG ( D3DTA,DIFFUSE );
  1297. SWITCH_ARG ( D3DTA,CURRENT );
  1298. SWITCH_ARG ( D3DTA,TEXTURE );
  1299. SWITCH_ARG ( D3DTA,TFACTOR );
  1300. default:
  1301. pszTemp = "Unknown";
  1302. break;
  1303. }
  1304. if ( ( TSSTATE ( i, D3DTSS_ALPHAARG2 ) & D3DTA_ALPHAREPLICATE ) != 0 )
  1305. {
  1306. pszTempPost = ".AR???";
  1307. }
  1308. else
  1309. {
  1310. pszTempPost = ".A";
  1311. }
  1312. if ( ( TSSTATE ( i, D3DTSS_ALPHAARG2 ) & D3DTA_COMPLEMENT ) != 0 )
  1313. {
  1314. pszTempPre = "1-";
  1315. }
  1316. else
  1317. {
  1318. pszTempPre = "";
  1319. }
  1320. pszArg2Pre = pszTempPre;
  1321. pszArg2Post = pszTempPost;
  1322. pszArg2 = pszTemp;
  1323. DISPDBG((iDebugNumber," A%i: %s: %s%s%s, %s%s%s",
  1324. i, pszOp, pszArg1Pre, pszArg1, pszArg1Post,
  1325. pszArg2Pre, pszArg2, pszArg2Post ));
  1326. if ( TSSTATE ( i, D3DTSS_TEXTUREMAP ) != 0 )
  1327. {
  1328. char szTemp[4];
  1329. // Setup texture 0.
  1330. pTexture = GetSurfaceFromHandle(pContext,
  1331. TSSTATE(i, D3DTSS_TEXTUREMAP));
  1332. if ( pTexture == NULL )
  1333. {
  1334. DISPDBG((iDebugNumber," Tex%i: 0x%x, TCI: %i, INVALID TEXTURE",
  1335. i, TSSTATE ( i, D3DTSS_TEXTUREMAP ),
  1336. TSSTATE ( i, D3DTSS_TEXCOORDINDEX ) ));
  1337. }
  1338. else
  1339. {
  1340. pFormatSurface = pTexture->pFormatSurface;
  1341. ASSERTDD ( pFormatSurface != NULL,
  1342. "** _D3DDisplayWholeTSSPipe: "
  1343. "Surface had NULL format!" );
  1344. // Find the filtering mode.
  1345. szTemp[3] = '\0';
  1346. switch ( TSSTATE ( i, D3DTSS_MINFILTER ) )
  1347. {
  1348. case D3DTFN_POINT:
  1349. szTemp[0] = 'P';
  1350. break;
  1351. case D3DTFN_LINEAR:
  1352. szTemp[0] = 'L';
  1353. break;
  1354. case D3DTFN_ANISOTROPIC:
  1355. szTemp[0] = 'A';
  1356. break;
  1357. default:
  1358. szTemp[0] = '?';
  1359. break;
  1360. }
  1361. switch ( TSSTATE ( i, D3DTSS_MIPFILTER ) )
  1362. {
  1363. case D3DTFP_NONE:
  1364. szTemp[1] = 'x';
  1365. break;
  1366. case D3DTFP_POINT:
  1367. szTemp[1] = 'P';
  1368. break;
  1369. case D3DTFP_LINEAR:
  1370. szTemp[1] = 'L';
  1371. break;
  1372. default:
  1373. szTemp[1] = '?';
  1374. break;
  1375. }
  1376. switch ( TSSTATE ( i, D3DTSS_MAGFILTER ) )
  1377. {
  1378. case D3DTFG_POINT:
  1379. szTemp[2] = 'P';
  1380. break;
  1381. case D3DTFG_LINEAR:
  1382. szTemp[2] = 'L';
  1383. break;
  1384. case D3DTFG_FLATCUBIC:
  1385. szTemp[2] = 'F';
  1386. break;
  1387. case D3DTFG_GAUSSIANCUBIC:
  1388. szTemp[2] = 'G';
  1389. break;
  1390. case D3DTFG_ANISOTROPIC:
  1391. szTemp[2] = 'A';
  1392. break;
  1393. default:
  1394. szTemp[2] = '?';
  1395. break;
  1396. }
  1397. DISPDBG((iDebugNumber," Tex%i: 0x%x, TCI: %i, %s:%dx%d %s",
  1398. i, TSSTATE ( i, D3DTSS_TEXTUREMAP ),
  1399. TSSTATE ( i, D3DTSS_TEXCOORDINDEX ),
  1400. pFormatSurface->pszStringFormat,
  1401. pTexture->wWidth,
  1402. pTexture->wHeight, szTemp ));
  1403. }
  1404. }
  1405. else
  1406. {
  1407. DISPDBG((iDebugNumber," Tex%i: NULL, TCI: %i",
  1408. i, TSSTATE ( i, D3DTSS_TEXCOORDINDEX ) ));
  1409. }
  1410. i++;
  1411. }
  1412. // Alpha-test.
  1413. if ( pContext->RenderStates[D3DRENDERSTATE_ALPHATESTENABLE] != 0 )
  1414. {
  1415. switch ( pContext->RenderStates[D3DRENDERSTATE_ALPHAFUNC] )
  1416. {
  1417. SWITCH_ARG ( D3DCMP,NEVER );
  1418. SWITCH_ARG ( D3DCMP,LESS );
  1419. SWITCH_ARG ( D3DCMP,EQUAL );
  1420. SWITCH_ARG ( D3DCMP,LESSEQUAL );
  1421. SWITCH_ARG ( D3DCMP,GREATER );
  1422. SWITCH_ARG ( D3DCMP,NOTEQUAL );
  1423. SWITCH_ARG ( D3DCMP,GREATEREQUAL );
  1424. SWITCH_ARG ( D3DCMP,ALWAYS );
  1425. default:
  1426. pszTemp = "Unknown";
  1427. break;
  1428. }
  1429. DISPDBG((iDebugNumber,"Alpha-test: %s:0x%x.",
  1430. pszTemp, pContext->RenderStates[D3DRENDERSTATE_ALPHAREF] ));
  1431. }
  1432. else
  1433. {
  1434. DISPDBG((iDebugNumber,"No alpha-test."));
  1435. }
  1436. // Alpha-blend.
  1437. if ( pContext->RenderStates[D3DRENDERSTATE_BLENDENABLE] != 0 )
  1438. {
  1439. switch ( pContext->RenderStates[D3DRENDERSTATE_SRCBLEND] )
  1440. {
  1441. SWITCH_ARG ( D3DBLEND,ZERO );
  1442. SWITCH_ARG ( D3DBLEND,ONE );
  1443. SWITCH_ARG ( D3DBLEND,SRCCOLOR );
  1444. SWITCH_ARG ( D3DBLEND,INVSRCCOLOR );
  1445. SWITCH_ARG ( D3DBLEND,SRCALPHA );
  1446. SWITCH_ARG ( D3DBLEND,INVSRCALPHA );
  1447. SWITCH_ARG ( D3DBLEND,DESTALPHA );
  1448. SWITCH_ARG ( D3DBLEND,INVDESTALPHA );
  1449. SWITCH_ARG ( D3DBLEND,DESTCOLOR );
  1450. SWITCH_ARG ( D3DBLEND,INVDESTCOLOR );
  1451. SWITCH_ARG ( D3DBLEND,SRCALPHASAT );
  1452. SWITCH_ARG ( D3DBLEND,BOTHSRCALPHA );
  1453. SWITCH_ARG ( D3DBLEND,BOTHINVSRCALPHA );
  1454. default:
  1455. pszTemp = "Unknown";
  1456. break;
  1457. }
  1458. pszSrc = pszTemp;
  1459. switch ( pContext->RenderStates[D3DRENDERSTATE_DESTBLEND] )
  1460. {
  1461. SWITCH_ARG ( D3DBLEND,ZERO );
  1462. SWITCH_ARG ( D3DBLEND,ONE );
  1463. SWITCH_ARG ( D3DBLEND,SRCCOLOR );
  1464. SWITCH_ARG ( D3DBLEND,INVSRCCOLOR );
  1465. SWITCH_ARG ( D3DBLEND,SRCALPHA );
  1466. SWITCH_ARG ( D3DBLEND,INVSRCALPHA );
  1467. SWITCH_ARG ( D3DBLEND,DESTALPHA );
  1468. SWITCH_ARG ( D3DBLEND,INVDESTALPHA );
  1469. SWITCH_ARG ( D3DBLEND,DESTCOLOR );
  1470. SWITCH_ARG ( D3DBLEND,INVDESTCOLOR );
  1471. SWITCH_ARG ( D3DBLEND,SRCALPHASAT );
  1472. SWITCH_ARG ( D3DBLEND,BOTHSRCALPHA );
  1473. SWITCH_ARG ( D3DBLEND,BOTHINVSRCALPHA );
  1474. default:
  1475. pszTemp = "Unknown";
  1476. break;
  1477. }
  1478. pszDest = pszTemp;
  1479. DISPDBG((iDebugNumber,"Blend %s:%s", pszSrc, pszDest));
  1480. }
  1481. else
  1482. {
  1483. DISPDBG((iDebugNumber,"No alpha-blend."));
  1484. }
  1485. #undef SWITCH_ARG
  1486. #endif //DBG
  1487. } // _D3DDisplayWholeTSSPipe
  1488. //-----------------------------------------------------------------------------
  1489. //
  1490. // __TXT_TranslateToChipBlendMode
  1491. //
  1492. // Translates the blend mode from D3D into what the chip understands
  1493. //
  1494. //-----------------------------------------------------------------------------
  1495. void
  1496. __TXT_TranslateToChipBlendMode(
  1497. P3_D3DCONTEXT *pContext,
  1498. TexStageState* pState,
  1499. P3_SOFTWARECOPY* pSoftP3RX,
  1500. int iTSStage,
  1501. int iChipStageNo )
  1502. {
  1503. struct TextureCompositeRGBAMode* pColorMode;
  1504. struct TextureCompositeRGBAMode* pAlphaMode;
  1505. struct TextureApplicationMode* pTAMode;
  1506. switch(iChipStageNo)
  1507. {
  1508. default:
  1509. DISPDBG((ERRLVL,"ERROR: Invalid texture stage!"));
  1510. // Fall through and treat as #0 in order not to AV anything
  1511. case 0:
  1512. pColorMode = &pSoftP3RX->P3RXTextureCompositeColorMode0;
  1513. pAlphaMode = &pSoftP3RX->P3RXTextureCompositeAlphaMode0;
  1514. pTAMode = NULL;
  1515. break;
  1516. case 1:
  1517. pColorMode = &pSoftP3RX->P3RXTextureCompositeColorMode1;
  1518. pAlphaMode = &pSoftP3RX->P3RXTextureCompositeAlphaMode1;
  1519. pTAMode = NULL;
  1520. break;
  1521. case 2:
  1522. pColorMode = NULL;
  1523. pAlphaMode = NULL;
  1524. pTAMode = &pSoftP3RX->P3RXTextureApplicationMode;
  1525. break;
  1526. }
  1527. DISPDBG((DBGLVL,"*** In __TXT_TranslateToChipBlendMode: "
  1528. "Chip Stage %d, D3D TSS Stage %d",
  1529. iChipStageNo, iTSStage ));
  1530. // Setup the arguments
  1531. if ( ( iChipStageNo == 0 ) || ( iChipStageNo == 1 ) )
  1532. {
  1533. // Texture composite unit.
  1534. DISPDBG((DBGLVL,"TexComp%d:", iChipStageNo ));
  1535. DISPDBG((DBGLVL,"Arg1:" ));
  1536. SETARG(pContext,
  1537. pColorMode,
  1538. pState->m_dwVal[D3DTSS_COLORARG1],
  1539. 1,
  1540. IS_COLOR_ARG,
  1541. iTSStage,
  1542. iChipStageNo);
  1543. SETARG(pContext,
  1544. pAlphaMode,
  1545. pState->m_dwVal[D3DTSS_ALPHAARG1],
  1546. 1,
  1547. IS_ALPHA_ARG,
  1548. iTSStage,
  1549. iChipStageNo);
  1550. DISPDBG((DBGLVL,"Arg2:" ));
  1551. SETARG(pContext,
  1552. pColorMode,
  1553. pState->m_dwVal[D3DTSS_COLORARG2],
  1554. 2,
  1555. IS_COLOR_ARG,
  1556. iTSStage,
  1557. iChipStageNo);
  1558. SETARG(pContext,
  1559. pAlphaMode,
  1560. pState->m_dwVal[D3DTSS_ALPHAARG2],
  1561. 2,
  1562. IS_ALPHA_ARG,
  1563. iTSStage,
  1564. iChipStageNo);
  1565. DISPDBG((DBGLVL,"Op:" ));
  1566. SETOP(pContext,
  1567. pColorMode,
  1568. pState->m_dwVal[D3DTSS_COLOROP],
  1569. iTSStage,
  1570. iChipStageNo,
  1571. IS_COLOR_ARG);
  1572. SETOP(pContext,
  1573. pAlphaMode,
  1574. pState->m_dwVal[D3DTSS_ALPHAOP],
  1575. iTSStage,
  1576. iChipStageNo,
  1577. IS_ALPHA_ARG);
  1578. }
  1579. else if ( iChipStageNo == 2 )
  1580. {
  1581. DISPDBG((DBGLVL,"TexApp:" ));
  1582. DISPDBG((DBGLVL,"Arg1:" ));
  1583. SETTAARG_COLOR(pContext,
  1584. pTAMode,
  1585. pState->m_dwVal[D3DTSS_COLORARG1],
  1586. 1 );
  1587. if ( ( pState->m_dwVal[D3DTSS_ALPHAOP] != D3DTOP_DISABLE ) &&
  1588. ( pState->m_dwVal[D3DTSS_ALPHAOP] != D3DTOP_SELECTARG2 ) )
  1589. {
  1590. SETTAARG_ALPHA(pContext,
  1591. pTAMode,
  1592. pState->m_dwVal[D3DTSS_ALPHAARG1], 1
  1593. );
  1594. }
  1595. DISPDBG((DBGLVL,"Arg2:" ));
  1596. SETTAARG_COLOR(pContext,
  1597. pTAMode,
  1598. pState->m_dwVal[D3DTSS_COLORARG2],
  1599. 2 );
  1600. if ( ( pState->m_dwVal[D3DTSS_ALPHAOP] != D3DTOP_DISABLE ) &&
  1601. ( pState->m_dwVal[D3DTSS_ALPHAOP] != D3DTOP_SELECTARG1 ) )
  1602. {
  1603. SETTAARG_ALPHA(pContext,
  1604. pTAMode,
  1605. pState->m_dwVal[D3DTSS_ALPHAARG2],
  1606. 2);
  1607. }
  1608. DISPDBG((DBGLVL,"Op:" ));
  1609. SETTAOP(pContext,
  1610. pTAMode,
  1611. pState->m_dwVal[D3DTSS_COLOROP],
  1612. IS_COLOR_ARG,
  1613. iTSStage,
  1614. iChipStageNo);
  1615. SETTAOP(pContext,
  1616. pTAMode,
  1617. pState->m_dwVal[D3DTSS_ALPHAOP],
  1618. IS_ALPHA_ARG,
  1619. iTSStage,
  1620. iChipStageNo);
  1621. }
  1622. else
  1623. {
  1624. DISPDBG(( ERRLVL,"** __TXT_TranslateToChipBlendMode: "
  1625. "iChipStage must be 0 to 2" ));
  1626. }
  1627. } // __TXT_TranslateToChipBlendMode
  1628. //-----------------------------------------------------------------------------
  1629. //
  1630. // __TXT_ValidateTextureUnitStage
  1631. //
  1632. // Validate the texture which we're trying to set up in stage iChipStage of
  1633. // the hardware, iTSStage of the D3D TSS.
  1634. //
  1635. //-----------------------------------------------------------------------------
  1636. BOOL
  1637. __TXT_ValidateTextureUnitStage(
  1638. P3_D3DCONTEXT* pContext,
  1639. int iChipStage,
  1640. int iTSStage,
  1641. P3_SURF_INTERNAL* pTexture)
  1642. {
  1643. DWORD dwTexHandle =
  1644. pContext->TextureStageState[iTSStage].m_dwVal[D3DTSS_TEXTUREMAP];
  1645. if( CHECK_SURF_INTERNAL_AND_DDSURFACE_VALIDITY(pTexture) &&
  1646. (pTexture->Location != SystemMemory) &&
  1647. (dwTexHandle != 0) )
  1648. {
  1649. // Texture is valid. Mark pCurrentTexturep[iChipStage] to point
  1650. // to its P3_SURF_INTERNAL structure.
  1651. pContext->pCurrentTexture[iChipStage] = pTexture;
  1652. DISPDBG((DBGLVL, "__TXT_ValidateTextureUnitStage: valid texture %x "
  1653. "(handle %d) for iChipStage= %d iTSStage= %d",
  1654. pTexture, dwTexHandle, iChipStage, iTSStage));
  1655. }
  1656. else
  1657. {
  1658. // Set texture as invalid & force texturing off
  1659. pContext->bTextureValid = FALSE;
  1660. pContext->pCurrentTexture[iChipStage] = NULL;
  1661. pContext->dwDirtyFlags |= CONTEXT_DIRTY_TEXTURE;
  1662. // Setup error if we're asked to validate the TSS setup
  1663. SET_BLEND_ERROR ( pContext, BSF_INVALID_TEXTURE );
  1664. DISPDBG((WRNLVL, "__TXT_ValidateTextureUnitStage: INVALID texture %x "
  1665. "(handle %d) for iChipStage= %d iTSStage= %d "
  1666. "Location=%d",
  1667. pTexture, dwTexHandle, iChipStage, iTSStage,
  1668. (pTexture !=NULL)?pTexture->Location:0));
  1669. }
  1670. return ( (BOOL)pContext->bTextureValid );
  1671. } // __TXT_ValidateTextureUnitStage
  1672. //-----------------------------------------------------------------------------
  1673. //
  1674. // __TXT_ConsiderSrcChromaKey
  1675. //
  1676. // Setup chromakeying for a certain texture bound to a certain stage.
  1677. // Note - "stage" is the chip stage, not the D3D stage.
  1678. //-----------------------------------------------------------------------------
  1679. static void
  1680. __TXT_ConsiderSrcChromaKey(
  1681. P3_D3DCONTEXT *pContext,
  1682. P3_SURF_INTERNAL* pTexture,
  1683. int stage )
  1684. {
  1685. P3_THUNKEDDATA * pThisDisplay = pContext->pThisDisplay;
  1686. P3_SOFTWARECOPY* pSoftP3RX = &pContext->SoftCopyGlint;
  1687. P3_DMA_DEFS();
  1688. if ((pTexture->dwFlagsInt & DDRAWISURF_HASCKEYSRCBLT) &&
  1689. pContext->RenderStates[D3DRENDERSTATE_COLORKEYENABLE])
  1690. {
  1691. DWORD LowerBound = 0x00000000;
  1692. DWORD UpperBound = 0xFFFFFFFF;
  1693. DWORD* pPalEntries = NULL;
  1694. DWORD dwPalFlags = 0;
  1695. DISPDBG((DBGLVL," Can Chroma Key texture stage %d", stage));
  1696. pContext->bCanChromaKey = TRUE;
  1697. #if DX7_PALETTETEXTURE
  1698. // Get the palette entries
  1699. if (pTexture->pixFmt.dwFlags & DDPF_PALETTEINDEXED8)
  1700. {
  1701. D3DHAL_DP2UPDATEPALETTE *pPalette = NULL;
  1702. pPalette = GetPaletteFromHandle(pContext,
  1703. pTexture->dwPaletteHandle);
  1704. if (pPalette)
  1705. {
  1706. pPalEntries = (LPDWORD)(pPalette + 1);
  1707. }
  1708. else
  1709. {
  1710. SET_BLEND_ERROR(pContext, BSF_INVALID_TEXTURE);
  1711. }
  1712. dwPalFlags = pTexture->dwPaletteFlags;
  1713. }
  1714. #endif
  1715. // Get the correct chroma value for the texture map to send to the chip.
  1716. Get8888ScaledChroma(pThisDisplay,
  1717. pTexture->dwFlagsInt,
  1718. &pTexture->pixFmt,
  1719. pTexture->dwCKLow,
  1720. pTexture->dwCKHigh,
  1721. &LowerBound,
  1722. &UpperBound,
  1723. pPalEntries,
  1724. dwPalFlags & DDRAWIPAL_ALPHA,
  1725. FALSE);
  1726. P3_DMA_GET_BUFFER_ENTRIES( 8);
  1727. // Send the upper and lower bounds for the alpha-map filtering
  1728. if( stage == 0 )
  1729. {
  1730. SEND_P3_DATA(TextureChromaLower0, LowerBound );
  1731. SEND_P3_DATA(TextureChromaUpper0, UpperBound );
  1732. pSoftP3RX->P3RXTextureFilterMode.AlphaMapEnable0 =
  1733. __PERMEDIA_ENABLE;
  1734. pSoftP3RX->P3RXTextureFilterMode.AlphaMapSense0 =
  1735. P3RX_ALPHAMAPSENSE_INRANGE;
  1736. }
  1737. else
  1738. {
  1739. ASSERTDD ( stage == 1,
  1740. "** __TXT_ConsiderSrcChromaKey: stage must be 0 or 1" );
  1741. }
  1742. // If we are mipmapping, we need to set up texture1's chromakey as well.
  1743. // If not, then this will be overridden when this gets called for tex1.
  1744. SEND_P3_DATA(TextureChromaLower1, LowerBound );
  1745. SEND_P3_DATA(TextureChromaUpper1, UpperBound );
  1746. pSoftP3RX->P3RXTextureFilterMode.AlphaMapEnable1 = __PERMEDIA_ENABLE;
  1747. pSoftP3RX->P3RXTextureFilterMode.AlphaMapSense1 =
  1748. P3RX_ALPHAMAPSENSE_INRANGE;
  1749. P3_DMA_COMMIT_BUFFER();
  1750. pSoftP3RX->P3RXTextureFilterMode.AlphaMapFiltering = __PERMEDIA_ENABLE;
  1751. }
  1752. else
  1753. {
  1754. DISPDBG((DBGLVL," Can't Chroma Key texture stage %d", stage));
  1755. if( stage == 0 )
  1756. {
  1757. pSoftP3RX->P3RXTextureFilterMode.AlphaMapEnable0 =
  1758. __PERMEDIA_DISABLE;
  1759. }
  1760. else
  1761. {
  1762. ASSERTDD ( stage == 1,
  1763. "** __TXT_ConsiderSrcChromaKey: stage must be 0 or 1" );
  1764. }
  1765. // If we are mipmapping, we need to set up texture1's chromakey (or
  1766. // lack of it) as well. If not, then this will be overridden when
  1767. // this gets called for tex1.
  1768. pSoftP3RX->P3RXTextureFilterMode.AlphaMapEnable1 = __PERMEDIA_DISABLE;
  1769. pSoftP3RX->P3RXTextureFilterMode.AlphaMapFiltering = __PERMEDIA_DISABLE;
  1770. }
  1771. } // __TXT_ConsiderSrcChromaKey
  1772. //-----------------------------------------------------------------------------
  1773. //
  1774. // __TXT_SetupTexture
  1775. //
  1776. // This is the new all-singing all-dancing texture setup code.
  1777. // Return is TRUE if setup succeeded, FALSE if it failed (for ValidateDevice)
  1778. // This sets up either texture 0 or texture 1, taking its wrapping, etc,
  1779. // info from iTSStage.
  1780. //
  1781. //-----------------------------------------------------------------------------
  1782. BOOL __TXT_SetupTexture (
  1783. P3_THUNKEDDATA * pThisDisplay,
  1784. int iTexNo,
  1785. int iTSStage,
  1786. P3_D3DCONTEXT* pContext,
  1787. P3_SURF_INTERNAL* pTexture,
  1788. P3_SOFTWARECOPY* pSoftP3RX,
  1789. BOOL bBothTexturesValid,
  1790. P3_MIP_BASES *pMipBases)
  1791. {
  1792. P3_SURF_FORMAT* pFormatSurface;
  1793. int iT0MaxLevel, iT1MaxLevel;
  1794. P3_DMA_DEFS();
  1795. ASSERTDD ( ( iTexNo >= 0 ) && ( iTexNo <= 1 ),
  1796. "**__TXT_SetupTexture: we only have two texture units!" );
  1797. if ( pTexture != NULL )
  1798. {
  1799. pFormatSurface = pTexture->pFormatSurface;
  1800. }
  1801. else
  1802. {
  1803. // Suceeded, but should never have got here!
  1804. DISPDBG((ERRLVL,"**__TXT_SetupTexture: should never "
  1805. "be called with handle of NULL"));
  1806. return ( TRUE );
  1807. }
  1808. P3_DMA_GET_BUFFER();
  1809. P3_ENSURE_DX_SPACE(32);
  1810. WAIT_FIFO(32);
  1811. // Set up the texture-relevant things.
  1812. switch ( iTexNo )
  1813. {
  1814. case 0:
  1815. {
  1816. // Set both bits in case we are mipmapping
  1817. pSoftP3RX->P3RXTextureFilterMode.ForceAlphaToOne0 =
  1818. pFormatSurface->bAlpha ?
  1819. __PERMEDIA_DISABLE :
  1820. __PERMEDIA_ENABLE;
  1821. pSoftP3RX->P3RXTextureFilterMode.ForceAlphaToOne1 =
  1822. pFormatSurface->bAlpha ?
  1823. __PERMEDIA_DISABLE :
  1824. __PERMEDIA_ENABLE;
  1825. // D3D UV Wrapping
  1826. if (pContext->RenderStates[D3DRENDERSTATE_WRAP0+iTSStage]
  1827. & D3DWRAP_U)
  1828. {
  1829. pSoftP3RX->P4DeltaFormatControl.WrapS = 1;
  1830. }
  1831. else
  1832. {
  1833. pSoftP3RX->P4DeltaFormatControl.WrapS = 0;
  1834. }
  1835. if (pContext->RenderStates[D3DRENDERSTATE_WRAP0+iTSStage]
  1836. & D3DWRAP_V)
  1837. {
  1838. pSoftP3RX->P4DeltaFormatControl.WrapT = 1;
  1839. }
  1840. else
  1841. {
  1842. pSoftP3RX->P4DeltaFormatControl.WrapT = 0;
  1843. }
  1844. // U Wrapping
  1845. switch (TSSTATE ( iTSStage, D3DTSS_ADDRESSU ))
  1846. {
  1847. case D3DTADDRESS_CLAMP:
  1848. pSoftP3RX->P3RXTextureCoordMode.WrapS =
  1849. __GLINT_TEXADDRESS_WRAP_CLAMP;
  1850. pSoftP3RX->P3RXTextureIndexMode0.WrapU =
  1851. P3RX_TEXINDEXMODE_WRAP_CLAMPEDGE;
  1852. break;
  1853. case D3DTADDRESS_WRAP:
  1854. pSoftP3RX->P3RXTextureCoordMode.WrapS =
  1855. __GLINT_TEXADDRESS_WRAP_REPEAT;
  1856. pSoftP3RX->P3RXTextureIndexMode0.WrapU =
  1857. P3RX_TEXINDEXMODE_WRAP_REPEAT;
  1858. break;
  1859. case D3DTADDRESS_MIRROR:
  1860. pSoftP3RX->P3RXTextureCoordMode.WrapS =
  1861. __GLINT_TEXADDRESS_WRAP_MIRROR;
  1862. pSoftP3RX->P3RXTextureIndexMode0.WrapU =
  1863. P3RX_TEXINDEXMODE_WRAP_MIRROR;
  1864. break;
  1865. default:
  1866. DISPDBG((ERRLVL,"ERROR: Unknown ADDRESSU!"));
  1867. SET_BLEND_ERROR ( pContext, BSF_UNDEFINED_STATE );
  1868. break;
  1869. }
  1870. // V Wrapping
  1871. switch (TSSTATE ( iTSStage, D3DTSS_ADDRESSV ))
  1872. {
  1873. case D3DTADDRESS_CLAMP:
  1874. pSoftP3RX->P3RXTextureCoordMode.WrapT =
  1875. __GLINT_TEXADDRESS_WRAP_CLAMP;
  1876. pSoftP3RX->P3RXTextureIndexMode0.WrapV =
  1877. P3RX_TEXINDEXMODE_WRAP_CLAMPEDGE;
  1878. break;
  1879. case D3DTADDRESS_WRAP:
  1880. pSoftP3RX->P3RXTextureCoordMode.WrapT =
  1881. __GLINT_TEXADDRESS_WRAP_REPEAT;
  1882. pSoftP3RX->P3RXTextureIndexMode0.WrapV =
  1883. P3RX_TEXINDEXMODE_WRAP_REPEAT;
  1884. break;
  1885. case D3DTADDRESS_MIRROR:
  1886. pSoftP3RX->P3RXTextureCoordMode.WrapT =
  1887. __GLINT_TEXADDRESS_WRAP_MIRROR;
  1888. pSoftP3RX->P3RXTextureIndexMode0.WrapV =
  1889. P3RX_TEXINDEXMODE_WRAP_MIRROR;
  1890. break;
  1891. default:
  1892. DISPDBG((ERRLVL,"ERROR: Unknown ADDRESSV!"));
  1893. SET_BLEND_ERROR ( pContext, BSF_UNDEFINED_STATE );
  1894. break;
  1895. }
  1896. #if DX8_3DTEXTURES
  1897. if (pTexture->b3DTexture)
  1898. {
  1899. // W Wrapping
  1900. switch (TSSTATE ( iTSStage, D3DTSS_ADDRESSW ))
  1901. {
  1902. case D3DTADDRESS_CLAMP:
  1903. pSoftP3RX->P3RXTextureCoordMode.WrapS1 =
  1904. __GLINT_TEXADDRESS_WRAP_CLAMP;
  1905. pSoftP3RX->P3RXTextureIndexMode1.WrapU =
  1906. P3RX_TEXINDEXMODE_WRAP_CLAMPEDGE;
  1907. break;
  1908. case D3DTADDRESS_WRAP:
  1909. pSoftP3RX->P3RXTextureCoordMode.WrapS1 =
  1910. __GLINT_TEXADDRESS_WRAP_REPEAT;
  1911. pSoftP3RX->P3RXTextureIndexMode1.WrapU =
  1912. P3RX_TEXINDEXMODE_WRAP_REPEAT;
  1913. break;
  1914. case D3DTADDRESS_MIRROR:
  1915. pSoftP3RX->P3RXTextureCoordMode.WrapS1 =
  1916. __GLINT_TEXADDRESS_WRAP_MIRROR;
  1917. pSoftP3RX->P3RXTextureIndexMode1.WrapU =
  1918. P3RX_TEXINDEXMODE_WRAP_MIRROR;
  1919. break;
  1920. default:
  1921. DISPDBG((ERRLVL,"ERROR: Unknown ADDRESSW!"));
  1922. SET_BLEND_ERROR ( pContext, BSF_UNDEFINED_STATE );
  1923. break;
  1924. }
  1925. }
  1926. #endif // DX8_3DTEXTURES
  1927. if(( TSSTATE( iTSStage, D3DTSS_ADDRESSU ) == D3DTADDRESS_CLAMP ) ||
  1928. ( TSSTATE( iTSStage, D3DTSS_ADDRESSV ) == D3DTADDRESS_CLAMP ))
  1929. {
  1930. if( (TSSTATE( iTSStage, D3DTSS_ADDRESSU ) != D3DTADDRESS_CLAMP) ||
  1931. (TSSTATE( iTSStage, D3DTSS_ADDRESSV ) != D3DTADDRESS_CLAMP))
  1932. {
  1933. DISPDBG((ERRLVL,"Warning: One texture coord clamped, but not "
  1934. "the other - can't appply TextureShift"));
  1935. }
  1936. pSoftP3RX->P4DeltaFormatControl.TextureShift =
  1937. __PERMEDIA_DISABLE;
  1938. }
  1939. else
  1940. {
  1941. pSoftP3RX->P4DeltaFormatControl.TextureShift =
  1942. __PERMEDIA_ENABLE;
  1943. }
  1944. ASSERTDD ( pFormatSurface != NULL,
  1945. "** SetupTextureUnitStage: logic error: "
  1946. "pFormatSurace is NULL" );
  1947. switch (pFormatSurface->DeviceFormat)
  1948. {
  1949. case SURF_CI8:
  1950. pSoftP3RX->P3RXTextureReadMode0.TextureType =
  1951. P3RX_TEXREADMODE_TEXTURETYPE_8BITINDEXED;
  1952. break;
  1953. case SURF_YUV422:
  1954. pSoftP3RX->P3RXTextureReadMode0.TextureType =
  1955. P3RX_TEXREADMODE_TEXTURETYPE_422_YVYU;
  1956. break;
  1957. default:
  1958. pSoftP3RX->P3RXTextureReadMode0.TextureType =
  1959. P3RX_TEXREADMODE_TEXTURETYPE_NORMAL;
  1960. break;
  1961. }
  1962. // MAG Filter
  1963. switch(TSSTATE ( iTSStage, D3DTSS_MAGFILTER ))
  1964. {
  1965. case D3DTFG_POINT:
  1966. pSoftP3RX->P3RXTextureIndexMode0.MagnificationFilter =
  1967. __GLINT_TEXTUREREAD_FILTER_NEAREST;
  1968. break;
  1969. case D3DTFG_LINEAR:
  1970. pSoftP3RX->P3RXTextureIndexMode0.MagnificationFilter =
  1971. __GLINT_TEXTUREREAD_FILTER_LINEAR;
  1972. break;
  1973. case D3DTFG_FLATCUBIC:
  1974. case D3DTFG_GAUSSIANCUBIC:
  1975. case D3DTFG_ANISOTROPIC:
  1976. DISPDBG((ERRLVL,"ERROR: Unsupported MAGFILTER!"));
  1977. SET_BLEND_ERROR ( pContext, BSF_UNSUPPORTED_FILTER );
  1978. break;
  1979. default:
  1980. DISPDBG((ERRLVL,"ERROR: Unknown MAGFILTER!"));
  1981. SET_BLEND_ERROR ( pContext, BSF_UNDEFINED_FILTER );
  1982. break;
  1983. }
  1984. switch(TSSTATE ( iTSStage, D3DTSS_MINFILTER ))
  1985. {
  1986. case D3DTFN_POINT:
  1987. pSoftP3RX->P3RXTextureIndexMode0.MinificationFilter =
  1988. __GLINT_TEXTUREREAD_FILTER_NEAREST;
  1989. break;
  1990. case D3DTFN_LINEAR:
  1991. pSoftP3RX->P3RXTextureIndexMode0.MinificationFilter =
  1992. __GLINT_TEXTUREREAD_FILTER_LINEAR;
  1993. break;
  1994. case D3DTFN_ANISOTROPIC:
  1995. DISPDBG((ERRLVL,"ERROR: Unsupported MINFILTER!"));
  1996. SET_BLEND_ERROR ( pContext, BSF_UNSUPPORTED_FILTER );
  1997. break;
  1998. default:
  1999. DISPDBG((ERRLVL,"ERROR: Unknown MINFILTER!"));
  2000. SET_BLEND_ERROR ( pContext, BSF_UNDEFINED_FILTER );
  2001. break;
  2002. }
  2003. switch(TSSTATE ( iTSStage, D3DTSS_MIPFILTER ))
  2004. {
  2005. case D3DTFP_NONE:
  2006. // No need to set the minification filter, it was done above
  2007. break;
  2008. case D3DTFP_POINT:
  2009. switch(TSSTATE ( iTSStage, D3DTSS_MINFILTER ))
  2010. {
  2011. case D3DTFN_POINT:
  2012. // Point Min, Point Mip
  2013. pSoftP3RX->P3RXTextureIndexMode0.MinificationFilter =
  2014. __GLINT_TEXTUREREAD_FILTER_NEARMIPNEAREST;
  2015. break;
  2016. case D3DTFN_LINEAR:
  2017. // Linear Min, Point Mip
  2018. pSoftP3RX->P3RXTextureIndexMode0.MinificationFilter =
  2019. __GLINT_TEXTUREREAD_FILTER_LINEARMIPNEAREST;
  2020. break;
  2021. }
  2022. break;
  2023. case D3DTFP_LINEAR:
  2024. if( bBothTexturesValid )
  2025. {
  2026. // We can only do per-poly mipmapping while
  2027. // multi-texturing, so don't enable inter-map filtering.
  2028. // Non-fatal error - drop back to nearest
  2029. // mipmap filtering.
  2030. SET_BLEND_ERROR ( pContext, BS_INVALID_FILTER );
  2031. switch(TSSTATE ( iTSStage, D3DTSS_MINFILTER ))
  2032. {
  2033. case D3DTFN_POINT:
  2034. // Point Min, Point Mip
  2035. pSoftP3RX->P3RXTextureIndexMode0.MinificationFilter =
  2036. __GLINT_TEXTUREREAD_FILTER_NEARMIPNEAREST;
  2037. break;
  2038. case D3DTFN_LINEAR:
  2039. // Linear Min, Point Mip
  2040. pSoftP3RX->P3RXTextureIndexMode0.MinificationFilter =
  2041. __GLINT_TEXTUREREAD_FILTER_LINEARMIPNEAREST;
  2042. break;
  2043. }
  2044. }
  2045. else
  2046. {
  2047. // Single texture - do inter-map filtering
  2048. switch(TSSTATE ( iTSStage, D3DTSS_MINFILTER ))
  2049. {
  2050. case D3DTFN_POINT:
  2051. // Point Min, Linear Mip
  2052. pSoftP3RX->P3RXTextureIndexMode0.MinificationFilter =
  2053. __GLINT_TEXTUREREAD_FILTER_NEARMIPLINEAR;
  2054. break;
  2055. case D3DTFN_LINEAR:
  2056. // Linear Min, Linear Mip
  2057. pSoftP3RX->P3RXTextureIndexMode0.MinificationFilter =
  2058. __GLINT_TEXTUREREAD_FILTER_LINEARMIPLINEAR;
  2059. break;
  2060. }
  2061. }
  2062. break;
  2063. default:
  2064. DISPDBG((ERRLVL,"ERROR: Unknown MIPFILTER!"));
  2065. SET_BLEND_ERROR ( pContext, BSF_UNDEFINED_FILTER );
  2066. break;
  2067. }
  2068. // MipMapping
  2069. if( (TSSTATE ( iTSStage, D3DTSS_MIPFILTER ) != D3DTFP_NONE) &&
  2070. (pTexture->bMipMap))
  2071. {
  2072. int iLOD;
  2073. INT iTexLOD;
  2074. DISPDBG(( DBGLVL, "Multiple texture levels" ));
  2075. // Load the mipmap levels for texture 0
  2076. // Mip level from pMipBases->dwTex0ActMaxLevel to
  2077. // pTexture->iMipLevels will be mapped to base address slot
  2078. // from pMipBases->dwTex0Mipbase to dwTex0MipMax
  2079. ASSERTDD ( pMipBases->dwTex0MipBase == 0,
  2080. "** __TXT_SetupTexture: "
  2081. "Texture 0 mipmap base is not 0" );
  2082. iLOD = pMipBases->dwTex0MipBase;
  2083. iTexLOD = pMipBases->dwTex0ActMaxLevel;
  2084. iT0MaxLevel = iTexLOD;
  2085. while(( iTexLOD < pTexture->iMipLevels ) &&
  2086. ( iLOD <= (int)pMipBases->dwTex0MipMax ))
  2087. {
  2088. DISPDBG((DBGLVL, " Setting Texture Base Address %d to 0x%x",
  2089. iLOD, pTexture->MipLevels[iLOD].dwOffsetFromMemoryBase));
  2090. pSoftP3RX->P3RXTextureMapWidth[iLOD] =
  2091. pTexture->MipLevels[iTexLOD].P3RXTextureMapWidth;
  2092. #if DX7_TEXMANAGEMENT
  2093. // If this is a driver managed texture surface, we need
  2094. // to use our privately allocated mem ptr
  2095. if (pTexture->dwCaps2 & DDSCAPS2_TEXTUREMANAGE)
  2096. {
  2097. SEND_P3_DATA_OFFSET(TextureBaseAddr0,
  2098. (DWORD)D3DTMMIPLVL_GETOFFSET(pTexture->MipLevels[iTexLOD], pThisDisplay),
  2099. iLOD);
  2100. }
  2101. else
  2102. #endif
  2103. {
  2104. SEND_P3_DATA_OFFSET(TextureBaseAddr0,
  2105. pTexture->MipLevels[iTexLOD].dwOffsetFromMemoryBase,
  2106. iLOD);
  2107. }
  2108. iLOD++;
  2109. iTexLOD++;
  2110. }
  2111. // If both textures are enabled we can't do per-pixel
  2112. // mipmapping because that uses both sets of texcoord
  2113. // DDAs to generate the LOD level. So we must do per-poly
  2114. // mipmapping. Per-poly mipmapping can only be done in
  2115. // hardware on P4 - we use a Delta renderer on P3 when
  2116. // mipmapping with both textures enabled.
  2117. if( bBothTexturesValid )
  2118. {
  2119. DISPDBG(( DBGLVL, "Both textures valid" ));
  2120. // Do per-poly mipmapping in the P4 DeltaFormat unit
  2121. pSoftP3RX->P3RXTextureCoordMode.EnableLOD =
  2122. __PERMEDIA_DISABLE;
  2123. pSoftP3RX->P3RXTextureCoordMode.EnableDY =
  2124. __PERMEDIA_DISABLE;
  2125. pSoftP3RX->P4DeltaFormatControl.PerPolyMipMap =
  2126. __PERMEDIA_ENABLE;
  2127. {
  2128. DWORD d;
  2129. *(float *)&d =
  2130. pContext->MipMapLODBias[TEXSTAGE_0] *
  2131. pTexture->dwPixelPitch *
  2132. pTexture->wHeight;
  2133. SEND_P3_DATA(TextureLODScale, d);
  2134. }
  2135. }
  2136. else
  2137. {
  2138. DISPDBG(( DBGLVL, "Single texture only" ));
  2139. // Do per-pixel mipmapping
  2140. pSoftP3RX->P3RXTextureCoordMode.EnableLOD =
  2141. __PERMEDIA_ENABLE;
  2142. pSoftP3RX->P3RXTextureCoordMode.EnableDY =
  2143. __PERMEDIA_ENABLE;
  2144. pSoftP3RX->P4DeltaFormatControl.PerPolyMipMap =
  2145. __PERMEDIA_DISABLE;
  2146. //@@BEGIN_DDKSPLIT
  2147. #if 0
  2148. // azn this would disable "automatic" mip mapping and we would be using the
  2149. // values supplied by writing into LOD and LOD1 (d3dprim.c) - don't forget!
  2150. pSoftP3RX->P3RXTextureCoordMode.EnableLOD =
  2151. __PERMEDIA_DISABLE;
  2152. pSoftP3RX->P3RXTextureCoordMode.EnableDY =
  2153. __PERMEDIA_DISABLE;
  2154. pSoftP3RX->P4DeltaFormatControl.PerPolyMipMap =
  2155. __PERMEDIA_ENABLE;
  2156. SEND_P3_DATA(TextureLODScale, 0);
  2157. #endif
  2158. //@@END_DDKSPLIT
  2159. {
  2160. float bias;
  2161. DWORD b;
  2162. bias = pContext->TextureStageState[TEXSTAGE_0].m_fVal[D3DTSS_MIPMAPLODBIAS];
  2163. // Convert LOD bias from float to 6.8
  2164. myFtoi( &b, bias * 256.0f );
  2165. SEND_P3_DATA(TextureLODBiasS, b);
  2166. SEND_P3_DATA(TextureLODBiasT, b);
  2167. }
  2168. }
  2169. pSoftP3RX->P3RXTextureIndexMode0.MipMapEnable =
  2170. __PERMEDIA_ENABLE;
  2171. }
  2172. else
  2173. {
  2174. int iTexLOD;
  2175. // No mipmapping.
  2176. DISPDBG(( DBGLVL, "Single texture level" ));
  2177. pSoftP3RX->P3RXTextureCoordMode.EnableLOD = __PERMEDIA_DISABLE;
  2178. pSoftP3RX->P3RXTextureCoordMode.EnableDY = __PERMEDIA_DISABLE;
  2179. pSoftP3RX->P4DeltaFormatControl.PerPolyMipMap =
  2180. __PERMEDIA_DISABLE;
  2181. pSoftP3RX->P3RXTextureIndexMode0.MipMapEnable =
  2182. __PERMEDIA_DISABLE;
  2183. ASSERTDD ( pMipBases->dwTex0MipBase == 0,
  2184. "** __TXT_SetupTexture: "
  2185. "Texture 0 mipmap base is not 0" );
  2186. // Use the maximum level indicated by D3DTSS_MAXMIPLEVEL
  2187. iTexLOD = pMipBases->dwTex0ActMaxLevel;
  2188. iT0MaxLevel = iTexLOD;
  2189. #if DX7_TEXMANAGEMENT
  2190. // If this is a driver managed texture surface, we need
  2191. // to use our privately allocated mem ptr
  2192. if (pTexture->dwCaps2 & DDSCAPS2_TEXTUREMANAGE)
  2193. {
  2194. SEND_P3_DATA_OFFSET(TextureBaseAddr0,
  2195. (DWORD)D3DTMMIPLVL_GETOFFSET(pTexture->MipLevels[iTexLOD], pThisDisplay),
  2196. 0);
  2197. }
  2198. else
  2199. #endif
  2200. {
  2201. SEND_P3_DATA_OFFSET(TextureBaseAddr0,
  2202. pTexture->MipLevels[iTexLOD].dwOffsetFromMemoryBase,
  2203. 0);
  2204. }
  2205. // No mipmapping, but could be combining the caches.
  2206. pSoftP3RX->P3RXTextureMapWidth[0] =
  2207. pTexture->MipLevels[iTexLOD].P3RXTextureMapWidth;
  2208. pSoftP3RX->P3RXTextureMapWidth[1] =
  2209. pTexture->MipLevels[iTexLOD].P3RXTextureMapWidth;
  2210. }
  2211. //@@BEGIN_DDKSPLIT
  2212. // There is only one TextureCoordMode, it is possible that it is
  2213. // not used at all
  2214. //@@END_DDKSPLIT
  2215. // Set maximum dimension of the texture
  2216. pSoftP3RX->P3RXTextureCoordMode.Width = pTexture->MipLevels[iT0MaxLevel].logWidth;
  2217. pSoftP3RX->P3RXTextureCoordMode.Height = pTexture->MipLevels[iT0MaxLevel].logHeight;
  2218. #if DX7_PALETTETEXTURE
  2219. // If it is a palette indexed texture, we simply follow the chain
  2220. // down from the surface to its palette and pull out the LUT values
  2221. // from the PALETTEENTRY's in the palette.
  2222. ASSERTDD ( pFormatSurface != NULL, "** SetupTextureUnitStage: logic error: pFormatSurace is NULL" );
  2223. if (pFormatSurface->DeviceFormat == SURF_CI8)
  2224. {
  2225. WAIT_FIFO(8);
  2226. pSoftP3RX->P3RXLUTMode.Enable = __PERMEDIA_ENABLE;
  2227. pSoftP3RX->P3RXLUTMode.InColorOrder = __PERMEDIA_ENABLE;
  2228. SEND_P3_DATA(LUTAddress, 0);
  2229. SEND_P3_DATA(LUTTransfer, 0);
  2230. SEND_P3_DATA(LUTIndex, 0);
  2231. COPY_P3_DATA(LUTMode, pSoftP3RX->P3RXLUTMode);
  2232. // In this case simply download the 256 entries each time the
  2233. // texture handle changes.
  2234. {
  2235. DWORD dwCount1, dwCount2;
  2236. D3DHAL_DP2UPDATEPALETTE *pPalette; // associated palette
  2237. LPDWORD lpColorTable; // array of palette entries
  2238. pPalette = GetPaletteFromHandle(pContext,
  2239. pTexture->dwPaletteHandle);
  2240. if (pPalette) // If palette can be found
  2241. {
  2242. lpColorTable = (LPDWORD)(pPalette + 1);
  2243. if (pTexture->dwPaletteFlags & DDRAWIPAL_ALPHA)
  2244. {
  2245. for (dwCount1 = 0; dwCount1 < 16; dwCount1++)
  2246. {
  2247. P3_ENSURE_DX_SPACE(17);
  2248. WAIT_FIFO(17);
  2249. P3RX_HOLD_CMD(LUTData, 16);
  2250. for (dwCount2 = 0; dwCount2 < 16; dwCount2++)
  2251. {
  2252. *dmaPtr++ = *lpColorTable++;
  2253. CHECK_FIFO(1);
  2254. }
  2255. }
  2256. }
  2257. else
  2258. {
  2259. for (dwCount1 = 0; dwCount1 < 16; dwCount1++)
  2260. {
  2261. P3_ENSURE_DX_SPACE(17);
  2262. WAIT_FIFO(17);
  2263. P3RX_HOLD_CMD(LUTData, 16);
  2264. for (dwCount2 = 0; dwCount2 < 16; dwCount2++)
  2265. {
  2266. *dmaPtr++ = CHROMA_UPPER_ALPHA(*(DWORD*)lpColorTable++);
  2267. CHECK_FIFO(1);
  2268. }
  2269. }
  2270. }
  2271. }
  2272. else
  2273. {
  2274. DISPDBG((ERRLVL,"Palette handle is missing for CI8 surf!"));
  2275. }
  2276. }
  2277. // Make sure there is room left over for the rest of the routine
  2278. P3_ENSURE_DX_SPACE(2);
  2279. WAIT_FIFO(2);
  2280. SEND_P3_DATA(LUTIndex, 0);
  2281. }
  2282. else
  2283. #endif // DX7_PALETTETEXTURE
  2284. {
  2285. // No LUT.
  2286. P3_ENSURE_DX_SPACE(4);
  2287. WAIT_FIFO(4);
  2288. pSoftP3RX->P3RXLUTMode.Enable = __PERMEDIA_DISABLE;
  2289. SEND_P3_DATA(LUTTransfer, __PERMEDIA_DISABLE);
  2290. COPY_P3_DATA(LUTMode, pSoftP3RX->P3RXLUTMode)
  2291. }
  2292. #if DX8_3DTEXTURES
  2293. P3_ENSURE_DX_SPACE(4);
  2294. WAIT_FIFO(4);
  2295. if (pTexture->b3DTexture)
  2296. {
  2297. //
  2298. // Set size of each 2D texture slice in texel size to TextureMapSize.
  2299. //
  2300. SEND_P3_DATA(TextureMapSize, pTexture->dwSliceInTexel);
  2301. }
  2302. else
  2303. {
  2304. SEND_P3_DATA(TextureMapSize, 0);
  2305. }
  2306. #endif // DX8_3DTEXTURES
  2307. P3_DMA_COMMIT_BUFFER();
  2308. __TXT_ConsiderSrcChromaKey( pContext, pTexture, 0 );
  2309. P3_DMA_GET_BUFFER();
  2310. // Setup TextureReadMode
  2311. pSoftP3RX->P3RXTextureReadMode0.MapBaseLevel =
  2312. pMipBases->dwTex0MipBase;
  2313. pSoftP3RX->P3RXTextureReadMode0.MapMaxLevel =
  2314. pMipBases->dwTex0MipMax;
  2315. pSoftP3RX->P3RXTextureReadMode0.Width = pTexture->MipLevels[iT0MaxLevel].logWidth;
  2316. pSoftP3RX->P3RXTextureReadMode0.Height = pTexture->MipLevels[iT0MaxLevel].logHeight;
  2317. pSoftP3RX->P3RXTextureReadMode0.TexelSize = pTexture->dwPixelSize;
  2318. pSoftP3RX->P3RXTextureReadMode0.LogicalTexture =
  2319. __PERMEDIA_DISABLE;
  2320. // Enable stage 0
  2321. pSoftP3RX->P3RXTextureIndexMode0.Enable = __PERMEDIA_ENABLE;
  2322. pSoftP3RX->P3RXTextureReadMode0.Enable = __PERMEDIA_ENABLE;
  2323. // Never set CombineCaches - chip bug
  2324. pSoftP3RX->P3RXTextureReadMode0.CombineCaches = __PERMEDIA_DISABLE;
  2325. pSoftP3RX->P3RXTextureFilterMode.CombineCaches = __PERMEDIA_DISABLE;
  2326. // Always copy TRM0 to TRM1 in case we are combining the caches
  2327. pSoftP3RX->P3RXTextureReadMode1 = pSoftP3RX->P3RXTextureReadMode0;
  2328. // Enable the texture index unit
  2329. // (this is a bit like the the texture read)
  2330. pSoftP3RX->P3RXTextureIndexMode0.Width = pTexture->MipLevels[iT0MaxLevel].logWidth;
  2331. pSoftP3RX->P3RXTextureIndexMode0.Height = pTexture->MipLevels[iT0MaxLevel].logHeight;
  2332. // Set both formats to be equal for texture 0 - this will be correct
  2333. // for single-texture per-pixel mipmap or non-mipmapped with a
  2334. // combined cache. If the second texture is valid it's setup below
  2335. // will set Format1 appropriately.
  2336. ASSERTDD ( pFormatSurface != NULL,
  2337. "** SetupTextureUnitStage: logic error: "
  2338. "pFormatSurace is NULL" );
  2339. pSoftP3RX->P3RXTextureFilterMode.Format0 =
  2340. pFormatSurface->FilterFormat;
  2341. pSoftP3RX->P3RXTextureFilterMode.Format1 =
  2342. pFormatSurface->FilterFormat;
  2343. #if DX8_3DTEXTURES
  2344. if (pTexture->b3DTexture)
  2345. {
  2346. //
  2347. // Enable 3D Texture registers.
  2348. //
  2349. pSoftP3RX->P3RX_P3DeltaMode.Texture3DEnable = __PERMEDIA_ENABLE;
  2350. pSoftP3RX->P3RXTextureReadMode0.Texture3D = __PERMEDIA_ENABLE;
  2351. pSoftP3RX->P3RXTextureIndexMode0.Texture3DEnable =
  2352. __PERMEDIA_ENABLE;
  2353. //
  2354. // ReadMode1 and IndexMode1 should have same data as 0.
  2355. //
  2356. pSoftP3RX->P3RXTextureReadMode1 = pSoftP3RX->P3RXTextureReadMode0;
  2357. pSoftP3RX->P3RXTextureIndexMode1 = pSoftP3RX->P3RXTextureIndexMode0;
  2358. //
  2359. // And put logDepth into IndexMode1.Width.
  2360. //
  2361. pSoftP3RX->P3RXTextureIndexMode1.Width = pTexture->logDepth;
  2362. }
  2363. else
  2364. {
  2365. pSoftP3RX->P3RXTextureReadMode0.Texture3D = __PERMEDIA_DISABLE;
  2366. pSoftP3RX->P3RXTextureIndexMode0.Texture3DEnable =
  2367. __PERMEDIA_DISABLE;
  2368. }
  2369. #endif // DX8_3DTEXTURES
  2370. break;
  2371. }
  2372. // Texture Stage 1
  2373. case 1:
  2374. {
  2375. pSoftP3RX->P3RXTextureFilterMode.ForceAlphaToOne1 =
  2376. pFormatSurface->bAlpha ?
  2377. __PERMEDIA_DISABLE :
  2378. __PERMEDIA_ENABLE;
  2379. // D3D UV Wrapping
  2380. if (pContext->RenderStates[D3DRENDERSTATE_WRAP0+iTSStage] &
  2381. D3DWRAP_U)
  2382. {
  2383. pSoftP3RX->P4DeltaFormatControl.WrapS1 = 1;
  2384. }
  2385. else
  2386. {
  2387. pSoftP3RX->P4DeltaFormatControl.WrapS1 = 0;
  2388. }
  2389. if (pContext->RenderStates[D3DRENDERSTATE_WRAP0+iTSStage] &
  2390. D3DWRAP_V)
  2391. {
  2392. pSoftP3RX->P4DeltaFormatControl.WrapT1 = 1;
  2393. }
  2394. else
  2395. {
  2396. pSoftP3RX->P4DeltaFormatControl.WrapT1 = 0;
  2397. }
  2398. // U Addressing
  2399. switch (TSSTATE ( iTSStage, D3DTSS_ADDRESSU ))
  2400. {
  2401. case D3DTADDRESS_CLAMP:
  2402. pSoftP3RX->P3RXTextureCoordMode.WrapS1 =
  2403. __GLINT_TEXADDRESS_WRAP_CLAMP;
  2404. pSoftP3RX->P3RXTextureIndexMode1.WrapU =
  2405. P3RX_TEXINDEXMODE_WRAP_CLAMPEDGE;
  2406. break;
  2407. case D3DTADDRESS_WRAP:
  2408. pSoftP3RX->P3RXTextureCoordMode.WrapS1 =
  2409. __GLINT_TEXADDRESS_WRAP_REPEAT;
  2410. pSoftP3RX->P3RXTextureIndexMode1.WrapU =
  2411. P3RX_TEXINDEXMODE_WRAP_REPEAT;
  2412. break;
  2413. case D3DTADDRESS_MIRROR:
  2414. pSoftP3RX->P3RXTextureCoordMode.WrapS1 =
  2415. __GLINT_TEXADDRESS_WRAP_MIRROR;
  2416. pSoftP3RX->P3RXTextureIndexMode1.WrapU =
  2417. P3RX_TEXINDEXMODE_WRAP_MIRROR;
  2418. break;
  2419. default:
  2420. DISPDBG((ERRLVL,"ERROR: Unknown ADDRESSU!"));
  2421. SET_BLEND_ERROR ( pContext, BSF_UNDEFINED_STATE );
  2422. break;
  2423. }
  2424. // V Addressing
  2425. switch (TSSTATE ( iTSStage, D3DTSS_ADDRESSV ))
  2426. {
  2427. case D3DTADDRESS_CLAMP:
  2428. pSoftP3RX->P3RXTextureCoordMode.WrapT1 =
  2429. __GLINT_TEXADDRESS_WRAP_CLAMP;
  2430. pSoftP3RX->P3RXTextureIndexMode1.WrapV =
  2431. P3RX_TEXINDEXMODE_WRAP_CLAMPEDGE;
  2432. break;
  2433. case D3DTADDRESS_WRAP:
  2434. pSoftP3RX->P3RXTextureCoordMode.WrapT1 =
  2435. __GLINT_TEXADDRESS_WRAP_REPEAT;
  2436. pSoftP3RX->P3RXTextureIndexMode1.WrapV =
  2437. P3RX_TEXINDEXMODE_WRAP_REPEAT;
  2438. break;
  2439. case D3DTADDRESS_MIRROR:
  2440. pSoftP3RX->P3RXTextureCoordMode.WrapT1 =
  2441. __GLINT_TEXADDRESS_WRAP_MIRROR;
  2442. pSoftP3RX->P3RXTextureIndexMode1.WrapV =
  2443. P3RX_TEXINDEXMODE_WRAP_MIRROR;
  2444. break;
  2445. default:
  2446. DISPDBG((ERRLVL,"ERROR: Unknown ADDRESSV!"));
  2447. SET_BLEND_ERROR ( pContext, BSF_UNDEFINED_STATE );
  2448. break;
  2449. }
  2450. if(( TSSTATE( iTSStage, D3DTSS_ADDRESSU ) == D3DTADDRESS_CLAMP ) ||
  2451. ( TSSTATE( iTSStage, D3DTSS_ADDRESSV ) == D3DTADDRESS_CLAMP ))
  2452. {
  2453. if ((TSSTATE( iTSStage, D3DTSS_ADDRESSU ) != D3DTADDRESS_CLAMP) ||
  2454. (TSSTATE( iTSStage, D3DTSS_ADDRESSV ) != D3DTADDRESS_CLAMP))
  2455. {
  2456. DISPDBG((ERRLVL,"Warning: One texture coord clamped, but not "
  2457. "the other - can't appply TextureShift"));
  2458. }
  2459. pSoftP3RX->P4DeltaFormatControl.TextureShift1 =
  2460. __PERMEDIA_DISABLE;
  2461. }
  2462. else
  2463. {
  2464. pSoftP3RX->P4DeltaFormatControl.TextureShift1 =
  2465. __PERMEDIA_ENABLE;
  2466. }
  2467. ASSERTDD ( pFormatSurface != NULL,
  2468. "** SetupTextureUnitStage: logic error: "
  2469. "pFormatSurace is NULL" );
  2470. switch (pFormatSurface->DeviceFormat)
  2471. {
  2472. case SURF_CI8:
  2473. pSoftP3RX->P3RXTextureReadMode1.TextureType =
  2474. P3RX_TEXREADMODE_TEXTURETYPE_8BITINDEXED;
  2475. break;
  2476. case SURF_YUV422:
  2477. pSoftP3RX->P3RXTextureReadMode1.TextureType =
  2478. P3RX_TEXREADMODE_TEXTURETYPE_422_YVYU;
  2479. break;
  2480. default:
  2481. pSoftP3RX->P3RXTextureReadMode1.TextureType =
  2482. P3RX_TEXREADMODE_TEXTURETYPE_NORMAL;
  2483. break;
  2484. }
  2485. // MAG Filter
  2486. switch(TSSTATE ( iTSStage, D3DTSS_MAGFILTER ))
  2487. {
  2488. case D3DTFG_POINT:
  2489. pSoftP3RX->P3RXTextureIndexMode1.MagnificationFilter =
  2490. __GLINT_TEXTUREREAD_FILTER_NEAREST;
  2491. break;
  2492. case D3DTFG_LINEAR:
  2493. pSoftP3RX->P3RXTextureIndexMode1.MagnificationFilter =
  2494. __GLINT_TEXTUREREAD_FILTER_LINEAR;
  2495. break;
  2496. case D3DTFG_FLATCUBIC:
  2497. case D3DTFG_GAUSSIANCUBIC:
  2498. case D3DTFG_ANISOTROPIC:
  2499. DISPDBG((ERRLVL,"ERROR: Unsupported MAGFILTER!"));
  2500. SET_BLEND_ERROR ( pContext, BSF_UNSUPPORTED_FILTER );
  2501. break;
  2502. default:
  2503. DISPDBG((ERRLVL,"ERROR: Unknown MAGFILTER!"));
  2504. SET_BLEND_ERROR ( pContext, BSF_UNDEFINED_FILTER );
  2505. break;
  2506. }
  2507. switch(TSSTATE ( iTSStage, D3DTSS_MINFILTER ))
  2508. {
  2509. case D3DTFN_POINT:
  2510. pSoftP3RX->P3RXTextureIndexMode1.MinificationFilter =
  2511. __GLINT_TEXTUREREAD_FILTER_NEAREST;
  2512. break;
  2513. case D3DTFN_LINEAR:
  2514. pSoftP3RX->P3RXTextureIndexMode1.MinificationFilter =
  2515. __GLINT_TEXTUREREAD_FILTER_LINEAR;
  2516. break;
  2517. case D3DTFN_ANISOTROPIC:
  2518. DISPDBG((ERRLVL,"ERROR: Unsupported MINFILTER!"));
  2519. SET_BLEND_ERROR ( pContext, BSF_UNSUPPORTED_FILTER );
  2520. break;
  2521. default:
  2522. DISPDBG((ERRLVL,"ERROR: Unknown MINFILTER!"));
  2523. SET_BLEND_ERROR ( pContext, BSF_UNDEFINED_FILTER );
  2524. break;
  2525. }
  2526. switch(TSSTATE ( iTSStage, D3DTSS_MIPFILTER ))
  2527. {
  2528. case D3DTFP_NONE:
  2529. // No need to set the minification filter
  2530. // it was done above
  2531. break;
  2532. case D3DTFP_LINEAR:
  2533. case D3DTFP_POINT:
  2534. if( bBothTexturesValid )
  2535. {
  2536. if ( TSSTATE ( iTSStage, D3DTSS_MIPFILTER ) ==
  2537. D3DTFP_LINEAR )
  2538. {
  2539. // Can't do trilinear with both textures
  2540. // - fall back to per-poly.
  2541. SET_BLEND_ERROR ( pContext, BS_INVALID_FILTER );
  2542. }
  2543. // We can only do per-poly mipmapping while
  2544. // multi-texturing, so don't enable
  2545. //inter-map filtering.
  2546. switch(TSSTATE ( iTSStage, D3DTSS_MINFILTER ))
  2547. {
  2548. case D3DTFN_POINT:
  2549. // Point Min, Point Mip
  2550. pSoftP3RX->P3RXTextureIndexMode1.MinificationFilter =
  2551. __GLINT_TEXTUREREAD_FILTER_NEARMIPNEAREST;
  2552. break;
  2553. case D3DTFN_LINEAR:
  2554. // Linear Min, Point Mip
  2555. pSoftP3RX->P3RXTextureIndexMode1.MinificationFilter =
  2556. __GLINT_TEXTUREREAD_FILTER_LINEARMIPNEAREST;
  2557. break;
  2558. }
  2559. }
  2560. else
  2561. {
  2562. DISPDBG((ERRLVL,"** Setting up the second stage, but "
  2563. "only one texture is valid"));
  2564. }
  2565. break;
  2566. default:
  2567. DISPDBG((ERRLVL,"ERROR: Invalid Mip filter!"));
  2568. SET_BLEND_ERROR ( pContext, BSF_UNDEFINED_FILTER );
  2569. break;
  2570. }
  2571. // MipMapping
  2572. // If the app chooses to have two mip-mapped textures or a
  2573. // single mip-mapped texture in stage 1 they only get
  2574. // per-poly mipmapping.
  2575. if( (TSSTATE ( iTSStage, D3DTSS_MIPFILTER ) != D3DTFP_NONE) &&
  2576. pTexture->bMipMap )
  2577. {
  2578. int iLOD, iTexLOD;
  2579. // Load the mipmap levels for texture 1
  2580. // Mip level from pMipBases->dwTex1ActMaxLevel to
  2581. // pTexture->iMipLevels will be mapped to base address slot
  2582. // from pMipBases->dwTex1Mipbase to dwTex1MipMax
  2583. iLOD = pMipBases->dwTex1MipBase;
  2584. iTexLOD = pMipBases->dwTex1ActMaxLevel;
  2585. iT1MaxLevel = iTexLOD;
  2586. P3_ENSURE_DX_SPACE(32);
  2587. WAIT_FIFO(32);
  2588. while(( iTexLOD < pTexture->iMipLevels ) &&
  2589. ( iLOD <= (int)pMipBases->dwTex1MipMax ))
  2590. {
  2591. DISPDBG((DBGLVL, " Setting Texture Base Address %d to 0x%x",
  2592. iLOD,
  2593. pTexture->MipLevels[iTexLOD].dwOffsetFromMemoryBase));
  2594. pSoftP3RX->P3RXTextureMapWidth[iLOD] =
  2595. pTexture->MipLevels[iTexLOD].P3RXTextureMapWidth;
  2596. #if DX7_TEXMANAGEMENT
  2597. // If this is a driver managed texture surface, we need
  2598. // to use our privately allocated mem ptr
  2599. if (pTexture->dwCaps2 & DDSCAPS2_TEXTUREMANAGE)
  2600. {
  2601. SEND_P3_DATA_OFFSET(TextureBaseAddr0,
  2602. (DWORD)D3DTMMIPLVL_GETOFFSET(pTexture->MipLevels[iTexLOD], pThisDisplay),
  2603. iLOD);
  2604. }
  2605. else
  2606. #endif
  2607. {
  2608. SEND_P3_DATA_OFFSET(TextureBaseAddr0,
  2609. pTexture->MipLevels[iTexLOD].dwOffsetFromMemoryBase,
  2610. iLOD);
  2611. }
  2612. iLOD++;
  2613. iTexLOD++;
  2614. }
  2615. pSoftP3RX->P3RXTextureCoordMode.EnableLOD = __PERMEDIA_DISABLE;
  2616. pSoftP3RX->P3RXTextureCoordMode.EnableDY = __PERMEDIA_DISABLE;
  2617. pSoftP3RX->P4DeltaFormatControl.PerPolyMipMap1 =
  2618. __PERMEDIA_ENABLE;
  2619. pSoftP3RX->P3RXTextureIndexMode1.MipMapEnable =
  2620. __PERMEDIA_ENABLE;
  2621. P3_ENSURE_DX_SPACE(2);
  2622. WAIT_FIFO(2);
  2623. {
  2624. DWORD d;
  2625. *(float *)&d =
  2626. pContext->MipMapLODBias[TEXSTAGE_1] *
  2627. pTexture->dwPixelPitch *
  2628. pTexture->wHeight;
  2629. SEND_P3_DATA(TextureLODScale1, d);
  2630. }
  2631. }
  2632. else
  2633. {
  2634. int iTexLOD;
  2635. // Use the maximum level indicated by D3DTSS_MAXMIPLEVEL
  2636. iTexLOD = pMipBases->dwTex0ActMaxLevel;
  2637. iT1MaxLevel = iTexLOD;
  2638. pSoftP3RX->P3RXTextureCoordMode.EnableLOD = __PERMEDIA_DISABLE;
  2639. pSoftP3RX->P3RXTextureCoordMode.EnableDY = __PERMEDIA_DISABLE;
  2640. pSoftP3RX->P4DeltaFormatControl.PerPolyMipMap1 =
  2641. __PERMEDIA_DISABLE;
  2642. pSoftP3RX->P3RXTextureIndexMode1.MipMapEnable =
  2643. __PERMEDIA_DISABLE;
  2644. P3_ENSURE_DX_SPACE(2);
  2645. WAIT_FIFO(2);
  2646. #if DX7_TEXMANAGEMENT
  2647. // If this is a driver managed texture surface, we need
  2648. // to use our privately allocated mem ptr
  2649. if (pTexture->dwCaps2 & DDSCAPS2_TEXTUREMANAGE)
  2650. {
  2651. SEND_P3_DATA_OFFSET(TextureBaseAddr0,
  2652. (DWORD)D3DTMMIPLVL_GETOFFSET(pTexture->MipLevels[iTexLOD], pThisDisplay),
  2653. pMipBases->dwTex1MipBase);
  2654. }
  2655. else
  2656. #endif
  2657. {
  2658. SEND_P3_DATA_OFFSET(TextureBaseAddr0,
  2659. pTexture->MipLevels[iTexLOD].dwOffsetFromMemoryBase,
  2660. pMipBases->dwTex1MipBase);
  2661. }
  2662. // No mipmapping.
  2663. pSoftP3RX->P3RXTextureMapWidth[pMipBases->dwTex1MipBase] =
  2664. pTexture->MipLevels[iTexLOD].P3RXTextureMapWidth;
  2665. }
  2666. ASSERTDD ( pFormatSurface != NULL,
  2667. "** SetupTextureUnitStage: logic error: "
  2668. "pFormatSurace is NULL" );
  2669. if (pFormatSurface->DeviceFormat == SURF_CI8)
  2670. {
  2671. // In the future, this will work as long as texture 0 isn't
  2672. // palettised, or if they share the palette.
  2673. // But that needs some restructuring - the whole LUT setup
  2674. // should be in a single bit of code in _D3DChangeTextureP3RX,
  2675. // since it is a shared resource.
  2676. DISPDBG((ERRLVL,"** SetupTextureUnitStage: allow second texture "
  2677. "to use LUTs"));
  2678. // For now, fail.
  2679. SET_BLEND_ERROR ( pContext, BSF_TOO_MANY_PALETTES );
  2680. }
  2681. P3_DMA_COMMIT_BUFFER();
  2682. __TXT_ConsiderSrcChromaKey( pContext, pTexture, 1 );
  2683. P3_DMA_GET_BUFFER();
  2684. // Setup TextureReadMode
  2685. pSoftP3RX->P3RXTextureReadMode1.MapBaseLevel =
  2686. pMipBases->dwTex1MipBase;
  2687. pSoftP3RX->P3RXTextureReadMode1.MapMaxLevel =
  2688. pMipBases->dwTex1MipMax;
  2689. pSoftP3RX->P3RXTextureReadMode1.Width = pTexture->MipLevels[iT1MaxLevel].logWidth;
  2690. pSoftP3RX->P3RXTextureReadMode1.Height = pTexture->MipLevels[iT1MaxLevel].logHeight;
  2691. pSoftP3RX->P3RXTextureReadMode1.TexelSize = pTexture->dwPixelSize;
  2692. pSoftP3RX->P3RXTextureReadMode1.LogicalTexture =
  2693. __PERMEDIA_DISABLE;
  2694. // Enable the texture index unit (this is a bit like the
  2695. // the texture read)
  2696. pSoftP3RX->P3RXTextureIndexMode1.Width = pTexture->MipLevels[iT1MaxLevel].logWidth;
  2697. pSoftP3RX->P3RXTextureIndexMode1.Height = pTexture->MipLevels[iT1MaxLevel].logHeight;
  2698. ASSERTDD ( pFormatSurface != NULL,
  2699. "** SetupTextureUnitStage: logic error: "
  2700. "pFormatSurace is NULL" );
  2701. pSoftP3RX->P3RXTextureFilterMode.Format1 =
  2702. pFormatSurface->FilterFormat;
  2703. // Enable stage 1
  2704. pSoftP3RX->P3RXTextureIndexMode1.Enable = __PERMEDIA_ENABLE;
  2705. pSoftP3RX->P3RXTextureReadMode1.Enable = __PERMEDIA_ENABLE;
  2706. #if DX7_PALETTETEXTURE
  2707. #if 0
  2708. // D3DValidateDeviceP3() will return error code for this case
  2709. ASSERTDD((pFormatSurface->DeviceFormat != SURF_CI8 &&
  2710. pFormatSurface->DeviceFormat != SURF_CI4),
  2711. "Texture surface can't be palettized when using a "
  2712. "second map!");
  2713. #endif
  2714. #endif
  2715. break;
  2716. }
  2717. }
  2718. P3_DMA_COMMIT_BUFFER();
  2719. return TRUE;
  2720. } // __TXT_SetupTexture
  2721. //-----------------------------------------------------------------------------
  2722. //
  2723. // __bD3DTexturesMatch
  2724. //
  2725. //
  2726. // A function to compare the two textures in two D3D stages, and determine
  2727. // if they could be satisfied by the same on-chip texture.
  2728. //
  2729. // int iStage1 D3D stage number of first texture.
  2730. // int iStage2 D3D stage number of second texture.
  2731. // *pContext The context.
  2732. //
  2733. // result: TRUE if the textures match, FALSE if they don't.
  2734. //
  2735. // An ASSERT is triggered if either stage is not using a texture. In the
  2736. // release build, the result will be TRUE, meaning that we could pack both
  2737. // textures stages requirements into one texture (because one or both do
  2738. // not use a texture).
  2739. //
  2740. //-----------------------------------------------------------------------------
  2741. BOOL
  2742. __bD3DTexturesMatch (
  2743. int iStage1,
  2744. int iStage2,
  2745. P3_D3DCONTEXT* pContext )
  2746. {
  2747. ASSERTDD ( iStage1 != iStage2,
  2748. "** __bD3DTexturesMatch: both stages are the same "
  2749. "- pointless comparison!" );
  2750. if ( TSSTATE ( iStage1, D3DTSS_TEXTUREMAP ) == 0 )
  2751. {
  2752. DISPDBG((ERRLVL,"** __bD3DTexturesMatch: first considered stage's "
  2753. "texture is NULL"));
  2754. return ( TRUE );
  2755. }
  2756. else if ( TSSTATE ( iStage2, D3DTSS_TEXTUREMAP ) == 0 )
  2757. {
  2758. DISPDBG((ERRLVL,"** __bD3DTexturesMatch: second considered stage's "
  2759. "texture is NULL"));
  2760. return ( TRUE );
  2761. }
  2762. else
  2763. {
  2764. #define CHECK_EQUALITY(name) ( TSSTATE ( iStage1, name ) == TSSTATE ( iStage2, name ) )
  2765. if (CHECK_EQUALITY ( D3DTSS_TEXTUREMAP ) &&
  2766. CHECK_EQUALITY ( D3DTSS_TEXCOORDINDEX ) )
  2767. {
  2768. // Yes, the textures have the same handle and coord set. Do
  2769. // some further checks.
  2770. // If the pointers are different, or the texcoord sets are
  2771. // different (for bumpmapping), this is a common occurrance,
  2772. // and need not be flagged. However, if they are the same,
  2773. // but a filter mode or something like that is different,
  2774. // it is likely to be an app bug, so flag it.
  2775. if (
  2776. // Should not need to check ADDRESS
  2777. // - should have been mirrored to ADDRESS[UV].
  2778. CHECK_EQUALITY ( D3DTSS_ADDRESSU ) &&
  2779. CHECK_EQUALITY ( D3DTSS_ADDRESSV ) &&
  2780. CHECK_EQUALITY ( D3DTSS_MAGFILTER ) &&
  2781. CHECK_EQUALITY ( D3DTSS_MINFILTER ) &&
  2782. CHECK_EQUALITY ( D3DTSS_MIPFILTER ) )
  2783. // I should also check all the other variables like
  2784. // MIPMAPLODBIAS, but they rely on mipmapping being
  2785. // enabled, etc, so it's more of a hassle. If an app
  2786. // really does manage to be this perverse, it's doing well!
  2787. {
  2788. // Looks good.
  2789. return ( TRUE );
  2790. }
  2791. else
  2792. {
  2793. // Well, the texcoords agree and the handle agree, but the
  2794. // others don't. I bet this is an app bug - you are unlikely
  2795. // to do this deliberately.
  2796. _D3DDisplayWholeTSSPipe ( pContext, WRNLVL );
  2797. DISPDBG((ERRLVL,"** __bD3DTexturesMatch: textures agree in "
  2798. "handle and texcoord, but not other things - "
  2799. "likely app bug."));
  2800. return ( FALSE );
  2801. }
  2802. }
  2803. else
  2804. {
  2805. // No, different textures.
  2806. return ( FALSE );
  2807. }
  2808. #undef CHECK_EQUALITY
  2809. }
  2810. return TRUE;
  2811. } // __bD3DTexturesMatch
  2812. //-----------------------------------------------------------------------------
  2813. //
  2814. // _D3DChangeTextureP3RX
  2815. //
  2816. // This function does whole setup of necessary texturing state according to
  2817. // the current renderestates and texture stage states. Disables texturing
  2818. // accordingly if this is needed.
  2819. //
  2820. //-----------------------------------------------------------------------------
  2821. void
  2822. _D3DChangeTextureP3RX(
  2823. P3_D3DCONTEXT* pContext)
  2824. {
  2825. P3_SURF_INTERNAL* pTexture0 = NULL;
  2826. P3_SURF_INTERNAL* pTexture1 = NULL;
  2827. P3_THUNKEDDATA * pThisDisplay = pContext->pThisDisplay;
  2828. P3_SOFTWARECOPY* pSoftP3RX = &pContext->SoftCopyGlint;
  2829. P3_MIP_BASES mipBases;
  2830. DWORD* pFlags = &pContext->Flags;
  2831. INT i, iLastChipStage;
  2832. DWORD dwT0MipLevels,
  2833. dwT1MipLevels,
  2834. dwTexAppTfactor,
  2835. dwTexComp0Tfactor,
  2836. dwTexComp1Tfactor;
  2837. BOOL bBothTexturesValid,
  2838. bProcessChipStage0,
  2839. bProcessChipStage1,
  2840. bProcessChipStage2,
  2841. bAlphaBlendDouble;
  2842. P3_DMA_DEFS();
  2843. DBG_ENTRY(_D3DChangeTextureP3RX);
  2844. pContext->iTexStage[0] = -1;
  2845. pContext->iTexStage[1] = -1;
  2846. // This is checked against the current state at the end of the routine.
  2847. bAlphaBlendDouble = FALSE;
  2848. // Verify if texturing should be disabled
  2849. if ( ( TSSTATE ( TEXSTAGE_0, D3DTSS_COLOROP ) == D3DTOP_DISABLE ) ||
  2850. ( ( TSSTATE ( TEXSTAGE_0, D3DTSS_TEXTUREMAP ) == 0 ) &&
  2851. ( TSSTATE ( TEXSTAGE_1, D3DTSS_COLOROP ) == D3DTOP_DISABLE ) &&
  2852. ( ( ( TSSTATESELECT ( TEXSTAGE_0, D3DTSS_COLORARG1 ) == D3DTA_TEXTURE ) &&
  2853. ( TSSTATE ( TEXSTAGE_0, D3DTSS_COLOROP ) != D3DTOP_SELECTARG2 ) ) ||
  2854. ( ( TSSTATESELECT ( TEXSTAGE_0, D3DTSS_COLORARG2 ) == D3DTA_TEXTURE ) &&
  2855. ( TSSTATE ( TEXSTAGE_0, D3DTSS_COLOROP ) != D3DTOP_SELECTARG1 ) ) )
  2856. ) )
  2857. {
  2858. // Stage 0 is disabled, so they just want the diffuse colour.
  2859. // Or, the texture handle is 0 , stage 1 is D3DTOP_DISABLE and in stage
  2860. // 0 we are selecting an arg that is not a D3DTA_TEXTURE
  2861. DISPDBG((DBGLVL, "All composite units disabled - setting diffuse colour"));
  2862. P3_DMA_GET_BUFFER_ENTRIES(20);
  2863. // Turn off texture address generation
  2864. pSoftP3RX->P3RXTextureCoordMode.Enable = __PERMEDIA_DISABLE;
  2865. COPY_P3_DATA(TextureCoordMode, pSoftP3RX->P3RXTextureCoordMode);
  2866. // Turn off texture reads
  2867. pSoftP3RX->P3RXTextureReadMode0.Enable = __PERMEDIA_DISABLE;
  2868. pSoftP3RX->P3RXTextureReadMode1.Enable = __PERMEDIA_DISABLE;
  2869. COPY_P3_DATA(TextureReadMode0, pSoftP3RX->P3RXTextureReadMode0);
  2870. COPY_P3_DATA(TextureReadMode1, pSoftP3RX->P3RXTextureReadMode1);
  2871. pSoftP3RX->P3RXTextureIndexMode0.Enable = __PERMEDIA_DISABLE;
  2872. pSoftP3RX->P3RXTextureIndexMode1.Enable = __PERMEDIA_DISABLE;
  2873. COPY_P3_DATA(TextureIndexMode0, pSoftP3RX->P3RXTextureIndexMode0);
  2874. COPY_P3_DATA(TextureIndexMode1, pSoftP3RX->P3RXTextureIndexMode1);
  2875. // Turn off the texture filter mode unit
  2876. pSoftP3RX->P3RXTextureFilterMode.Enable = __PERMEDIA_DISABLE;
  2877. COPY_P3_DATA(TextureFilterMode, pSoftP3RX->P3RXTextureFilterMode);
  2878. // Turn off texture color mode unit
  2879. pSoftP3RX->P3RXTextureApplicationMode.Enable = __PERMEDIA_DISABLE;
  2880. COPY_P3_DATA(TextureApplicationMode,
  2881. pSoftP3RX->P3RXTextureApplicationMode);
  2882. // Not compositing
  2883. SEND_P3_DATA(TextureCompositeMode, __PERMEDIA_DISABLE);
  2884. *pFlags &= ~SURFACE_TEXTURING;
  2885. pSoftP3RX->P3RXLUTMode.Enable = __PERMEDIA_DISABLE;
  2886. COPY_P3_DATA(LUTMode, pSoftP3RX->P3RXLUTMode);
  2887. // Specular texture can be enabled without texturing on
  2888. COPY_P3_DATA(DeltaMode, pSoftP3RX->P3RX_P3DeltaMode);
  2889. P3_DMA_COMMIT_BUFFER();
  2890. // Turn off texturing in the render command
  2891. RENDER_TEXTURE_DISABLE(pContext->RenderCommand);
  2892. pContext->bTextureValid = TRUE;
  2893. pContext->pCurrentTexture[0] = NULL;
  2894. pContext->pCurrentTexture[1] = NULL;
  2895. // Track just for debugging purpouses
  2896. pContext->bTexDisabled = TRUE;
  2897. bAlphaBlendDouble = FALSE;
  2898. if ( bAlphaBlendDouble != pContext->bAlphaBlendMustDoubleSourceColour )
  2899. {
  2900. pContext->bAlphaBlendMustDoubleSourceColour = bAlphaBlendDouble;
  2901. DIRTY_ALPHABLEND(pContext);
  2902. }
  2903. DBG_EXIT(_D3DChangeTextureP3RX,1);
  2904. return;
  2905. }
  2906. if ( TSSTATE ( TEXSTAGE_0, D3DTSS_TEXTUREMAP ) == 0 )
  2907. if ( ( ( TSSTATE ( TEXSTAGE_0, D3DTSS_COLORARG1 ) == D3DTA_TFACTOR ) &&
  2908. ( TSSTATE ( TEXSTAGE_0, D3DTSS_COLOROP ) == D3DTOP_SELECTARG1 ) ) ||
  2909. ( ( TSSTATE ( TEXSTAGE_0, D3DTSS_COLORARG2 ) == D3DTA_TFACTOR ) &&
  2910. ( TSSTATE ( TEXSTAGE_0, D3DTSS_COLOROP ) == D3DTOP_SELECTARG2 ) ) )
  2911. {
  2912. // This is an unusual way to set up the diffuse color : take
  2913. // it from the the D3DTA_TFACTOR. But some apps use it.
  2914. // we need to treat it separately for the Perm3 setup because
  2915. // it might not be binded with any texture
  2916. DISPDBG((DBGLVL, "Diffuse color comes from D3DTA_TFACTOR"));
  2917. P3_DMA_GET_BUFFER_ENTRIES(30);
  2918. // Turn off texture address generation
  2919. pSoftP3RX->P3RXTextureCoordMode.Enable = __PERMEDIA_DISABLE;
  2920. COPY_P3_DATA(TextureCoordMode, pSoftP3RX->P3RXTextureCoordMode);
  2921. // Turn off texture reads
  2922. pSoftP3RX->P3RXTextureReadMode0.Enable = __PERMEDIA_DISABLE;
  2923. pSoftP3RX->P3RXTextureReadMode1.Enable = __PERMEDIA_DISABLE;
  2924. COPY_P3_DATA(TextureReadMode0, pSoftP3RX->P3RXTextureReadMode0);
  2925. COPY_P3_DATA(TextureReadMode1, pSoftP3RX->P3RXTextureReadMode1);
  2926. pSoftP3RX->P3RXTextureIndexMode0.Enable = __PERMEDIA_DISABLE;
  2927. pSoftP3RX->P3RXTextureIndexMode1.Enable = __PERMEDIA_DISABLE;
  2928. COPY_P3_DATA(TextureIndexMode0, pSoftP3RX->P3RXTextureIndexMode0);
  2929. COPY_P3_DATA(TextureIndexMode1, pSoftP3RX->P3RXTextureIndexMode1);
  2930. // Turn off the texture filter mode unit
  2931. pSoftP3RX->P3RXTextureFilterMode.Enable = __PERMEDIA_DISABLE;
  2932. COPY_P3_DATA(TextureFilterMode, pSoftP3RX->P3RXTextureFilterMode);
  2933. // Setup texture color mode unit
  2934. pSoftP3RX->P3RXTextureApplicationMode.Enable = __PERMEDIA_ENABLE;
  2935. pSoftP3RX->P3RXTextureApplicationMode.ColorA = P3RX_TEXAPP_A_KC;
  2936. pSoftP3RX->P3RXTextureApplicationMode.ColorOperation = P3RX_TEXAPP_OPERATION_PASS_A;
  2937. pSoftP3RX->P3RXTextureApplicationMode.AlphaA = P3RX_TEXAPP_A_KA;
  2938. pSoftP3RX->P3RXTextureApplicationMode.AlphaOperation = P3RX_TEXAPP_OPERATION_PASS_A;
  2939. COPY_P3_DATA(TextureApplicationMode,
  2940. pSoftP3RX->P3RXTextureApplicationMode);
  2941. // Setup compositing
  2942. pSoftP3RX->P3RXTextureCompositeAlphaMode0.Enable = __PERMEDIA_ENABLE;
  2943. pSoftP3RX->P3RXTextureCompositeAlphaMode0.Arg1 = P3RX_TEXCOMP_FA;
  2944. pSoftP3RX->P3RXTextureCompositeAlphaMode0.InvertArg1 = __PERMEDIA_DISABLE;
  2945. pSoftP3RX->P3RXTextureCompositeAlphaMode0.A = P3RX_TEXCOMP_ARG1;
  2946. pSoftP3RX->P3RXTextureCompositeAlphaMode0.Operation = P3RX_TEXCOMP_OPERATION_PASS_A;
  2947. pSoftP3RX->P3RXTextureCompositeAlphaMode0.Scale = P3RX_TEXCOMP_OPERATION_SCALE_ONE;
  2948. COPY_P3_DATA(TextureCompositeAlphaMode0,
  2949. pSoftP3RX->P3RXTextureCompositeAlphaMode0);
  2950. pSoftP3RX->P3RXTextureCompositeColorMode0.Enable = __PERMEDIA_ENABLE;
  2951. pSoftP3RX->P3RXTextureCompositeColorMode0.Arg1 = P3RX_TEXCOMP_FC;
  2952. pSoftP3RX->P3RXTextureCompositeColorMode0.InvertArg1 = __PERMEDIA_DISABLE;
  2953. pSoftP3RX->P3RXTextureCompositeColorMode0.A = P3RX_TEXCOMP_ARG1;
  2954. pSoftP3RX->P3RXTextureCompositeColorMode0.Operation = P3RX_TEXCOMP_OPERATION_PASS_A;
  2955. pSoftP3RX->P3RXTextureCompositeColorMode0.Scale = P3RX_TEXCOMP_OPERATION_SCALE_ONE;
  2956. COPY_P3_DATA(TextureCompositeColorMode0,
  2957. pSoftP3RX->P3RXTextureCompositeColorMode0);
  2958. pSoftP3RX->P3RXTextureCompositeAlphaMode1.Enable = __PERMEDIA_DISABLE;
  2959. COPY_P3_DATA(TextureCompositeAlphaMode1,
  2960. pSoftP3RX->P3RXTextureCompositeAlphaMode1);
  2961. pSoftP3RX->P3RXTextureCompositeColorMode1.Enable = __PERMEDIA_DISABLE;
  2962. COPY_P3_DATA(TextureCompositeColorMode1,
  2963. pSoftP3RX->P3RXTextureCompositeColorMode1);
  2964. SEND_P3_DATA(TextureCompositeMode, __PERMEDIA_ENABLE);
  2965. *pFlags &= ~SURFACE_TEXTURING;
  2966. pSoftP3RX->P3RXLUTMode.Enable = __PERMEDIA_DISABLE;
  2967. COPY_P3_DATA(LUTMode, pSoftP3RX->P3RXLUTMode);
  2968. // Specular texture can be enabled without texturing on
  2969. COPY_P3_DATA(DeltaMode, pSoftP3RX->P3RX_P3DeltaMode);
  2970. P3_DMA_COMMIT_BUFFER();
  2971. // Turn off texturing in the render command
  2972. // RENDER_TEXTURE_DISABLE(pContext->RenderCommand);
  2973. RENDER_TEXTURE_ENABLE(pContext->RenderCommand);
  2974. pContext->bTextureValid = TRUE;
  2975. pContext->pCurrentTexture[0] = NULL;
  2976. pContext->pCurrentTexture[1] = NULL;
  2977. // Track just for debugging purpouses
  2978. pContext->bTexDisabled = FALSE;
  2979. DBG_EXIT(_D3DChangeTextureP3RX,1);
  2980. return;
  2981. }
  2982. // Track just for debugging purpouses
  2983. pContext->bTexDisabled = FALSE;
  2984. // Dump to the debugger our current TSS setup
  2985. _D3DDisplayWholeTSSPipe(pContext, DBGLVL);
  2986. // Deal with the textures.
  2987. // Find the texture mappings. If D3D stage 0 uses a texture, it must
  2988. // always be chip texture 0 to keep the bumpmap working. Fortunately,
  2989. // this is the only non-orthogonal case, so everything else can cope
  2990. // with this restriction.
  2991. for ( i = TEXSTAGE_0; i < D3DTSS_MAX; i++ )
  2992. {
  2993. if ( TSSTATE ( i, D3DTSS_COLOROP ) == D3DTOP_DISABLE )
  2994. {
  2995. // Finished processing.
  2996. break;
  2997. }
  2998. // This code could be slightly optimised - if a texture is set up,
  2999. // but none of the relevant arguments are TEXTURE (with additional
  3000. // flags), then of course we don't need to set the texture up at all.
  3001. // Normally, both arguments are "relevant", but with SELECTARG1 and
  3002. // SELECTARG2, one of them is not. Also, watch out for PREMODULATE -
  3003. // it is an implicit reference to a stage's texture.
  3004. if (
  3005. ( TSSTATE ( i, D3DTSS_TEXTUREMAP ) == 0 ) ||
  3006. ( (
  3007. ( ( TSSTATESELECT ( i, D3DTSS_COLORARG1 ) != D3DTA_TEXTURE ) ||
  3008. ( TSSTATE ( i, D3DTSS_COLOROP ) == D3DTOP_SELECTARG2 ) ) &&
  3009. ( ( TSSTATESELECT ( i, D3DTSS_COLORARG2 ) != D3DTA_TEXTURE ) ||
  3010. ( TSSTATE ( i, D3DTSS_COLOROP ) == D3DTOP_SELECTARG1 ) ) &&
  3011. ( ( TSSTATESELECT ( i, D3DTSS_ALPHAARG1 ) != D3DTA_TEXTURE ) ||
  3012. ( TSSTATE ( i, D3DTSS_ALPHAOP ) == D3DTOP_SELECTARG2 ) ) &&
  3013. ( ( TSSTATESELECT ( i, D3DTSS_ALPHAARG2 ) != D3DTA_TEXTURE ) ||
  3014. ( TSSTATE ( i, D3DTSS_ALPHAOP ) == D3DTOP_SELECTARG1 ) )
  3015. ) &&
  3016. ( TSSTATE ( i, D3DTSS_COLOROP ) != D3DTOP_PREMODULATE ) &&
  3017. ( TSSTATE ( i-1, D3DTSS_COLOROP ) != D3DTOP_PREMODULATE )
  3018. ) )
  3019. {
  3020. // This D3D stage doesn't use a texture.
  3021. pContext->iStageTex[i] = -1;
  3022. }
  3023. else
  3024. {
  3025. // Note that the below code should be put into a little loop
  3026. // for any future devices that have more than 2 textures, otherwise
  3027. // the code will get big, nested and crufty. But for only 2, it's
  3028. // manageable, and slightly faster this way.
  3029. // A texture is used - is texture 0 free?
  3030. if ( pContext->iTexStage[0] == -1 )
  3031. {
  3032. // Texture 0 is free - make it this stage.
  3033. ASSERTDD ( pContext->iTexStage[1] == -1,
  3034. "** _D3DChangeTextureP3RX: pContext->iTexStage[1] "
  3035. "should be -1 if pContext->iTexStage[0] is" );
  3036. pContext->iTexStage[0] = i;
  3037. pContext->iStageTex[i] = 0;
  3038. }
  3039. else
  3040. {
  3041. // Texture 0 is assigned - see if this is the same as it.
  3042. if ( __bD3DTexturesMatch ( i,
  3043. pContext->iTexStage[0],
  3044. pContext ) )
  3045. {
  3046. // Yes, they match - no need to use texture 1.
  3047. pContext->iStageTex[i] = 0;
  3048. }
  3049. else
  3050. {
  3051. // No, they don't match. Is texture 1 free?
  3052. if ( pContext->iTexStage[1] == -1 )
  3053. {
  3054. // Texture 1 is free - make it this stage.
  3055. ASSERTDD ( pContext->iTexStage[0] != -1,
  3056. "** _D3DChangeTextureP3RX: "
  3057. "pContext->iTexStage[0] should not be "
  3058. "-1 if pContext->iTexStage[1] is not." );
  3059. pContext->iTexStage[1] = i;
  3060. pContext->iStageTex[i] = 1;
  3061. }
  3062. else
  3063. {
  3064. // Texture 1 is assigned - see if this is the same
  3065. // as it.
  3066. if ( __bD3DTexturesMatch ( i,
  3067. pContext->iTexStage[1],
  3068. pContext ) )
  3069. {
  3070. // Yes, they match - mark it.
  3071. pContext->iStageTex[i] = 1;
  3072. }
  3073. else
  3074. {
  3075. // No, they don't match, and both chip textures
  3076. // have been assigned. Fail a ValidateDevice().
  3077. DISPDBG((ERRLVL,"** _D3DChangeTextureP3RX: app tried "
  3078. "to use more than two textures."));
  3079. SET_BLEND_ERROR ( pContext, BSF_TOO_MANY_TEXTURES );
  3080. pContext->iStageTex[i] = -1;
  3081. }
  3082. }
  3083. }
  3084. }
  3085. }
  3086. // A quick sanity check.
  3087. #if DBG
  3088. if ( TSSTATE ( i, D3DTSS_TEXTUREMAP ) == 0 )
  3089. {
  3090. // That's fine, then.
  3091. ASSERTDD ( pContext->iStageTex[i] == -1,
  3092. "** _D3DChangeTextureP3RX: something failed with the "
  3093. "texture-assignment logic" );
  3094. }
  3095. else if ( pContext->iStageTex[i] == -1 )
  3096. {
  3097. // That's fine - texture may have been set up but not referenced.
  3098. }
  3099. else if ( pContext->iTexStage[pContext->iStageTex[i]] == -1 )
  3100. {
  3101. // Oops.
  3102. DISPDBG((ERRLVL,"** _D3DChangeTextureP3RX: something failed with "
  3103. "the texture-assignment logic"));
  3104. }
  3105. else if ( pContext->iTexStage[pContext->iStageTex[i]] == i )
  3106. {
  3107. // That's fine, then.
  3108. }
  3109. else if ( __bD3DTexturesMatch ( i,
  3110. pContext->iTexStage[pContext->iStageTex[i]],
  3111. pContext ) )
  3112. {
  3113. // That's fine, then.
  3114. }
  3115. else
  3116. {
  3117. // Oops.
  3118. DISPDBG((ERRLVL,"** _D3DChangeTextureP3RX: something failed with "
  3119. "the texture-assignment logic"));
  3120. }
  3121. #endif // DBG
  3122. }
  3123. // And a few more gratuitous sanity checks at the end of the loop.
  3124. ASSERTDD ( ( pContext->iTexStage[0] == -1 ) ||
  3125. ( pContext->iStageTex[pContext->iTexStage[0]] == 0 ),
  3126. "** _D3DChangeTextureP3RX: something failed with the "
  3127. "texture-assignment logic" );
  3128. ASSERTDD ( ( pContext->iTexStage[1] == -1 ) ||
  3129. ( pContext->iStageTex[pContext->iTexStage[1]] == 1 ),
  3130. "** _D3DChangeTextureP3RX: something failed with the "
  3131. "texture-assignment logic" );
  3132. #if DBG
  3133. if ( pContext->iTexStage[0] != -1 )
  3134. {
  3135. DISPDBG((DBGLVL, "Setting new texture0 data, Handle: 0x%x",
  3136. TSSTATE ( pContext->iTexStage[0], D3DTSS_TEXTUREMAP )));
  3137. }
  3138. else
  3139. {
  3140. DISPDBG((DBGLVL, "Texture0 not used" ));
  3141. }
  3142. if ( pContext->iTexStage[1] != -1 )
  3143. {
  3144. DISPDBG((DBGLVL, "Setting new texture1 data, Handle: 0x%x",
  3145. TSSTATE ( pContext->iTexStage[1], D3DTSS_TEXTUREMAP )));
  3146. }
  3147. else
  3148. {
  3149. DISPDBG((DBGLVL, "Texture1 not used" ));
  3150. }
  3151. #endif //DBG
  3152. // Set the texture valid flag to true.
  3153. // If anything resets it then the texture state is invalid.
  3154. pContext->bTextureValid = TRUE;
  3155. pContext->bCanChromaKey = FALSE;
  3156. pContext->bTex0Valid = FALSE;
  3157. pContext->bTex1Valid = FALSE;
  3158. pContext->bStage0DotProduct = FALSE;
  3159. // Set up the textures.
  3160. if ( pContext->iTexStage[0] != -1 )
  3161. {
  3162. // Setup texture 0.
  3163. pTexture0 = GetSurfaceFromHandle(pContext,
  3164. TSSTATE(pContext->iTexStage[0],
  3165. D3DTSS_TEXTUREMAP) );
  3166. if (NULL == pTexture0)
  3167. {
  3168. DISPDBG((ERRLVL, "ERROR: Texture Surface (0) is NULL"));
  3169. DBG_EXIT(_D3DChangeTextureP3RX,1);
  3170. return;
  3171. }
  3172. #if DX7_TEXMANAGEMENT
  3173. if (pTexture0->dwCaps2 & DDSCAPS2_TEXTUREMANAGE)
  3174. {
  3175. if (!_D3D_TM_Preload_Tex_IntoVidMem(pContext, pTexture0))
  3176. {
  3177. return; // something bad happened !!!
  3178. }
  3179. _D3D_TM_TimeStampTexture(pContext->pTextureManager,
  3180. pTexture0);
  3181. }
  3182. #endif // DX7_TEXMANAGEMENT
  3183. pContext->bTex0Valid =
  3184. __TXT_ValidateTextureUnitStage(pContext,
  3185. 0,
  3186. pContext->iTexStage[0],
  3187. pTexture0 );
  3188. if ( !pContext->bTex0Valid )
  3189. {
  3190. SET_BLEND_ERROR ( pContext, BSF_INVALID_TEXTURE );
  3191. // Pretend that no texture was set.
  3192. pSoftP3RX->P3RXTextureReadMode0.Enable = __PERMEDIA_DISABLE;
  3193. pSoftP3RX->P3RXTextureIndexMode0.Enable = __PERMEDIA_DISABLE;
  3194. pContext->bTex0Valid = FALSE;
  3195. pTexture0 = NULL;
  3196. }
  3197. }
  3198. else
  3199. {
  3200. pSoftP3RX->P3RXTextureReadMode0.Enable = __PERMEDIA_DISABLE;
  3201. pSoftP3RX->P3RXTextureIndexMode0.Enable = __PERMEDIA_DISABLE;
  3202. pContext->bTex0Valid = FALSE;
  3203. pTexture0 = NULL;
  3204. }
  3205. if ( pContext->iTexStage[1] != -1 )
  3206. {
  3207. // Setup texture 1.
  3208. if ( pContext->iTexStage[0] == -1 )
  3209. {
  3210. DISPDBG((ERRLVL,"** _D3DChangeTextureP3RX: Should not be "
  3211. "using tex1 if tex0 not used."));
  3212. SET_BLEND_ERROR ( pContext, BSF_TOO_MANY_BLEND_STAGES );
  3213. }
  3214. pTexture1 = GetSurfaceFromHandle(pContext,
  3215. TSSTATE ( pContext->iTexStage[1],
  3216. D3DTSS_TEXTUREMAP ) );
  3217. if (NULL == pTexture1)
  3218. {
  3219. DISPDBG((ERRLVL, "ERROR: Texture Surface (1) is NULL"));
  3220. DBG_EXIT(_D3DChangeTextureP3RX,1);
  3221. return;
  3222. }
  3223. #if DX7_TEXMANAGEMENT
  3224. if (pTexture1->dwCaps2 & DDSCAPS2_TEXTUREMANAGE)
  3225. {
  3226. if (!_D3D_TM_Preload_Tex_IntoVidMem(pContext, pTexture1))
  3227. {
  3228. return; // something bad happened !!!
  3229. }
  3230. _D3D_TM_TimeStampTexture(pContext->pTextureManager,
  3231. pTexture1);
  3232. }
  3233. #endif // DX7_TEXMANAGEMENT
  3234. pContext->bTex1Valid =
  3235. __TXT_ValidateTextureUnitStage(pContext,
  3236. 1,
  3237. pContext->iTexStage[1],
  3238. pTexture1 );
  3239. if ( !pContext->bTex1Valid )
  3240. {
  3241. SET_BLEND_ERROR ( pContext, BSF_INVALID_TEXTURE );
  3242. // Pretend that no texture was set.
  3243. pSoftP3RX->P3RXTextureReadMode1.Enable = __PERMEDIA_DISABLE;
  3244. pSoftP3RX->P3RXTextureIndexMode1.Enable = __PERMEDIA_DISABLE;
  3245. pContext->bTex1Valid = FALSE;
  3246. pTexture1 = NULL;
  3247. }
  3248. }
  3249. else
  3250. {
  3251. pSoftP3RX->P3RXTextureReadMode1.Enable = __PERMEDIA_DISABLE;
  3252. pSoftP3RX->P3RXTextureIndexMode1.Enable = __PERMEDIA_DISABLE;
  3253. pContext->bTex1Valid = FALSE;
  3254. pTexture1 = NULL;
  3255. }
  3256. bBothTexturesValid = pContext->bTex0Valid && pContext->bTex1Valid;
  3257. if( pContext->bTex0Valid )
  3258. {
  3259. dwT0MipLevels = pContext->TextureStageState[0].m_dwVal[D3DTSS_MAXMIPLEVEL];
  3260. #if DX7_TEXMANAGEMENT
  3261. if ( dwT0MipLevels < pTexture0->m_dwTexLOD)
  3262. {
  3263. dwT0MipLevels = pTexture0->m_dwTexLOD;
  3264. }
  3265. #endif // DX7_TEXMANAGEMENT
  3266. if (dwT0MipLevels > ((DWORD)(pTexture0->iMipLevels - 1)))
  3267. {
  3268. // Set the actuall maximum mip level that will be used in rendering
  3269. mipBases.dwTex0ActMaxLevel = pTexture0->iMipLevels - 1;
  3270. dwT0MipLevels = 1;
  3271. }
  3272. else
  3273. {
  3274. // Set the actuall maximum mip level that will be used in rendering
  3275. mipBases.dwTex0ActMaxLevel = dwT0MipLevels;
  3276. dwT0MipLevels = pTexture0->iMipLevels - dwT0MipLevels;
  3277. }
  3278. }
  3279. if( pContext->bTex1Valid )
  3280. {
  3281. ASSERTDD ( pContext->bTex0Valid,
  3282. "** _D3DChangeTextureP3RX: tex1 should not be used "
  3283. "unless tex0 is used as well" );
  3284. dwT1MipLevels = pContext->TextureStageState[1].m_dwVal[D3DTSS_MAXMIPLEVEL];
  3285. #if DX7_TEXMANAGEMENT
  3286. if ( dwT1MipLevels < pTexture1->m_dwTexLOD)
  3287. {
  3288. dwT1MipLevels = pTexture1->m_dwTexLOD;
  3289. }
  3290. #endif // DX7_TEXMANAGEMENT
  3291. if (dwT1MipLevels > ((DWORD)(pTexture1->iMipLevels - 1)))
  3292. {
  3293. // Set the actuall maximum mip level that will be used in rendering
  3294. mipBases.dwTex1ActMaxLevel = pTexture1->iMipLevels - 1;
  3295. dwT1MipLevels = 1;
  3296. }
  3297. else
  3298. {
  3299. // Set the actuall maximum mip level that will be used in rendering
  3300. mipBases.dwTex1ActMaxLevel = dwT1MipLevels;
  3301. dwT1MipLevels = pTexture1->iMipLevels - dwT1MipLevels;
  3302. }
  3303. // Enable generation of the second set of texture coordinates.
  3304. // Strictly, we should check whether texture 0 is being used, and
  3305. // if not move the second texture to the first (thus enabling
  3306. // mipmapping, etc) but that's for later.
  3307. pSoftP3RX->P3RX_P3DeltaMode.TextureEnable1 = __PERMEDIA_ENABLE;
  3308. pSoftP3RX->P3RX_P3DeltaControl.ShareQ = 1;
  3309. }
  3310. else
  3311. {
  3312. // Turn off generation of the second set of texture coordinates
  3313. pSoftP3RX->P3RX_P3DeltaMode.TextureEnable1 = __PERMEDIA_DISABLE;
  3314. pSoftP3RX->P3RX_P3DeltaControl.ShareQ = 0;
  3315. }
  3316. if( bBothTexturesValid )
  3317. {
  3318. float totBases, baseRatio;
  3319. DWORD t0Count, res;
  3320. totBases = (float)dwT0MipLevels + dwT1MipLevels;
  3321. // Adjust mip levels to fit in N - 2 slots as each texture
  3322. // needs at least one slot.
  3323. baseRatio = ( P3_TEX_MAP_MAX_LEVEL - 1 ) / totBases;
  3324. // Calculate number of slots for texture 0, texture 1 then
  3325. // gets the remainder.
  3326. myFtoi( &res, dwT0MipLevels * baseRatio );
  3327. t0Count = 1 + res;
  3328. ASSERTDD( t0Count > 0, "No slots for texture 0" );
  3329. ASSERTDD( t0Count <= P3_TEX_MAP_MAX_LEVEL, "No slots for texture 1" );
  3330. #define FIXED_ALLOC 0
  3331. #if FIXED_ALLOC
  3332. mipBases.dwTex0MipBase = 0;
  3333. mipBases.dwTex0MipMax = min( dwT0MipLevels - 1, 7 );
  3334. mipBases.dwTex1MipBase = 8;
  3335. mipBases.dwTex1MipMax = 8 + min( dwT1MipLevels - 1,
  3336. P3_TEX_MAP_MAX_LEVEL - 8 );
  3337. #else
  3338. mipBases.dwTex0MipBase = 0;
  3339. mipBases.dwTex0MipMax = min( dwT0MipLevels - 1, t0Count - 1 );
  3340. mipBases.dwTex1MipBase = t0Count;
  3341. mipBases.dwTex1MipMax = t0Count + min( dwT1MipLevels - 1,
  3342. P3_TEX_MAP_MAX_LEVEL - t0Count );
  3343. #endif
  3344. }
  3345. else
  3346. {
  3347. if( pContext->bTex0Valid )
  3348. {
  3349. mipBases.dwTex0MipBase = 0;
  3350. mipBases.dwTex0MipMax = min( dwT0MipLevels - 1,
  3351. P3_TEX_MAP_MAX_LEVEL );
  3352. mipBases.dwTex1MipBase = 0;
  3353. mipBases.dwTex1MipMax = min( dwT0MipLevels - 1,
  3354. P3_TEX_MAP_MAX_LEVEL );
  3355. }
  3356. if( pContext->bTex1Valid )
  3357. {
  3358. mipBases.dwTex0MipBase = 0;
  3359. mipBases.dwTex0MipMax = min( dwT1MipLevels - 1,
  3360. P3_TEX_MAP_MAX_LEVEL );
  3361. mipBases.dwTex1MipBase = 0;
  3362. mipBases.dwTex1MipMax = min( dwT1MipLevels - 1,
  3363. P3_TEX_MAP_MAX_LEVEL );
  3364. }
  3365. }
  3366. DISPDBG(( DBGLVL, "tex0 base %d", mipBases.dwTex0MipBase ));
  3367. DISPDBG(( DBGLVL, "tex0 max %d", mipBases.dwTex0MipMax ));
  3368. DISPDBG(( DBGLVL, "tex1 base %d", mipBases.dwTex1MipBase ));
  3369. DISPDBG(( DBGLVL, "tex1 max %d", mipBases.dwTex1MipMax ));
  3370. // Recalculate the LOD biases for per-poly mipmapping
  3371. pContext->MipMapLODBias[TEXSTAGE_0] =
  3372. pow4( pContext->TextureStageState[TEXSTAGE_0].
  3373. m_fVal[D3DTSS_MIPMAPLODBIAS] );
  3374. pContext->MipMapLODBias[TEXSTAGE_1] =
  3375. pow4( pContext->TextureStageState[TEXSTAGE_1].
  3376. m_fVal[D3DTSS_MIPMAPLODBIAS] );
  3377. if ( pTexture0 != NULL )
  3378. {
  3379. __TXT_SetupTexture ( pThisDisplay,
  3380. 0,
  3381. pContext->iTexStage[0],
  3382. pContext,
  3383. pTexture0,
  3384. pSoftP3RX,
  3385. bBothTexturesValid,
  3386. &mipBases);
  3387. }
  3388. if ( pTexture1 != NULL )
  3389. {
  3390. __TXT_SetupTexture ( pThisDisplay,
  3391. 1,
  3392. pContext->iTexStage[1],
  3393. pContext,
  3394. pTexture1,
  3395. pSoftP3RX,
  3396. bBothTexturesValid,
  3397. &mipBases);
  3398. #if DX7_PALETTETEXTURE
  3399. if (GET_BLEND_ERROR(pContext) == BSF_TOO_MANY_PALETTES)
  3400. {
  3401. if (pTexture0 &&
  3402. (pTexture0->dwPaletteHandle == pTexture1->dwPaletteHandle))
  3403. {
  3404. RESET_BLEND_ERROR(pContext);
  3405. }
  3406. }
  3407. #endif
  3408. }
  3409. // Fix up the D3DRENDERSTATE_MODULATE case.
  3410. if( pTexture0 != NULL )
  3411. {
  3412. if( pContext->Flags & SURFACE_MODULATE )
  3413. {
  3414. // If SURFACE_MODULATE is set then we must have seen a
  3415. // DX5-style texture blend
  3416. // Note : bAlpha is true for CI8 and CI4 textures
  3417. BOOL bSelectArg1 = pTexture0->pFormatSurface->bAlpha;
  3418. #if DX7_PALETTETEXTURE
  3419. if( pTexture0->pixFmt.dwFlags & DDPF_PALETTEINDEXED8 )
  3420. {
  3421. bSelectArg1 = pTexture0->dwPaletteFlags & DDRAWIPAL_ALPHA;
  3422. }
  3423. #endif
  3424. if( bSelectArg1 )
  3425. {
  3426. TSSTATE( pContext->iChipStage[0], D3DTSS_ALPHAOP ) =
  3427. D3DTOP_SELECTARG1;
  3428. }
  3429. else
  3430. {
  3431. TSSTATE( pContext->iChipStage[0], D3DTSS_ALPHAOP ) =
  3432. D3DTOP_SELECTARG2;
  3433. }
  3434. }
  3435. }
  3436. P3_DMA_GET_BUFFER();
  3437. // Textures set up - now do the blending.
  3438. // These might be overidden later for special blends.
  3439. dwTexAppTfactor = pContext->RenderStates[D3DRENDERSTATE_TEXTUREFACTOR];
  3440. dwTexComp0Tfactor = pContext->RenderStates[D3DRENDERSTATE_TEXTUREFACTOR];
  3441. dwTexComp1Tfactor = pContext->RenderStates[D3DRENDERSTATE_TEXTUREFACTOR];
  3442. // Detect the stage 0 & 1 bumpmap setup code.
  3443. if (( TSSTATE ( TEXSTAGE_0, D3DTSS_TEXTUREMAP ) != 0 ) &&
  3444. ( TSSTATE ( TEXSTAGE_1, D3DTSS_TEXTUREMAP ) != 0 ) &&
  3445. ( TSSTATE ( TEXSTAGE_2, D3DTSS_COLOROP ) != D3DTOP_DISABLE ) )
  3446. {
  3447. // Looking good for a bumpmap. Now find various special cases.
  3448. // First of all, do they want anything in the stage 2 current colour?
  3449. if (
  3450. ( ( ( TSSTATEINVMASK ( TEXSTAGE_2, D3DTSS_COLORARG1 ) != D3DTA_CURRENT ) &&
  3451. ( TSSTATEINVMASK ( TEXSTAGE_2, D3DTSS_COLORARG2 ) != D3DTA_CURRENT ) ) ||
  3452. ( ( TSSTATE ( TEXSTAGE_2, D3DTSS_COLOROP ) == D3DTOP_SELECTARG1 ) &&
  3453. ( TSSTATEINVMASK ( TEXSTAGE_2, D3DTSS_COLORARG1 ) != D3DTA_CURRENT ) ) ||
  3454. ( ( TSSTATE ( TEXSTAGE_2, D3DTSS_COLOROP ) == D3DTOP_SELECTARG2 ) &&
  3455. ( TSSTATEINVMASK ( TEXSTAGE_2, D3DTSS_COLORARG2 ) != D3DTA_CURRENT ) ) ) &&
  3456. ( TSSTATE ( TEXSTAGE_0, D3DTSS_COLOROP ) != D3DTOP_DOTPRODUCT3 ) &&
  3457. ( TSSTATE ( TEXSTAGE_1, D3DTSS_COLOROP ) != D3DTOP_DOTPRODUCT3 ) )
  3458. {
  3459. // Nope - they don't care what the current colour channel is, and
  3460. // no dotproducts are used in stages 0 and 1 (they affect the alpha
  3461. // channel) so ignore what is in the colour channel - this is a
  3462. // bumpmap so far.
  3463. // Now see if they want a bumpmap or an inverted bumpmap. People
  3464. // are so fussy.
  3465. // Check first stage.
  3466. if (( ( ( TSSTATE ( TEXSTAGE_0, D3DTSS_ALPHAOP ) == D3DTOP_SELECTARG1 ) &&
  3467. ( TSSTATEALPHA ( TEXSTAGE_0, D3DTSS_ALPHAARG1 ) == D3DTA_TEXTURE ) ) ||
  3468. ( ( TSSTATE ( TEXSTAGE_0, D3DTSS_ALPHAOP ) == D3DTOP_SELECTARG2 ) &&
  3469. ( TSSTATEALPHA ( TEXSTAGE_0, D3DTSS_ALPHAARG2 ) == D3DTA_TEXTURE ) ) ) &&
  3470. ( TSSTATE ( TEXSTAGE_1, D3DTSS_ALPHAOP ) == D3DTOP_ADDSIGNED ) )
  3471. {
  3472. // First stage fine and not inverted. Check second stage.
  3473. if (( ( TSSTATEALPHA ( TEXSTAGE_1, D3DTSS_ALPHAARG1 ) == ( D3DTA_TEXTURE | D3DTA_COMPLEMENT ) ) &&
  3474. ( TSSTATEALPHA ( TEXSTAGE_1, D3DTSS_ALPHAARG2 ) == D3DTA_CURRENT ) ) ||
  3475. ( ( TSSTATEALPHA ( TEXSTAGE_1, D3DTSS_ALPHAARG2 ) == ( D3DTA_TEXTURE | D3DTA_COMPLEMENT ) ) &&
  3476. ( TSSTATEALPHA ( TEXSTAGE_1, D3DTSS_ALPHAARG1 ) == D3DTA_CURRENT ) ) )
  3477. {
  3478. // Fine, not inverted.
  3479. pContext->bBumpmapEnabled = TRUE;
  3480. pContext->bBumpmapInverted = FALSE;
  3481. }
  3482. else if (
  3483. ( ( TSSTATEALPHA ( TEXSTAGE_1, D3DTSS_ALPHAARG1 ) == ( D3DTA_CURRENT | D3DTA_COMPLEMENT ) ) &&
  3484. ( TSSTATEALPHA ( TEXSTAGE_1, D3DTSS_ALPHAARG2 ) == D3DTA_TEXTURE ) ) ||
  3485. ( ( TSSTATEALPHA ( TEXSTAGE_1, D3DTSS_ALPHAARG2 ) == ( D3DTA_CURRENT | D3DTA_COMPLEMENT ) ) &&
  3486. ( TSSTATEALPHA ( TEXSTAGE_1, D3DTSS_ALPHAARG1 ) == D3DTA_TEXTURE ) ) )
  3487. {
  3488. // Fine, inverted.
  3489. pContext->bBumpmapEnabled = TRUE;
  3490. pContext->bBumpmapInverted = TRUE;
  3491. }
  3492. else
  3493. {
  3494. // Nope, second stage is no good.
  3495. pContext->bBumpmapEnabled = FALSE;
  3496. pContext->bBumpmapInverted = FALSE;
  3497. }
  3498. }
  3499. else if (
  3500. ( ( ( TSSTATE ( TEXSTAGE_0, D3DTSS_ALPHAOP ) == D3DTOP_SELECTARG1 ) &&
  3501. ( TSSTATEALPHA ( TEXSTAGE_0, D3DTSS_ALPHAARG1 ) == (D3DTA_TEXTURE | D3DTA_COMPLEMENT) ) ) ||
  3502. ( ( TSSTATE ( TEXSTAGE_0, D3DTSS_ALPHAOP ) == D3DTOP_SELECTARG2 ) &&
  3503. ( TSSTATEALPHA ( TEXSTAGE_0, D3DTSS_ALPHAARG2 ) == (D3DTA_TEXTURE | D3DTA_COMPLEMENT) ) ) ) &&
  3504. ( TSSTATE ( TEXSTAGE_1, D3DTSS_ALPHAOP ) == D3DTOP_ADDSIGNED ) )
  3505. {
  3506. // First stage fine and inverted. Check second stage.
  3507. if (( ( TSSTATEALPHA ( TEXSTAGE_1, D3DTSS_ALPHAARG1 ) == D3DTA_TEXTURE ) &&
  3508. ( TSSTATEALPHA ( TEXSTAGE_1, D3DTSS_ALPHAARG2 ) == D3DTA_CURRENT ) ) ||
  3509. ( ( TSSTATEALPHA ( TEXSTAGE_1, D3DTSS_ALPHAARG2 ) == D3DTA_TEXTURE ) &&
  3510. ( TSSTATEALPHA ( TEXSTAGE_1, D3DTSS_ALPHAARG1 ) == D3DTA_CURRENT ) ) )
  3511. {
  3512. // Fine, inverted.
  3513. pContext->bBumpmapEnabled = TRUE;
  3514. pContext->bBumpmapInverted = TRUE;
  3515. }
  3516. else if (
  3517. ( ( TSSTATEALPHA ( TEXSTAGE_1, D3DTSS_ALPHAARG1 ) == ( D3DTA_CURRENT | D3DTA_COMPLEMENT ) ) &&
  3518. ( TSSTATEALPHA ( TEXSTAGE_1, D3DTSS_ALPHAARG2 ) == ( D3DTA_TEXTURE | D3DTA_COMPLEMENT ) ) ) ||
  3519. ( ( TSSTATEALPHA ( TEXSTAGE_1, D3DTSS_ALPHAARG2 ) == ( D3DTA_CURRENT | D3DTA_COMPLEMENT ) ) &&
  3520. ( TSSTATEALPHA ( TEXSTAGE_1, D3DTSS_ALPHAARG1 ) == ( D3DTA_TEXTURE | D3DTA_COMPLEMENT ) ) ) )
  3521. {
  3522. // Fine, not inverted.
  3523. pContext->bBumpmapEnabled = TRUE;
  3524. pContext->bBumpmapInverted = FALSE;
  3525. }
  3526. else
  3527. {
  3528. // Nope, second stage is no good.
  3529. pContext->bBumpmapEnabled = FALSE;
  3530. pContext->bBumpmapInverted = FALSE;
  3531. }
  3532. }
  3533. else
  3534. {
  3535. // Nope, first stage is no good.
  3536. pContext->bBumpmapEnabled = FALSE;
  3537. pContext->bBumpmapInverted = FALSE;
  3538. }
  3539. }
  3540. else
  3541. {
  3542. // Could do some more checking, e.g. is all they want in the current colour
  3543. // channel easily available from a single input, e.g. tex0.c, in which case
  3544. // that's fine. A non-bumpmap variant also needs to sense that the first
  3545. // stage is simply a selectarg1/2 and thus can ignore the first stage as
  3546. // a texcomp stage.
  3547. // But that's for later.
  3548. pContext->bBumpmapEnabled = FALSE;
  3549. pContext->bBumpmapInverted = FALSE;
  3550. }
  3551. }
  3552. else
  3553. {
  3554. pContext->bBumpmapEnabled = FALSE;
  3555. pContext->bBumpmapInverted = FALSE;
  3556. }
  3557. if ( pContext->bBumpmapEnabled )
  3558. {
  3559. DISPDBG((DBGLVL,"Enabling emboss bumpmapping"));
  3560. // Remap stages 1 & 2 out of existence.
  3561. pContext->iChipStage[0] = TEXSTAGE_2;
  3562. pContext->iChipStage[1] = TEXSTAGE_3;
  3563. pContext->iChipStage[2] = TEXSTAGE_4;
  3564. pContext->iChipStage[3] = TEXSTAGE_5;
  3565. }
  3566. else
  3567. {
  3568. // Normal mapping.
  3569. pContext->iChipStage[0] = TEXSTAGE_0;
  3570. pContext->iChipStage[1] = TEXSTAGE_1;
  3571. pContext->iChipStage[2] = TEXSTAGE_2;
  3572. pContext->iChipStage[3] = TEXSTAGE_3;
  3573. }
  3574. iLastChipStage = 0;
  3575. // Set these flags to FALSE as the stages are processed.
  3576. bProcessChipStage0 = TRUE;
  3577. bProcessChipStage1 = TRUE;
  3578. bProcessChipStage2 = TRUE;
  3579. // Turn on the basic enables.
  3580. pSoftP3RX->P3RXTextureApplicationMode.Enable = __PERMEDIA_ENABLE;
  3581. // pSoftP3RX->P3RXTextureApplicationMode.EnableKs = __PERMEDIA_DISABLE;
  3582. pSoftP3RX->P3RXTextureApplicationMode.EnableKd = __PERMEDIA_DISABLE;
  3583. pSoftP3RX->P3RXTextureApplicationMode.MotionCompEnable = __PERMEDIA_DISABLE;
  3584. // Handle chip stage 0.
  3585. // Detect the very special-case glossmap+bumpmap code. There is no easy way
  3586. // to generalise it, so the whole chunk gets checked here.
  3587. if ( bProcessChipStage0 && bProcessChipStage1 && bProcessChipStage2 && pContext->bTex0Valid && pContext->bTex1Valid &&
  3588. // Colour channel of stage 0 can be whatever you want.
  3589. ( TSSTATE ( TEXSTAGE_1, D3DTSS_COLOROP ) == D3DTOP_MODULATEALPHA_ADDCOLOR ) && // Early-out test - nothing uses this!
  3590. ( TSSTATE ( TEXSTAGE_0, D3DTSS_ALPHAOP ) == D3DTOP_SELECTARG1 ) &&
  3591. ( TSSTATE ( TEXSTAGE_0, D3DTSS_ALPHAARG1 ) == D3DTA_DIFFUSE ) &&
  3592. ( TSSTATE ( TEXSTAGE_1, D3DTSS_COLORARG1 ) == D3DTA_CURRENT ) &&
  3593. ( TSSTATE ( TEXSTAGE_1, D3DTSS_COLORARG2 ) == D3DTA_TEXTURE ) &&
  3594. ( TSSTATE ( TEXSTAGE_1, D3DTSS_ALPHAOP ) == D3DTOP_SELECTARG1 ) &&
  3595. ( TSSTATE ( TEXSTAGE_1, D3DTSS_ALPHAARG1 ) == D3DTA_TEXTURE ) &&
  3596. ( TSSTATE ( TEXSTAGE_2, D3DTSS_COLOROP ) == D3DTOP_SELECTARG1 ) &&
  3597. ( TSSTATE ( TEXSTAGE_2, D3DTSS_COLORARG1 ) == D3DTA_CURRENT ) &&
  3598. ( TSSTATE ( TEXSTAGE_2, D3DTSS_ALPHAOP ) == D3DTOP_ADDSIGNED ) &&
  3599. ( TSSTATEINVMASK ( TEXSTAGE_2, D3DTSS_ALPHAARG1 ) == D3DTA_TEXTURE ) &&
  3600. ( TSSTATEINVMASK ( TEXSTAGE_2, D3DTSS_ALPHAARG2 ) == D3DTA_CURRENT ) &&
  3601. ( TSSTATE ( TEXSTAGE_3, D3DTSS_COLOROP ) == D3DTOP_MODULATE2X ) &&
  3602. ( TSSTATE ( TEXSTAGE_3, D3DTSS_COLORARG1 ) == D3DTA_CURRENT ) &&
  3603. ( TSSTATE ( TEXSTAGE_3, D3DTSS_COLORARG2 ) == (D3DTA_CURRENT | D3DTA_ALPHAREPLICATE) ) &&
  3604. ( TSSTATE ( TEXSTAGE_3, D3DTSS_ALPHAOP ) == D3DTOP_SELECTARG1 ) &&
  3605. ( TSSTATE ( TEXSTAGE_3, D3DTSS_ALPHAARG1 ) == D3DTA_TFACTOR ) &&
  3606. ( TSSTATE ( TEXSTAGE_4, D3DTSS_COLOROP ) == D3DTOP_DISABLE ) &&
  3607. ( pContext->iStageTex[0] == 0 ) &&
  3608. ( pContext->iStageTex[1] == 1 ) &&
  3609. ( pContext->iStageTex[2] == 0 )
  3610. )
  3611. {
  3612. int iMode;
  3613. // OK, looks good. Check which way round the bumpmapping is being done.
  3614. if (( TSSTATE ( TEXSTAGE_2, D3DTSS_ALPHAARG1 ) == D3DTA_TEXTURE ) &&
  3615. ( TSSTATE ( TEXSTAGE_2, D3DTSS_ALPHAARG2 ) == (D3DTA_CURRENT | D3DTA_COMPLEMENT) ) )
  3616. {
  3617. // Standard emboss.
  3618. iMode = 0;
  3619. }
  3620. else if (( TSSTATE ( TEXSTAGE_2, D3DTSS_ALPHAARG1 ) == (D3DTA_TEXTURE | D3DTA_COMPLEMENT) ) &&
  3621. ( TSSTATE ( TEXSTAGE_2, D3DTSS_ALPHAARG2 ) == D3DTA_CURRENT ) )
  3622. {
  3623. // Inverted emboss.
  3624. iMode = 1;
  3625. }
  3626. else
  3627. {
  3628. // No good - can't do it.
  3629. iMode = -1;
  3630. }
  3631. if ( iMode == -1 )
  3632. {
  3633. // Nope.
  3634. SET_BLEND_ERROR ( pContext, BSF_TOO_MANY_BLEND_STAGES );
  3635. bProcessChipStage0 = FALSE;
  3636. bProcessChipStage1 = FALSE;
  3637. bProcessChipStage2 = FALSE;
  3638. iLastChipStage = 3;
  3639. }
  3640. else
  3641. {
  3642. // Set up the colour channel of tc0.
  3643. // Alpha channel will be overridden later.
  3644. __TXT_TranslateToChipBlendMode(pContext,
  3645. &pContext->TextureStageState[0],
  3646. pSoftP3RX,
  3647. 0,
  3648. 0);
  3649. // Pass through bump.a, maybe inverted.
  3650. pSoftP3RX->P3RXTextureCompositeAlphaMode0.Enable = __PERMEDIA_ENABLE;
  3651. pSoftP3RX->P3RXTextureCompositeAlphaMode0.Operation = P3RX_TEXCOMP_OPERATION_PASS_A;
  3652. pSoftP3RX->P3RXTextureCompositeAlphaMode0.Scale = P3RX_TEXCOMP_OPERATION_SCALE_ONE;
  3653. pSoftP3RX->P3RXTextureCompositeAlphaMode0.Arg1 = P3RX_TEXCOMP_HEIGHTA;
  3654. pSoftP3RX->P3RXTextureCompositeAlphaMode0.Arg2 = P3RX_TEXCOMP_CA;
  3655. pSoftP3RX->P3RXTextureCompositeAlphaMode0.I = P3RX_TEXCOMP_I_CA;
  3656. pSoftP3RX->P3RXTextureCompositeAlphaMode0.A = P3RX_TEXCOMP_ARG1;
  3657. pSoftP3RX->P3RXTextureCompositeAlphaMode0.B = P3RX_TEXCOMP_ARG2;
  3658. if ( iMode )
  3659. {
  3660. // Inverted bumpmap.
  3661. pSoftP3RX->P3RXTextureCompositeAlphaMode0.InvertArg1 = __PERMEDIA_ENABLE;
  3662. }
  3663. else
  3664. {
  3665. // Non-inverted bumpmap.
  3666. pSoftP3RX->P3RXTextureCompositeAlphaMode0.InvertArg1 = __PERMEDIA_DISABLE;
  3667. }
  3668. pSoftP3RX->P3RXTextureCompositeAlphaMode0.InvertArg2 = __PERMEDIA_DISABLE;
  3669. pSoftP3RX->P3RXTextureCompositeAlphaMode0.InvertI = __PERMEDIA_DISABLE;
  3670. // Do tex1.c * diff.a + current.c
  3671. pSoftP3RX->P3RXTextureCompositeColorMode1.Enable = __PERMEDIA_ENABLE;
  3672. pSoftP3RX->P3RXTextureCompositeColorMode1.Operation = P3RX_TEXCOMP_OPERATION_MODULATE_AI_ADD_B;
  3673. pSoftP3RX->P3RXTextureCompositeColorMode1.Scale = P3RX_TEXCOMP_OPERATION_SCALE_ONE;
  3674. pSoftP3RX->P3RXTextureCompositeColorMode1.Arg1 = P3RX_TEXCOMP_T1C;
  3675. pSoftP3RX->P3RXTextureCompositeColorMode1.Arg2 = P3RX_TEXCOMP_OC;
  3676. pSoftP3RX->P3RXTextureCompositeColorMode1.I = P3RX_TEXCOMP_I_CA;
  3677. pSoftP3RX->P3RXTextureCompositeColorMode1.A = P3RX_TEXCOMP_ARG1;
  3678. pSoftP3RX->P3RXTextureCompositeColorMode1.B = P3RX_TEXCOMP_ARG2;
  3679. pSoftP3RX->P3RXTextureCompositeColorMode1.InvertArg1 = __PERMEDIA_DISABLE;
  3680. pSoftP3RX->P3RXTextureCompositeColorMode1.InvertArg2 = __PERMEDIA_DISABLE;
  3681. pSoftP3RX->P3RXTextureCompositeColorMode1.InvertI = __PERMEDIA_DISABLE;
  3682. // Pass through bump.a again.
  3683. pSoftP3RX->P3RXTextureCompositeAlphaMode1.Enable = __PERMEDIA_ENABLE;
  3684. pSoftP3RX->P3RXTextureCompositeAlphaMode1.Operation = P3RX_TEXCOMP_OPERATION_PASS_A;
  3685. pSoftP3RX->P3RXTextureCompositeAlphaMode1.Scale = P3RX_TEXCOMP_OPERATION_SCALE_ONE;
  3686. pSoftP3RX->P3RXTextureCompositeAlphaMode1.Arg1 = P3RX_TEXCOMP_OA;
  3687. pSoftP3RX->P3RXTextureCompositeAlphaMode1.Arg2 = P3RX_TEXCOMP_CA;
  3688. pSoftP3RX->P3RXTextureCompositeAlphaMode1.I = P3RX_TEXCOMP_I_CA;
  3689. pSoftP3RX->P3RXTextureCompositeAlphaMode1.A = P3RX_TEXCOMP_ARG1;
  3690. pSoftP3RX->P3RXTextureCompositeAlphaMode1.B = P3RX_TEXCOMP_ARG2;
  3691. pSoftP3RX->P3RXTextureCompositeAlphaMode1.InvertArg1 = __PERMEDIA_DISABLE;
  3692. pSoftP3RX->P3RXTextureCompositeAlphaMode1.InvertArg2 = __PERMEDIA_DISABLE;
  3693. pSoftP3RX->P3RXTextureCompositeAlphaMode1.InvertI = __PERMEDIA_DISABLE;
  3694. // Do current.c * current.a, by doing B*I+A. A=black, B=current.c, I=current.a
  3695. pSoftP3RX->P3RXTextureApplicationMode.ColorA = P3RX_TEXAPP_A_KC;
  3696. pSoftP3RX->P3RXTextureApplicationMode.ColorB = P3RX_TEXAPP_B_TC;
  3697. pSoftP3RX->P3RXTextureApplicationMode.ColorI = P3RX_TEXAPP_I_TA;
  3698. pSoftP3RX->P3RXTextureApplicationMode.ColorInvertI = __PERMEDIA_DISABLE;
  3699. pSoftP3RX->P3RXTextureApplicationMode.ColorOperation = P3RX_TEXAPP_OPERATION_MODULATE_BI_ADD_A;
  3700. // Set the colour channel to black (allow the alpha channel to be preserved).
  3701. dwTexAppTfactor &= 0xff000000;
  3702. // Alpha channel selects the constant color.
  3703. pSoftP3RX->P3RXTextureApplicationMode.AlphaA = P3RX_TEXAPP_A_KA;
  3704. pSoftP3RX->P3RXTextureApplicationMode.AlphaB = P3RX_TEXAPP_B_KA;
  3705. pSoftP3RX->P3RXTextureApplicationMode.AlphaInvertI = __PERMEDIA_DISABLE;
  3706. pSoftP3RX->P3RXTextureApplicationMode.AlphaOperation = P3RX_TEXAPP_OPERATION_PASS_B;
  3707. // Do *2 in alpha-blend unit.
  3708. bAlphaBlendDouble = TRUE;
  3709. // We don't actually need the remap (and it doesn't mean much),
  3710. // but it stops erroneous errors being flagged.
  3711. pContext->iChipStage[0] = TEXSTAGE_0;
  3712. pContext->iChipStage[1] = TEXSTAGE_1;
  3713. pContext->iChipStage[2] = TEXSTAGE_3;
  3714. pContext->iChipStage[3] = TEXSTAGE_4;
  3715. bProcessChipStage0 = FALSE;
  3716. bProcessChipStage1 = FALSE;
  3717. bProcessChipStage2 = FALSE;
  3718. iLastChipStage = 3;
  3719. }
  3720. }
  3721. // Detect the special-case 3-blend-unit bumpmapping mode.
  3722. // Third stage will be set up by the standard routines - only the first
  3723. // two are special-cased and shoehorned into TexComp0.
  3724. if ( bProcessChipStage0 && !pContext->bBumpmapEnabled && pContext->bTex0Valid && pContext->bTex1Valid &&
  3725. ( TSSTATE ( TEXSTAGE_0, D3DTSS_COLOROP ) == D3DTOP_MODULATE ) &&
  3726. ( TSSTATE ( TEXSTAGE_0, D3DTSS_COLORARG1 ) == D3DTA_TEXTURE ) &&
  3727. ( TSSTATE ( TEXSTAGE_0, D3DTSS_COLORARG2 ) == D3DTA_DIFFUSE ) &&
  3728. ( TSSTATE ( TEXSTAGE_1, D3DTSS_COLOROP ) == D3DTOP_SELECTARG1 ) &&
  3729. ( TSSTATE ( TEXSTAGE_1, D3DTSS_COLORARG1 ) == D3DTA_CURRENT ) &&
  3730. ( TSSTATE ( TEXSTAGE_0, D3DTSS_ALPHAOP ) == D3DTOP_SELECTARG1 ) &&
  3731. ( TSSTATE ( TEXSTAGE_0, D3DTSS_ALPHAARG1 ) == D3DTA_TEXTURE ) &&
  3732. // ( TSSTATE ( TEXSTAGE_0, D3DTSS_ALPHAARG2 ) == D3DTA_DIFFUSE ) dont care &&
  3733. ( TSSTATE ( TEXSTAGE_1, D3DTSS_ALPHAOP ) == D3DTOP_ADDSIGNED ) &&
  3734. (
  3735. ( ( TSSTATE ( TEXSTAGE_1, D3DTSS_ALPHAARG1 ) == ( D3DTA_TEXTURE | D3DTA_COMPLEMENT ) ) &&
  3736. ( TSSTATE ( TEXSTAGE_1, D3DTSS_ALPHAARG2 ) == D3DTA_CURRENT ) ) ||
  3737. ( ( TSSTATE ( TEXSTAGE_1, D3DTSS_ALPHAARG1 ) == D3DTA_TEXTURE ) &&
  3738. ( TSSTATE ( TEXSTAGE_1, D3DTSS_ALPHAARG2 ) == ( D3DTA_CURRENT | D3DTA_COMPLEMENT ) ) )
  3739. ) )
  3740. {
  3741. // Yep, looks good. Set it up.
  3742. ASSERTDD ( pContext->iTexStage[0] == 0, "** _D3DChangeTextureP3RX: textures not correct for special bumpmapping" );
  3743. ASSERTDD ( pContext->iTexStage[1] == 1, "** _D3DChangeTextureP3RX: textures not correct for special bumpmapping" );
  3744. pSoftP3RX->P3RXTextureCompositeColorMode0.Enable = __PERMEDIA_ENABLE;
  3745. pSoftP3RX->P3RXTextureCompositeColorMode0.Operation = P3RX_TEXCOMP_OPERATION_MODULATE_AB;
  3746. pSoftP3RX->P3RXTextureCompositeColorMode0.Scale = P3RX_TEXCOMP_OPERATION_SCALE_ONE;
  3747. pSoftP3RX->P3RXTextureCompositeColorMode0.Arg1 = P3RX_TEXCOMP_T0C;
  3748. pSoftP3RX->P3RXTextureCompositeColorMode0.Arg2 = P3RX_TEXCOMP_CC;
  3749. pSoftP3RX->P3RXTextureCompositeColorMode0.I = P3RX_TEXCOMP_I_CA;
  3750. pSoftP3RX->P3RXTextureCompositeColorMode0.A = P3RX_TEXCOMP_ARG1;
  3751. pSoftP3RX->P3RXTextureCompositeColorMode0.B = P3RX_TEXCOMP_ARG2;
  3752. pSoftP3RX->P3RXTextureCompositeColorMode0.InvertArg1 = __PERMEDIA_DISABLE;
  3753. pSoftP3RX->P3RXTextureCompositeColorMode0.InvertArg2 = __PERMEDIA_DISABLE;
  3754. pSoftP3RX->P3RXTextureCompositeColorMode0.InvertI = __PERMEDIA_DISABLE;
  3755. pSoftP3RX->P3RXTextureCompositeAlphaMode0.Enable = __PERMEDIA_ENABLE;
  3756. pSoftP3RX->P3RXTextureCompositeAlphaMode0.Operation = P3RX_TEXCOMP_OPERATION_PASS_A;
  3757. pSoftP3RX->P3RXTextureCompositeAlphaMode0.Scale = P3RX_TEXCOMP_OPERATION_SCALE_ONE;
  3758. pSoftP3RX->P3RXTextureCompositeAlphaMode0.Arg1 = P3RX_TEXCOMP_HEIGHTA;
  3759. pSoftP3RX->P3RXTextureCompositeAlphaMode0.Arg2 = P3RX_TEXCOMP_CA;
  3760. pSoftP3RX->P3RXTextureCompositeAlphaMode0.I = P3RX_TEXCOMP_I_CA;
  3761. pSoftP3RX->P3RXTextureCompositeAlphaMode0.A = P3RX_TEXCOMP_ARG1;
  3762. pSoftP3RX->P3RXTextureCompositeAlphaMode0.B = P3RX_TEXCOMP_ARG2;
  3763. pSoftP3RX->P3RXTextureCompositeAlphaMode0.InvertArg2 = __PERMEDIA_DISABLE;
  3764. pSoftP3RX->P3RXTextureCompositeAlphaMode0.InvertI = __PERMEDIA_DISABLE;
  3765. if ( ( TSSTATE ( TEXSTAGE_1, D3DTSS_ALPHAARG1 ) == D3DTA_TEXTURE ) &&
  3766. ( TSSTATE ( TEXSTAGE_1, D3DTSS_ALPHAARG2 ) == ( D3DTA_CURRENT | D3DTA_COMPLEMENT ) ) )
  3767. {
  3768. // Inverted bumpmap.
  3769. pSoftP3RX->P3RXTextureCompositeAlphaMode0.InvertArg1 = __PERMEDIA_ENABLE;
  3770. }
  3771. else
  3772. {
  3773. // Normal bumpmap.
  3774. pSoftP3RX->P3RXTextureCompositeAlphaMode0.InvertArg1 = __PERMEDIA_DISABLE;
  3775. }
  3776. // Done chip stage 0, TSS stage 0 & 1. Move chip stage 1 on a notch.
  3777. pContext->iChipStage[0] = TEXSTAGE_0;
  3778. pContext->iChipStage[1] = TEXSTAGE_2;
  3779. pContext->iChipStage[2] = TEXSTAGE_3;
  3780. pContext->iChipStage[3] = TEXSTAGE_4;
  3781. iLastChipStage = 1;
  3782. bProcessChipStage0 = FALSE;
  3783. }
  3784. // Detect a chipstage 0 MODULATE+ADD concatenation. Used by lightmaps.
  3785. // This compresses two stages into texcomp0. The alpha channel has
  3786. // two modes - either one of the two stages just does a selectarg1 (current),
  3787. // and the other gets set up as normal, or (for specular stuff) they
  3788. // both do ADDSIGNED (cur, cur), in which case it's special-cased.
  3789. if ( bProcessChipStage0 && pContext->bBumpmapEnabled &&
  3790. ( TSSTATE ( pContext->iChipStage[0], D3DTSS_COLOROP ) == D3DTOP_MODULATE ) &&
  3791. ( TSSTATE ( pContext->iChipStage[0], D3DTSS_COLORARG1 ) == ( D3DTA_CURRENT | D3DTA_ALPHAREPLICATE ) ) &&
  3792. ( TSSTATE ( pContext->iChipStage[0], D3DTSS_COLORARG2 ) == D3DTA_DIFFUSE ) &&
  3793. ( ( ( TSSTATE ( pContext->iChipStage[1], D3DTSS_COLOROP ) == D3DTOP_ADD ) &&
  3794. ( TSSTATE ( pContext->iChipStage[1], D3DTSS_COLORARG1 ) == D3DTA_CURRENT ) &&
  3795. ( TSSTATE ( pContext->iChipStage[1], D3DTSS_COLORARG2 ) == D3DTA_TEXTURE ) ) ||
  3796. ( ( TSSTATE ( pContext->iChipStage[1], D3DTSS_COLOROP ) == D3DTOP_SELECTARG1 ) &&
  3797. ( TSSTATE ( pContext->iChipStage[1], D3DTSS_COLORARG1 ) == D3DTA_CURRENT ) ) ) )
  3798. {
  3799. // Colour channel is correct and can be squashed down to one stage.
  3800. // Check that the alpha channel is OK.
  3801. int bOK;
  3802. if (( ( TSSTATE ( pContext->iChipStage[0], D3DTSS_ALPHAOP ) == D3DTOP_SELECTARG1 ) &&
  3803. ( TSSTATE ( pContext->iChipStage[0], D3DTSS_ALPHAARG1 ) == D3DTA_CURRENT ) ) ||
  3804. ( ( TSSTATE ( pContext->iChipStage[0], D3DTSS_ALPHAOP ) == D3DTOP_SELECTARG2 ) &&
  3805. ( TSSTATE ( pContext->iChipStage[0], D3DTSS_ALPHAARG2 ) == D3DTA_CURRENT ) ) )
  3806. {
  3807. // Stage 0 is set to pass-through - set up texcomp0 as stage 1.
  3808. // Colour channel will be overridden later.
  3809. __TXT_TranslateToChipBlendMode(pContext,
  3810. &pContext->TextureStageState[pContext->iChipStage[1]],
  3811. pSoftP3RX,
  3812. pContext->iChipStage[1],
  3813. 0);
  3814. bOK = TRUE;
  3815. }
  3816. else if (( ( TSSTATE ( pContext->iChipStage[1], D3DTSS_ALPHAOP ) == D3DTOP_SELECTARG1 ) &&
  3817. ( TSSTATE ( pContext->iChipStage[1], D3DTSS_ALPHAARG1 ) == D3DTA_CURRENT ) ) ||
  3818. ( ( TSSTATE ( pContext->iChipStage[1], D3DTSS_ALPHAOP ) == D3DTOP_SELECTARG2 ) &&
  3819. ( TSSTATE ( pContext->iChipStage[1], D3DTSS_ALPHAARG2 ) == D3DTA_CURRENT ) ) )
  3820. {
  3821. // Stage 1 is set to pass-through - set up texcomp0 as stage 0.
  3822. // Colour channel will be overridden later.
  3823. __TXT_TranslateToChipBlendMode(pContext,
  3824. &pContext->TextureStageState[pContext->iChipStage[0]],
  3825. pSoftP3RX,
  3826. pContext->iChipStage[0],
  3827. 0);
  3828. bOK = TRUE;
  3829. }
  3830. else if (( TSSTATE ( pContext->iChipStage[0], D3DTSS_ALPHAOP ) == D3DTOP_ADDSIGNED ) &&
  3831. ( TSSTATE ( pContext->iChipStage[0], D3DTSS_ALPHAARG1 ) == D3DTA_CURRENT ) &&
  3832. ( TSSTATE ( pContext->iChipStage[0], D3DTSS_ALPHAARG2 ) == D3DTA_CURRENT ) &&
  3833. ( TSSTATE ( pContext->iChipStage[1], D3DTSS_ALPHAOP ) == D3DTOP_ADDSIGNED ) &&
  3834. ( TSSTATE ( pContext->iChipStage[1], D3DTSS_ALPHAARG1 ) == D3DTA_CURRENT ) &&
  3835. ( TSSTATE ( pContext->iChipStage[1], D3DTSS_ALPHAARG2 ) == D3DTA_CURRENT ) )
  3836. {
  3837. // Set up to do ( 4 * cur.a - 1.5 ), or rather 4 * ( cur.a - 0.375 )
  3838. dwTexComp0Tfactor = 0x60606060; // All channels set to (0.375)
  3839. pSoftP3RX->P3RXTextureCompositeAlphaMode0.Enable = __PERMEDIA_ENABLE;
  3840. pSoftP3RX->P3RXTextureCompositeAlphaMode0.Operation = P3RX_TEXCOMP_OPERATION_SUBTRACT_AB;
  3841. pSoftP3RX->P3RXTextureCompositeAlphaMode0.Scale = P3RX_TEXCOMP_OPERATION_SCALE_FOUR;
  3842. pSoftP3RX->P3RXTextureCompositeAlphaMode0.Arg1 = P3RX_TEXCOMP_HEIGHTA;
  3843. pSoftP3RX->P3RXTextureCompositeAlphaMode0.Arg2 = P3RX_TEXCOMP_FA;
  3844. pSoftP3RX->P3RXTextureCompositeAlphaMode0.I = P3RX_TEXCOMP_I_CA;
  3845. pSoftP3RX->P3RXTextureCompositeAlphaMode0.A = P3RX_TEXCOMP_ARG1;
  3846. pSoftP3RX->P3RXTextureCompositeAlphaMode0.B = P3RX_TEXCOMP_ARG2;
  3847. if ( pContext->bBumpmapInverted )
  3848. {
  3849. pSoftP3RX->P3RXTextureCompositeAlphaMode0.InvertArg1 = __PERMEDIA_ENABLE;
  3850. }
  3851. else
  3852. {
  3853. pSoftP3RX->P3RXTextureCompositeAlphaMode0.InvertArg1 = __PERMEDIA_DISABLE;
  3854. }
  3855. pSoftP3RX->P3RXTextureCompositeAlphaMode0.InvertArg2 = __PERMEDIA_DISABLE;
  3856. pSoftP3RX->P3RXTextureCompositeAlphaMode0.InvertI = __PERMEDIA_DISABLE;
  3857. bOK = TRUE;
  3858. }
  3859. else
  3860. {
  3861. bOK = FALSE;
  3862. }
  3863. if ( bOK )
  3864. {
  3865. // OK, the alpha channel is fine - set up the colour channel now.
  3866. pSoftP3RX->P3RXTextureCompositeColorMode0.Enable = __PERMEDIA_ENABLE;
  3867. if ( TSSTATE ( pContext->iChipStage[1], D3DTSS_COLOROP ) == D3DTOP_ADD )
  3868. {
  3869. // Yes, this is the ((diff.c*cur.a)+tex.c) case.
  3870. pSoftP3RX->P3RXTextureCompositeColorMode0.Operation = P3RX_TEXCOMP_OPERATION_MODULATE_AI_ADD_B;
  3871. pSoftP3RX->P3RXTextureCompositeColorMode0.Scale = P3RX_TEXCOMP_OPERATION_SCALE_ONE;
  3872. pSoftP3RX->P3RXTextureCompositeColorMode0.Arg1 = P3RX_TEXCOMP_CC;
  3873. if ( pContext->iStageTex[pContext->iChipStage[1]] == 0 )
  3874. {
  3875. pSoftP3RX->P3RXTextureCompositeColorMode0.Arg2 = P3RX_TEXCOMP_T0C;
  3876. }
  3877. else
  3878. {
  3879. pSoftP3RX->P3RXTextureCompositeColorMode0.Arg2 = P3RX_TEXCOMP_T1C;
  3880. }
  3881. pSoftP3RX->P3RXTextureCompositeColorMode0.I = P3RX_TEXCOMP_I_HA;
  3882. pSoftP3RX->P3RXTextureCompositeColorMode0.A = P3RX_TEXCOMP_ARG1;
  3883. pSoftP3RX->P3RXTextureCompositeColorMode0.B = P3RX_TEXCOMP_ARG2;
  3884. pSoftP3RX->P3RXTextureCompositeColorMode0.InvertArg1 = __PERMEDIA_DISABLE;
  3885. pSoftP3RX->P3RXTextureCompositeColorMode0.InvertArg2 = __PERMEDIA_DISABLE;
  3886. if ( pContext->bBumpmapInverted )
  3887. {
  3888. pSoftP3RX->P3RXTextureCompositeColorMode0.InvertI = __PERMEDIA_ENABLE;
  3889. }
  3890. else
  3891. {
  3892. pSoftP3RX->P3RXTextureCompositeColorMode0.InvertI = __PERMEDIA_DISABLE;
  3893. }
  3894. }
  3895. else
  3896. {
  3897. // Yes, this is just the (diff.c*cur.a) case.
  3898. pSoftP3RX->P3RXTextureCompositeColorMode0.Operation = P3RX_TEXCOMP_OPERATION_MODULATE_AB;
  3899. pSoftP3RX->P3RXTextureCompositeColorMode0.Scale = P3RX_TEXCOMP_OPERATION_SCALE_ONE;
  3900. pSoftP3RX->P3RXTextureCompositeColorMode0.Arg1 = P3RX_TEXCOMP_CC;
  3901. pSoftP3RX->P3RXTextureCompositeColorMode0.Arg2 = P3RX_TEXCOMP_HEIGHTA;
  3902. pSoftP3RX->P3RXTextureCompositeColorMode0.I = P3RX_TEXCOMP_I_OA;
  3903. pSoftP3RX->P3RXTextureCompositeColorMode0.A = P3RX_TEXCOMP_ARG1;
  3904. pSoftP3RX->P3RXTextureCompositeColorMode0.B = P3RX_TEXCOMP_ARG2;
  3905. pSoftP3RX->P3RXTextureCompositeColorMode0.InvertArg1 = __PERMEDIA_DISABLE;
  3906. pSoftP3RX->P3RXTextureCompositeColorMode0.InvertArg2 = __PERMEDIA_DISABLE;
  3907. if ( pContext->bBumpmapInverted )
  3908. {
  3909. pSoftP3RX->P3RXTextureCompositeColorMode0.InvertI = __PERMEDIA_ENABLE;
  3910. }
  3911. else
  3912. {
  3913. pSoftP3RX->P3RXTextureCompositeColorMode0.InvertI = __PERMEDIA_DISABLE;
  3914. }
  3915. }
  3916. // Done chip stage 0, TSS stage 0 & 1. Move chip stage 1 on a notch.
  3917. pContext->iChipStage[1]++;
  3918. pContext->iChipStage[2]++;
  3919. pContext->iChipStage[3]++;
  3920. iLastChipStage = 1;
  3921. bProcessChipStage0 = FALSE;
  3922. }
  3923. }
  3924. if ( TSSTATE ( pContext->iChipStage[0], D3DTSS_COLOROP ) == D3DTOP_DISABLE )
  3925. {
  3926. // Nothing more to do.
  3927. bProcessChipStage0 = FALSE;
  3928. bProcessChipStage1 = FALSE;
  3929. bProcessChipStage2 = FALSE;
  3930. }
  3931. if ( pContext->iStageTex[pContext->iChipStage[0]] == -1 )
  3932. {
  3933. // This stage has no texture - is anyone trying to use it?
  3934. if (( TSSTATESELECT ( pContext->iChipStage[0], D3DTSS_COLORARG1 ) == D3DTA_TEXTURE ) && ( TSSTATE ( pContext->iChipStage[0], D3DTSS_COLOROP ) != D3DTOP_SELECTARG2 ) ||
  3935. ( TSSTATESELECT ( pContext->iChipStage[0], D3DTSS_COLORARG2 ) == D3DTA_TEXTURE ) && ( TSSTATE ( pContext->iChipStage[0], D3DTSS_COLOROP ) != D3DTOP_SELECTARG1 ) ||
  3936. ( TSSTATESELECT ( pContext->iChipStage[0], D3DTSS_ALPHAARG1 ) == D3DTA_TEXTURE ) && ( TSSTATE ( pContext->iChipStage[0], D3DTSS_ALPHAOP ) != D3DTOP_SELECTARG2 ) ||
  3937. ( TSSTATESELECT ( pContext->iChipStage[0], D3DTSS_ALPHAARG2 ) == D3DTA_TEXTURE ) && ( TSSTATE ( pContext->iChipStage[0], D3DTSS_ALPHAOP ) != D3DTOP_SELECTARG1 ) )
  3938. {
  3939. // Panic! In future, we should feed white to the argument using the TFACTOR thing,
  3940. // but for now just disable the rest of the pipeline.
  3941. bProcessChipStage0 = FALSE;
  3942. bProcessChipStage1 = FALSE;
  3943. bProcessChipStage2 = FALSE;
  3944. }
  3945. }
  3946. if ( bProcessChipStage0 )
  3947. {
  3948. // Set up stage 0
  3949. DISPDBG((DBGLVL,"Texture Stage 0 is valid - setting it up"));
  3950. __TXT_TranslateToChipBlendMode(pContext,
  3951. &pContext->TextureStageState[pContext->iChipStage[0]],
  3952. pSoftP3RX,
  3953. pContext->iChipStage[0],
  3954. 0);
  3955. iLastChipStage = 1;
  3956. bProcessChipStage0 = FALSE;
  3957. }
  3958. // Handle chip stage 1.
  3959. if ( TSSTATE ( pContext->iChipStage[1], D3DTSS_COLOROP ) == D3DTOP_DISABLE )
  3960. {
  3961. // Nothing more to do.
  3962. bProcessChipStage1 = FALSE;
  3963. bProcessChipStage2 = FALSE;
  3964. }
  3965. if ( pContext->iStageTex[pContext->iChipStage[1]] == -1 )
  3966. {
  3967. // This stage has no texture - is anyone trying to use it?
  3968. if (( TSSTATESELECT ( pContext->iChipStage[1], D3DTSS_COLORARG1 ) == D3DTA_TEXTURE ) && ( TSSTATE ( pContext->iChipStage[1], D3DTSS_COLOROP ) != D3DTOP_SELECTARG2 ) ||
  3969. ( TSSTATESELECT ( pContext->iChipStage[1], D3DTSS_COLORARG2 ) == D3DTA_TEXTURE ) && ( TSSTATE ( pContext->iChipStage[1], D3DTSS_COLOROP ) != D3DTOP_SELECTARG1 ) ||
  3970. ( TSSTATESELECT ( pContext->iChipStage[1], D3DTSS_ALPHAARG1 ) == D3DTA_TEXTURE ) && ( TSSTATE ( pContext->iChipStage[1], D3DTSS_ALPHAOP ) != D3DTOP_SELECTARG2 ) ||
  3971. ( TSSTATESELECT ( pContext->iChipStage[1], D3DTSS_ALPHAARG2 ) == D3DTA_TEXTURE ) && ( TSSTATE ( pContext->iChipStage[1], D3DTSS_ALPHAOP ) != D3DTOP_SELECTARG1 ) )
  3972. {
  3973. // Panic! In future, we should feed white to the argument using the TFACTOR thing,
  3974. // but for now just disable the rest of the pipeline.
  3975. bProcessChipStage1 = FALSE;
  3976. bProcessChipStage2 = FALSE;
  3977. }
  3978. }
  3979. if ( bProcessChipStage1 )
  3980. {
  3981. // Set up stage 1
  3982. DISPDBG((DBGLVL,"Texture Stage 1 is valid - setting it up"));
  3983. __TXT_TranslateToChipBlendMode(pContext,
  3984. &pContext->TextureStageState[pContext->iChipStage[1]],
  3985. pSoftP3RX,
  3986. pContext->iChipStage[1],
  3987. 1);
  3988. iLastChipStage = 2;
  3989. bProcessChipStage1 = FALSE;
  3990. }
  3991. // Handle chip stage 2.
  3992. if ( TSSTATE ( pContext->iChipStage[2], D3DTSS_COLOROP ) == D3DTOP_DISABLE )
  3993. {
  3994. // Nothing more to do.
  3995. bProcessChipStage2 = FALSE;
  3996. }
  3997. if ( pContext->iStageTex[pContext->iChipStage[2]] == -1 )
  3998. {
  3999. // This stage has no texture - is anyone trying to use it?
  4000. if (( TSSTATESELECT ( pContext->iChipStage[2], D3DTSS_COLORARG1 ) == D3DTA_TEXTURE ) && ( TSSTATE ( pContext->iChipStage[2], D3DTSS_COLOROP ) != D3DTOP_SELECTARG2 ) ||
  4001. ( TSSTATESELECT ( pContext->iChipStage[2], D3DTSS_COLORARG2 ) == D3DTA_TEXTURE ) && ( TSSTATE ( pContext->iChipStage[2], D3DTSS_COLOROP ) != D3DTOP_SELECTARG1 ) ||
  4002. ( TSSTATESELECT ( pContext->iChipStage[2], D3DTSS_ALPHAARG1 ) == D3DTA_TEXTURE ) && ( TSSTATE ( pContext->iChipStage[2], D3DTSS_ALPHAOP ) != D3DTOP_SELECTARG2 ) ||
  4003. ( TSSTATESELECT ( pContext->iChipStage[2], D3DTSS_ALPHAARG2 ) == D3DTA_TEXTURE ) && ( TSSTATE ( pContext->iChipStage[2], D3DTSS_ALPHAOP ) != D3DTOP_SELECTARG1 ) )
  4004. {
  4005. // Panic! In future, we should feed white to the argument using the TFACTOR thing,
  4006. // but for now just disable the rest of the pipeline.
  4007. bProcessChipStage2 = FALSE;
  4008. }
  4009. }
  4010. if ( bProcessChipStage2 )
  4011. {
  4012. // Set up chip stage 2 - texapp.
  4013. DISPDBG((DBGLVL,"Texture Stage 2 is valid - setting it up"));
  4014. DISPDBG((ERRLVL,"** _D3DChangeTextureP3RX: Cool - an app is using the "
  4015. "TexApp unit - tell someone!"));
  4016. __TXT_TranslateToChipBlendMode(pContext,
  4017. &pContext->TextureStageState[pContext->iChipStage[2]],
  4018. pSoftP3RX,
  4019. pContext->iChipStage[2],
  4020. 2);
  4021. iLastChipStage = 3;
  4022. bProcessChipStage2 = FALSE;
  4023. }
  4024. // This must be last.
  4025. if ( TSSTATE ( pContext->iChipStage[3], D3DTSS_COLOROP ) != D3DTOP_DISABLE )
  4026. {
  4027. // Oops - ran out of stages to set up.
  4028. SET_BLEND_ERROR ( pContext, BSF_TOO_MANY_BLEND_STAGES );
  4029. iLastChipStage = 3;
  4030. }
  4031. switch ( iLastChipStage )
  4032. {
  4033. case 0:
  4034. DISPDBG((DBGLVL,"Texture Composite 0 is disabled"));
  4035. // This should have been caught ages ago.
  4036. pSoftP3RX->P3RXTextureCompositeColorMode0.Arg2 = P3RX_TEXCOMP_CC;
  4037. pSoftP3RX->P3RXTextureCompositeColorMode0.InvertArg2 = __PERMEDIA_DISABLE;
  4038. pSoftP3RX->P3RXTextureCompositeColorMode0.A = P3RX_TEXCOMP_ARG2;
  4039. pSoftP3RX->P3RXTextureCompositeColorMode0.Operation = P3RX_TEXCOMP_OPERATION_PASS_A;
  4040. pSoftP3RX->P3RXTextureCompositeColorMode0.Scale = P3RX_TEXCOMP_OPERATION_SCALE_ONE;
  4041. pSoftP3RX->P3RXTextureCompositeColorMode0.Enable = __PERMEDIA_ENABLE;
  4042. pSoftP3RX->P3RXTextureCompositeAlphaMode0.Arg2 = P3RX_TEXCOMP_CA;
  4043. pSoftP3RX->P3RXTextureCompositeAlphaMode0.InvertArg1 = __PERMEDIA_DISABLE;
  4044. pSoftP3RX->P3RXTextureCompositeAlphaMode0.A = P3RX_TEXCOMP_ARG2;
  4045. pSoftP3RX->P3RXTextureCompositeAlphaMode0.Operation = P3RX_TEXCOMP_OPERATION_PASS_A;
  4046. pSoftP3RX->P3RXTextureCompositeAlphaMode0.Scale = P3RX_TEXCOMP_OPERATION_SCALE_ONE;
  4047. pSoftP3RX->P3RXTextureCompositeAlphaMode0.Enable = __PERMEDIA_ENABLE;
  4048. // fall through
  4049. case 1:
  4050. DISPDBG((DBGLVL,"Texture Composite 1 is disabled"));
  4051. // Make sure the second stage passes the texel that the first stage generated
  4052. if ( pContext->bStage0DotProduct )
  4053. {
  4054. // First stage was a dot-product - do the summing (even in the alpha channel).
  4055. pSoftP3RX->P3RXTextureCompositeColorMode1.Arg2 = P3RX_TEXCOMP_SUM;
  4056. pSoftP3RX->P3RXTextureCompositeAlphaMode1.Arg2 = P3RX_TEXCOMP_SUM;
  4057. }
  4058. else
  4059. {
  4060. pSoftP3RX->P3RXTextureCompositeColorMode1.Arg2 = P3RX_TEXCOMP_OC;
  4061. pSoftP3RX->P3RXTextureCompositeAlphaMode1.Arg2 = P3RX_TEXCOMP_OA;
  4062. }
  4063. pSoftP3RX->P3RXTextureCompositeColorMode1.InvertArg2 = __PERMEDIA_DISABLE;
  4064. pSoftP3RX->P3RXTextureCompositeColorMode1.A = P3RX_TEXCOMP_ARG2;
  4065. pSoftP3RX->P3RXTextureCompositeColorMode1.Operation = P3RX_TEXCOMP_OPERATION_PASS_A;
  4066. pSoftP3RX->P3RXTextureCompositeColorMode1.Scale = P3RX_TEXCOMP_OPERATION_SCALE_ONE;
  4067. pSoftP3RX->P3RXTextureCompositeColorMode1.Enable = __PERMEDIA_ENABLE;
  4068. pSoftP3RX->P3RXTextureCompositeAlphaMode1.InvertArg2 = __PERMEDIA_DISABLE;
  4069. pSoftP3RX->P3RXTextureCompositeAlphaMode1.A = P3RX_TEXCOMP_ARG2;
  4070. pSoftP3RX->P3RXTextureCompositeAlphaMode1.Operation = P3RX_TEXCOMP_OPERATION_PASS_A;
  4071. pSoftP3RX->P3RXTextureCompositeAlphaMode1.Scale = P3RX_TEXCOMP_OPERATION_SCALE_ONE;
  4072. pSoftP3RX->P3RXTextureCompositeAlphaMode1.Enable = __PERMEDIA_ENABLE;
  4073. // fall through
  4074. case 2:
  4075. // Texapp to passthrough.
  4076. DISPDBG((DBGLVL,"Texture Application is disabled"));
  4077. pSoftP3RX->P3RXTextureApplicationMode.ColorB = P3RX_TEXAPP_B_TC;
  4078. pSoftP3RX->P3RXTextureApplicationMode.ColorOperation = P3RX_TEXAPP_OPERATION_PASS_B;
  4079. pSoftP3RX->P3RXTextureApplicationMode.ColorInvertI = __PERMEDIA_DISABLE;
  4080. pSoftP3RX->P3RXTextureApplicationMode.AlphaB = P3RX_TEXAPP_B_TC;
  4081. pSoftP3RX->P3RXTextureApplicationMode.AlphaOperation = P3RX_TEXAPP_OPERATION_PASS_B;
  4082. pSoftP3RX->P3RXTextureApplicationMode.AlphaInvertI = __PERMEDIA_DISABLE;
  4083. // fall through
  4084. case 3:
  4085. // Nothing else in the pipeline to disable.
  4086. // fall through
  4087. break;
  4088. default:
  4089. DISPDBG((ERRLVL,"** _D3DChangeTextureP3RX: iLastChipStage was > 3 - oops."));
  4090. break;
  4091. }
  4092. // Set up the alpha-map filtering to reflect the single/multi/mip-mapped texturing status
  4093. // All the other colour-key stuff has already been set up.
  4094. if( pContext->bCanChromaKey )
  4095. {
  4096. ASSERTDD ( pTexture0 != NULL, "** _D3DChangeTextureP3RX: pTexture was NULL" );
  4097. if( pTexture0->bMipMap )
  4098. {
  4099. pSoftP3RX->P3RXTextureFilterMode.AlphaMapFilterLimit0 = 4;
  4100. pSoftP3RX->P3RXTextureFilterMode.AlphaMapFilterLimit1 = 4;
  4101. if ( pContext->bTex0Valid )
  4102. {
  4103. // Filter mode is irrelevant - this just works!
  4104. pSoftP3RX->P3RXTextureFilterMode.AlphaMapFilterLimit01 = 7;
  4105. }
  4106. else
  4107. {
  4108. DISPDBG((ERRLVL,"** _D3DChangeTextureP3RX: Trying to mipmap without a valid texture."));
  4109. pSoftP3RX->P3RXTextureFilterMode.AlphaMapFilterLimit01 = 8;
  4110. }
  4111. ASSERTDD ( !pContext->bTex1Valid, "** _D3DChangeTextureP3RX: Trying to mipmap with too many textures." );
  4112. }
  4113. else
  4114. {
  4115. // No mipmapping.
  4116. if ( pContext->bTex0Valid )
  4117. {
  4118. // Don't care about filter mode - this just works.
  4119. pSoftP3RX->P3RXTextureFilterMode.AlphaMapFilterLimit0 = 7;
  4120. }
  4121. else
  4122. {
  4123. pSoftP3RX->P3RXTextureFilterMode.AlphaMapFilterLimit0 = 4;
  4124. }
  4125. if ( pContext->bTex1Valid )
  4126. {
  4127. // Don't care about filter mode - this just works.
  4128. pSoftP3RX->P3RXTextureFilterMode.AlphaMapFilterLimit1 = 7;
  4129. }
  4130. else
  4131. {
  4132. pSoftP3RX->P3RXTextureFilterMode.AlphaMapFilterLimit1 = 4;
  4133. }
  4134. }
  4135. }
  4136. // Enable Texture Address calculation
  4137. pSoftP3RX->P3RXTextureCoordMode.Enable = __PERMEDIA_ENABLE;
  4138. // Enable filtering
  4139. pSoftP3RX->P3RXTextureFilterMode.Enable = __PERMEDIA_ENABLE;
  4140. // // Enable Texel color generation
  4141. // pSoftP3RX->P3RXTextureApplicationMode.Enable = __PERMEDIA_ENABLE;
  4142. // Do we need to share the texture coordinates ?
  4143. if ( pContext->bTex0Valid && pContext->bTex1Valid &&
  4144. ( TSSTATE ( pContext->iTexStage[0], D3DTSS_TEXCOORDINDEX ) ==
  4145. TSSTATE ( pContext->iTexStage[1], D3DTSS_TEXCOORDINDEX ) ) )
  4146. {
  4147. pSoftP3RX->P3RX_P3DeltaControl.ShareS = __PERMEDIA_ENABLE;
  4148. pSoftP3RX->P3RX_P3DeltaControl.ShareT = __PERMEDIA_ENABLE;
  4149. }
  4150. else
  4151. {
  4152. pSoftP3RX->P3RX_P3DeltaControl.ShareS = __PERMEDIA_DISABLE;
  4153. pSoftP3RX->P3RX_P3DeltaControl.ShareT = __PERMEDIA_DISABLE;
  4154. }
  4155. P3_ENSURE_DX_SPACE((P3_LOD_LEVELS*2));
  4156. WAIT_FIFO((P3_LOD_LEVELS*2));
  4157. for (i = 0; i < P3_LOD_LEVELS; i++)
  4158. {
  4159. COPY_P3_DATA_OFFSET(TextureMapWidth0, pSoftP3RX->P3RXTextureMapWidth[i], i);
  4160. }
  4161. if ( ( GET_BLEND_ERROR(pContext) & BLEND_STATUS_FATAL_FLAG ) != 0 )
  4162. {
  4163. // Got a fatal blend error - signal it to the user.
  4164. DISPDBG((ERRLVL,"** _D3DChangeTextureP3RX: invalid blend mode"));
  4165. _D3DDisplayWholeTSSPipe ( pContext, WRNLVL );
  4166. // And make sure this is re-evaluated next time we render,
  4167. // so that this (probably very munged) invalid setup doesn't cripple
  4168. // any subsequent valid renderstates.
  4169. DIRTY_EVERYTHING(pContext);
  4170. }
  4171. P3_ENSURE_DX_SPACE(32);
  4172. WAIT_FIFO(32);
  4173. SEND_P3_DATA(TextureCompositeMode, __PERMEDIA_ENABLE);
  4174. COPY_P3_DATA(TextureFilterMode, pSoftP3RX->P3RXTextureFilterMode);
  4175. COPY_P3_DATA(TextureApplicationMode, pSoftP3RX->P3RXTextureApplicationMode);
  4176. COPY_P3_DATA(TextureCoordMode, pSoftP3RX->P3RXTextureCoordMode);
  4177. COPY_P3_DATA(DeltaControl, pSoftP3RX->P3RX_P3DeltaControl);
  4178. // Copy the current TFACTOR values.
  4179. SEND_P3_DATA ( TextureEnvColor, FORMAT_8888_32BIT_BGR(dwTexAppTfactor) );
  4180. SEND_P3_DATA ( TextureCompositeFactor0, FORMAT_8888_32BIT_BGR(dwTexComp0Tfactor) );
  4181. SEND_P3_DATA ( TextureCompositeFactor1, FORMAT_8888_32BIT_BGR(dwTexComp1Tfactor) );
  4182. DISPDBG((DBGLVL,"Current TFACTOR values. %x %x %x",
  4183. dwTexAppTfactor,
  4184. dwTexComp0Tfactor,
  4185. dwTexComp1Tfactor));
  4186. COPY_P3_DATA(DeltaMode, pSoftP3RX->P3RX_P3DeltaMode);
  4187. P3_ENSURE_DX_SPACE(32);
  4188. WAIT_FIFO(32);
  4189. COPY_P3_DATA(TextureCompositeColorMode0, pSoftP3RX->P3RXTextureCompositeColorMode0);
  4190. COPY_P3_DATA(TextureCompositeColorMode1, pSoftP3RX->P3RXTextureCompositeColorMode1);
  4191. COPY_P3_DATA(TextureCompositeAlphaMode0, pSoftP3RX->P3RXTextureCompositeAlphaMode0);
  4192. COPY_P3_DATA(TextureCompositeAlphaMode1, pSoftP3RX->P3RXTextureCompositeAlphaMode1);
  4193. COPY_P3_DATA(TextureReadMode1, pSoftP3RX->P3RXTextureReadMode1);
  4194. COPY_P3_DATA(TextureIndexMode1, pSoftP3RX->P3RXTextureIndexMode1);
  4195. COPY_P3_DATA(TextureReadMode0, pSoftP3RX->P3RXTextureReadMode0);
  4196. COPY_P3_DATA(TextureIndexMode0, pSoftP3RX->P3RXTextureIndexMode0);
  4197. // Make sure the texture cache is invalidated
  4198. P3RX_INVALIDATECACHE(__PERMEDIA_ENABLE, __PERMEDIA_DISABLE);
  4199. SEND_P3_DATA(LOD, 0);
  4200. SEND_P3_DATA(LOD1, 0);
  4201. {
  4202. struct LodRange range;
  4203. // Clear down whole register
  4204. *(DWORD *)&range = 0;
  4205. // Each of the Min and Max LODs are in 4.8 format. We only deal
  4206. // with integer LODs in the range (0, N) so we just compute the
  4207. // upper value N and shift it up 8 bits.
  4208. range.Min = 0;
  4209. range.Max = ( mipBases.dwTex0MipMax - mipBases.dwTex0MipBase ) << 8;
  4210. COPY_P3_DATA( LodRange0, range );
  4211. range.Min = 0;
  4212. range.Max = ( mipBases.dwTex1MipMax - mipBases.dwTex1MipBase ) << 8;
  4213. COPY_P3_DATA( LodRange1, range );
  4214. }
  4215. *pFlags |= SURFACE_TEXTURING;
  4216. // Turn texturing on in the render command
  4217. RENDER_TEXTURE_ENABLE(pContext->RenderCommand);
  4218. P3_DMA_COMMIT_BUFFER();
  4219. // See if the alpha-blend unit needs to be updated.
  4220. if ( bAlphaBlendDouble != pContext->bAlphaBlendMustDoubleSourceColour )
  4221. {
  4222. pContext->bAlphaBlendMustDoubleSourceColour = bAlphaBlendDouble;
  4223. DIRTY_ALPHABLEND(pContext);
  4224. }
  4225. DBG_EXIT(_D3DChangeTextureP3RX,0);
  4226. } // _D3DChangeTextureP3RX