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.

1282 lines
43 KiB

  1. //----------------------------------------------------------------------------
  2. //
  3. // rastctx.cpp
  4. //
  5. // Context functions + state functions.
  6. //
  7. // Copyright (C) Microsoft Corporation, 1997.
  8. //
  9. //----------------------------------------------------------------------------
  10. #include "pch.cpp"
  11. #pragma hdrstop
  12. #include "rampif.h"
  13. #include "rampmat.hpp"
  14. // Unlock previous texture if necessary. It's called before the texture handle
  15. // is going to be changed.
  16. #define CHECK_AND_UNLOCK_TEXTURE \
  17. { \
  18. if (m_uFlags & D3DCONTEXT_TEXTURE_LOCKED) \
  19. { \
  20. RastUnlockSpanTexture(); \
  21. } \
  22. }
  23. inline void
  24. D3DContext::RampSetFogData(UINT32 uState, UINT32 uStateVal)
  25. {
  26. RLDDIRampLightingDriver *pRampdrv =
  27. (RLDDIRampLightingDriver*)m_RastCtx.pRampDrv;
  28. if (pRampdrv != NULL)
  29. {
  30. switch(uState)
  31. {
  32. case D3DRENDERSTATE_FOGENABLE :
  33. pRampdrv->fog_enable = uStateVal;
  34. break;
  35. case D3DRENDERSTATE_FOGCOLOR :
  36. pRampdrv->fog_color = uStateVal;
  37. break;
  38. case D3DRENDERSTATE_FOGTABLEMODE :
  39. pRampdrv->driver.fog_mode = (D3DFOGMODE)uStateVal;
  40. break;
  41. case D3DRENDERSTATE_FOGTABLESTART :
  42. pRampdrv->driver.fog_start = (FLOAT)uStateVal;
  43. break;
  44. case D3DRENDERSTATE_FOGTABLEEND :
  45. pRampdrv->driver.fog_end = (FLOAT)uStateVal;
  46. break;
  47. case D3DRENDERSTATE_FOGTABLEDENSITY:
  48. pRampdrv->driver.fog_density = (FLOAT)uStateVal;
  49. break;
  50. }
  51. }
  52. }
  53. //----------------------------------------------------------------------------
  54. //
  55. // FillContext
  56. //
  57. // Fill the context with the info. from the surfaces.
  58. //
  59. //----------------------------------------------------------------------------
  60. HRESULT
  61. D3DContext::FillContext(LPDIRECTDRAWSURFACE pDDS,
  62. LPDIRECTDRAWSURFACE pDDSZ)
  63. {
  64. HRESULT hr;
  65. LPDDRAWI_DDRAWSURFACE_LCL pLcl =
  66. ((LPDDRAWI_DDRAWSURFACE_INT)(pDDS))->lpLcl;
  67. m_RastCtx.iSurfaceStride = DDSurf_Pitch(pLcl);
  68. m_RastCtx.iSurfaceBitCount = DDSurf_BitDepth(pLcl);
  69. m_RastCtx.iSurfaceStep = m_RastCtx.iSurfaceBitCount/8;
  70. HR_RET(FindOutSurfFormat(&(DDSurf_PixFmt(pLcl)),
  71. (D3DI_SPANTEX_FORMAT *)&(m_RastCtx.iSurfaceType)));
  72. m_RastCtx.Clip.left = m_RastCtx.Clip.top = 0;
  73. m_RastCtx.Clip.bottom = DDSurf_Height(pLcl);
  74. m_RastCtx.Clip.right = DDSurf_Width(pLcl);
  75. if (pDDSZ != NULL)
  76. {
  77. pLcl = ((LPDDRAWI_DDRAWSURFACE_INT)(pDDSZ))->lpLcl;
  78. m_RastCtx.pZBits = (PUINT8)SURFACE_MEMORY(pDDSZ);
  79. m_RastCtx.iZStride = DDSurf_Pitch(pLcl);
  80. m_RastCtx.iZBitCount = DDSurf_BitDepth(pLcl);
  81. m_RastCtx.iZStep = m_RastCtx.iZBitCount/8;
  82. }
  83. else
  84. {
  85. m_RastCtx.pZBits = NULL;
  86. m_RastCtx.iZStride = 0;
  87. m_RastCtx.iZBitCount = 0;
  88. m_RastCtx.iZStep = 0;
  89. }
  90. m_RastCtx.pDDS = pDDS;
  91. m_RastCtx.pDDSZ = pDDSZ;
  92. m_RastCtx.dwSize = sizeof(D3DI_RASTCTX);
  93. // Make sure SpanInit is called at least once
  94. SetAllStatesDirtyBits();
  95. // Check for MsGolf AppHack
  96. if (pLcl->lpSurfMore->lpDD_lcl->dwAppHackFlags & DDRAW_APPCOMPAT_FORCEMODULATED)
  97. {
  98. m_RastCtx.uFlags |= RASTCTXFLAGS_APPHACK_MSGOLF;
  99. }
  100. return D3D_OK;
  101. }
  102. HRESULT
  103. D3DContext::Initialize(LPDIRECTDRAWSURFACE pDDS,
  104. LPDIRECTDRAWSURFACE pDDSZ,
  105. DWORD BeadSet,
  106. DWORD devVer)
  107. {
  108. HRESULT hr;
  109. // Initialize the primitive processor.
  110. HR_RET(m_PrimProc.Initialize());
  111. memset(&m_RastCtx, 0, sizeof(m_RastCtx));
  112. m_uFlags = 0;
  113. HR_RET(FillContext(pDDS, pDDSZ));
  114. m_PrimProc.SetCtx(&m_RastCtx);
  115. dwSize = sizeof(D3DContext);
  116. // Initialize bead table enum
  117. m_RastCtx.BeadSet = (D3DI_BEADSET)BeadSet;
  118. STATESET_INIT(m_renderstate_override);
  119. // Init FVF data as legacy TL vertex
  120. m_fvfData.preFVF = -1;
  121. CheckFVF(D3DFVF_TLVERTEX);
  122. m_RastCtx.uDevVer = devVer;
  123. // All render and texture stage state is initialized by
  124. // DIRECT3DDEVICEI::stateInitialize
  125. // Init prim function table. It will be updated for RAMP, or when FVF
  126. // control word changes or when fill mode changes.
  127. m_fnPrims.pfnTri = RGB_TriNoPackSolid;
  128. m_fnPrims.pfnPoint = RGB_PointNoPack;
  129. m_fnPrims.pfnLine = RGB_LineNoPack;
  130. // This one should be always the same.
  131. m_fnPrims.pfnStoreLastPixelState = RGBRAMP_StoreLastPixelState;
  132. m_fnPrims.pfnDp2SetRenderStates = RGBRAMP_Dp2SetRenderStates;
  133. m_fnPrims.pfnDp2TextureStageState = RGBRAMP_Dp2TextureStageState;
  134. m_fnPrims.pfnDp2SetViewport = RGBRAMP_Dp2SetViewport;
  135. m_fnPrims.pfnDp2SetWRange = RGBRAMP_Dp2SetWRange;
  136. // Enable MMX Fast Paths (Monolithics) if a registry key for it is not 0
  137. m_RastCtx.dwMMXFPDisableMask[0] = 0x0; // enable MMX FP's by default
  138. HKEY hKey = (HKEY) NULL;
  139. if (ERROR_SUCCESS == RegOpenKey(HKEY_LOCAL_MACHINE, RESPATH_D3D, &hKey) )
  140. {
  141. DWORD dwType;
  142. DWORD dwValue;
  143. DWORD dwDisableMask[MMX_FP_DISABLE_MASK_NUM] = {0x0};
  144. DWORD dwSize = 4;
  145. // only code up looking at one mask, for now
  146. DDASSERT(MMX_FP_DISABLE_MASK_NUM == 1);
  147. if ( ERROR_SUCCESS == RegQueryValueEx( hKey, "MMXFPDisableMask0", NULL, &dwType, (LPBYTE) &dwValue, &dwSize) &&
  148. dwType == REG_DWORD )
  149. {
  150. dwDisableMask[0] = dwValue;
  151. }
  152. if ( ERROR_SUCCESS == RegQueryValueEx( hKey, "MMX Fast Path", NULL, &dwType, (LPBYTE) &dwValue, &dwSize) &&
  153. dwType == REG_DWORD)
  154. {
  155. if (dwValue == 0)
  156. {
  157. // Override MMXFPDisableMask0 and disable all MMX Fast Paths
  158. m_RastCtx.dwMMXFPDisableMask[0] = 0xffffffff;
  159. }
  160. else
  161. {
  162. // Take all MMX paths not disabled by MMXFPDisableMask0
  163. m_RastCtx.dwMMXFPDisableMask[0] = dwDisableMask[0];
  164. }
  165. }
  166. RegCloseKey( hKey );
  167. }
  168. return D3D_OK;
  169. }
  170. HRESULT
  171. D3DContext::SetViewport(LPD3DHAL_DP2VIEWPORTINFO pVpt)
  172. {
  173. m_RastCtx.Clip.left = pVpt->dwX;
  174. m_RastCtx.Clip.top = pVpt->dwY;
  175. m_RastCtx.Clip.bottom = pVpt->dwY + pVpt->dwHeight;
  176. m_RastCtx.Clip.right = pVpt->dwX + pVpt->dwWidth;
  177. return D3D_OK;
  178. }
  179. inline HRESULT
  180. D3DContext::CreateRampLightingDriver(void)
  181. {
  182. m_RastCtx.pRampDrv = RLDDIRampCreate(&m_RastCtx);
  183. if (m_RastCtx.pRampDrv == NULL)
  184. {
  185. return DDERR_OUTOFMEMORY;
  186. }
  187. else
  188. {
  189. return D3D_OK;
  190. }
  191. }
  192. inline void
  193. D3DContext::DestroyRampLightingDriver(void)
  194. {
  195. RLDDIRampDestroy((RLDDIRampLightingDriver*)m_RastCtx.pRampDrv);
  196. m_RastCtx.pRampDrv = NULL;
  197. }
  198. //----------------------------------------------------------------------------
  199. //
  200. // RastContextCreateC
  201. //
  202. // Calls RastContextCreate with the C bead set.
  203. //
  204. //----------------------------------------------------------------------------
  205. DWORD __stdcall
  206. RastContextCreateC(LPD3DHAL_CONTEXTCREATEDATA pCtxData)
  207. {
  208. return RastContextCreate(pCtxData, (DWORD)D3DIBS_C);
  209. }
  210. //----------------------------------------------------------------------------
  211. //
  212. // RastContextCreateCMMX
  213. //
  214. // Calls RastContextCreate with the CMMX bead set.
  215. //
  216. //----------------------------------------------------------------------------
  217. DWORD __stdcall
  218. RastContextCreateCMMX(LPD3DHAL_CONTEXTCREATEDATA pCtxData)
  219. {
  220. return RastContextCreate(pCtxData, (DWORD)D3DIBS_CMMX);
  221. }
  222. //----------------------------------------------------------------------------
  223. //
  224. // RastContextCreateMMX
  225. //
  226. // Calls RastContextCreate with the MMX bead set.
  227. //
  228. //----------------------------------------------------------------------------
  229. DWORD __stdcall
  230. RastContextCreateMMX(LPD3DHAL_CONTEXTCREATEDATA pCtxData)
  231. {
  232. return RastContextCreate(pCtxData, (DWORD)D3DIBS_MMX);
  233. }
  234. //----------------------------------------------------------------------------
  235. //
  236. // RastContextCreateMMXAsRGB
  237. //
  238. // Calls RastContextCreate with the MMX bead set, but remember that we
  239. // came from RGB.
  240. //
  241. //----------------------------------------------------------------------------
  242. DWORD __stdcall
  243. RastContextCreateMMXAsRGB(LPD3DHAL_CONTEXTCREATEDATA pCtxData)
  244. {
  245. return RastContextCreate(pCtxData, (DWORD)D3DIBS_MMXASRGB);
  246. }
  247. //----------------------------------------------------------------------------
  248. //
  249. // RastContextCreateRamp
  250. //
  251. // Calls RastContextCreate with the ramp bead set.
  252. //
  253. //----------------------------------------------------------------------------
  254. DWORD __stdcall
  255. RastContextCreateRamp(LPD3DHAL_CONTEXTCREATEDATA pCtxData)
  256. {
  257. HRESULT hr;
  258. hr = RastContextCreate(pCtxData, (DWORD)D3DIBS_RAMP);
  259. if (pCtxData->ddrval != D3D_OK)
  260. {
  261. return hr;
  262. }
  263. // Create a RampLightingDriver
  264. D3DContext *pDCtx = (D3DContext *)pCtxData->dwhContext;
  265. pCtxData->ddrval = pDCtx->CreateRampLightingDriver();
  266. // Init prim function table for RAMP
  267. pDCtx->InitRampFuncs();
  268. return hr;
  269. }
  270. //----------------------------------------------------------------------------
  271. //
  272. // RastContextCreate
  273. //
  274. // Creates a RASTCTX and initializes it with the info passed in.
  275. //
  276. //----------------------------------------------------------------------------
  277. DWORD __stdcall
  278. RastContextCreate(LPD3DHAL_CONTEXTCREATEDATA pCtxData, DWORD BeadSet)
  279. {
  280. DDASSERT(pCtxData != NULL);
  281. D3DContext *pDCtx = new D3DContext;
  282. if (pDCtx == NULL)
  283. {
  284. pCtxData->ddrval = DDERR_OUTOFMEMORY;
  285. return DDHAL_DRIVER_HANDLED;
  286. }
  287. pCtxData->ddrval =
  288. pDCtx->Initialize(pCtxData->lpDDS,
  289. pCtxData->lpDDSZ,
  290. BeadSet,
  291. (DWORD)pCtxData->dwhContext);
  292. pCtxData->dwhContext = (ULONG_PTR)pDCtx;
  293. PD3DI_RASTCTX pCtx = pDCtx->GetRastCtx();
  294. if ((D3DI_SPTFMT_PALETTE8 == pCtx->iSurfaceType) &&
  295. (D3DIBS_RAMP != BeadSet))
  296. {
  297. // need a ramp lighting driver for 8 bit palettized RGB output
  298. pCtxData->ddrval = pDCtx->CreateRampLightingDriver();
  299. if (pCtxData->ddrval == D3D_OK)
  300. {
  301. // initialize the RGB8 palette
  302. RLDDIRampMakePaletteRGB8((RLDDIRampLightingDriver*)pCtx->pRampDrv);
  303. // Make sure DD Palette is updated after it gets set by FindLightingRange
  304. RLDDIRampUpdateDDPalette(pCtx);
  305. }
  306. }
  307. return DDHAL_DRIVER_HANDLED;
  308. }
  309. //----------------------------------------------------------------------------
  310. //
  311. // RastContextDestroy
  312. //
  313. // Destroy a rast context.
  314. //
  315. //----------------------------------------------------------------------------
  316. DWORD __stdcall
  317. RastContextDestroy(LPD3DHAL_CONTEXTDESTROYDATA pCtxDestroyData)
  318. {
  319. D3DContext *pDCtx;
  320. VALIDATE_D3DCONTEXT("RastContextDestroy", pCtxDestroyData);
  321. PD3DI_RASTCTX pCtx = pDCtx->GetRastCtx();
  322. if (pCtx->pRampDrv)
  323. {
  324. // destroy the ramp lighting driver, if one was created
  325. pDCtx->DestroyRampLightingDriver();
  326. }
  327. delete pDCtx;
  328. pCtxDestroyData->ddrval = D3D_OK;
  329. return DDHAL_DRIVER_HANDLED;
  330. }
  331. //----------------------------------------------------------------------------
  332. //
  333. // ValidateTextureStageState
  334. //
  335. // Utility function that returns an appropriate D3DERR_ if the current
  336. // multi-texture setup can not be rendered, D3D_OK otherwise.
  337. //
  338. //----------------------------------------------------------------------------
  339. HRESULT
  340. D3DContext::ValidateTextureStageState(void)
  341. {
  342. #if DBG
  343. if ((m_RastCtx.pTexture[0] == m_RastCtx.pTexture[1]) &&
  344. (m_RastCtx.pTexture[0] != NULL) )
  345. {
  346. // except under very special circumstances, this will not work in RGB/MMX
  347. // since we keep a lot of stage state in the D3DI_SPANTEX structure
  348. D3D_ERR("(Rast) ValidateTextureStageState Warning, pTexture[0] == pTexture[1]");
  349. }
  350. #endif
  351. for (INT i = 0; i < 2; i++)
  352. {
  353. switch(m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(i,D3DTSS_COLOROP)])
  354. {
  355. default:
  356. return D3DERR_UNSUPPORTEDCOLOROPERATION;
  357. case D3DTOP_DISABLE:
  358. return D3D_OK; // don't have to validate further if the stage is disabled
  359. case D3DTOP_SELECTARG1:
  360. case D3DTOP_SELECTARG2:
  361. case D3DTOP_MODULATE:
  362. case D3DTOP_MODULATE2X:
  363. case D3DTOP_MODULATE4X:
  364. case D3DTOP_ADD:
  365. case D3DTOP_ADDSIGNED:
  366. case D3DTOP_BLENDDIFFUSEALPHA:
  367. case D3DTOP_BLENDTEXTUREALPHA:
  368. case D3DTOP_BLENDFACTORALPHA:
  369. case D3DTOP_BLENDTEXTUREALPHAPM:
  370. break;
  371. }
  372. switch(m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(i,D3DTSS_COLORARG1)] &
  373. ~(D3DTA_ALPHAREPLICATE|D3DTA_COMPLEMENT))
  374. {
  375. default:
  376. return D3DERR_UNSUPPORTEDCOLORARG;
  377. case (D3DTA_TEXTURE):
  378. break;
  379. }
  380. switch(m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(i,D3DTSS_COLORARG2)] &
  381. ~(D3DTA_ALPHAREPLICATE|D3DTA_COMPLEMENT))
  382. {
  383. default:
  384. return D3DERR_UNSUPPORTEDCOLORARG;
  385. case (D3DTA_TFACTOR):
  386. case (D3DTA_CURRENT):
  387. case (D3DTA_DIFFUSE):
  388. break;
  389. }
  390. switch(m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(i,D3DTSS_ALPHAOP)])
  391. {
  392. default:
  393. return D3DERR_UNSUPPORTEDALPHAOPERATION;
  394. case D3DTOP_DISABLE:
  395. break;
  396. case D3DTOP_SELECTARG1:
  397. case D3DTOP_SELECTARG2:
  398. case D3DTOP_MODULATE:
  399. case D3DTOP_MODULATE2X:
  400. case D3DTOP_MODULATE4X:
  401. case D3DTOP_ADD:
  402. case D3DTOP_ADDSIGNED:
  403. case D3DTOP_BLENDDIFFUSEALPHA:
  404. case D3DTOP_BLENDTEXTUREALPHA:
  405. case D3DTOP_BLENDFACTORALPHA:
  406. case D3DTOP_BLENDTEXTUREALPHAPM:
  407. // only validate alpha args if alpha op is not disable
  408. switch(m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(i,D3DTSS_ALPHAARG1)] &
  409. ~(D3DTA_ALPHAREPLICATE|D3DTA_COMPLEMENT))
  410. {
  411. default:
  412. return D3DERR_UNSUPPORTEDALPHAARG;
  413. case (D3DTA_TEXTURE):
  414. break;
  415. }
  416. switch(m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(i,D3DTSS_ALPHAARG2)] &
  417. ~(D3DTA_ALPHAREPLICATE|D3DTA_COMPLEMENT))
  418. {
  419. default:
  420. return D3DERR_UNSUPPORTEDALPHAARG;
  421. case (D3DTA_TFACTOR):
  422. case (D3DTA_CURRENT):
  423. case (D3DTA_DIFFUSE):
  424. break;
  425. }
  426. break;
  427. }
  428. }
  429. // allow unused state to be zero'ed since this is so common
  430. if ( !((m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(2,D3DTSS_COLOROP)] == D3DTOP_DISABLE) ||
  431. (m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(2,D3DTSS_COLOROP)] == 0)) )
  432. {
  433. return D3DERR_TOOMANYOPERATIONS;
  434. }
  435. return D3D_OK;
  436. }
  437. //----------------------------------------------------------------------------
  438. //
  439. // RastValidateTextureStageState
  440. //
  441. // Returns whether the current multitexture setup can be rendered and, if
  442. // so, the number of passes required to render it.
  443. //
  444. //----------------------------------------------------------------------------
  445. DWORD __stdcall
  446. RastValidateTextureStageState(LPD3DHAL_VALIDATETEXTURESTAGESTATEDATA pData)
  447. {
  448. D3DContext *pDCtx;
  449. VALIDATE_D3DCONTEXT("RastValidateTextureStageState", pData);
  450. pData->dwNumPasses = 1;
  451. pData->ddrval = pDCtx->ValidateTextureStageState();
  452. return DDHAL_DRIVER_HANDLED;
  453. }
  454. //----------------------------------------------------------------------------
  455. //
  456. // RastContextDestroyRamp
  457. //
  458. // Destroy a rast context.
  459. //
  460. //----------------------------------------------------------------------------
  461. DWORD __stdcall
  462. RastContextDestroyRamp(LPD3DHAL_CONTEXTDESTROYDATA pCtxDestroyData)
  463. {
  464. D3DContext *pDCtx;
  465. VALIDATE_D3DCONTEXT("RastContextDestroy", pCtxDestroyData);
  466. pDCtx->DestroyRampLightingDriver();
  467. delete pDCtx;
  468. pCtxDestroyData->ddrval = D3D_OK;
  469. return DDHAL_DRIVER_HANDLED;
  470. }
  471. //----------------------------------------------------------------------------
  472. //
  473. // RastSetRenderTarget
  474. //
  475. // Update a rast context with the info from a new render target.
  476. //
  477. //----------------------------------------------------------------------------
  478. DWORD __stdcall
  479. RastSetRenderTarget(LPD3DHAL_SETRENDERTARGETDATA pTgtData)
  480. {
  481. D3DContext *pDCtx;
  482. VALIDATE_D3DCONTEXT("RastSetRenderTarget", pTgtData);
  483. pTgtData->ddrval = pDCtx->FillContext(pTgtData->lpDDS, pTgtData->lpDDSZ);
  484. return DDHAL_DRIVER_HANDLED;
  485. }
  486. //----------------------------------------------------------------------------
  487. //
  488. // SetRenderState
  489. //
  490. // Check to see if a state change requires an update to the D3DCTX.
  491. //
  492. //----------------------------------------------------------------------------
  493. HRESULT
  494. D3DContext::SetRenderState(UINT32 uState, UINT32 uStateVal)
  495. {
  496. // Assume d3dim has filtered out unchanged states
  497. StateChanged(uState);
  498. m_RastCtx.pdwRenderState[uState] = uStateVal;
  499. switch(uState)
  500. {
  501. case D3DRENDERSTATE_FOGENABLE :
  502. case D3DRENDERSTATE_FOGCOLOR :
  503. case D3DRENDERSTATE_FOGTABLEMODE :
  504. case D3DRENDERSTATE_FOGTABLESTART :
  505. case D3DRENDERSTATE_FOGTABLEEND :
  506. case D3DRENDERSTATE_FOGTABLEDENSITY:
  507. RampSetFogData(uState, uStateVal);
  508. break;
  509. case D3DRENDERSTATE_CULLMODE:
  510. // Set face culling sign from state.
  511. switch(uStateVal)
  512. {
  513. case D3DCULL_CCW:
  514. m_RastCtx.uCullFaceSign = 1;
  515. break;
  516. case D3DCULL_CW:
  517. m_RastCtx.uCullFaceSign = 0;
  518. break;
  519. case D3DCULL_NONE:
  520. m_RastCtx.uCullFaceSign = 2;
  521. break;
  522. }
  523. break;
  524. case D3DRENDERSTATE_ZENABLE:
  525. if ( (D3DZB_FALSE != uStateVal) && (NULL == m_RastCtx.pDDSZ) )
  526. {
  527. DPF(0, "(ERROR) (Rast) SetRenderState: Can't set D3DRENDERSTATE_ZENABLE to %d if there is no Z Buffer", uStateVal);
  528. m_RastCtx.pdwRenderState[uState] = D3DZB_FALSE;
  529. }
  530. break;
  531. case D3DRENDERSTATE_LASTPIXEL:
  532. // Set last-pixel flag from state.
  533. if (uStateVal)
  534. {
  535. m_PrimProc.SetFlags(PPF_DRAW_LAST_LINE_PIXEL);
  536. }
  537. else
  538. {
  539. m_PrimProc.ClrFlags(PPF_DRAW_LAST_LINE_PIXEL);
  540. }
  541. break;
  542. // map legacy modes with one-to-one mappings to texture stage 0
  543. case D3DRENDERSTATE_TEXTUREADDRESS:
  544. m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_ADDRESS)] =
  545. m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_ADDRESSU)] =
  546. m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_ADDRESSV)] = uStateVal;
  547. MapTextureStage0State();
  548. break;
  549. case D3DRENDERSTATE_TEXTUREADDRESSU:
  550. m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_ADDRESSU)] = uStateVal;
  551. MapTextureStage0State();
  552. break;
  553. case D3DRENDERSTATE_TEXTUREADDRESSV:
  554. m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_ADDRESSV)] = uStateVal;
  555. MapTextureStage0State();
  556. break;
  557. case D3DRENDERSTATE_MIPMAPLODBIAS:
  558. m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_MIPMAPLODBIAS)] = uStateVal;
  559. MapTextureStage0State();
  560. break;
  561. case D3DRENDERSTATE_BORDERCOLOR:
  562. m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_BORDERCOLOR)] = uStateVal;
  563. MapTextureStage0State();
  564. break;
  565. case D3DRENDERSTATE_TEXTUREMAG:
  566. case D3DRENDERSTATE_TEXTUREMIN:
  567. // map legacy filtering/sampling state to texture stage 0
  568. MapLegacyTextureFilter();
  569. // assign to current texture
  570. MapTextureStage0State();
  571. break;
  572. case D3DRENDERSTATE_TEXTUREMAPBLEND:
  573. // map legacy blending state to texture stage 0
  574. MapLegacyTextureBlend();
  575. break;
  576. // map legacy WRAPU/V to per-index controls
  577. case D3DRENDERSTATE_WRAPU:
  578. m_RastCtx.pdwRenderState[D3DRENDERSTATE_WRAP0] &= ~D3DWRAP_U;
  579. m_RastCtx.pdwRenderState[D3DRENDERSTATE_WRAP0] |= ((uStateVal) ? D3DWRAP_U : 0);
  580. StateChanged(D3DRENDERSTATE_WRAP0);
  581. break;
  582. case D3DRENDERSTATE_WRAPV:
  583. m_RastCtx.pdwRenderState[D3DRENDERSTATE_WRAP0] &= ~D3DWRAP_V;
  584. m_RastCtx.pdwRenderState[D3DRENDERSTATE_WRAP0] |= ((uStateVal) ? D3DWRAP_V : 0);
  585. StateChanged(D3DRENDERSTATE_WRAP0);
  586. break;
  587. //
  588. // NOTE - this compututation of cActTex does not account for blend-only stages
  589. //
  590. case D3DRENDERSTATE_TEXTUREHANDLE:
  591. CHECK_AND_UNLOCK_TEXTURE;
  592. // map handle thru to stage 0
  593. m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_TEXTUREMAP)] = uStateVal;
  594. m_RastCtx.pTexture[1] = NULL;
  595. // set up for single stage
  596. if (uStateVal == 0)
  597. {
  598. m_RastCtx.pTexture[0] = NULL;
  599. }
  600. else
  601. {
  602. m_RastCtx.pTexture[0] = HANDLE_TO_SPANTEX(uStateVal);
  603. }
  604. // map stage 0 state to first texture
  605. MapTextureStage0State();
  606. UpdateActiveTexStageCount();
  607. break;
  608. case D3DHAL_TSS_TEXTUREMAP0:
  609. // Silently zero out legacy handle. They didn't mean it.
  610. if (m_RastCtx.pdwRenderState[D3DRENDERSTATE_TEXTUREHANDLE] != 0 &&
  611. uStateVal != 0)
  612. {
  613. m_RastCtx.pdwRenderState[D3DRENDERSTATE_TEXTUREHANDLE] = 0;
  614. }
  615. CHECK_AND_UNLOCK_TEXTURE;
  616. if (uStateVal == 0)
  617. {
  618. if (m_RastCtx.pdwRenderState[D3DRENDERSTATE_TEXTUREHANDLE] == 0)
  619. {
  620. m_RastCtx.pTexture[0] = NULL;
  621. }
  622. // don't set m_RastCtx.pTexture[1] = NULL (in case the handle is never
  623. // sent again). cActTex will keep it from being used until pTexture[0] is
  624. // set to something
  625. }
  626. else
  627. {
  628. #if DBG
  629. if (HANDLE_TO_SPANTEX(uStateVal) == m_RastCtx.pTexture[1])
  630. {
  631. D3D_ERR( "Stage1 and 2 have same texture handle." );
  632. return DDERR_INVALIDPARAMS;
  633. }
  634. #endif
  635. m_RastCtx.pTexture[0] = HANDLE_TO_SPANTEX(uStateVal);
  636. }
  637. // map stage 0 state to first texture
  638. MapTextureStage0State();
  639. UpdateActiveTexStageCount();
  640. break;
  641. case D3DHAL_TSS_TEXTUREMAP1:
  642. // Silently zero out legacy handle. They didn't mean it.
  643. if (m_RastCtx.pdwRenderState[D3DRENDERSTATE_TEXTUREHANDLE] != 0 &&
  644. uStateVal != 0)
  645. {
  646. m_RastCtx.pdwRenderState[D3DRENDERSTATE_TEXTUREHANDLE] = 0;
  647. }
  648. CHECK_AND_UNLOCK_TEXTURE;
  649. if (uStateVal == 0)
  650. {
  651. m_RastCtx.pTexture[1] = NULL;
  652. }
  653. else
  654. {
  655. // 2nd texture can only be enabled if there's an active
  656. // 1st texture, but computation of cActTex will prevent this
  657. // from happening
  658. #if DBG
  659. if (HANDLE_TO_SPANTEX(uStateVal) == m_RastCtx.pTexture[0])
  660. {
  661. D3D_ERR( "Stage1 and 2 have same texture handle." );
  662. return DDERR_INVALIDPARAMS;
  663. }
  664. #endif
  665. m_RastCtx.pTexture[1] = HANDLE_TO_SPANTEX(uStateVal);
  666. }
  667. // map stage 1 state to second texture
  668. MapTextureStage1State();
  669. UpdateActiveTexStageCount();
  670. break;
  671. // map single set ADDRESS to both U and V controls for stages 0 & 1
  672. case D3DHAL_TSS_OFFSET(0,D3DTSS_ADDRESS):
  673. m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_ADDRESSU)] = uStateVal;
  674. m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_ADDRESSV)] = uStateVal;
  675. MapTextureStage0State();
  676. break;
  677. case D3DHAL_TSS_OFFSET(1,D3DTSS_ADDRESS):
  678. m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(1,D3DTSS_ADDRESSU)] = uStateVal;
  679. m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(1,D3DTSS_ADDRESSV)] = uStateVal;
  680. MapTextureStage1State();
  681. break;
  682. case D3DHAL_TSS_OFFSET(0,D3DTSS_ADDRESSU):
  683. case D3DHAL_TSS_OFFSET(0,D3DTSS_ADDRESSV):
  684. case D3DHAL_TSS_OFFSET(0,D3DTSS_MIPMAPLODBIAS):
  685. case D3DHAL_TSS_OFFSET(0,D3DTSS_MAXMIPLEVEL):
  686. case D3DHAL_TSS_OFFSET(0,D3DTSS_BORDERCOLOR):
  687. case D3DHAL_TSS_OFFSET(0,D3DTSS_MAGFILTER):
  688. case D3DHAL_TSS_OFFSET(0,D3DTSS_MINFILTER):
  689. case D3DHAL_TSS_OFFSET(0,D3DTSS_MIPFILTER):
  690. MapTextureStage0State();
  691. break;
  692. case D3DHAL_TSS_OFFSET(1,D3DTSS_ADDRESSU):
  693. case D3DHAL_TSS_OFFSET(1,D3DTSS_ADDRESSV):
  694. case D3DHAL_TSS_OFFSET(1,D3DTSS_MIPMAPLODBIAS):
  695. case D3DHAL_TSS_OFFSET(1,D3DTSS_MAXMIPLEVEL):
  696. case D3DHAL_TSS_OFFSET(1,D3DTSS_BORDERCOLOR):
  697. case D3DHAL_TSS_OFFSET(1,D3DTSS_MAGFILTER):
  698. case D3DHAL_TSS_OFFSET(1,D3DTSS_MINFILTER):
  699. case D3DHAL_TSS_OFFSET(1,D3DTSS_MIPFILTER):
  700. MapTextureStage1State();
  701. break;
  702. case D3DHAL_TSS_OFFSET(0,D3DTSS_COLOROP):
  703. case D3DHAL_TSS_OFFSET(0,D3DTSS_COLORARG1):
  704. case D3DHAL_TSS_OFFSET(0,D3DTSS_COLORARG2):
  705. case D3DHAL_TSS_OFFSET(0,D3DTSS_ALPHAOP):
  706. case D3DHAL_TSS_OFFSET(0,D3DTSS_ALPHAARG1):
  707. case D3DHAL_TSS_OFFSET(0,D3DTSS_ALPHAARG2):
  708. case D3DHAL_TSS_OFFSET(1,D3DTSS_COLOROP):
  709. case D3DHAL_TSS_OFFSET(1,D3DTSS_COLORARG1):
  710. case D3DHAL_TSS_OFFSET(1,D3DTSS_COLORARG2):
  711. case D3DHAL_TSS_OFFSET(1,D3DTSS_ALPHAOP):
  712. case D3DHAL_TSS_OFFSET(1,D3DTSS_ALPHAARG1):
  713. case D3DHAL_TSS_OFFSET(1,D3DTSS_ALPHAARG2):
  714. // anything that effects the validity of the texture blending
  715. // could change the number of active texture stages
  716. UpdateActiveTexStageCount();
  717. break;
  718. }
  719. return D3D_OK;
  720. }
  721. //-----------------------------------------------------------------------------
  722. //
  723. // UpdateActiveTexStageCount - Steps through per-stage renderstate and computes
  724. // a count of currently active texture stages. For legacy texture, the count
  725. // is at most one.
  726. //
  727. //-----------------------------------------------------------------------------
  728. HRESULT D3DContext::UpdateActiveTexStageCount( void )
  729. {
  730. HRESULT hr;
  731. UINT cNewActTex = 0;
  732. // conservative but correct
  733. if ((hr = ValidateTextureStageState()) == D3D_OK)
  734. {
  735. // always one active texture stage for legacy texture mode
  736. if ( NULL != m_RastCtx.pdwRenderState[D3DRENDERSTATE_TEXTUREHANDLE] )
  737. {
  738. cNewActTex = 1;
  739. }
  740. else
  741. {
  742. // count number of contiguous-from-zero active texture blend stages
  743. for ( INT iStage=0; iStage<2; iStage++ )
  744. {
  745. // check for disabled stage (subsequent are thus inactive)
  746. // also conservatively checks for incorrectly enabled stage (might be legacy)
  747. if ( ( m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(iStage,D3DTSS_COLOROP)] == D3DTOP_DISABLE ) ||
  748. ( m_RastCtx.pTexture[iStage] == NULL ) )
  749. {
  750. break;
  751. }
  752. // stage is active
  753. cNewActTex ++;
  754. }
  755. }
  756. }
  757. if (m_RastCtx.cActTex != cNewActTex)
  758. {
  759. CHECK_AND_UNLOCK_TEXTURE;
  760. StateChanged(D3DRENDERSTATE_TEXTUREHANDLE);
  761. m_RastCtx.cActTex = cNewActTex;
  762. }
  763. return hr;
  764. }
  765. //----------------------------------------------------------------------------
  766. //
  767. // UpdateRenderStates
  768. //
  769. // Update a list of render states and notify components of state change.
  770. //
  771. //----------------------------------------------------------------------------
  772. HRESULT D3DContext::
  773. UpdateRenderStates(LPDWORD puStateChange, UINT cStateChanges)
  774. {
  775. HRESULT hr;
  776. INT i;
  777. UINT32 State, StateVal;
  778. if (cStateChanges == 0)
  779. {
  780. return D3D_OK;
  781. }
  782. // Update the D3DCTX
  783. for (i = 0; i < (INT)cStateChanges; i++)
  784. {
  785. State = *puStateChange ++;
  786. StateVal = * puStateChange++;
  787. HR_RET(SetRenderState(State, StateVal));
  788. }
  789. return D3D_OK;
  790. }
  791. //----------------------------------------------------------------------------
  792. //
  793. // UpdateAllRenderStates
  794. //
  795. // Update all render states.
  796. // It is still kept here because we probably need it in the case of fail-over.
  797. //
  798. //----------------------------------------------------------------------------
  799. HRESULT
  800. D3DContext::UpdateAllRenderStates(LPDWORD puStates)
  801. {
  802. HRESULT hr, hrSet;
  803. INT i;
  804. DDASSERT(puStates != NULL);
  805. // Update D3DCTX.
  806. // Attempt to set as many states as possible, even if there are
  807. // errors on some. This allows context initialization to work
  808. // even though some of the states fail due to dependencies on
  809. // other state, such as active texture handles.
  810. // SetRenderState failures are noted and returned eventually,
  811. // even if everything else succeeds.
  812. hrSet = D3D_OK;
  813. for (i = 0; i < D3DHAL_MAX_RSTATES_AND_STAGES; i++)
  814. {
  815. if ((hr = SetRenderState(i, puStates[i])) != D3D_OK)
  816. {
  817. hrSet = hr;
  818. }
  819. }
  820. return hrSet;
  821. }
  822. //----------------------------------------------------------------------------
  823. //
  824. // Dp2SetRenderStates
  825. //
  826. // Called by Drawprim2 to set render states..
  827. //
  828. //----------------------------------------------------------------------------
  829. HRESULT
  830. D3DContext::Dp2SetRenderStates(LPD3DHAL_DP2COMMAND pCmd, LPDWORD lpdwRuntimeRStates)
  831. {
  832. WORD wStateCount = pCmd->wStateCount;
  833. INT i;
  834. HRESULT hr;
  835. D3DHAL_DP2RENDERSTATE *pRenderState =
  836. (D3DHAL_DP2RENDERSTATE *)(pCmd + 1);
  837. // Flush the prim proc before any state changs
  838. HR_RET(End(FALSE));
  839. for (i = 0; i < (INT)wStateCount; i++, pRenderState++)
  840. {
  841. UINT32 type = (UINT32) pRenderState->RenderState;
  842. // Check for overrides
  843. if (IS_OVERRIDE(type)) {
  844. UINT32 override = GET_OVERRIDE(type);
  845. if (pRenderState->dwState)
  846. STATESET_SET(m_renderstate_override, override);
  847. else
  848. STATESET_CLEAR(m_renderstate_override, override);
  849. continue;
  850. }
  851. if (STATESET_ISSET(m_renderstate_override, type))
  852. continue;
  853. // Set the runtime copy (if necessary)
  854. if (NULL != lpdwRuntimeRStates)
  855. {
  856. lpdwRuntimeRStates[pRenderState->RenderState] = pRenderState->dwState;
  857. }
  858. // Set the state
  859. HR_RET(SetRenderState(pRenderState->RenderState,
  860. pRenderState->dwState));
  861. }
  862. hr = Begin();
  863. return hr;
  864. }
  865. //----------------------------------------------------------------------------
  866. //
  867. // Begin - Before rendering preparation
  868. //
  869. //
  870. //----------------------------------------------------------------------------
  871. HRESULT
  872. D3DContext::Begin(void)
  873. {
  874. HRESULT hr;
  875. DDASSERT((m_uFlags & D3DCONTEXT_IN_BEGIN) == 0);
  876. // ATTENTION call this less often?
  877. UpdateColorKeyAndPalette();
  878. // Check for state changes
  879. if (IsAnyStatesChanged())
  880. {
  881. // Check for fillmode change
  882. if (IsStateChanged(D3DRENDERSTATE_FILLMODE))
  883. {
  884. UpdatePrimFunctionTbl();
  885. }
  886. BOOL bMaxMipLevelsDirty = FALSE;
  887. for (INT j = 0; j < (INT)m_RastCtx.cActTex; j++)
  888. {
  889. PD3DI_SPANTEX pSpanTex = m_RastCtx.pTexture[j];
  890. if (pSpanTex)
  891. {
  892. bMaxMipLevelsDirty = bMaxMipLevelsDirty || (pSpanTex->uFlags & D3DI_SPANTEX_MAXMIPLEVELS_DIRTY);
  893. }
  894. }
  895. if (IsStateChanged(D3DRENDERSTATE_TEXTUREHANDLE) ||
  896. IsStateChanged(D3DHAL_TSS_TEXTUREMAP0) ||
  897. IsStateChanged(D3DHAL_TSS_TEXTUREMAP1) ||
  898. bMaxMipLevelsDirty)
  899. {
  900. // Relock texture if texture handles have changed.
  901. // SetRenderState should have already unlocked the texture.
  902. if (m_uFlags & D3DCONTEXT_TEXTURE_LOCKED)
  903. {
  904. RastUnlockSpanTexture();
  905. }
  906. HR_RET(RastLockSpanTexture());
  907. }
  908. // Check for WRAP state change
  909. for (int iWrap=0; iWrap<8; iWrap++)
  910. {
  911. D3DRENDERSTATETYPE iWrapState = (D3DRENDERSTATETYPE)(D3DRENDERSTATE_WRAP0+iWrap);
  912. if (IsStateChanged(iWrapState))
  913. {
  914. int i;
  915. for (i=0; i < 2; i++)
  916. {
  917. if (m_fvfData.TexIdx[i] == iWrap)
  918. {
  919. m_RastCtx.pdwWrap[i] = m_RastCtx.pdwRenderState[iWrapState];
  920. }
  921. }
  922. }
  923. }
  924. // Notify primitive Processor of state change.
  925. m_PrimProc.StateChanged();
  926. // Clear state dirtybits
  927. ClearAllStatesDirtyBits();
  928. // Must call SpanInit AFTER texture is locked, since this
  929. // sets various flags and fields that are needed for bead choosing
  930. // Call SpanInit to setup the beads
  931. HR_RET(SpanInit(&m_RastCtx));
  932. }
  933. // If texture is not locked yet, lock it
  934. if (!(m_uFlags & D3DCONTEXT_TEXTURE_LOCKED))
  935. {
  936. HR_RET(RastLockSpanTexture());
  937. }
  938. // Lock rendering target.
  939. if ((hr=LockSurface(m_RastCtx.pDDS, (LPVOID *)&(m_RastCtx.pSurfaceBits))) != D3D_OK)
  940. {
  941. RastUnlockSpanTexture();
  942. return hr;
  943. }
  944. if (m_RastCtx.pDDSZ != NULL)
  945. {
  946. if ((hr=LockSurface(m_RastCtx.pDDSZ, (LPVOID *)&(m_RastCtx.pZBits))) != D3D_OK)
  947. {
  948. RastUnlockSpanTexture();
  949. UnlockSurface(m_RastCtx.pDDS);
  950. return hr;
  951. }
  952. }
  953. else
  954. {
  955. m_RastCtx.pZBits = NULL;
  956. }
  957. // Prepare the primitive processor
  958. m_PrimProc.Begin();
  959. m_uFlags |= D3DCONTEXT_IN_BEGIN;
  960. if (m_RastCtx.pRampDrv)
  961. {
  962. pTexRampmapSave = m_RastCtx.pTexRampMap;
  963. }
  964. return D3D_OK;
  965. }
  966. //-----------------------------------------------------------------------------
  967. //
  968. // MapTextureStage0/1State - Maps state0/stage1 texture state to spantex object
  969. //
  970. //-----------------------------------------------------------------------------
  971. void
  972. D3DContext::MapTextureStage0State( void )
  973. {
  974. if (m_RastCtx.pTexture[0] == NULL) return;
  975. //
  976. // assign texture state from stage 0
  977. //
  978. m_RastCtx.pTexture[0]->TexAddrU = (D3DTEXTUREADDRESS)(m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_ADDRESSU)]);
  979. m_RastCtx.pTexture[0]->TexAddrV = (D3DTEXTUREADDRESS)(m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_ADDRESSV)]);
  980. m_RastCtx.pTexture[0]->BorderColor = (D3DCOLOR)(m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_BORDERCOLOR)]);
  981. m_RastCtx.pTexture[0]->uMagFilter = (D3DTEXTUREMAGFILTER)(m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_MAGFILTER)]);
  982. m_RastCtx.pTexture[0]->uMinFilter = (D3DTEXTUREMINFILTER)(m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_MINFILTER)]);
  983. m_RastCtx.pTexture[0]->uMipFilter = (D3DTEXTUREMIPFILTER)(m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_MIPFILTER)]);
  984. m_RastCtx.pTexture[0]->cLOD =
  985. (D3DTFP_NONE == m_RastCtx.pTexture[0]->uMipFilter)
  986. ? 0 : m_RastCtx.pTexture[0]->cLODTex;
  987. {
  988. m_RastCtx.pTexture[0]->fLODBias = m_RastCtx.pfRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_MIPMAPLODBIAS)];
  989. }
  990. if (m_RastCtx.pTexture[0]->iMaxMipLevel != (INT32)m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_MAXMIPLEVEL)])
  991. {
  992. m_RastCtx.pTexture[0]->iMaxMipLevel = (INT32)m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_MAXMIPLEVEL)];
  993. m_RastCtx.pTexture[0]->uFlags |= D3DI_SPANTEX_MAXMIPLEVELS_DIRTY;
  994. }
  995. }
  996. void
  997. D3DContext::MapTextureStage1State( void )
  998. {
  999. if (m_RastCtx.pTexture[1] == NULL) return;
  1000. //
  1001. // assign texture state from stage 0
  1002. //
  1003. m_RastCtx.pTexture[1]->TexAddrU = (D3DTEXTUREADDRESS)(m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(1,D3DTSS_ADDRESSU)]);
  1004. m_RastCtx.pTexture[1]->TexAddrV = (D3DTEXTUREADDRESS)(m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(1,D3DTSS_ADDRESSV)]);
  1005. m_RastCtx.pTexture[1]->BorderColor = (D3DCOLOR)(m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(1,D3DTSS_BORDERCOLOR)]);
  1006. m_RastCtx.pTexture[1]->uMagFilter = (D3DTEXTUREMAGFILTER)(m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(1,D3DTSS_MAGFILTER)]);
  1007. m_RastCtx.pTexture[1]->uMinFilter = (D3DTEXTUREMINFILTER)(m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(1,D3DTSS_MINFILTER)]);
  1008. m_RastCtx.pTexture[1]->uMipFilter = (D3DTEXTUREMIPFILTER)(m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(1,D3DTSS_MIPFILTER)]);
  1009. m_RastCtx.pTexture[1]->cLOD =
  1010. (D3DTFP_NONE == m_RastCtx.pTexture[1]->uMipFilter)
  1011. ? 0 : m_RastCtx.pTexture[1]->cLODTex;
  1012. {
  1013. m_RastCtx.pTexture[1]->fLODBias = m_RastCtx.pfRenderState[D3DHAL_TSS_OFFSET(1,D3DTSS_MIPMAPLODBIAS)];
  1014. }
  1015. if (m_RastCtx.pTexture[1]->iMaxMipLevel != (INT32)m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(1,D3DTSS_MAXMIPLEVEL)])
  1016. {
  1017. m_RastCtx.pTexture[1]->iMaxMipLevel = (INT32)m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(1,D3DTSS_MAXMIPLEVEL)];
  1018. m_RastCtx.pTexture[1]->uFlags |= D3DI_SPANTEX_MAXMIPLEVELS_DIRTY;
  1019. }
  1020. }
  1021. //-----------------------------------------------------------------------------
  1022. //
  1023. // MapLegacyTextureFilter -
  1024. //
  1025. //-----------------------------------------------------------------------------
  1026. void
  1027. D3DContext::MapLegacyTextureFilter( void )
  1028. {
  1029. // D3D legacy filter specifications are (XXXMIP)YYY where XXX is the
  1030. // mip filter and YYY is the filter used within an LOD
  1031. // map MAG filter - legacy support is point or linear (and maybe aniso)
  1032. switch ( m_RastCtx.pdwRenderState[D3DRENDERSTATE_TEXTUREMAG] )
  1033. {
  1034. default:
  1035. case D3DFILTER_NEAREST:
  1036. m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_MAGFILTER)] = D3DTFG_POINT;
  1037. break;
  1038. case D3DFILTER_LINEAR:
  1039. // select based on aniso enable
  1040. m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_MAGFILTER)] = D3DTFG_LINEAR;
  1041. break;
  1042. }
  1043. // map MIN and MIP filter at the same time - legacy support
  1044. // has them intermingled...
  1045. switch ( m_RastCtx.pdwRenderState[D3DRENDERSTATE_TEXTUREMIN] )
  1046. {
  1047. case D3DFILTER_NEAREST:
  1048. m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_MINFILTER)] = D3DTFN_POINT;
  1049. m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_MIPFILTER)] = D3DTFP_NONE;
  1050. break;
  1051. case D3DFILTER_MIPNEAREST:
  1052. m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_MINFILTER)] = D3DTFN_POINT;
  1053. m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_MIPFILTER)] = D3DTFP_POINT;
  1054. break;
  1055. case D3DFILTER_LINEARMIPNEAREST:
  1056. m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_MINFILTER)] = D3DTFN_POINT;
  1057. m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_MIPFILTER)] = D3DTFP_LINEAR;
  1058. break;
  1059. case D3DFILTER_LINEAR:
  1060. m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_MINFILTER)] = D3DTFN_LINEAR;
  1061. m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_MIPFILTER)] = D3DTFP_NONE;
  1062. break;
  1063. case D3DFILTER_MIPLINEAR:
  1064. m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_MINFILTER)] = D3DTFN_LINEAR;
  1065. m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_MIPFILTER)] = D3DTFP_POINT;
  1066. break;
  1067. case D3DFILTER_LINEARMIPLINEAR:
  1068. m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_MINFILTER)] = D3DTFN_LINEAR;
  1069. m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_MIPFILTER)] = D3DTFP_LINEAR;
  1070. break;
  1071. }
  1072. }
  1073. //-----------------------------------------------------------------------------
  1074. //
  1075. // MapLegacyTextureBlend - Maps legacy (pre-DX6) texture blend modes to DX6
  1076. // texture blending controls. Uses per-stage program mode (first stage only).
  1077. // This mapping is done whenever the legacy TBLEND renderstate is set, and
  1078. // does overwrite any previously set DX6 texture blending controls.
  1079. //
  1080. //-----------------------------------------------------------------------------
  1081. void
  1082. D3DContext::MapLegacyTextureBlend( void )
  1083. {
  1084. // disable texture blend processing stage 1 (this also disables subsequent stages)
  1085. m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(1,D3DTSS_COLOROP)] = D3DTOP_DISABLE;
  1086. // set texture blend processing stage 0 to match legacy mode
  1087. switch ( m_RastCtx.pdwRenderState[D3DRENDERSTATE_TEXTUREMAPBLEND] )
  1088. {
  1089. default:
  1090. case D3DTBLEND_DECALMASK: // unsupported - do decal
  1091. case D3DTBLEND_DECAL:
  1092. case D3DTBLEND_COPY:
  1093. m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_COLOROP)] = D3DTOP_SELECTARG1;
  1094. m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_COLORARG1)] = D3DTA_TEXTURE;
  1095. m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_ALPHAOP)] = D3DTOP_SELECTARG1;
  1096. m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_ALPHAARG1)] = D3DTA_TEXTURE;
  1097. break;
  1098. case D3DTBLEND_MODULATEMASK: // unsupported - do modulate
  1099. case D3DTBLEND_MODULATE:
  1100. m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_COLOROP)] = D3DTOP_MODULATE;
  1101. m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_COLORARG1)] = D3DTA_TEXTURE;
  1102. m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_COLORARG2)] = D3DTA_DIFFUSE;
  1103. m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_ALPHAOP)] = D3DTOP_SELECTARG1;
  1104. m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_ALPHAARG1)] = D3DTA_TEXTURE;
  1105. m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_ALPHAARG2)] = D3DTA_DIFFUSE;
  1106. break;
  1107. case D3DTBLEND_MODULATEALPHA:
  1108. m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_COLOROP)] = D3DTOP_MODULATE;
  1109. m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_COLORARG1)] = D3DTA_TEXTURE;
  1110. m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_COLORARG2)] = D3DTA_DIFFUSE;
  1111. m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_ALPHAOP)] = D3DTOP_MODULATE;
  1112. m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_ALPHAARG1)] = D3DTA_TEXTURE;
  1113. m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_ALPHAARG2)] = D3DTA_DIFFUSE;
  1114. break;
  1115. case D3DTBLEND_DECALALPHA:
  1116. m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_COLOROP)] = D3DTOP_BLENDTEXTUREALPHA;
  1117. m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_COLORARG1)] = D3DTA_TEXTURE;
  1118. m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_COLORARG2)] = D3DTA_DIFFUSE;
  1119. m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_ALPHAOP)] = D3DTOP_SELECTARG2;
  1120. m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_ALPHAARG1)] = D3DTA_TEXTURE;
  1121. m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_ALPHAARG2)] = D3DTA_DIFFUSE;
  1122. break;
  1123. case D3DTBLEND_ADD:
  1124. m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_COLOROP)] = D3DTOP_ADD;
  1125. m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_COLORARG1)] = D3DTA_TEXTURE;
  1126. m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_COLORARG2)] = D3DTA_DIFFUSE;
  1127. m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_ALPHAOP)] = D3DTOP_SELECTARG2;
  1128. m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_ALPHAARG1)] = D3DTA_TEXTURE;
  1129. m_RastCtx.pdwRenderState[D3DHAL_TSS_OFFSET(0,D3DTSS_ALPHAARG2)] = D3DTA_DIFFUSE;
  1130. break;
  1131. }
  1132. // since we change [D3DHAL_TSS_OFFSET(0,D3DTSS_COLOROP), we can go from DISABLE to
  1133. // something else, and we can need to update the TexStageCount
  1134. UpdateActiveTexStageCount();
  1135. }