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.

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