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.

406 lines
15 KiB

  1. /*==========================================================================;
  2. *
  3. * Copyright (C) 1995 Microsoft Corporation. All Rights Reserved.
  4. *
  5. * File: haltex.c
  6. * Content: Direct3D HAL texture handling
  7. *@@BEGIN_MSINTERNAL
  8. *
  9. * $Id: haltex.c,v 1.1 1995/11/21 15:12:43 sjl Exp $
  10. *
  11. * History:
  12. * Date By Reason
  13. * ==== == ======
  14. * 07/11/95 stevela Initial rev.
  15. *@@END_MSINTERNAL
  16. *
  17. ***************************************************************************/
  18. #include "pch.cpp"
  19. #pragma hdrstop
  20. /*
  21. * Texture functionality is not emulated.
  22. */
  23. HRESULT D3DHAL_TextureCreate(LPDIRECT3DDEVICEI lpDevI,
  24. LPD3DTEXTUREHANDLE lphTex,
  25. LPDIRECTDRAWSURFACE lpDDS)
  26. {
  27. if (IS_DX7HAL_DEVICE(lpDevI))
  28. {
  29. *lphTex =
  30. ((LPDDRAWI_DDRAWSURFACE_INT)lpDDS)->lpLcl->lpSurfMore->dwSurfaceHandle;
  31. }
  32. else
  33. {
  34. D3DHAL_TEXTURECREATEDATA data;
  35. HRESULT ret;
  36. if (!lpDevI->lpD3DHALCallbacks->TextureCreate) {
  37. D3D_ERR("TextureCreate called, but no texture support.");
  38. return (D3DERR_TEXTURE_NO_SUPPORT);
  39. }
  40. memset(&data, 0, sizeof(D3DHAL_TEXTURECREATEDATA));
  41. data.dwhContext = lpDevI->dwhContext;
  42. data.lpDDS = lpDDS;
  43. D3D_INFO(6, "TextureCreate, creating texture dwhContext = %08lx, lpDDS = %08lx",
  44. data.dwhContext, data.lpDDS);
  45. CALL_HALONLY(ret, lpDevI, TextureCreate, &data);
  46. if (ret != DDHAL_DRIVER_HANDLED || data.ddrval != DD_OK) {
  47. D3D_ERR("HAL failed to handle TextureCreate");
  48. return (D3DERR_TEXTURE_CREATE_FAILED);
  49. }
  50. *lphTex = data.dwHandle;
  51. }
  52. D3D_INFO(6, "TextureCreate, created texture hTex = %08lx", *lphTex);
  53. return (D3D_OK);
  54. }
  55. HRESULT D3DHAL_TextureDestroy(LPD3DI_TEXTUREBLOCK lpBlock)
  56. {
  57. LPDIRECT3DDEVICEI lpDevI=lpBlock->lpDevI;
  58. D3DTEXTUREHANDLE hTex=lpBlock->hTex;
  59. D3DHAL_TEXTUREDESTROYDATA data;
  60. HRESULT ret;
  61. lpBlock->hTex=0;
  62. if (!IS_DX7HAL_DEVICE(lpDevI))
  63. {
  64. // on winnt we alway use the surfacehandle, so there is no need calling driver
  65. if (!lpDevI->lpD3DHALCallbacks->TextureDestroy) {
  66. D3D_ERR("TextureDestroy called, but no texture support.");
  67. return (D3DERR_TEXTURE_NO_SUPPORT);
  68. }
  69. }
  70. // The following code ensures that before we ask the driver to unmap
  71. // the texture, we set the stages to NULL if the texture is still present
  72. // in any stage. This is probably not necessary, but we are just trying
  73. // to be extra cautious here. The CAVEAT here is that it is possible that
  74. // D3DHAL_TextureDestroy() is being called from DestroyDevice() and hence
  75. // IT COULD BE REALLY BAD TO BATCH additional commands to the device at
  76. // this stage. (snene - 3/2/98)
  77. BOOL bNeedFlush = FALSE;
  78. if (IS_DP2HAL_DEVICE(lpDevI)) {
  79. int dwStage;
  80. CDirect3DDeviceIDP2 *dp2dev = static_cast<CDirect3DDeviceIDP2 *>(lpDevI);
  81. // Find out the first stage with hTex and NULL out
  82. for (dwStage=0;dwStage<(int)lpDevI->dwMaxTextureBlendStages; dwStage++)
  83. {
  84. if (hTex == lpDevI->tsstates[dwStage][D3DTSS_TEXTUREMAP])
  85. {
  86. dp2dev->SetTSSI(dwStage, (D3DTEXTURESTAGESTATETYPE)D3DTSS_TEXTUREMAP, 0);
  87. bNeedFlush = TRUE;
  88. }
  89. }
  90. }
  91. DWORD txh;
  92. if(lpDevI->GetRenderState(D3DRENDERSTATE_TEXTUREHANDLE, &txh) != D3D_OK)
  93. {
  94. D3D_WARN(0, "Error getting texture handle in D3DHAL_TextureDestroy");
  95. }
  96. else
  97. {
  98. if (txh == hTex)
  99. {
  100. lpDevI->rstates[D3DRENDERSTATE_TEXTUREHANDLE] = 0;
  101. lpDevI->SetRenderStateI(D3DRENDERSTATE_TEXTUREHANDLE, 0);
  102. bNeedFlush = TRUE;
  103. }
  104. }
  105. // Make sure that we send down the command immediately to guarantee
  106. // that the driver gets it before we call it with Destroy
  107. if(bNeedFlush)
  108. {
  109. if(lpDevI->FlushStates() != D3D_OK)
  110. {
  111. D3D_ERR("Error trying to render batched commands in D3DHAL_TextureDestroy");
  112. }
  113. }
  114. else // Now we decide whether to flush due to a referenced texture in the batch or not
  115. {
  116. LPD3DBUCKET list;
  117. if(lpBlock->lpD3DTextureI->lpDDS != NULL)
  118. {
  119. list = reinterpret_cast<LPD3DBUCKET>(((LPDDRAWI_DDRAWSURFACE_INT)(lpBlock->lpD3DTextureI->lpDDS))->lpLcl->lpSurfMore->lpD3DDevIList);
  120. }
  121. else
  122. {
  123. list = reinterpret_cast<LPD3DBUCKET>(((LPDDRAWI_DDRAWSURFACE_INT)(lpBlock->lpD3DTextureI->lpDDSSys))->lpLcl->lpSurfMore->lpD3DDevIList);
  124. }
  125. while(list != NULL)
  126. {
  127. if(list->lpD3DDevI == lpDevI)
  128. {
  129. if(lpDevI->FlushStates() != D3D_OK)
  130. {
  131. D3D_ERR("Error trying to render batched commands in D3DHAL_TextureDestroy");
  132. }
  133. break;
  134. }
  135. list = list->next;
  136. }
  137. }
  138. if (!IS_DX7HAL_DEVICE(lpDevI))
  139. {
  140. memset(&data, 0, sizeof(D3DHAL_TEXTUREDESTROYDATA));
  141. data.dwhContext = lpDevI->dwhContext;
  142. data.dwHandle = hTex;
  143. D3D_INFO(6, "TextureDestroy, destroying texture dwhContext = %08lx, hTex = %08lx",
  144. data.dwhContext, hTex);
  145. CALL_HALONLY(ret, lpDevI, TextureDestroy, &data);
  146. if (ret != DDHAL_DRIVER_HANDLED || data.ddrval != DD_OK) {
  147. D3D_ERR("HAL failed to handle TextureDestroy");
  148. return (D3DERR_TEXTURE_DESTROY_FAILED);
  149. }
  150. }
  151. D3D_INFO(6, "TextureDestroy, destroyed texture hTex = %08lx", hTex);
  152. return (D3D_OK);
  153. }
  154. HRESULT D3DHAL_TextureSwap(LPDIRECT3DDEVICEI lpDevI,
  155. D3DTEXTUREHANDLE hTex1,
  156. D3DTEXTUREHANDLE hTex2)
  157. {
  158. D3DHAL_TEXTURESWAPDATA data;
  159. HRESULT ret;
  160. if (!lpDevI->lpD3DHALCallbacks->TextureSwap) {
  161. D3D_ERR("TextureSwapcalled, but no texture support.");
  162. return (D3DERR_TEXTURE_NO_SUPPORT);
  163. }
  164. memset(&data, 0, sizeof(D3DHAL_TEXTURESWAPDATA));
  165. data.dwhContext = lpDevI->dwhContext;
  166. data.dwHandle1 = hTex1;
  167. data.dwHandle2 = hTex2;
  168. data.ddrval = D3D_OK;
  169. D3D_INFO(6, "TextureSwap, dwhContext = %d. hTex1 = %d, hTex2 = %d",
  170. data.dwhContext, hTex1, hTex2);
  171. CALL_HALONLY(ret, lpDevI, TextureSwap, &data);
  172. if (ret != DDHAL_DRIVER_HANDLED || data.ddrval != DD_OK) {
  173. D3D_ERR("HAL failed to handle TextureSwap");
  174. return (D3DERR_TEXTURE_SWAP_FAILED);
  175. }
  176. return (D3D_OK);
  177. }
  178. __declspec (dllexport) HRESULT
  179. D3DHAL_TextureGetSurf(LPDIRECT3DDEVICEI lpDevI,
  180. D3DTEXTUREHANDLE hTex,
  181. LPDIRECTDRAWSURFACE* lpDDS)
  182. {
  183. if (IS_DX7HAL_DEVICE(lpDevI))
  184. {
  185. LPD3DI_TEXTUREBLOCK tBlock=LIST_FIRST(&lpDevI->texBlocks);
  186. while (tBlock)
  187. {
  188. if (tBlock->hTex == hTex)
  189. {
  190. *lpDDS = (LPDIRECTDRAWSURFACE)tBlock->lpD3DTextureI->lpDDS1Tex;
  191. return D3D_OK;
  192. }
  193. tBlock=LIST_NEXT(tBlock,devList);
  194. }
  195. return (D3DERR_TEXTURE_CREATE_FAILED);
  196. }
  197. else
  198. {
  199. D3DHAL_TEXTUREGETSURFDATA data;
  200. HRESULT ret;
  201. if (!lpDevI->lpD3DHALCallbacks->TextureGetSurf) {
  202. D3D_ERR("TextureGetSurf called, but no texture support.");
  203. return (D3DERR_TEXTURE_NO_SUPPORT);
  204. }
  205. memset(&data, 0, sizeof(D3DHAL_TEXTUREGETSURFDATA));
  206. data.dwhContext = lpDevI->dwhContext;
  207. data.dwHandle = hTex;
  208. D3D_INFO(6, "TextureGetSurf, getting texture for dwhContext = %d, hTex = %d",
  209. data.dwhContext, hTex);
  210. CALL_HALONLY(ret, lpDevI, TextureGetSurf, &data);
  211. if (ret != DDHAL_DRIVER_HANDLED || data.ddrval != DD_OK) {
  212. D3D_ERR("HAL failed to handle TextureGetSurf");
  213. return (D3DERR_TEXTURE_CREATE_FAILED);
  214. }
  215. *lpDDS = (LPDIRECTDRAWSURFACE)data.lpDDS;
  216. return (D3D_OK);
  217. }
  218. }
  219. HRESULT D3DHELInst_D3DOP_TEXTURELOAD(LPDIRECT3DDEVICEI lpDevI,
  220. DWORD dwCount,
  221. LPD3DTEXTURELOAD load)
  222. {
  223. HRESULT ddrval;
  224. DWORD i;
  225. LPDIRECTDRAWSURFACE lpDDSSrc;
  226. LPDIRECTDRAWSURFACE lpDDSDst;
  227. DDSURFACEDESC ddsd;
  228. PALETTEENTRY ppe[256];
  229. LPDIRECTDRAWPALETTE lpDDPalSrc, lpDDPalDst;
  230. int psize;
  231. for (i = 0; i < dwCount; i++) {
  232. if (D3DHAL_TextureGetSurf(lpDevI, load->hSrcTexture, &lpDDSSrc)) {
  233. D3D_ERR("HAL failed to get source surface in D3DHELInst_D3DOP_TEXTURELOAD");
  234. return (D3DERR_TEXTURE_LOAD_FAILED);
  235. }
  236. if (D3DHAL_TextureGetSurf(lpDevI, load->hDestTexture, &lpDDSDst)) {
  237. D3D_ERR("HAL failed to get destination surface in D3DHELInst_D3DOP_TEXTURELOAD");
  238. return (D3DERR_TEXTURE_LOAD_FAILED);
  239. }
  240. memset(&ddsd, 0, sizeof ddsd);
  241. ddsd.dwSize = sizeof(ddsd);
  242. ddrval = lpDDSDst->GetSurfaceDesc(&ddsd);
  243. if (ddrval != DD_OK) {
  244. D3D_ERR("Failed to get surface description of source texture surface in D3DHELInst_D3DOP_TEXTURELOAD");
  245. return (D3DERR_TEXTURE_LOAD_FAILED);
  246. }
  247. if (ddsd.ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED8) {
  248. psize = 256;
  249. } else if (ddsd.ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED4) {
  250. psize = 16;
  251. } else {
  252. psize = 0;
  253. }
  254. if (psize) {
  255. ddrval = lpDDSSrc->GetPalette(&lpDDPalSrc);
  256. if (ddrval != DD_OK) {
  257. if (ddrval != DDERR_NOPALETTEATTACHED) {
  258. D3D_ERR("Failed to get palette of source texture in D3DHELInst_D3DOP_TEXTURELOAD");
  259. return (D3DERR_TEXTURE_LOAD_FAILED);
  260. }
  261. } else {
  262. ddrval = lpDDPalSrc->GetEntries(0, 0, psize, ppe);
  263. if (ddrval != DD_OK) {
  264. D3D_ERR("Failed to get palette entries of source texture in D3DHELInst_D3DOP_TEXTURELOAD");
  265. lpDDPalSrc->Release();
  266. return (D3DERR_TEXTURE_LOAD_FAILED);
  267. }
  268. lpDDPalSrc->Release();
  269. ddrval = lpDDSDst->GetPalette(&lpDDPalDst);
  270. if (ddrval != DD_OK) {
  271. D3D_ERR("Failed to get palette of destination texture in D3DHELInst_D3DOP_TEXTURELOAD");
  272. return (D3DERR_TEXTURE_LOAD_FAILED);
  273. }
  274. ddrval = lpDDPalDst->SetEntries(0, 0, psize, ppe);
  275. if (ddrval != DD_OK) {
  276. D3D_ERR("Failed to set palette entries of destination texture in D3DHELInst_D3DOP_TEXTURELOAD");
  277. lpDDPalDst->Release();
  278. return (D3DERR_TEXTURE_LOAD_FAILED);
  279. }
  280. lpDDPalDst->Release();
  281. }
  282. }
  283. lpDDSSrc->AddRef();
  284. lpDDSDst->AddRef();
  285. do {
  286. DDSCAPS ddscaps;
  287. LPDIRECTDRAWSURFACE lpDDSTmp;
  288. ddrval = lpDDSDst->Blt(NULL, lpDDSSrc,
  289. NULL, DDBLT_WAIT, NULL);
  290. if (ddrval == E_NOTIMPL && (psize == 16 || psize == 4 || psize == 2) ) {
  291. DDSURFACEDESC ddsd_s, ddsd_d;
  292. LPBYTE psrc, pdst;
  293. DWORD i;
  294. DWORD dwBytesPerLine;
  295. memset(&ddsd_s, 0, sizeof ddsd_s);
  296. memset(&ddsd_d, 0, sizeof ddsd_d);
  297. ddsd_s.dwSize = ddsd_d.dwSize = sizeof(DDSURFACEDESC);
  298. if ((ddrval = lpDDSSrc->Lock(NULL, &ddsd_s, DDLOCK_WAIT, NULL)) != DD_OK) {
  299. lpDDSSrc->Release();
  300. lpDDSDst->Release();
  301. D3D_ERR("Failed to lock src surface");
  302. return ddrval;
  303. }
  304. if ((ddrval = lpDDSDst->Lock(NULL, &ddsd_d, DDLOCK_WAIT, NULL)) != DD_OK) {
  305. lpDDSSrc->Unlock(NULL);
  306. lpDDSSrc->Release();
  307. lpDDSDst->Release();
  308. D3D_ERR("Failed to lock dst surface");
  309. return ddrval;
  310. }
  311. switch (psize)
  312. {
  313. case 16: dwBytesPerLine = (ddsd.dwWidth + 1) / 2; break;
  314. case 4: dwBytesPerLine = (ddsd.dwWidth + 3) / 4; break;
  315. case 2: dwBytesPerLine = (ddsd.dwWidth + 7) / 8; break;
  316. }
  317. psrc = (LPBYTE)ddsd_s.lpSurface;
  318. pdst = (LPBYTE)ddsd_d.lpSurface;
  319. for (i = 0; i < ddsd_s.dwHeight; i++) {
  320. memcpy( pdst, psrc, dwBytesPerLine );
  321. psrc += ddsd_s.lPitch;
  322. pdst += ddsd_d.lPitch;
  323. }
  324. lpDDSSrc->Unlock(NULL);
  325. lpDDSDst->Unlock(NULL);
  326. lpDDSSrc->Release();
  327. lpDDSDst->Release();
  328. return D3D_OK;
  329. }
  330. if (ddrval != DD_OK)
  331. {
  332. lpDDSSrc->Release();
  333. lpDDSDst->Release();
  334. return ddrval;
  335. }
  336. memset(&ddscaps, 0, sizeof(DDSCAPS));
  337. ddscaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_MIPMAP;
  338. ddrval = lpDDSSrc->GetAttachedSurface(&ddscaps, &lpDDSTmp);
  339. lpDDSSrc->Release();
  340. lpDDSSrc = lpDDSTmp;
  341. if (ddrval == DDERR_NOTFOUND) {
  342. // no more surfaces in the chain
  343. lpDDSDst->Release();
  344. break;
  345. } else if (ddrval != DD_OK) {
  346. lpDDSDst->Release();
  347. D3D_ERR("GetAttachedSurface of source failed in D3DHELInst_D3DOP_TEXTURELOAD");
  348. return (D3DERR_TEXTURE_LOAD_FAILED);
  349. }
  350. memset(&ddscaps, 0, sizeof(DDSCAPS));
  351. ddscaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_MIPMAP;
  352. ddrval = lpDDSDst->GetAttachedSurface(&ddscaps, &lpDDSTmp);
  353. lpDDSDst->Release();
  354. lpDDSDst = lpDDSTmp;
  355. if (ddrval == DDERR_NOTFOUND) {
  356. lpDDSSrc->Release();
  357. D3D_ERR("Destination texture has fewer attached mipmap surfaces than source in D3DHELInst_D3DOP_TEXTURELOAD");
  358. return (D3DERR_TEXTURE_LOAD_FAILED);
  359. } else if (ddrval != DD_OK) {
  360. lpDDSSrc->Release();
  361. D3D_ERR("GetAttachedSurface of destination failed in D3DHELInst_D3DOP_TEXTURELOAD");
  362. return (D3DERR_TEXTURE_LOAD_FAILED);
  363. }
  364. } while (1);
  365. load++;
  366. }
  367. return (D3D_OK);
  368. }