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.

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