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.

1061 lines
34 KiB

  1. /*==========================================================================;
  2. *
  3. * Copyright (C) 1995 Microsoft Corporation. All Rights Reserved.
  4. *
  5. * File: texture.c
  6. * Content: Direct3DTexture interface
  7. *@@BEGIN_MSINTERNAL
  8. *
  9. * $Id$
  10. *
  11. * History:
  12. * Date By Reason
  13. * ==== == ======
  14. * 07/12/95 stevela Merged Colin's changes.
  15. * 10/12/95 stevela Removed AGGREGATE_D3D
  16. * 17/04/96 colinmc Bug 12185: Debug output too aggresive
  17. * 30/04/96 stevela Bug 18898: Wrong error returned on invalid GetHandle
  18. *@@END_MSINTERNAL
  19. *
  20. ***************************************************************************/
  21. #include "pch.cpp"
  22. #pragma hdrstop
  23. /*
  24. * Create an api for the Direct3DTexture object
  25. */
  26. #undef DPF_MODNAME
  27. #define DPF_MODNAME "Direct3DTexture"
  28. /*
  29. * Routines to associate textures with the D3DDevice.
  30. *
  31. * Note that the texture block structures support both the Texture/Texture2
  32. * interface and the Texture3 interface (the block struct has
  33. * pointers to both and one of the pointers must be NULL). This
  34. * means that the 'hook' call for each must null out the pointer
  35. * for the other, and the GetTextureHandle must not return a valid
  36. * handle for the 'other' texture interface (return NULL).
  37. *
  38. * The D3DI_RemoveTextureBlock is the only call made to cleanup
  39. * when devices go away. In this case, it is called for both
  40. * Texture(2) and Texture3, so it checks the pointers and calls
  41. * the Texture3 version if appropriate.
  42. */
  43. LPD3DI_TEXTUREBLOCK hookTextureToDevice(LPDIRECT3DDEVICEI lpDevI,
  44. LPDIRECT3DTEXTUREI lpD3DText)
  45. {
  46. LPD3DI_TEXTUREBLOCK nBlock;
  47. if (D3DMalloc((void**)&nBlock, sizeof(D3DI_TEXTUREBLOCK)) != D3D_OK)
  48. {
  49. D3D_ERR("failed to allocate space for texture block");
  50. return NULL;
  51. }
  52. nBlock->lpDevI = lpDevI;
  53. nBlock->lpD3DTextureI = lpD3DText;
  54. nBlock->hTex = 0; // initialized to be zero
  55. LIST_INSERT_ROOT(&lpD3DText->blocks, nBlock, list);
  56. LIST_INSERT_ROOT(&lpDevI->texBlocks, nBlock, devList);
  57. return nBlock;
  58. }
  59. void D3DI_RemoveTextureHandle(LPD3DI_TEXTUREBLOCK lpBlock)
  60. {
  61. /* check if this block refers to a Texture/Texture2 - this
  62. * needs to handle both texture types for device cleanup
  63. */
  64. if (lpBlock->hTex)
  65. {
  66. // block refers to a Texture/Texture2
  67. LPD3DI_MATERIALBLOCK mat;
  68. // Remove the texture from any materials which reference it.
  69. for (mat = LIST_FIRST(&lpBlock->lpDevI->matBlocks);
  70. mat; mat = LIST_NEXT(mat,devList)) {
  71. if (mat->lpD3DMaterialI->dmMaterial.hTexture == lpBlock->hTex) {
  72. D3DMATERIAL m = mat->lpD3DMaterialI->dmMaterial;
  73. LPDIRECT3DMATERIAL lpMat =
  74. (LPDIRECT3DMATERIAL) mat->lpD3DMaterialI;
  75. m.hTexture = 0L;
  76. lpMat->SetMaterial(&m);
  77. }
  78. }
  79. D3DHAL_TextureDestroy(lpBlock);
  80. }
  81. }
  82. LPD3DI_TEXTUREBLOCK D3DI_FindTextureBlock(LPDIRECT3DTEXTUREI lpTex,
  83. LPDIRECT3DDEVICEI lpDev)
  84. {
  85. LPD3DI_TEXTUREBLOCK tBlock;
  86. tBlock = LIST_FIRST(&lpTex->blocks);
  87. while (tBlock) {
  88. // return match for Texture(2) only (not Texture3)
  89. if (tBlock->lpDevI == lpDev) {
  90. return tBlock;
  91. }
  92. tBlock = LIST_NEXT(tBlock,list);
  93. }
  94. return NULL;
  95. }
  96. HRESULT D3DAPI DIRECT3DTEXTUREI::Initialize(LPDIRECT3DDEVICE lpD3D, LPDIRECTDRAWSURFACE lpDDS)
  97. {
  98. return DDERR_ALREADYINITIALIZED;
  99. }
  100. /*
  101. * Create a texture.
  102. *
  103. * NOTE: Radical modifications to support the aggregatable texture
  104. * interface (so textures can be queried off DirectDraw surfaces):
  105. *
  106. * 1) This call is no longer a member of the Direct3D device interface.
  107. * It is now an API function exported from the Direct3D DLL. Its
  108. * a hidden API function - only DirectDraw will ever invoke it.
  109. *
  110. * 2) This call no longer establishes the realtionship between a
  111. * texture and a device. That is performed by the GetHandle()
  112. * member of the Direct3DTexture interface.
  113. *
  114. * 3) This call is, in effect, the class factory for Direct3DTexture
  115. * objects. This function will be invoked to create the aggregated
  116. * texture object hanging off the DirectDraw surface.
  117. *
  118. * NOTE: So the Direct3DTexture knows which DirectDraw surface is
  119. * supplying its bits this function is passed an interface pointer
  120. * for that DirectDraw surface. I suspect this blows a nice big
  121. * hole in the COM model as the DirectDraw surface is also the
  122. * owning interface of the texture and I don't think aggregated
  123. * objects should know about thier owning interfaces. However, to
  124. * make this thing work this is what we have to do.
  125. *
  126. * EXTRA BIG NOTE: Because of the above don't take a reference to
  127. * the DirectDraw surface passed in. If you do you will get a circular
  128. * reference and the bloody thing will never die. When aggregated
  129. * the texture interface's lifetime is entirely defined by the
  130. * lifetime of its owning interface (the DirectDraw surface) so the
  131. * DirectDraw surface can never go away before the texture.
  132. */
  133. #undef DPF_MODNAME
  134. #define DPF_MODNAME "Direct3DCreateTexture"
  135. HRESULT D3DAPI Direct3DCreateTexture(REFIID riid,
  136. LPDIRECTDRAWSURFACE lpDDS,
  137. LPUNKNOWN* lplpD3DText,
  138. IUnknown* pUnkOuter)
  139. {
  140. LPDDRAWI_DDRAWSURFACE_LCL lpLcl;
  141. LPDDPIXELFORMAT lpPF;
  142. LPDIRECT3DTEXTUREI lpText;
  143. LPDIRECTDRAWPALETTE lpDDPal;
  144. HRESULT ddrval;
  145. DWORD dwFlags;
  146. *lplpD3DText = NULL;
  147. CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock.
  148. // Release in the destructor
  149. /* No need to validate params as they are passed to us by DirectDraw */
  150. if ((!IsEqualIID(riid, IID_IDirect3DTexture)) &&
  151. (!IsEqualIID(riid, IID_IDirect3DTexture2))) {
  152. /*
  153. * Not an error worth reporting by debug messages as this is
  154. * almost certainly just DirectDraw probing us with an
  155. * unknown IID.
  156. */
  157. return (E_NOINTERFACE);
  158. }
  159. lpText = static_cast<LPDIRECT3DTEXTUREI>(new DIRECT3DTEXTUREI(pUnkOuter));
  160. if (!lpText) {
  161. D3D_ERR("failed to allocate space for texture object");
  162. return (DDERR_OUTOFMEMORY);
  163. }
  164. // QI lpDDS for lpDDS4 interface
  165. ddrval = lpDDS->QueryInterface(IID_IDirectDrawSurface4, (LPVOID*)&lpText->lpDDS);
  166. if(FAILED(ddrval))
  167. {
  168. D3D_ERR("QI for IID_IDirectDrawSurface4 failed");
  169. delete lpText;
  170. return ddrval;
  171. }
  172. memcpy(&lpText->DDSInt4,lpText->lpDDS,sizeof(DDRAWI_DDRAWSURFACE_INT));
  173. lpText->lpDDS->Release();
  174. lpLcl = ((LPDDRAWI_DDRAWSURFACE_INT) lpDDS)->lpLcl;
  175. if (DDSCAPS2_TEXTUREMANAGE & lpLcl->lpSurfMore->ddsCapsEx.dwCaps2)
  176. {
  177. lpText->lpDDSSys=(LPDIRECTDRAWSURFACE4)&lpText->DDSInt4;
  178. lpText->lpDDSSys1Tex=lpDDS; //save it for create texture handle to driver
  179. lpText->lpDDS=NULL;
  180. lpText->lpDDS1Tex=NULL;
  181. // Next, we need to loop thru and set pointers to the dirty
  182. // bit in the DDraw surfaces
  183. DDSCAPS2 ddscaps;
  184. LPDIRECTDRAWSURFACE4 lpDDSTmp, lpDDS = lpText->lpDDSSys;
  185. do
  186. {
  187. ((LPDDRAWI_DDRAWSURFACE_INT) lpDDS)->lpLcl->lpSurfMore->lpbDirty = &(lpText->bDirty);
  188. memset(&ddscaps, 0, sizeof(ddscaps));
  189. ddscaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_MIPMAP;
  190. ddrval = lpDDS->GetAttachedSurface(&ddscaps, &lpDDSTmp);
  191. if(lpDDS != lpText->lpDDSSys)
  192. lpDDS->Release();
  193. lpDDS = lpDDSTmp;
  194. if(ddrval != DD_OK && ddrval != DDERR_NOTFOUND)
  195. {
  196. D3D_ERR("GetAttachedSurface for obtaining mipmaps failed");
  197. delete lpText;
  198. return ddrval;
  199. }
  200. }
  201. while(ddrval == DD_OK);
  202. }
  203. else
  204. {
  205. lpText->lpDDSSys=NULL;
  206. lpText->lpDDSSys1Tex=NULL;
  207. lpText->lpDDS=(LPDIRECTDRAWSURFACE4)&lpText->DDSInt4;
  208. lpText->lpDDS1Tex=lpDDS; //save it for create texture handle to driver
  209. }
  210. lpText->lpTMBucket=NULL;
  211. lpText->LogTexSize=0;
  212. lpText->bDirty = TRUE;
  213. /*
  214. * Are we palettized?
  215. */
  216. if (lpLcl->dwFlags & DDRAWISURF_HASPIXELFORMAT)
  217. lpPF = &lpLcl->lpGbl->ddpfSurface;
  218. else
  219. lpPF = &lpLcl->lpGbl->lpDD->vmiData.ddpfDisplay;
  220. if ( (lpPF->dwFlags & DDPF_PALETTEINDEXED1) ||
  221. (lpPF->dwFlags & DDPF_PALETTEINDEXED2) ||
  222. (lpPF->dwFlags & DDPF_PALETTEINDEXED4) ||
  223. (lpPF->dwFlags & DDPF_PALETTEINDEXED8) )
  224. {
  225. ddrval = lpDDS->GetPalette(&lpDDPal);
  226. if (ddrval != DD_OK) {
  227. if (ddrval != DDERR_NOPALETTEATTACHED) {
  228. delete lpText;
  229. D3D_ERR("No palette in a palettized texture");
  230. return ddrval;
  231. }
  232. D3D_INFO(3, "Texture is not palettized");
  233. lpText->bIsPalettized = false;
  234. } else {
  235. lpText->bIsPalettized = true;
  236. lpDDPal->Release();
  237. D3D_INFO(3, "Texture is palettized");
  238. }
  239. }
  240. /*
  241. * Note, we return the IUnknown rather than the texture
  242. * interface. So if you want to do anything real with
  243. * this baby you must query for the texture interface.
  244. */
  245. *lplpD3DText = static_cast<LPUNKNOWN>(&(lpText->mTexUnk));
  246. return (D3D_OK);
  247. }
  248. DIRECT3DTEXTUREI::DIRECT3DTEXTUREI(LPUNKNOWN pUnkOuter)
  249. {
  250. /*
  251. * setup the object
  252. *
  253. * NOTE: Device and handle established when GetHandle() is called
  254. */
  255. mTexUnk.refCnt = 1;
  256. LIST_INITIALIZE(&blocks);
  257. mTexUnk.pTexI=this;
  258. /*
  259. * Are we really being aggregated?
  260. */
  261. if (pUnkOuter != NULL)
  262. {
  263. /*
  264. * Yup - we are being aggregated. Store the supplied
  265. * IUnknown so we can punt to that.
  266. * NOTE: We explicitly DO NOT AddRef here.
  267. */
  268. lpOwningIUnknown = pUnkOuter;
  269. }
  270. else
  271. {
  272. /*
  273. * Nope - but we pretend we are anyway by storing our
  274. * own IUnknown as the parent IUnknown. This makes the
  275. * code much neater.
  276. */
  277. lpOwningIUnknown = static_cast<LPUNKNOWN>(&(this->mTexUnk));
  278. }
  279. // Not currently in use
  280. bInUse = FALSE;
  281. }
  282. /*
  283. * GetHandle
  284. *
  285. * NOTE: Now establishes relationship betwewn texture and device
  286. * (which used to be done by CreateTexture) and generates the
  287. * texture handle.
  288. */
  289. #undef DPF_MODNAME
  290. #define DPF_MODNAME "Direct3DTexture::GetHandle"
  291. HRESULT D3DAPI DIRECT3DTEXTUREI::GetHandle(LPDIRECT3DDEVICE lpD3DDevice,
  292. LPD3DTEXTUREHANDLE lphTex)
  293. {
  294. LPDIRECT3DDEVICEI lpDev;
  295. LPD3DI_TEXTUREBLOCK lptBlock;
  296. CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock.
  297. // Release in the destructor
  298. /*
  299. * validate parms
  300. */
  301. TRY
  302. {
  303. if (!VALID_DIRECT3DTEXTURE2_PTR(this)) {
  304. D3D_ERR( "Invalid Direct3DTexture pointer" );
  305. return DDERR_INVALIDOBJECT;
  306. }
  307. if (!VALID_DIRECT3DDEVICE_PTR(lpD3DDevice)) {
  308. D3D_ERR( "Invalid Direct3DDevice pointer" );
  309. return DDERR_INVALIDOBJECT;
  310. }
  311. if (!VALID_D3DTEXTUREHANDLE_PTR(lphTex)) {
  312. D3D_ERR( "Invalid D3DTEXTUREHANDLE pointer" );
  313. return DDERR_INVALIDOBJECT;
  314. }
  315. }
  316. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  317. {
  318. D3D_ERR( "Exception encountered validating parameters" );
  319. return DDERR_INVALIDPARAMS;
  320. }
  321. if (lpDDSSys)
  322. {
  323. D3D_ERR( "Handle is not available since the texture is managed" );
  324. return DDERR_INVALIDOBJECT; //managed texture has no handle
  325. }
  326. lpDev = static_cast<LPDIRECT3DDEVICEI>(lpD3DDevice);
  327. lptBlock = D3DI_FindTextureBlock(this, lpDev);
  328. *lphTex=0;
  329. if (NULL == lptBlock) {
  330. /*
  331. * NOTE: We used to do this in CreateTexture. Perhaps the service
  332. * name should be changed (as the texture is now already created
  333. * when this function is invoked).
  334. *
  335. * Indicate to driver that source is a DirectDraw surface, so it
  336. * can Lock() when required.
  337. */
  338. lptBlock = hookTextureToDevice(lpDev, this);
  339. if ( NULL == lptBlock) {
  340. D3D_ERR("failed to associate texture with device");
  341. return DDERR_OUTOFMEMORY;
  342. }
  343. }
  344. if (!lptBlock->hTex)
  345. {
  346. HRESULT ret;
  347. ret = D3DHAL_TextureCreate(lpDev, &lptBlock->hTex, lpDDS1Tex);
  348. if (ret != D3D_OK)
  349. {
  350. return ret;
  351. }
  352. D3D_INFO(6,"lpTexI=%08lx lptBlock=%08lx hTex=%08lx",this,lptBlock,lptBlock->hTex);
  353. }
  354. *lphTex=lptBlock->hTex;
  355. DDASSERT(lptBlock->hTex);
  356. return D3D_OK;
  357. }
  358. HRESULT D3DAPI DIRECT3DTEXTUREI::GetHandle(LPDIRECT3DDEVICE2 lpD3DDevice,
  359. LPD3DTEXTUREHANDLE lphTex)
  360. {
  361. LPDIRECT3DDEVICEI lpDev;
  362. LPD3DI_TEXTUREBLOCK lptBlock;
  363. HRESULT ret;
  364. CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock.
  365. // Release in the destructor
  366. /*
  367. * validate parms
  368. */
  369. TRY
  370. {
  371. if (!VALID_DIRECT3DTEXTURE2_PTR(this)) {
  372. D3D_ERR( "Invalid Direct3DTexture2 pointer" );
  373. return DDERR_INVALIDOBJECT;
  374. }
  375. if (!VALID_DIRECT3DDEVICE2_PTR(lpD3DDevice)) {
  376. D3D_ERR( "Invalid Direct3DDevice2 pointer" );
  377. return DDERR_INVALIDOBJECT;
  378. }
  379. if (!VALID_D3DTEXTUREHANDLE_PTR(lphTex)) {
  380. D3D_ERR( "Invalid D3DTEXTUREHANDLE pointer" );
  381. return DDERR_INVALIDOBJECT;
  382. }
  383. }
  384. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  385. {
  386. D3D_ERR( "Exception encountered validating parameters" );
  387. return DDERR_INVALIDPARAMS;
  388. }
  389. if (lpDDSSys)
  390. {
  391. D3D_ERR( "Handle is not available since texture is managed" );
  392. return DDERR_INVALIDOBJECT; //managed texture has no handle
  393. }
  394. lpDev = static_cast<LPDIRECT3DDEVICEI>(lpD3DDevice);
  395. lptBlock = D3DI_FindTextureBlock(this, lpDev);
  396. /*
  397. * Do cap verification if we've not used this device before.
  398. */
  399. *lphTex=0;
  400. if (NULL == lptBlock) {
  401. ret=VerifyTextureCaps(lpDev, (LPDDRAWI_DDRAWSURFACE_INT)lpDDS);
  402. if (ret != D3D_OK)
  403. {
  404. return ret;
  405. }
  406. /*
  407. * Put this device in the list of those owned by the
  408. * Direct3DDevice object
  409. */
  410. lptBlock = hookTextureToDevice(lpDev, this);
  411. if ( NULL == lptBlock) {
  412. D3D_ERR("failed to associate texture with device");
  413. return DDERR_OUTOFMEMORY;
  414. }
  415. }
  416. if (!lptBlock->hTex)
  417. {
  418. ret = D3DHAL_TextureCreate(lpDev, &lptBlock->hTex, lpDDS1Tex);
  419. if (ret != D3D_OK)
  420. {
  421. return ret;
  422. }
  423. D3D_INFO(6,"lpTexI=%08lx lptBlock=%08lx hTex=%08lx",this,lptBlock,lptBlock->hTex);
  424. }
  425. *lphTex=lptBlock->hTex;
  426. DDASSERT(lptBlock->hTex);
  427. return D3D_OK;
  428. }
  429. #undef DPF_MODNAME
  430. #define DPF_MODNAME "GetTextureDDIHandle"
  431. HRESULT
  432. GetTextureDDIHandle(LPDIRECT3DTEXTUREI lpTexI,
  433. LPDIRECT3DDEVICEI lpDevI,
  434. LPD3DI_TEXTUREBLOCK* lplpBlock)
  435. {
  436. #ifdef __DD_OPT_SURFACE
  437. LPDDRAWI_DDRAWSURFACE_LCL pSurf_lcl = NULL;
  438. #endif //__DD_OPT_SURFACE
  439. HRESULT ret;
  440. LPD3DI_TEXTUREBLOCK lpBlock=*lplpBlock; //in case has the pointer
  441. #ifdef __DD_OPT_SURFACE
  442. // If the surface is Empty, return 0 handle
  443. if (lpTexI->lpDDS)
  444. {
  445. pSurf_lcl = ((LPDDRAWI_DDRAWSURFACE_INT)lpTexI->lpDDS)->lpLcl;
  446. }
  447. else
  448. {
  449. pSurf_lcl = ((LPDDRAWI_DDRAWSURFACE_INT)lpTexI->lpDDSSys)->lpLcl;
  450. }
  451. DDASSERT (pSurf_lcl);
  452. if (pSurf_lcl->dwFlags & DDRAWISURF_EMPTYSURFACE)
  453. {
  454. D3D_WARN(1, "Cannot get DDI handle to an empty surface, call load first");
  455. return D3DERR_OPTTEX_CANNOTCOPY;
  456. }
  457. #endif //__DD_OPT_SURFACE
  458. DDASSERT(lpTexI && lpDevI);
  459. /*
  460. * Find out if we've used this device before.
  461. */
  462. if (!lpBlock)
  463. {
  464. lpBlock = D3DI_FindTextureBlock(lpTexI, lpDevI);
  465. if (!lpBlock)
  466. {
  467. /*
  468. * Put this device in the list of those owned by the
  469. * Direct3DDevice object
  470. */
  471. lpBlock=hookTextureToDevice(lpDevI, lpTexI);
  472. if (!lpBlock)
  473. {
  474. D3D_ERR("failed to associate texture with device");
  475. return DDERR_OUTOFMEMORY;
  476. }
  477. }
  478. *lplpBlock = lpBlock;
  479. }
  480. if (!lpBlock->hTex)
  481. {
  482. LPDIRECTDRAWSURFACE lpDDS1Temp;
  483. if (!lpTexI->lpDDS)
  484. {
  485. if (lpDevI->dwFEFlags & D3DFE_REALHAL)
  486. {
  487. // We need to make sure that we don't evict any mapped textures
  488. DWORD dwStage;
  489. for (dwStage=0;dwStage < lpDevI->dwMaxTextureBlendStages; dwStage++)
  490. if(lpDevI->lpD3DMappedTexI[dwStage])
  491. lpDevI->lpD3DMappedTexI[dwStage]->bInUse = TRUE;
  492. ret=lpDevI->lpDirect3DI->lpTextureManager->allocNode(lpBlock);
  493. for (dwStage=0;dwStage < lpDevI->dwMaxTextureBlendStages; dwStage++)
  494. if(lpDevI->lpD3DMappedTexI[dwStage])
  495. lpDevI->lpD3DMappedTexI[dwStage]->bInUse = FALSE;
  496. if (D3D_OK != ret)
  497. {
  498. D3D_ERR("Failed to create video memory surface");
  499. return ret;
  500. }
  501. if (!(lpDevI->lpD3DHALGlobalDriverData->hwCaps.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_ZBUFFERLESSHSR))
  502. lpDevI->lpDirect3DI->lpTextureManager->TimeStamp(lpTexI->lpTMBucket);
  503. if (lpBlock->hTex) return D3D_OK; //this means Texmanager reused a texture handle
  504. // QI lpDDS4 for lpDDS interface
  505. if (DD_OK != (ret=lpTexI->lpDDS->QueryInterface(IID_IDirectDrawSurface, (LPVOID*)&lpDDS1Temp)))
  506. {
  507. D3D_ERR("QI IID_IDirectDrawSurface failed");
  508. lpTexI->lpTMBucket->lpD3DTexI=NULL; //clean up
  509. lpTexI->lpTMBucket=NULL;
  510. lpTexI->lpDDS->Release();
  511. lpTexI->lpDDS=NULL;
  512. return ret;
  513. }
  514. lpTexI->lpDDS1Tex = lpDDS1Temp;
  515. }
  516. else
  517. {
  518. lpDDS1Temp = lpTexI->lpDDSSys1Tex;
  519. }
  520. }
  521. else
  522. lpDDS1Temp = lpTexI->lpDDS1Tex;
  523. DDASSERT(NULL != lpDDS1Temp);
  524. {
  525. CLockD3DST lockObject(lpDevI, DPF_MODNAME, REMIND(""));
  526. if (D3D_OK != (ret=D3DHAL_TextureCreate(lpDevI, &lpBlock->hTex, lpDDS1Temp)))
  527. return ret;
  528. }
  529. }
  530. else
  531. if (lpTexI->lpTMBucket && !(lpDevI->lpD3DHALGlobalDriverData->hwCaps.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_ZBUFFERLESSHSR))
  532. lpDevI->lpDirect3DI->lpTextureManager->TimeStamp(lpTexI->lpTMBucket);
  533. DDASSERT(lpBlock->hTex);
  534. return D3D_OK;
  535. }
  536. /*
  537. * Load
  538. */
  539. #undef DPF_MODNAME
  540. #define DPF_MODNAME "Direct3DTexture::Load"
  541. #define HEL_BLT_ALPAHPIXELS_BROKEN
  542. HRESULT D3DAPI DIRECT3DTEXTUREI::Load(LPDIRECT3DTEXTURE lpD3DSrc)
  543. {
  544. LPDIRECT3DTEXTUREI this_src;
  545. HRESULT ddrval;
  546. LPDIRECTDRAWSURFACE4 lpDDSSrc, lpDDSDst;
  547. CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock.
  548. // Release in the destructor
  549. /*
  550. * validate parms
  551. */
  552. TRY
  553. {
  554. if (!VALID_DIRECT3DTEXTURE_PTR(this)) {
  555. D3D_ERR( "Invalid Direct3DTexture pointer" );
  556. return DDERR_INVALIDOBJECT;
  557. }
  558. if (!VALID_DIRECT3DTEXTURE_PTR(lpD3DSrc)) {
  559. D3D_ERR( "Invalid Direct3DTexture pointer" );
  560. return DDERR_INVALIDOBJECT;
  561. }
  562. }
  563. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  564. {
  565. D3D_ERR( "Exception encountered validating parameters" );
  566. return DDERR_INVALIDPARAMS;
  567. }
  568. this_src = static_cast<LPDIRECT3DTEXTUREI>(lpD3DSrc);
  569. lpDDSSrc = this_src->lpDDSSys;
  570. if (!lpDDSSrc)
  571. lpDDSSrc = this_src->lpDDS;
  572. lpDDSDst = lpDDSSys;
  573. if (!lpDDSDst)
  574. lpDDSDst = lpDDS;
  575. ddrval = CopySurface(lpDDSDst, lpDDSSrc, NULL);
  576. return ddrval;
  577. }
  578. HRESULT D3DAPI DIRECT3DTEXTUREI::Load(LPDIRECT3DTEXTURE2 lpD3DSrc)
  579. {
  580. LPDIRECT3DTEXTUREI this_src;
  581. HRESULT ddrval;
  582. LPDIRECTDRAWSURFACE4 lpDDSSrc, lpDDSDst;
  583. CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock.
  584. // Release in the destructor
  585. /*
  586. * validate parms
  587. */
  588. TRY
  589. {
  590. this_src = static_cast<LPDIRECT3DTEXTUREI>(lpD3DSrc);
  591. if (!VALID_DIRECT3DTEXTURE2_PTR(this)) {
  592. D3D_ERR( "Invalid Direct3DTexture pointer" );
  593. return DDERR_INVALIDOBJECT;
  594. }
  595. if (!VALID_DIRECT3DTEXTURE2_PTR(this_src)) {
  596. D3D_ERR( "Invalid Direct3DTexture pointer" );
  597. return DDERR_INVALIDOBJECT;
  598. }
  599. }
  600. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  601. {
  602. D3D_ERR( "Exception encountered validating parameters" );
  603. return DDERR_INVALIDPARAMS;
  604. }
  605. lpDDSSrc = this_src->lpDDSSys;
  606. if (!lpDDSSrc)
  607. lpDDSSrc = this_src->lpDDS;
  608. lpDDSDst = lpDDSSys;
  609. if (!lpDDSDst)
  610. lpDDSDst = lpDDS;
  611. ddrval = CopySurface(lpDDSDst, lpDDSSrc, NULL);
  612. return ddrval;
  613. }
  614. #undef DPF_MODNAME
  615. #define DPF_MODNAME "CopySurface"
  616. HRESULT CopySurface(LPDIRECTDRAWSURFACE4 lpDDSDst,
  617. LPDIRECTDRAWSURFACE4 lpDDSSrc,
  618. LPDIRECTDRAWCLIPPER lpClipper)
  619. {
  620. DDSURFACEDESC2 ddsd;
  621. #ifdef __DD_OPT_SURFACE
  622. DDSURFACEDESC2 ddsdSrc;
  623. BOOL bDstIsOptimized, bSrcIsOptimized;
  624. LPDIRECTDRAWOPTSURFACE pOptSurfSrc = NULL;
  625. LPDIRECTDRAWOPTSURFACE pOptSurfDst = NULL;
  626. #endif //__DD_OPT_SURFACE
  627. HRESULT ddrval=DD_OK;
  628. PALETTEENTRY ppe[256];
  629. LPDIRECTDRAWPALETTE lpDDPalSrc, lpDDPalDst;
  630. int psize;
  631. DDCOLORKEY ckey;
  632. if (!lpDDSSrc || !lpDDSDst) return DD_OK;
  633. memset(&ddsd, 0, sizeof(ddsd));
  634. ddsd.dwSize = sizeof(ddsd);
  635. ddrval = lpDDSDst->GetSurfaceDesc(&ddsd);
  636. #ifdef __DD_OPT_SURFACE
  637. memset(&ddsdSrc, 0, sizeof(ddsdSrc));
  638. ddsdSrc.dwSize = sizeof(ddsdSrc);
  639. ddrval = lpDDSSrc->GetSurfaceDesc(&ddsdSrc);
  640. if (bDstIsOptimized = (ddsd.ddsCaps.dwCaps & DDSCAPS_OPTIMIZED))
  641. {
  642. // Fetch the OptSurface Interface
  643. ddrval = lpDDSDst->QueryInterface (IID_IDirectDrawOptSurface,
  644. (LPVOID *)&pOptSurfDst);
  645. if (ddrval != DD_OK)
  646. {
  647. D3D_ERR( "QI failed for Opt Surfaces" );
  648. goto exit_copy_surf;
  649. }
  650. }
  651. if (bSrcIsOptimized = (ddsdSrc.ddsCaps.dwCaps & DDSCAPS_OPTIMIZED))
  652. {
  653. // Fetch the OptSurface Interface
  654. ddrval = lpDDSDst->QueryInterface (IID_IDirectDrawOptSurface,
  655. (LPVOID *)&pOptSurfSrc);
  656. if (ddrval != DD_OK)
  657. {
  658. D3D_ERR( "QI failed for Opt Surfaces" );
  659. goto exit_copy_surf;
  660. }
  661. }
  662. // Cases:
  663. // Dst=Opt Src=Opt : Copy the surface
  664. // Dst=Opt Src=UnOpt: Optimize the surface
  665. // Dst=UnOpt Src=Opt : UnOptimize and load
  666. // Dst=UnOpt Src=UnOpt: Normal operation
  667. //
  668. if (bDstIsOptimized && bSrcIsOptimized)
  669. {
  670. // Copy the surface
  671. ddrval = pOptSurfSrc->CopyOptimizedSurf (pOptSurfSrc);
  672. if (ddrval != DD_OK)
  673. {
  674. D3D_ERR ("CopyOptimizedSurf failed");
  675. }
  676. goto exit_copy_surf;
  677. }
  678. else if (bDstIsOptimized && !bSrcIsOptimized)
  679. {
  680. LPDIRECTDRAWSURFACE4 pDDS4 = NULL;
  681. // Optimize the surface
  682. ddrval = lpDDSDst->QueryInterface (IID_IDirectDrawSurface4,
  683. (LPVOID *)&pOptSurfSrc);
  684. if (ddrval != DD_OK)
  685. {
  686. D3D_ERR( "QI failed for IID_IDirectDrawSurface4" );
  687. goto exit_copy_surf;
  688. }
  689. ddrval = pOptSurfSrc->LoadUnoptimizedSurf (pDDS4);
  690. if (ddrval != DD_OK)
  691. {
  692. D3D_ERR ("CopyOptimizedSurf failed");
  693. }
  694. pDDS4->Release();
  695. goto exit_copy_surf;
  696. }
  697. else if (!bDstIsOptimized && bSrcIsOptimized)
  698. {
  699. LPDIRECTDRAWOPTSURFACE pDDS4 = NULL;
  700. // ATTENTION: Unoptimize the surface ??
  701. D3D_ERR ("CopyOptimizedSurf failed");
  702. ddrval = D3DERR_OPTTEX_CANNOTCOPY;
  703. goto exit_copy_surf;
  704. }
  705. #endif //__DD_OPT_SURFACE
  706. if (ddsd.ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED8) {
  707. psize = 256;
  708. } else if (ddsd.ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED4) {
  709. psize = 16;
  710. } else {
  711. psize = 0;
  712. }
  713. if (psize) {
  714. ddrval = lpDDSSrc->GetPalette(&lpDDPalSrc);
  715. if (ddrval != DD_OK) {
  716. if (ddrval != DDERR_NOPALETTEATTACHED) {
  717. D3D_ERR("Failed to get palette");
  718. return ddrval;
  719. }
  720. } else {
  721. ddrval = lpDDPalSrc->GetEntries(0, 0, psize, ppe);
  722. if (ddrval != DD_OK) {
  723. D3D_ERR("Failed to get palette entries");
  724. lpDDPalSrc->Release();
  725. return ddrval;
  726. }
  727. lpDDPalSrc->Release();
  728. ddrval = lpDDSDst->GetPalette(&lpDDPalDst);
  729. if (ddrval != DD_OK) {
  730. D3D_ERR("Failed to get palette");
  731. return ddrval;
  732. }
  733. ddrval = lpDDPalDst->SetEntries(0, 0, psize, ppe);
  734. if (ddrval != DD_OK) {
  735. D3D_ERR("Failed to set palette entries");
  736. lpDDPalDst->Release();
  737. return ddrval;
  738. }
  739. lpDDPalDst->Release();
  740. }
  741. }
  742. lpDDSSrc->AddRef();
  743. lpDDSDst->AddRef();
  744. do {
  745. DDSCAPS2 ddscaps;
  746. LPDIRECTDRAWSURFACE4 lpDDSTmp;
  747. LPREGIONLIST lpRegionList = ((LPDDRAWI_DDRAWSURFACE_INT)lpDDSSrc)->lpLcl->lpSurfMore->lpRegionList;
  748. if(lpClipper)
  749. {
  750. if(lpRegionList)
  751. {
  752. if(lpRegionList->rdh.nCount &&
  753. lpRegionList->rdh.nCount != NUM_RECTS_IN_REGIONLIST)
  754. {
  755. if(lpClipper->SetClipList((LPRGNDATA)lpRegionList, 0) != DD_OK)
  756. {
  757. D3D_ERR("Failed to set clip list");
  758. }
  759. if(lpDDSDst->SetClipper(lpClipper) != DD_OK)
  760. {
  761. D3D_ERR("Failed to detach the clipper");
  762. }
  763. }
  764. }
  765. }
  766. ddrval = lpDDSDst->Blt(NULL, lpDDSSrc,
  767. NULL, DDBLT_WAIT, NULL);
  768. if(lpClipper)
  769. {
  770. if(lpRegionList)
  771. {
  772. if(lpRegionList->rdh.nCount)
  773. {
  774. if(lpRegionList->rdh.nCount != NUM_RECTS_IN_REGIONLIST)
  775. {
  776. if(lpDDSDst->SetClipper(NULL) != DD_OK)
  777. {
  778. D3D_ERR("Failed to detach the clipper");
  779. }
  780. }
  781. lpRegionList->rdh.nCount = 0;
  782. lpRegionList->rdh.nRgnSize = 0;
  783. lpRegionList->rdh.rcBound.left = LONG_MAX;
  784. lpRegionList->rdh.rcBound.right = 0;
  785. lpRegionList->rdh.rcBound.top = LONG_MAX;
  786. lpRegionList->rdh.rcBound.bottom = 0;
  787. }
  788. }
  789. }
  790. if (ddrval == E_NOTIMPL && (psize == 16 || psize == 4 || psize == 2) ) {
  791. DDSURFACEDESC2 ddsd_s, ddsd_d;
  792. LPBYTE psrc, pdst;
  793. DWORD i;
  794. DWORD dwBytesPerLine;
  795. memset(&ddsd_s, 0, sizeof ddsd_s);
  796. memset(&ddsd_d, 0, sizeof ddsd_d);
  797. ddsd_s.dwSize = ddsd_d.dwSize = sizeof(ddsd_s);
  798. if ((ddrval = lpDDSSrc->Lock(NULL, &ddsd_s, DDLOCK_WAIT, NULL)) != DD_OK) {
  799. lpDDSSrc->Release();
  800. lpDDSDst->Release();
  801. D3D_ERR("Failed to lock src surface");
  802. return ddrval;
  803. }
  804. if ((ddrval = lpDDSDst->Lock(NULL, &ddsd_d, DDLOCK_WAIT, NULL)) != DD_OK) {
  805. lpDDSSrc->Unlock(NULL);
  806. lpDDSSrc->Release();
  807. lpDDSDst->Release();
  808. D3D_ERR("Failed to lock dst surface");
  809. return ddrval;
  810. }
  811. switch (psize)
  812. {
  813. case 16: dwBytesPerLine = (ddsd.dwWidth + 1) / 2; break;
  814. case 4: dwBytesPerLine = (ddsd.dwWidth + 3) / 4; break;
  815. case 2: dwBytesPerLine = (ddsd.dwWidth + 7) / 8; break;
  816. }
  817. psrc = (LPBYTE)ddsd_s.lpSurface;
  818. pdst = (LPBYTE)ddsd_d.lpSurface;
  819. for (i = 0; i < ddsd_s.dwHeight; i++) {
  820. memcpy( pdst, psrc, dwBytesPerLine );
  821. psrc += ddsd_s.lPitch;
  822. pdst += ddsd_d.lPitch;
  823. }
  824. lpDDSSrc->Unlock(NULL);
  825. lpDDSDst->Unlock(NULL);
  826. lpDDSSrc->Release(); //Offset the AddRefs before
  827. lpDDSDst->Release();
  828. return D3D_OK;
  829. }
  830. else if (ddrval != DD_OK)
  831. {
  832. lpDDSSrc->Release(); //Offset the AddRefs before
  833. lpDDSDst->Release();
  834. D3D_ERR("Blt failure");
  835. return ddrval;
  836. }
  837. /* Copy color keys */
  838. ddrval = lpDDSSrc->GetColorKey(DDCKEY_DESTBLT, &ckey);
  839. if (DD_OK == ddrval)
  840. lpDDSDst->SetColorKey(DDCKEY_DESTBLT, &ckey);
  841. ddrval = lpDDSSrc->GetColorKey(DDCKEY_SRCBLT, &ckey);
  842. if (DD_OK == ddrval)
  843. lpDDSDst->SetColorKey(DDCKEY_SRCBLT, &ckey);
  844. memset(&ddscaps, 0, sizeof(ddscaps));
  845. ddscaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_MIPMAP;
  846. ddrval = lpDDSSrc->GetAttachedSurface(&ddscaps, &lpDDSTmp);
  847. lpDDSSrc->Release();
  848. lpDDSSrc = lpDDSTmp;
  849. if (ddrval == DDERR_NOTFOUND) {
  850. // no more surfaces in the chain
  851. lpDDSDst->Release();
  852. break;
  853. } else if (ddrval != DD_OK) {
  854. lpDDSDst->Release();
  855. D3D_ERR("GetAttachedSurface failed with something other than DDERR_NOTFOUND.");
  856. return ddrval;
  857. }
  858. memset(&ddscaps, 0, sizeof(ddscaps));
  859. ddscaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_MIPMAP;
  860. ddrval = lpDDSDst->GetAttachedSurface(&ddscaps, &lpDDSTmp);
  861. lpDDSDst->Release();
  862. lpDDSDst = lpDDSTmp;
  863. if (ddrval == DDERR_NOTFOUND) {
  864. lpDDSSrc->Release();
  865. D3D_ERR("Destination texture has fewer attached mipmap surfaces than source.");
  866. return ddrval;
  867. } else if (ddrval != DD_OK) {
  868. lpDDSSrc->Release();
  869. D3D_ERR("GetAttachedSurface failed with something other than DDERR_NOTFOUND.");
  870. return ddrval;
  871. }
  872. } while (1);
  873. return D3D_OK;
  874. #ifdef __DD_OPT_SURFACE
  875. exit_copy_surf:
  876. // Job done, release any optimized surface interfaces
  877. if (pOptSurfSrc)
  878. {
  879. pOptSurfSrc->Release();
  880. pOptSurfSrc = NULL;
  881. }
  882. if (pOptSurfDst)
  883. {
  884. pOptSurfDst->Release();
  885. pOptSurfDst = NULL;
  886. }
  887. return ddrval;
  888. #endif //__DD_OPT_SURFACE
  889. }
  890. /*
  891. * Unload
  892. */
  893. #undef DPF_MODNAME
  894. #define DPF_MODNAME "Direct3DTexture::Unload"
  895. HRESULT D3DAPI DIRECT3DTEXTUREI::Unload()
  896. {
  897. HRESULT ret = D3D_OK;
  898. CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock.
  899. // Release in the destructor
  900. /*
  901. * validate parms
  902. */
  903. TRY
  904. {
  905. if (!VALID_DIRECT3DTEXTURE_PTR(this)) {
  906. D3D_ERR( "Invalid Direct3DTexture pointer" );
  907. return DDERR_INVALIDOBJECT;
  908. }
  909. }
  910. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  911. {
  912. D3D_ERR( "Exception encountered validating parameters" );
  913. return DDERR_INVALIDPARAMS;
  914. }
  915. return (ret);
  916. }
  917. /*
  918. * PaletteChanged
  919. */
  920. #undef DPF_MODNAME
  921. #define DPF_MODNAME "Direct3DTexture::PaletteChanged"
  922. HRESULT D3DAPI DIRECT3DTEXTUREI::PaletteChanged(DWORD dwStart, DWORD dwCount)
  923. {
  924. HRESULT ret = D3D_OK;
  925. CLockD3D lockObject(DPF_MODNAME, REMIND("")); // Takes D3D lock.
  926. // Release in the destructor
  927. /*
  928. * validate parms
  929. */
  930. TRY
  931. {
  932. if (!VALID_DIRECT3DTEXTURE_PTR(this)) {
  933. D3D_ERR( "Invalid Direct3DTexture pointer" );
  934. return DDERR_INVALIDOBJECT;
  935. }
  936. }
  937. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  938. {
  939. D3D_ERR( "Exception encountered validating parameters" );
  940. return DDERR_INVALIDPARAMS;
  941. }
  942. // if haven't mapped to a device yet, can ignore this call, since will
  943. // be creating the ramp palette from scratch anyway.
  944. LPD3DI_TEXTUREBLOCK tBlock = LIST_FIRST(&this->blocks);
  945. while (tBlock) {
  946. if (tBlock->hTex)
  947. {
  948. if(tBlock->lpDevI->pfnRampService!=NULL)
  949. {
  950. ret = CallRampService(tBlock->lpDevI, RAMP_SERVICE_PALETTE_CHANGED,tBlock->hTex,0);
  951. }
  952. }
  953. tBlock=LIST_NEXT(tBlock,list);
  954. }
  955. return (ret);
  956. }