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.

604 lines
18 KiB

  1. //----------------------------------------------------------------------------
  2. //
  3. // rasttex.cpp
  4. //
  5. // Texture functions.
  6. //
  7. // Copyright (C) Microsoft Corporation, 1997.
  8. //
  9. //----------------------------------------------------------------------------
  10. #include "pch.cpp"
  11. #pragma hdrstop
  12. //----------------------------------------------------------------------------
  13. //
  14. // SetSizesSpanTexture
  15. //
  16. // Initialize pSpanTex data using current iMaxMipLevel info, Getting the
  17. // surfaces from pSurf. Assumes InitSpanTexture has been called first.
  18. //
  19. //----------------------------------------------------------------------------
  20. HRESULT
  21. D3DContext::SetSizesSpanTexture(PD3DI_SPANTEX pSpanTex)
  22. {
  23. LPDDRAWI_DDRAWSURFACE_LCL pLcl;
  24. INT iFirstSurf = min(pSpanTex->iMaxMipLevel, pSpanTex->cLODTex);
  25. LPDIRECTDRAWSURFACE pDDS = pSpanTex->pSurf[iFirstSurf];
  26. INT i;
  27. // Init
  28. pLcl = ((LPDDRAWI_DDRAWSURFACE_INT)pDDS)->lpLcl;
  29. pSpanTex->iSizeU = (INT16)DDSurf_Width(pLcl);
  30. pSpanTex->iSizeV = (INT16)DDSurf_Height(pLcl);
  31. pSpanTex->uMaskU = (INT16)(pSpanTex->iSizeU - 1);
  32. pSpanTex->uMaskV = (INT16)(pSpanTex->iSizeV - 1);
  33. pSpanTex->iShiftU = (INT16)IntLog2(pSpanTex->iSizeU);
  34. if (0 != DDSurf_BitDepth(pLcl))
  35. {
  36. pSpanTex->iShiftPitch[0] =
  37. (INT16)IntLog2((UINT32)(DDSurf_Pitch(pLcl) * 8)/DDSurf_BitDepth(pLcl));
  38. }
  39. else
  40. {
  41. pSpanTex->iShiftPitch[0] =
  42. (INT16)IntLog2(((UINT32)DDSurf_Width(pLcl) * 8));
  43. }
  44. pSpanTex->iShiftV = (INT16)IntLog2(pSpanTex->iSizeV);
  45. pSpanTex->uMaskV = pSpanTex->uMaskV;
  46. // Check if the texture size is power of 2
  47. if (!ValidTextureSize(pSpanTex->iSizeU, pSpanTex->iShiftU,
  48. pSpanTex->iSizeV, pSpanTex->iShiftV))
  49. {
  50. // this texture can only be used for a ramp fill
  51. pSpanTex->uFlags |= D3DI_SPANTEX_NON_POWER_OF_2;
  52. pSpanTex->cLODTex = 0;
  53. }
  54. // Check for mipmap if any.
  55. // iPreSizeU and iPreSizeV store the size(u and v) of the previous level
  56. // mipmap. They are init'ed with the first texture size.
  57. INT16 iPreSizeU = pSpanTex->iSizeU, iPreSizeV = pSpanTex->iSizeV;
  58. for ( i = iFirstSurf + 1; i <= pSpanTex->cLODTex; i++)
  59. {
  60. pDDS = pSpanTex->pSurf[i];
  61. // Check for invalid mipmap texture size
  62. pLcl = ((LPDDRAWI_DDRAWSURFACE_INT)pDDS)->lpLcl;
  63. if (!ValidMipmapSize(iPreSizeU, (INT16)DDSurf_Width(pLcl)) ||
  64. !ValidMipmapSize(iPreSizeV, (INT16)DDSurf_Height(pLcl)))
  65. {
  66. return DDERR_INVALIDPARAMS;
  67. }
  68. if (0 != DDSurf_BitDepth(pLcl))
  69. {
  70. pSpanTex->iShiftPitch[i - iFirstSurf] =
  71. (INT16)IntLog2(((UINT32)DDSurf_Pitch(pLcl)*8)/DDSurf_BitDepth(pLcl));
  72. }
  73. else
  74. {
  75. pSpanTex->iShiftPitch[0] =
  76. (INT16)IntLog2(((UINT32)DDSurf_Width(pLcl)*8));
  77. }
  78. iPreSizeU = (INT16)DDSurf_Width(pLcl);
  79. iPreSizeV = (INT16)DDSurf_Height(pLcl);
  80. }
  81. pSpanTex->iMaxScaledLOD = ((pSpanTex->cLODTex + 1) << LOD_SHIFT) - 1;
  82. pSpanTex->uFlags &= ~D3DI_SPANTEX_MAXMIPLEVELS_DIRTY;
  83. return D3D_OK;
  84. }
  85. //----------------------------------------------------------------------------
  86. //
  87. // InitSpanTexture
  88. //
  89. // Initializes the entire array of pSurf's (regardless of iMaxMipLevel) pointed
  90. // to by the root surface of pDDS. Sets all pSpanTex state that will not ever
  91. // change in SetSizesSpanTexture.
  92. //
  93. //----------------------------------------------------------------------------
  94. HRESULT
  95. D3DContext::InitSpanTexture(PD3DI_SPANTEX pSpanTex, LPDIRECTDRAWSURFACE pDDS)
  96. {
  97. HRESULT hr;
  98. LPDDRAWI_DDRAWSURFACE_LCL pLcl;
  99. DDSCAPS ddscaps;
  100. static INT32 iGeneration = 0;
  101. // Init
  102. pSpanTex->iGeneration = iGeneration++;
  103. // Note that all pSpanTex elements are initialized to 0
  104. pLcl = ((LPDDRAWI_DDRAWSURFACE_INT)pDDS)->lpLcl;
  105. // Set the transparent bit and the transparent color with pSurf[0]
  106. // initially
  107. if ((pLcl->dwFlags & DDRAWISURF_HASCKEYSRCBLT) != 0)
  108. {
  109. pSpanTex->uFlags |= D3DI_SPANTEX_HAS_TRANSPARENT;
  110. pSpanTex->TransparentColor =
  111. pLcl->ddckCKSrcBlt.dwColorSpaceHighValue;
  112. }
  113. else
  114. {
  115. pSpanTex->uFlags &= ~D3DI_SPANTEX_HAS_TRANSPARENT;
  116. }
  117. HR_RET(FindOutSurfFormat(&(DDSurf_PixFmt(pLcl)), &(pSpanTex->Format)));
  118. if (pSpanTex->Format == D3DI_SPTFMT_PALETTE8 ||
  119. pSpanTex->Format == D3DI_SPTFMT_PALETTE4)
  120. {
  121. if (pLcl->lpDDPalette)
  122. {
  123. LPDDRAWI_DDRAWPALETTE_GBL pPal = pLcl->lpDDPalette->lpLcl->lpGbl;
  124. if (pPal->dwFlags & DDRAWIPAL_ALPHA)
  125. {
  126. pSpanTex->uFlags |= D3DI_SPANTEX_ALPHAPALETTE;
  127. }
  128. pSpanTex->pPalette = (PUINT32)pPal->lpColorTable;
  129. }
  130. if (pSpanTex->Format == D3DI_SPTFMT_PALETTE8)
  131. {
  132. pSpanTex->iPaletteSize = 256;
  133. }
  134. else
  135. {
  136. // PALETTE4
  137. pSpanTex->iPaletteSize = 16;
  138. }
  139. }
  140. pSpanTex->TexAddrU = D3DTADDRESS_WRAP;
  141. pSpanTex->TexAddrV = D3DTADDRESS_WRAP;
  142. pSpanTex->BorderColor = RGBA_MAKE(0xff, 0x00, 0xff, 0xff);
  143. // assign first pSurf here (mipmap chain gets assigned below)
  144. pSpanTex->pSurf[0] = pDDS;
  145. // Check for mipmap if any.
  146. LPDIRECTDRAWSURFACE pTmpS;
  147. // iPreSizeU and iPreSizeV store the size(u and v) of the previous level
  148. // mipmap. They are init'ed with the first texture size.
  149. INT16 iPreSizeU = pSpanTex->iSizeU, iPreSizeV = pSpanTex->iSizeV;
  150. for (;;)
  151. {
  152. memset(&ddscaps, 0, sizeof(DDSCAPS));
  153. ddscaps.dwCaps = DDSCAPS_TEXTURE;
  154. hr = pDDS->GetAttachedSurface(&ddscaps, &pTmpS); //implicit AddRef
  155. if (hr == DDERR_NOTFOUND)
  156. {
  157. break;
  158. }
  159. else if (hr != D3D_OK)
  160. {
  161. return hr;
  162. }
  163. pDDS = pTmpS;
  164. pSpanTex->cLODTex ++;
  165. pSpanTex->pSurf[pSpanTex->cLODTex] = pTmpS;
  166. }
  167. pSpanTex->dwSize = sizeof(D3DI_SPANTEX);
  168. return D3D_OK;
  169. }
  170. //----------------------------------------------------------------------------
  171. //
  172. // RemoveTexture
  173. //
  174. // Check to see if the to-be-destroyed pSpanTex is currently used by the
  175. // context. If yes, set the according entry to be NULL to disable texture.
  176. //
  177. //----------------------------------------------------------------------------
  178. void D3DContext::RemoveTexture(PD3DI_SPANTEX pSpanTex)
  179. {
  180. INT i;
  181. INT cActTex = (INT)m_RastCtx.cActTex;
  182. for (i = 0; i < cActTex; i++)
  183. {
  184. if (m_RastCtx.pTexture[i] == pSpanTex)
  185. {
  186. // NULL out the according texture and set dirty bits
  187. m_RastCtx.cActTex --;
  188. StateChanged(D3DRENDERSTATE_TEXTUREHANDLE);
  189. m_RastCtx.pTexture[i] = NULL;
  190. for (int j=pSpanTex->cLODTex;j>0;j--) //release attached surfs
  191. {
  192. pSpanTex->pSurf[j]->Release();
  193. }
  194. }
  195. }
  196. }
  197. //----------------------------------------------------------------------------
  198. //
  199. // RastTextureCreate
  200. //
  201. // Creates a RAST texture and initializes it with the info passed in.
  202. //
  203. //----------------------------------------------------------------------------
  204. DWORD __stdcall
  205. RastTextureCreate(LPD3DHAL_TEXTURECREATEDATA pTexData)
  206. {
  207. PD3DI_SPANTEX *ppSpanTex;
  208. PD3DI_SPANTEX pSpanTex;
  209. D3DContext *pDCtx;
  210. VALIDATE_D3DCONTEXT("RastTextureCreate", pTexData);
  211. // Create the span texture
  212. ppSpanTex = new PD3DI_SPANTEX;
  213. pSpanTex = new D3DI_SPANTEX;
  214. if (ppSpanTex == NULL || pSpanTex == NULL)
  215. {
  216. delete ppSpanTex;
  217. delete pSpanTex;
  218. D3D_ERR("(Rast) Out of memory in RastTextureCreate");
  219. pTexData->ddrval = DDERR_OUTOFMEMORY;
  220. return DDHAL_DRIVER_HANDLED;
  221. }
  222. memset(pSpanTex, 0, sizeof(D3DI_SPANTEX));
  223. // Point indirector to this texture initially.
  224. *ppSpanTex = pSpanTex;
  225. // Init the span texture
  226. if ((pTexData->ddrval = pDCtx->InitSpanTexture(pSpanTex, pTexData->lpDDS))
  227. != D3D_OK)
  228. {
  229. delete ppSpanTex;
  230. delete pSpanTex;
  231. return DDHAL_DRIVER_HANDLED;
  232. }
  233. if ((pTexData->ddrval = pDCtx->SetSizesSpanTexture(pSpanTex))
  234. != D3D_OK)
  235. {
  236. delete ppSpanTex;
  237. delete pSpanTex;
  238. return DDHAL_DRIVER_HANDLED;
  239. }
  240. // ppSpanTex is used as the texture handle returned to d3dim.
  241. pTexData->dwHandle = (UINT32)(ULONG_PTR)ppSpanTex;
  242. pTexData->ddrval = D3D_OK;
  243. return DDHAL_DRIVER_HANDLED;
  244. }
  245. //----------------------------------------------------------------------------
  246. //
  247. // RastTextureDestroy
  248. //
  249. // Destroy a RAST texture.
  250. //
  251. //----------------------------------------------------------------------------
  252. DWORD __stdcall
  253. RastTextureDestroy(LPD3DHAL_TEXTUREDESTROYDATA pTexDestroyData)
  254. {
  255. PD3DI_SPANTEX *ppSpanTex;
  256. PD3DI_SPANTEX pSpanTex;
  257. D3DContext *pDCtx;
  258. VALIDATE_D3DCONTEXT("RastTextureDestroy", pTexDestroyData);
  259. if (!VALID_D3DI_SPANTEX_PTR_PTR(
  260. (PD3DI_SPANTEX*)ULongToPtr(pTexDestroyData->dwHandle)))
  261. {
  262. D3D_ERR("(Rast) in RastTextureDestroy, invalid texture handle");
  263. pTexDestroyData->ddrval = DDERR_INVALIDPARAMS;
  264. return DDHAL_DRIVER_HANDLED;
  265. }
  266. // Find the texture
  267. ppSpanTex = (PD3DI_SPANTEX *)ULongToPtr(pTexDestroyData->dwHandle);
  268. pSpanTex = *ppSpanTex;
  269. pDCtx->RemoveTexture(pSpanTex);
  270. // Delete it
  271. if (pSpanTex)
  272. {
  273. delete ppSpanTex;
  274. delete pSpanTex;
  275. }
  276. else
  277. {
  278. pTexDestroyData->ddrval = DDERR_INVALIDPARAMS;
  279. }
  280. return DDHAL_DRIVER_HANDLED;
  281. }
  282. //----------------------------------------------------------------------------
  283. //
  284. // RastTextureSwap
  285. //
  286. // Swaps over the ownership of two texture handles.
  287. //
  288. //----------------------------------------------------------------------------
  289. DWORD __stdcall
  290. RastTextureSwap(LPD3DHAL_TEXTURESWAPDATA pTexSwapData)
  291. {
  292. D3DContext *pDCtx;
  293. VALIDATE_D3DCONTEXT("RastTextureSwap", pTexSwapData);
  294. // Check out the span textures
  295. PD3DI_SPANTEX pSpanTex1, pSpanTex2;
  296. pSpanTex1 = HANDLE_TO_SPANTEX(pTexSwapData->dwHandle1);
  297. pSpanTex2 = HANDLE_TO_SPANTEX(pTexSwapData->dwHandle2);
  298. // Swap
  299. if (pSpanTex1 != NULL && pSpanTex2 != NULL)
  300. {
  301. HANDLE_TO_SPANTEX(pTexSwapData->dwHandle1) = pSpanTex2;
  302. HANDLE_TO_SPANTEX(pTexSwapData->dwHandle2) = pSpanTex1;
  303. pTexSwapData->ddrval = D3D_OK;
  304. }
  305. else
  306. {
  307. pTexSwapData->ddrval = DDERR_INVALIDPARAMS;
  308. }
  309. return DDHAL_DRIVER_HANDLED;
  310. }
  311. //----------------------------------------------------------------------------
  312. //
  313. // RastTextureGetSurf
  314. //
  315. // Returns the surface pointer associate with a texture handle.
  316. //
  317. //----------------------------------------------------------------------------
  318. DWORD __stdcall
  319. RastTextureGetSurf(LPD3DHAL_TEXTUREGETSURFDATA pTexGetSurf)
  320. {
  321. D3DContext *pDCtx;
  322. VALIDATE_D3DCONTEXT("RastTextureGetSurf", pTexGetSurf);
  323. // Check out the span texture
  324. PD3DI_SPANTEX pSpanTex;
  325. pSpanTex = HANDLE_TO_SPANTEX(pTexGetSurf->dwHandle);
  326. if (pSpanTex)
  327. {
  328. pTexGetSurf->lpDDS = (UINT_PTR)pSpanTex->pSurf[0];
  329. pTexGetSurf->ddrval = D3D_OK;
  330. }
  331. else
  332. {
  333. pTexGetSurf->ddrval = DDERR_INVALIDPARAMS;
  334. }
  335. return DDHAL_DRIVER_HANDLED;
  336. }
  337. //----------------------------------------------------------------------------
  338. //
  339. // RastLockSpanTexture
  340. //
  341. // Lock current texture surface before the texture bits are accessed.
  342. //
  343. //----------------------------------------------------------------------------
  344. HRESULT
  345. D3DContext::RastLockSpanTexture(void)
  346. {
  347. INT i, j;
  348. PD3DI_SPANTEX pSpanTex;
  349. HRESULT hr;
  350. if (IsTextureOff())
  351. {
  352. return D3D_OK;
  353. }
  354. DDASSERT((m_uFlags & D3DCONTEXT_TEXTURE_LOCKED) == 0);
  355. for (j = 0;
  356. j < (INT)m_RastCtx.cActTex;
  357. j++)
  358. {
  359. pSpanTex = m_RastCtx.pTexture[j];
  360. if (pSpanTex->uFlags & D3DI_SPANTEX_MAXMIPLEVELS_DIRTY)
  361. {
  362. hr = SetSizesSpanTexture(pSpanTex);
  363. if (hr != D3D_OK)
  364. {
  365. goto EH_Unlock;
  366. }
  367. }
  368. INT iFirstSurf = min(pSpanTex->iMaxMipLevel, pSpanTex->cLODTex);
  369. // Currently recursive locks are not allowed.
  370. DDASSERT((pSpanTex->uFlags & D3DI_SPANTEX_SURFACES_LOCKED) == 0);
  371. for (i = iFirstSurf; i <= pSpanTex->cLODTex; i++)
  372. {
  373. hr = LockSurface(pSpanTex->pSurf[i],
  374. (LPVOID*)&(pSpanTex->pBits[i-iFirstSurf]));
  375. if (hr != D3D_OK)
  376. {
  377. // Unlock any partial mipmap locks we've taken, as
  378. // RastUnlock can only handle entire textures being
  379. // locked or unlocked.
  380. while (--i >= 0)
  381. {
  382. UnlockSurface(pSpanTex->pSurf[i]);
  383. }
  384. // Make sure that i is signed and that the above
  385. // loop exited properly.
  386. DDASSERT(i < 0);
  387. goto EH_Unlock;
  388. }
  389. }
  390. pSpanTex->uFlags |= D3DI_SPANTEX_SURFACES_LOCKED;
  391. }
  392. m_uFlags |= D3DCONTEXT_TEXTURE_LOCKED;
  393. return D3D_OK;
  394. EH_Unlock:
  395. if (j > 0)
  396. {
  397. // Unlock complete textures we've already locked.
  398. // RastUnlock will check the flags to figure
  399. // out which ones to unlock.
  400. RastUnlockSpanTexture();
  401. }
  402. return hr;
  403. }
  404. //----------------------------------------------------------------------------
  405. //
  406. // RastUnlockTexture
  407. //
  408. // Unlock texture surface after the texture bits are accessed.
  409. // The input is a D3DI_SPANTEX. NULL texture needs to be checked before this
  410. // function gets called.
  411. //
  412. //----------------------------------------------------------------------------
  413. void
  414. D3DContext::RastUnlockSpanTexture(void)
  415. {
  416. INT i, j;
  417. PD3DI_SPANTEX pSpanTex;;
  418. if (IsTextureOff())
  419. {
  420. return;
  421. }
  422. DDASSERT((m_uFlags & D3DCONTEXT_TEXTURE_LOCKED) != 0);
  423. for (j = 0;
  424. j < (INT)m_RastCtx.cActTex;
  425. j++)
  426. {
  427. pSpanTex = m_RastCtx.pTexture[j];
  428. INT iFirstSurf = min(pSpanTex->iMaxMipLevel, pSpanTex->cLODTex);
  429. // RastUnlock is used for cleanup in RastLock so it needs to
  430. // be able to handle partially locked mipmap chains.
  431. if (pSpanTex->uFlags & D3DI_SPANTEX_SURFACES_LOCKED)
  432. {
  433. for (i = iFirstSurf; i <= pSpanTex->cLODTex; i++)
  434. {
  435. UnlockSurface(pSpanTex->pSurf[i]);
  436. }
  437. pSpanTex->uFlags &= ~D3DI_SPANTEX_SURFACES_LOCKED;
  438. }
  439. }
  440. m_uFlags &= ~D3DCONTEXT_TEXTURE_LOCKED;
  441. }
  442. //----------------------------------------------------------------------------
  443. //
  444. // UpdateColorKeyAndPalette
  445. //
  446. // Updates the color key value and palette.
  447. //
  448. // Also, if the ColorKey enable for the texture has changed, set the texture handle
  449. // dirty bit so the new mode is recognized in span init.
  450. //
  451. //----------------------------------------------------------------------------
  452. void
  453. D3DContext::UpdateColorKeyAndPalette(void)
  454. {
  455. INT j;
  456. PD3DI_SPANTEX pSpanTex;
  457. // Set the transparent bit and the transparent color with pSurf[0]
  458. LPDDRAWI_DDRAWSURFACE_LCL pLcl;
  459. for (j = 0;
  460. j < (INT)m_RastCtx.cActTex;
  461. j++)
  462. {
  463. pSpanTex = m_RastCtx.pTexture[j];
  464. if ((pSpanTex != NULL) && (pSpanTex->pSurf[0] != NULL))
  465. {
  466. pLcl = ((LPDDRAWI_DDRAWSURFACE_INT) pSpanTex->pSurf[0])->lpLcl;
  467. // Palette might be changed
  468. if (pSpanTex->Format == D3DI_SPTFMT_PALETTE8 ||
  469. pSpanTex->Format == D3DI_SPTFMT_PALETTE4)
  470. {
  471. if (pLcl->lpDDPalette)
  472. {
  473. LPDDRAWI_DDRAWPALETTE_GBL pPal = pLcl->lpDDPalette->lpLcl->lpGbl;
  474. if (pPal->dwFlags & DDRAWIPAL_ALPHA)
  475. {
  476. pSpanTex->uFlags |= D3DI_SPANTEX_ALPHAPALETTE;
  477. }
  478. pSpanTex->pPalette = (PUINT32)pPal->lpColorTable;
  479. }
  480. }
  481. if ((pLcl->dwFlags & DDRAWISURF_HASCKEYSRCBLT) != 0)
  482. {
  483. // texture has a ColorKey value
  484. pSpanTex->TransparentColor =
  485. pLcl->ddckCKSrcBlt.dwColorSpaceHighValue;
  486. if (!(pSpanTex->uFlags & D3DI_SPANTEX_HAS_TRANSPARENT))
  487. {
  488. pSpanTex->uFlags |= D3DI_SPANTEX_HAS_TRANSPARENT;
  489. // make sure this state change is recognized, and a new
  490. // texture read function is used
  491. StateChanged(D3DHAL_TSS_OFFSET(j, D3DTSS_TEXTUREMAP));
  492. }
  493. }
  494. else
  495. {
  496. // texture does not have a ColorKey value
  497. if (pSpanTex->uFlags & D3DI_SPANTEX_HAS_TRANSPARENT)
  498. {
  499. pSpanTex->uFlags &= ~D3DI_SPANTEX_HAS_TRANSPARENT;
  500. // make sure this state change is recognized, and a new
  501. // texture read function is used
  502. StateChanged(D3DHAL_TSS_OFFSET(j, D3DTSS_TEXTUREMAP));
  503. }
  504. }
  505. }
  506. }
  507. }
  508. //----------------------------------------------------------------------------
  509. //
  510. // Dp2TextureStageState
  511. //
  512. // Called by Drawprim2 to set texture stage states..
  513. //
  514. //----------------------------------------------------------------------------
  515. HRESULT
  516. D3DContext::Dp2TextureStageState(LPD3DHAL_DP2COMMAND pCmd, DWORD dwFvf)
  517. {
  518. WORD wStateCount = pCmd->wStateCount;
  519. INT i;
  520. HRESULT hr;
  521. LPD3DHAL_DP2TEXTURESTAGESTATE pTexStageState =
  522. (D3DHAL_DP2TEXTURESTAGESTATE *)(pCmd + 1);
  523. // Flush the prim proc before any state changs
  524. HR_RET(End(FALSE));
  525. for (i = 0; i < (INT)wStateCount; i++, pTexStageState++)
  526. {
  527. HR_RET(SetRenderState(D3DHAL_TSS_OFFSET((DWORD)pTexStageState->wStage,
  528. (DWORD)pTexStageState->TSState),
  529. pTexStageState->dwValue));
  530. }
  531. HR_RET(CheckFVF(dwFvf));
  532. hr = Begin();
  533. return hr;
  534. }