gfxD3D9TextureManager.cpp 22 KB

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