gfxD3D9TextureManager.cpp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2012 GarageGames, LLC
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to
  6. // deal in the Software without restriction, including without limitation the
  7. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. // sell copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  20. // IN THE SOFTWARE.
  21. //-----------------------------------------------------------------------------
  22. #ifdef _MSC_VER
  23. #pragma warning(disable: 4996)
  24. #endif
  25. #include "gfx/D3D9/gfxD3D9Device.h"
  26. #include "gfx/D3D9/gfxD3D9EnumTranslate.h"
  27. #include "gfx/bitmap/bitmapUtils.h"
  28. #include "gfx/gfxCardProfile.h"
  29. #include "core/strings/unicode.h"
  30. #include "core/util/swizzle.h"
  31. #include "core/util/safeDelete.h"
  32. #include "console/console.h"
  33. #include "core/resourceManager.h"
  34. //-----------------------------------------------------------------------------
  35. // Utility function, valid only in this file
  36. #ifdef D3D_TEXTURE_SPEW
  37. U32 GFXD3D9TextureObject::mTexCount = 0;
  38. #endif
  39. //-----------------------------------------------------------------------------
  40. // Constructor
  41. //-----------------------------------------------------------------------------
  42. GFXD3D9TextureManager::GFXD3D9TextureManager( LPDIRECT3DDEVICE9 d3ddevice, U32 adapterIndex )
  43. {
  44. mD3DDevice = d3ddevice;
  45. mAdapterIndex = adapterIndex;
  46. dMemset( mCurTexSet, 0, sizeof( mCurTexSet ) );
  47. mD3DDevice->GetDeviceCaps(&mDeviceCaps);
  48. }
  49. //-----------------------------------------------------------------------------
  50. // Destructor
  51. //-----------------------------------------------------------------------------
  52. GFXD3D9TextureManager::~GFXD3D9TextureManager()
  53. {
  54. // Destroy texture table now so just in case some texture objects
  55. // are still left, we don't crash on a pure virtual method call.
  56. SAFE_DELETE_ARRAY( mHashTable );
  57. }
  58. //-----------------------------------------------------------------------------
  59. // _innerCreateTexture
  60. //-----------------------------------------------------------------------------
  61. void GFXD3D9TextureManager::_innerCreateTexture( GFXD3D9TextureObject *retTex,
  62. U32 height,
  63. U32 width,
  64. U32 depth,
  65. GFXFormat format,
  66. GFXTextureProfile *profile,
  67. U32 numMipLevels,
  68. bool forceMips,
  69. S32 antialiasLevel)
  70. {
  71. GFXD3D9Device* d3d = static_cast<GFXD3D9Device*>(GFX);
  72. // Some relevant helper information...
  73. bool supportsAutoMips = GFX->getCardProfiler()->queryProfile("autoMipMapLevel", true);
  74. DWORD usage = 0; // 0, D3DUSAGE_RENDERTARGET, or D3DUSAGE_DYNAMIC
  75. D3DPOOL pool = D3DPOOL_DEFAULT;
  76. retTex->mProfile = profile;
  77. D3DFORMAT d3dTextureFormat = GFXD3D9TextureFormat[format];
  78. #ifndef TORQUE_OS_XENON
  79. if( retTex->mProfile->isDynamic() )
  80. {
  81. usage = D3DUSAGE_DYNAMIC;
  82. }
  83. else
  84. {
  85. usage = 0;
  86. pool = d3d->isD3D9Ex() ? D3DPOOL_DEFAULT : D3DPOOL_MANAGED;
  87. }
  88. if( retTex->mProfile->isRenderTarget() )
  89. {
  90. pool = D3DPOOL_DEFAULT;
  91. usage |= D3DUSAGE_RENDERTARGET;
  92. }
  93. if(retTex->mProfile->isZTarget())
  94. {
  95. usage |= D3DUSAGE_DEPTHSTENCIL;
  96. pool = D3DPOOL_DEFAULT;
  97. }
  98. if( retTex->mProfile->isSystemMemory() )
  99. {
  100. pool = D3DPOOL_SYSTEMMEM;
  101. }
  102. if( supportsAutoMips &&
  103. !forceMips &&
  104. !retTex->mProfile->isSystemMemory() &&
  105. numMipLevels == 0 &&
  106. !(depth > 0) )
  107. {
  108. usage |= D3DUSAGE_AUTOGENMIPMAP;
  109. }
  110. #else
  111. if(retTex->mProfile->isRenderTarget())
  112. {
  113. d3dTextureFormat = (D3DFORMAT)MAKELEFMT(d3dTextureFormat);
  114. }
  115. #endif
  116. // Set the managed flag...
  117. retTex->isManaged = (pool == D3DPOOL_MANAGED) || d3d->isD3D9Ex();
  118. if( depth > 0 )
  119. {
  120. #ifdef TORQUE_OS_XENON
  121. D3D9Assert( mD3DDevice->CreateVolumeTexture( width, height, depth, numMipLevels, 0 /* usage ignored on the 360 */,
  122. d3dTextureFormat, pool, retTex->get3DTexPtr(), NULL), "Failed to create volume texture" );
  123. #else
  124. D3D9Assert(
  125. GFXD3DX.D3DXCreateVolumeTexture(
  126. mD3DDevice,
  127. width,
  128. height,
  129. depth,
  130. numMipLevels,
  131. usage,
  132. d3dTextureFormat,
  133. pool,
  134. retTex->get3DTexPtr()
  135. ), "GFXD3D9TextureManager::_createTexture - failed to create volume texture!"
  136. );
  137. #endif
  138. retTex->mTextureSize.set( width, height, depth );
  139. retTex->mMipLevels = retTex->get3DTex()->GetLevelCount();
  140. // required for 3D texture support - John Kabus
  141. retTex->mFormat = format;
  142. }
  143. else
  144. {
  145. #ifdef TORQUE_OS_XENON
  146. D3D9Assert( mD3DDevice->CreateTexture(width, height, numMipLevels, usage, d3dTextureFormat, pool, retTex->get2DTexPtr(), NULL), "Failed to create texture" );
  147. retTex->mMipLevels = retTex->get2DTex()->GetLevelCount();
  148. #else
  149. // Figure out AA settings for depth and render targets
  150. D3DMULTISAMPLE_TYPE mstype;
  151. DWORD mslevel;
  152. switch (antialiasLevel)
  153. {
  154. case 0 :
  155. mstype = D3DMULTISAMPLE_NONE;
  156. mslevel = 0;
  157. break;
  158. case AA_MATCH_BACKBUFFER :
  159. mstype = d3d->getMultisampleType();
  160. mslevel = d3d->getMultisampleLevel();
  161. break;
  162. default :
  163. {
  164. mstype = D3DMULTISAMPLE_NONMASKABLE;
  165. mslevel = antialiasLevel;
  166. #ifdef TORQUE_DEBUG
  167. DWORD MaxSampleQualities;
  168. d3d->getD3D()->CheckDeviceMultiSampleType(mAdapterIndex, D3DDEVTYPE_HAL, d3dTextureFormat, FALSE, D3DMULTISAMPLE_NONMASKABLE, &MaxSampleQualities);
  169. AssertFatal(mslevel < MaxSampleQualities, "Invalid AA level!");
  170. #endif
  171. }
  172. break;
  173. }
  174. bool fastCreate = true;
  175. // Check for power of 2 textures - this is a problem with FX 5xxx cards
  176. // with current drivers - 3/2/05
  177. if( !isPow2(width) || !isPow2(height) )
  178. {
  179. fastCreate = false;
  180. }
  181. if(retTex->mProfile->isZTarget())
  182. {
  183. D3D9Assert(mD3DDevice->CreateDepthStencilSurface(width, height, d3dTextureFormat,
  184. mstype, mslevel, retTex->mProfile->canDiscard(), retTex->getSurfacePtr(), NULL), "Failed to create Z surface" );
  185. retTex->mFormat = format; // Assigning format like this should be fine.
  186. }
  187. else
  188. {
  189. // Try to create the texture directly - should gain us a bit in high
  190. // performance cases where we know we're creating good stuff and we
  191. // don't want to bother with D3DX - slow function.
  192. HRESULT res = D3DERR_INVALIDCALL;
  193. if( fastCreate )
  194. {
  195. res = mD3DDevice->CreateTexture(width, height, numMipLevels, usage, d3dTextureFormat, pool, retTex->get2DTexPtr(), NULL);
  196. }
  197. if( !fastCreate || (res != D3D_OK) )
  198. {
  199. D3D9Assert(
  200. GFXD3DX.D3DXCreateTexture(
  201. mD3DDevice,
  202. width,
  203. height,
  204. numMipLevels,
  205. usage,
  206. d3dTextureFormat,
  207. pool,
  208. retTex->get2DTexPtr()
  209. ), "GFXD3D9TextureManager::_createTexture - failed to create texture!"
  210. );
  211. }
  212. // If this is a render target, and it wants AA or wants to match the backbuffer (for example, to share the z)
  213. // Check the caps though, if we can't stretchrect between textures, use the old RT method. (Which hopefully means
  214. // that they can't force AA on us as well.)
  215. if (retTex->mProfile->isRenderTarget() && mslevel != 0 && (mDeviceCaps.Caps2 & D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES))
  216. {
  217. D3D9Assert(mD3DDevice->CreateRenderTarget(width, height, d3dTextureFormat,
  218. mstype, mslevel, false, retTex->getSurfacePtr(), NULL),
  219. "GFXD3D9TextureManager::_createTexture - unable to create render target");
  220. }
  221. // All done!
  222. retTex->mMipLevels = retTex->get2DTex()->GetLevelCount();
  223. }
  224. #endif
  225. // Get the actual size of the texture...
  226. D3DSURFACE_DESC probeDesc;
  227. ZeroMemory(&probeDesc, sizeof probeDesc);
  228. if( retTex->get2DTex() != NULL )
  229. D3D9Assert( retTex->get2DTex()->GetLevelDesc( 0, &probeDesc ), "Failed to get surface description");
  230. else if( retTex->getSurface() != NULL )
  231. D3D9Assert( retTex->getSurface()->GetDesc( &probeDesc ), "Failed to get surface description");
  232. retTex->mTextureSize.set(probeDesc.Width, probeDesc.Height, 0);
  233. S32 fmt = probeDesc.Format;
  234. #if !defined(TORQUE_OS_XENON)
  235. GFXREVERSE_LOOKUP( GFXD3D9TextureFormat, GFXFormat, fmt );
  236. retTex->mFormat = (GFXFormat)fmt;
  237. #else
  238. retTex->mFormat = format;
  239. #endif
  240. }
  241. }
  242. //-----------------------------------------------------------------------------
  243. // createTexture
  244. //-----------------------------------------------------------------------------
  245. GFXTextureObject *GFXD3D9TextureManager::_createTextureObject( U32 height,
  246. U32 width,
  247. U32 depth,
  248. GFXFormat format,
  249. GFXTextureProfile *profile,
  250. U32 numMipLevels,
  251. bool forceMips,
  252. S32 antialiasLevel,
  253. GFXTextureObject *inTex )
  254. {
  255. GFXD3D9TextureObject *retTex;
  256. if ( inTex )
  257. {
  258. AssertFatal( dynamic_cast<GFXD3D9TextureObject*>( inTex ), "GFXD3D9TextureManager::_createTexture() - Bad inTex type!" );
  259. retTex = static_cast<GFXD3D9TextureObject*>( inTex );
  260. retTex->release();
  261. }
  262. else
  263. {
  264. retTex = new GFXD3D9TextureObject( GFX, profile );
  265. retTex->registerResourceWithDevice( GFX );
  266. }
  267. _innerCreateTexture(retTex, height, width, depth, format, profile, numMipLevels, forceMips, antialiasLevel);
  268. return retTex;
  269. }
  270. //-----------------------------------------------------------------------------
  271. // loadTexture - GBitmap
  272. //-----------------------------------------------------------------------------
  273. bool GFXD3D9TextureManager::_loadTexture(GFXTextureObject *aTexture, GBitmap *pDL)
  274. {
  275. PROFILE_SCOPE(GFXD3D9TextureManager_loadTexture);
  276. GFXD3D9TextureObject *texture = static_cast<GFXD3D9TextureObject*>(aTexture);
  277. #ifdef TORQUE_OS_XENON
  278. // If the texture is currently bound, it needs to be unbound before modifying it
  279. if( texture->getTex() && texture->getTex()->IsSet( mD3DDevice ) )
  280. {
  281. mD3DDevice->SetTexture( 0, NULL );
  282. mD3DDevice->SetTexture( 1, NULL );
  283. mD3DDevice->SetTexture( 2, NULL );
  284. mD3DDevice->SetTexture( 3, NULL );
  285. mD3DDevice->SetTexture( 4, NULL );
  286. mD3DDevice->SetTexture( 5, NULL );
  287. mD3DDevice->SetTexture( 6, NULL );
  288. mD3DDevice->SetTexture( 7, NULL );
  289. }
  290. #endif
  291. // Check with profiler to see if we can do automatic mipmap generation.
  292. const bool supportsAutoMips = GFX->getCardProfiler()->queryProfile("autoMipMapLevel", true);
  293. // Helper bool
  294. const bool isCompressedTexFmt = aTexture->mFormat >= GFXFormatDXT1 && aTexture->mFormat <= GFXFormatDXT5;
  295. GFXD3D9Device* dev = static_cast<GFXD3D9Device *>(GFX);
  296. // Settings for mipmap generation
  297. U32 maxDownloadMip = pDL->getNumMipLevels();
  298. U32 nbMipMapLevel = pDL->getNumMipLevels();
  299. if( supportsAutoMips && !isCompressedTexFmt )
  300. {
  301. maxDownloadMip = 1;
  302. nbMipMapLevel = aTexture->mMipLevels;
  303. }
  304. // Fill the texture...
  305. for( int i = 0; i < maxDownloadMip; i++ )
  306. {
  307. LPDIRECT3DSURFACE9 surf = NULL;
  308. D3D9Assert(texture->get2DTex()->GetSurfaceLevel( i, &surf ), "Failed to get surface");
  309. D3DLOCKED_RECT lockedRect;
  310. #ifdef TORQUE_OS_XENON
  311. // On the 360, doing a LockRect doesn't work like it does with untiled memory
  312. // so instead swizzle into some temporary memory, and then later use D3DX
  313. // to do the upload properly.
  314. FrameTemp<U8> swizzleMem(pDL->getWidth(i) * pDL->getHeight(i) * pDL->getBytesPerPixel());
  315. lockedRect.pBits = (void*)~swizzleMem;
  316. #else
  317. U32 waterMark = 0;
  318. if (!dev->isD3D9Ex())
  319. surf->LockRect( &lockedRect, NULL, 0 );
  320. else
  321. {
  322. waterMark = FrameAllocator::getWaterMark();
  323. lockedRect.pBits = static_cast<void*>(FrameAllocator::alloc(pDL->getWidth(i) * pDL->getHeight(i) * pDL->getBytesPerPixel()));
  324. }
  325. #endif
  326. switch( texture->mFormat )
  327. {
  328. case GFXFormatR8G8B8:
  329. {
  330. PROFILE_SCOPE(Swizzle24_Upload);
  331. AssertFatal( pDL->getFormat() == GFXFormatR8G8B8, "Assumption failed" );
  332. GFX->getDeviceSwizzle24()->ToBuffer( lockedRect.pBits, pDL->getBits(i),
  333. pDL->getWidth(i) * pDL->getHeight(i) * pDL->getBytesPerPixel() );
  334. }
  335. break;
  336. case GFXFormatR8G8B8A8:
  337. case GFXFormatR8G8B8X8:
  338. {
  339. PROFILE_SCOPE(Swizzle32_Upload);
  340. GFX->getDeviceSwizzle32()->ToBuffer( lockedRect.pBits, pDL->getBits(i),
  341. pDL->getWidth(i) * pDL->getHeight(i) * pDL->getBytesPerPixel() );
  342. }
  343. break;
  344. default:
  345. {
  346. // Just copy the bits in no swizzle or padding
  347. PROFILE_SCOPE(SwizzleNull_Upload);
  348. AssertFatal( pDL->getFormat() == texture->mFormat, "Format mismatch" );
  349. dMemcpy( lockedRect.pBits, pDL->getBits(i),
  350. pDL->getWidth(i) * pDL->getHeight(i) * pDL->getBytesPerPixel() );
  351. }
  352. }
  353. #ifdef TORQUE_OS_XENON
  354. RECT srcRect;
  355. srcRect.bottom = pDL->getHeight(i);
  356. srcRect.top = 0;
  357. srcRect.left = 0;
  358. srcRect.right = pDL->getWidth(i);
  359. D3DXLoadSurfaceFromMemory(surf, NULL, NULL, ~swizzleMem, (D3DFORMAT)MAKELINFMT(GFXD3D9TextureFormat[pDL->getFormat()]),
  360. pDL->getWidth(i) * pDL->getBytesPerPixel(), NULL, &srcRect, false, 0, 0, D3DX_FILTER_NONE, 0);
  361. #else
  362. if (!dev->isD3D9Ex())
  363. surf->UnlockRect();
  364. else
  365. {
  366. RECT srcRect;
  367. srcRect.top = 0;
  368. srcRect.left = 0;
  369. srcRect.right = pDL->getWidth(i);
  370. srcRect.bottom = pDL->getHeight(i);
  371. D3DXLoadSurfaceFromMemory(surf, NULL, NULL, lockedRect.pBits, GFXD3D9TextureFormat[pDL->getFormat()], pDL->getBytesPerPixel() * pDL->getWidth(i), NULL, &srcRect, D3DX_DEFAULT, 0);
  372. FrameAllocator::setWaterMark(waterMark);
  373. }
  374. #endif
  375. surf->Release();
  376. }
  377. return true;
  378. }
  379. //-----------------------------------------------------------------------------
  380. // loadTexture - raw
  381. //-----------------------------------------------------------------------------
  382. bool GFXD3D9TextureManager::_loadTexture( GFXTextureObject *inTex, void *raw )
  383. {
  384. PROFILE_SCOPE(GFXD3D9TextureManager_loadTextureRaw);
  385. GFXD3D9TextureObject *texture = (GFXD3D9TextureObject *) inTex;
  386. // currently only for volume textures...
  387. if( texture->getDepth() < 1 ) return false;
  388. U32 bytesPerPix = 1;
  389. switch( texture->mFormat )
  390. {
  391. case GFXFormatR8G8B8:
  392. bytesPerPix = 3;
  393. break;
  394. case GFXFormatR8G8B8A8:
  395. case GFXFormatR8G8B8X8:
  396. case GFXFormatB8G8R8A8:
  397. bytesPerPix = 4;
  398. break;
  399. }
  400. U32 rowPitch = texture->getWidth() * bytesPerPix;
  401. U32 slicePitch = texture->getWidth() * texture->getHeight() * bytesPerPix;
  402. D3DBOX box;
  403. box.Left = 0;
  404. box.Right = texture->getWidth();
  405. box.Front = 0;
  406. box.Back = texture->getDepth();
  407. box.Top = 0;
  408. box.Bottom = texture->getHeight();
  409. LPDIRECT3DVOLUME9 volume = NULL;
  410. D3D9Assert( texture->get3DTex()->GetVolumeLevel( 0, &volume ), "Failed to load volume" );
  411. #ifdef TORQUE_OS_XENON
  412. D3DLOCKED_BOX lockedBox;
  413. volume->LockBox( &lockedBox, &box, 0 );
  414. dMemcpy( lockedBox.pBits, raw, slicePitch * texture->getDepth() );
  415. volume->UnlockBox();
  416. #else
  417. D3D9Assert(
  418. GFXD3DX.D3DXLoadVolumeFromMemory(
  419. volume,
  420. NULL,
  421. NULL,
  422. raw,
  423. GFXD3D9TextureFormat[texture->mFormat],
  424. rowPitch,
  425. slicePitch,
  426. NULL,
  427. &box,
  428. #ifdef TORQUE_OS_XENON
  429. false, 0, 0, 0, // Unique to Xenon -pw
  430. #endif
  431. D3DX_FILTER_NONE,
  432. 0
  433. ),
  434. "Failed to load volume texture"
  435. );
  436. #endif
  437. volume->Release();
  438. return true;
  439. }
  440. //-----------------------------------------------------------------------------
  441. // refreshTexture
  442. //-----------------------------------------------------------------------------
  443. bool GFXD3D9TextureManager::_refreshTexture(GFXTextureObject *texture)
  444. {
  445. U32 usedStrategies = 0;
  446. GFXD3D9TextureObject *realTex = static_cast<GFXD3D9TextureObject *>( texture );
  447. if(texture->mProfile->doStoreBitmap())
  448. {
  449. // SAFE_RELEASE(realTex->mD3DTexture);
  450. // _innerCreateTexture(realTex, texture->mTextureSize.x, texture->mTextureSize.y, texture->mFormat, texture->mProfile, texture->mMipLevels);
  451. if(texture->mBitmap)
  452. _loadTexture(texture, texture->mBitmap);
  453. if(texture->mDDS)
  454. _loadTexture(texture, texture->mDDS);
  455. usedStrategies++;
  456. }
  457. if(texture->mProfile->isRenderTarget() || texture->mProfile->isDynamic() ||
  458. texture->mProfile->isZTarget())
  459. {
  460. realTex->release();
  461. _innerCreateTexture(realTex, texture->getHeight(), texture->getWidth(), texture->getDepth(), texture->mFormat,
  462. texture->mProfile, texture->mMipLevels, false, texture->mAntialiasLevel);
  463. usedStrategies++;
  464. }
  465. AssertFatal(usedStrategies < 2, "GFXD3D9TextureManager::_refreshTexture - Inconsistent profile flags!");
  466. return true;
  467. }
  468. //-----------------------------------------------------------------------------
  469. // freeTexture
  470. //-----------------------------------------------------------------------------
  471. bool GFXD3D9TextureManager::_freeTexture(GFXTextureObject *texture, bool zombify)
  472. {
  473. AssertFatal(dynamic_cast<GFXD3D9TextureObject *>(texture),"Not an actual d3d texture object!");
  474. GFXD3D9TextureObject *tex = static_cast<GFXD3D9TextureObject *>( texture );
  475. // If it's a managed texture and we're zombifying, don't blast it, D3D allows
  476. // us to keep it.
  477. if(zombify && tex->isManaged)
  478. return true;
  479. tex->release();
  480. return true;
  481. }
  482. /// Load a texture from a proper DDSFile instance.
  483. bool GFXD3D9TextureManager::_loadTexture(GFXTextureObject *aTexture, DDSFile *dds)
  484. {
  485. PROFILE_SCOPE(GFXD3D9TextureManager_loadTextureDDS);
  486. GFXD3D9TextureObject *texture = static_cast<GFXD3D9TextureObject*>(aTexture);
  487. // Fill the texture...
  488. for( S32 i = 0; i < aTexture->mMipLevels; i++ )
  489. {
  490. PROFILE_SCOPE(GFXD3DTexMan_loadSurface);
  491. LPDIRECT3DSURFACE9 surf = NULL;
  492. D3D9Assert(texture->get2DTex()->GetSurfaceLevel( i, &surf ), "Failed to get surface");
  493. #if defined(TORQUE_OS_XENON)
  494. XGTEXTURE_DESC surfDesc;
  495. dMemset(&surfDesc, 0, sizeof(XGTEXTURE_DESC));
  496. XGGetSurfaceDesc(surf, &surfDesc);
  497. RECT srcRect;
  498. srcRect.top = srcRect.left = 0;
  499. srcRect.bottom = dds->getHeight(i);
  500. srcRect.right = dds->getWidth(i);
  501. D3DXLoadSurfaceFromMemory(surf, NULL, NULL, dds->mSurfaces[0]->mMips[i],
  502. (D3DFORMAT)MAKELINFMT(GFXD3D9TextureFormat[dds->mFormat]), dds->getSurfacePitch(i),
  503. NULL, &srcRect, false, 0, 0, D3DX_FILTER_NONE, 0);
  504. #else
  505. GFXD3D9Device* dev = static_cast<GFXD3D9Device *>(GFX);
  506. if (dev->isD3D9Ex())
  507. {
  508. RECT r;
  509. r.top = r.left = 0;
  510. r.bottom = dds->getHeight(i);
  511. r.right = dds->getWidth(i);
  512. D3DXLoadSurfaceFromMemory(surf, NULL, NULL, dds->mSurfaces[0]->mMips[i], GFXD3D9TextureFormat[dds->mFormat], dds->getSurfacePitch(i), NULL, &r, D3DX_DEFAULT, 0);
  513. }
  514. else
  515. {
  516. D3DLOCKED_RECT lockedRect;
  517. D3D9Assert( surf->LockRect( &lockedRect, NULL, 0 ), "Failed to lock surface level for load" );
  518. AssertFatal( dds->mSurfaces.size() > 0, "Assumption failed. DDSFile has no surfaces." );
  519. if ( dds->getSurfacePitch( i ) != lockedRect.Pitch )
  520. {
  521. // Do a row-by-row copy.
  522. U32 srcPitch = dds->getSurfacePitch( i );
  523. U32 srcHeight = dds->getHeight();
  524. U8* srcBytes = dds->mSurfaces[0]->mMips[i];
  525. U8* dstBytes = (U8*)lockedRect.pBits;
  526. for (U32 i = 0; i<srcHeight; i++)
  527. {
  528. dMemcpy( dstBytes, srcBytes, srcPitch );
  529. dstBytes += lockedRect.Pitch;
  530. srcBytes += srcPitch;
  531. }
  532. surf->UnlockRect();
  533. surf->Release();
  534. return true;
  535. }
  536. dMemcpy( lockedRect.pBits, dds->mSurfaces[0]->mMips[i], dds->getSurfaceSize(i) );
  537. surf->UnlockRect();
  538. }
  539. #endif
  540. surf->Release();
  541. }
  542. return true;
  543. }