BsD3D9Texture.cpp 37 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141
  1. #include "BsCoreThread.h"
  2. #include "BsD3D9Texture.h"
  3. #include "BsD3D9PixelBuffer.h"
  4. #include "BsException.h"
  5. #include "BsBitwise.h"
  6. #include "BsD3D9Mappings.h"
  7. #include "BsD3D9RenderSystem.h"
  8. #include "BsD3D9TextureManager.h"
  9. #include "BsD3D9Device.h"
  10. #include "BsD3D9DeviceManager.h"
  11. #include "BsD3D9ResourceManager.h"
  12. #include "BsRenderStats.h"
  13. namespace BansheeEngine
  14. {
  15. D3D9TextureCore::D3D9TextureCore(TextureType textureType, UINT32 width, UINT32 height, UINT32 depth, UINT32 numMipmaps,
  16. PixelFormat format, int usage, bool hwGamma, UINT32 multisampleCount)
  17. :TextureCore(textureType, width, height, depth, numMipmaps, format, usage, hwGamma, multisampleCount),
  18. mD3DPool(D3DPOOL_MANAGED), mDynamicTextures(false), mHwGammaReadSupported(false), mHwGammaWriteSupported(false),
  19. mMultisampleType(D3DMULTISAMPLE_NONE), mMultisampleQuality(0), mIsBindableAsShaderResource(true)
  20. { }
  21. D3D9TextureCore::~D3D9TextureCore()
  22. {
  23. }
  24. void D3D9TextureCore::initialize()
  25. {
  26. THROW_IF_NOT_CORE_THREAD;
  27. for (UINT32 i = 0; i < D3D9RenderSystem::getResourceCreationDeviceCount(); ++i)
  28. {
  29. IDirect3DDevice9* d3d9Device = D3D9RenderSystem::getResourceCreationDevice(i);
  30. createInternalResources(d3d9Device);
  31. }
  32. BS_INC_RENDER_STAT_CAT(ResCreated, RenderStatObject_Texture);
  33. TextureCore::initialize();
  34. }
  35. void D3D9TextureCore::destroy()
  36. {
  37. THROW_IF_NOT_CORE_THREAD;
  38. for (auto& resPair : mMapDeviceToTextureResources)
  39. {
  40. TextureResources* textureResource = resPair.second;
  41. freeTextureResources(resPair.first, textureResource);
  42. }
  43. for (auto& resPair : mMapDeviceToTextureResources)
  44. {
  45. TextureResources* textureResource = resPair.second;
  46. if (textureResource != nullptr)
  47. bs_delete(textureResource);
  48. }
  49. mMapDeviceToTextureResources.clear();
  50. mSurfaceList.clear();
  51. BS_INC_RENDER_STAT_CAT(ResDestroyed, RenderStatObject_Texture);
  52. TextureCore::destroy();
  53. }
  54. PixelData D3D9TextureCore::lockImpl(GpuLockOptions options, UINT32 mipLevel, UINT32 face)
  55. {
  56. if (mProperties.getMultisampleCount() > 0)
  57. BS_EXCEPT(InvalidStateException, "Multisampled textures cannot be accessed from the CPU directly.");
  58. if(mLockedBuffer != nullptr)
  59. BS_EXCEPT(InternalErrorException, "Trying to lock a buffer that's already locked.");
  60. if (mProperties.getUsage() == TU_DEPTHSTENCIL)
  61. BS_EXCEPT(InternalErrorException, "Cannot lock a depth stencil texture.");
  62. UINT32 mipWidth = mProperties.getWidth() >> mipLevel;
  63. UINT32 mipHeight = mProperties.getHeight() >> mipLevel;
  64. UINT32 mipDepth = mProperties.getDepth() >> mipLevel;
  65. PixelData lockedArea(mipWidth, mipHeight, mipDepth, mProperties.getFormat());
  66. mLockedBuffer = getBuffer(face, mipLevel);
  67. lockedArea.setExternalBuffer((UINT8*)mLockedBuffer->lock(options));
  68. return lockedArea;
  69. }
  70. void D3D9TextureCore::unlockImpl()
  71. {
  72. if(mLockedBuffer == nullptr)
  73. BS_EXCEPT(InternalErrorException, "Trying to unlock a buffer that's not locked.");
  74. mLockedBuffer->unlock();
  75. mLockedBuffer = nullptr;
  76. }
  77. void D3D9TextureCore::readData(PixelData& dest, UINT32 mipLevel, UINT32 face)
  78. {
  79. if (mProperties.getMultisampleCount() > 0)
  80. BS_EXCEPT(InvalidStateException, "Multisampled textures cannot be accessed from the CPU directly.");
  81. if (mProperties.getUsage() == TU_DEPTHSTENCIL || mProperties.getUsage() == TU_RENDERTARGET) // Render targets cannot be locked normally
  82. {
  83. IDirect3DDevice9* device = D3D9RenderSystem::getActiveD3D9Device();
  84. D3D9PixelBuffer* sourceBuffer = static_cast<D3D9PixelBuffer*>(getBuffer(face, mipLevel).get());
  85. UINT32 mipWidth = mProperties.getWidth() >> mipLevel;
  86. UINT32 mipHeight = mProperties.getHeight() >> mipLevel;
  87. D3DFORMAT format = chooseD3DFormat(device);
  88. // Note: I'm allocating and releasing a texture every time we read.
  89. // I might consider adding a flag to keep this texture permanent which would make reading
  90. // faster but at the cost of double the memory.
  91. IDirect3DTexture9* stagingTexture = nullptr;
  92. HRESULT hr = D3DXCreateTexture(device, (UINT)mipWidth, (UINT)mipHeight, 1,
  93. 0, format, D3DPOOL_SYSTEMMEM, &stagingTexture);
  94. if (FAILED(hr))
  95. {
  96. String msg = DXGetErrorDescription(hr);
  97. BS_EXCEPT(RenderingAPIException, "Failed to create a texture: " + msg);
  98. }
  99. IDirect3DSurface9* stagingSurface = nullptr;
  100. hr = stagingTexture->GetSurfaceLevel(0, &stagingSurface);
  101. if (FAILED(hr))
  102. {
  103. String msg = DXGetErrorDescription(hr);
  104. BS_EXCEPT(RenderingAPIException, "Failed to retrieve a texture surface: " + msg);
  105. }
  106. hr = device->GetRenderTargetData(sourceBuffer->getSurface(device), stagingSurface);
  107. if (FAILED(hr))
  108. {
  109. String msg = DXGetErrorDescription(hr);
  110. BS_EXCEPT(RenderingAPIException, "Failed to retrieve render target data: " + msg);
  111. }
  112. PixelData myData(mipWidth, mipHeight, 1, mProperties.getFormat());
  113. D3DLOCKED_RECT lrect;
  114. hr = stagingSurface->LockRect(&lrect, nullptr, D3DLOCK_READONLY);
  115. if (FAILED(hr))
  116. {
  117. String msg = DXGetErrorDescription(hr);
  118. BS_EXCEPT(RenderingAPIException, "Failed to lock surface: " + msg);
  119. }
  120. D3D9PixelBuffer::initPixelDataFromD3DLock(myData, lrect);
  121. #if BS_DEBUG_MODE
  122. if (dest.getConsecutiveSize() != myData.getConsecutiveSize())
  123. BS_EXCEPT(InternalErrorException, "Buffer sizes don't match.");
  124. #endif
  125. PixelUtil::bulkPixelConversion(myData, dest);
  126. hr = stagingSurface->UnlockRect();
  127. if (FAILED(hr))
  128. {
  129. String msg = DXGetErrorDescription(hr);
  130. BS_EXCEPT(RenderingAPIException, "Failed to unlock surface: " + msg);
  131. }
  132. SAFE_RELEASE(stagingSurface);
  133. SAFE_RELEASE(stagingTexture);
  134. }
  135. else
  136. {
  137. PixelData myData = lock(GBL_READ_ONLY, mipLevel, face);
  138. #if BS_DEBUG_MODE
  139. if (dest.getConsecutiveSize() != myData.getConsecutiveSize())
  140. {
  141. unlock();
  142. BS_EXCEPT(InternalErrorException, "Buffer sizes don't match.");
  143. }
  144. #endif
  145. PixelUtil::bulkPixelConversion(myData, dest);
  146. unlock();
  147. }
  148. }
  149. void D3D9TextureCore::writeData(const PixelData& src, UINT32 mipLevel, UINT32 face, bool discardWholeBuffer)
  150. {
  151. if (mProperties.getMultisampleCount() > 0)
  152. BS_EXCEPT(InvalidStateException, "Multisampled textures cannot be accessed from the CPU directly.");
  153. if (mProperties.getUsage() == TU_DYNAMIC || mProperties.getUsage() == TU_STATIC)
  154. {
  155. PixelData myData = lock(discardWholeBuffer ? GBL_WRITE_ONLY_DISCARD : GBL_WRITE_ONLY, mipLevel, face);
  156. PixelUtil::bulkPixelConversion(src, myData);
  157. unlock();
  158. }
  159. else
  160. {
  161. BS_EXCEPT(RenderingAPIException, "Trying to write into a buffer with unsupported usage: " + toString(mProperties.getUsage()));
  162. }
  163. }
  164. void D3D9TextureCore::copyImpl(UINT32 srcFace, UINT32 srcMipLevel, UINT32 destFace, UINT32 destMipLevel, const SPtr<TextureCore>& target)
  165. {
  166. THROW_IF_NOT_CORE_THREAD;
  167. TextureType texType = mProperties.getTextureType();
  168. if (texType == TEX_TYPE_1D || texType == TEX_TYPE_3D)
  169. BS_EXCEPT(NotImplementedException, "Copy not implemented for 1D and 3D textures yet.");
  170. HRESULT hr;
  171. D3D9TextureCore* other = static_cast<D3D9TextureCore*>(target.get());
  172. for (auto& resPair : mMapDeviceToTextureResources)
  173. {
  174. TextureResources* srcTextureResource = resPair.second;
  175. TextureResources* dstTextureResource = other->getTextureResources(resPair.first);
  176. IDirect3DSurface9 *sourceSurface = nullptr;
  177. IDirect3DSurface9 *destSurface = nullptr;
  178. if (texType == TEX_TYPE_2D && srcTextureResource->pNormTex != nullptr && dstTextureResource->pNormTex != nullptr)
  179. {
  180. if(FAILED(hr = srcTextureResource->pNormTex->GetSurfaceLevel(srcMipLevel, &sourceSurface)))
  181. {
  182. String msg = DXGetErrorDescription(hr);
  183. BS_EXCEPT(RenderingAPIException, "Cannot retrieve source surface for copy: " + msg);
  184. }
  185. if(FAILED(hr = dstTextureResource->pNormTex->GetSurfaceLevel(destMipLevel, &destSurface)))
  186. {
  187. String msg = DXGetErrorDescription(hr);
  188. BS_EXCEPT(RenderingAPIException, "Cannot retrieve destination surface for copy: " + msg);
  189. }
  190. }
  191. else if (texType == TEX_TYPE_CUBE_MAP && srcTextureResource->pCubeTex != nullptr && dstTextureResource->pCubeTex != nullptr)
  192. {
  193. IDirect3DSurface9 *sourceSurface = nullptr;
  194. if (FAILED(hr = srcTextureResource->pCubeTex->GetCubeMapSurface((D3DCUBEMAP_FACES)srcFace, srcMipLevel, &sourceSurface)))
  195. {
  196. String msg = DXGetErrorDescription(hr);
  197. BS_EXCEPT(RenderingAPIException, "Cannot retrieve source surface for copy: " + msg);
  198. }
  199. IDirect3DSurface9 *destSurface = nullptr;
  200. if (FAILED(hr = dstTextureResource->pCubeTex->GetCubeMapSurface((D3DCUBEMAP_FACES)destFace, destMipLevel, &destSurface)))
  201. {
  202. String msg = DXGetErrorDescription(hr);
  203. BS_EXCEPT(RenderingAPIException, "Cannot retrieve destination surface for copy: " + msg);
  204. }
  205. }
  206. if (sourceSurface != nullptr && destSurface != nullptr)
  207. {
  208. if (sourceSurface->Pool != D3DPOOL_DEFAULT)
  209. BS_EXCEPT(InvalidStateException, "Source surface must be in the default pool.");
  210. if (destSurface->Pool != D3DPOOL_DEFAULT)
  211. BS_EXCEPT(InvalidStateException, "Destination surface must be in the default pool.");
  212. if (FAILED(hr = resPair.first->StretchRect(sourceSurface, NULL, destSurface, NULL, D3DTEXF_NONE)))
  213. {
  214. String msg = DXGetErrorDescription(hr);
  215. BS_EXCEPT(RenderingAPIException, "StretchRect failed during copy: " + msg);
  216. }
  217. }
  218. SAFE_RELEASE(sourceSurface);
  219. SAFE_RELEASE(destSurface);
  220. }
  221. }
  222. D3D9TextureCore::TextureResources* D3D9TextureCore::getTextureResources(IDirect3DDevice9* d3d9Device)
  223. {
  224. auto iterFind = mMapDeviceToTextureResources.find(d3d9Device);
  225. if (iterFind == mMapDeviceToTextureResources.end())
  226. return nullptr;
  227. return iterFind->second;
  228. }
  229. D3D9TextureCore::TextureResources* D3D9TextureCore::allocateTextureResources(IDirect3DDevice9* d3d9Device)
  230. {
  231. assert(mMapDeviceToTextureResources.find(d3d9Device) == mMapDeviceToTextureResources.end());
  232. TextureResources* textureResources = bs_new<TextureResources>();
  233. textureResources->pNormTex = nullptr;
  234. textureResources->pCubeTex = nullptr;
  235. textureResources->pVolumeTex = nullptr;
  236. textureResources->pBaseTex = nullptr;
  237. textureResources->pMultisampleSurface = nullptr;
  238. textureResources->pDepthStencilSurface = nullptr;
  239. mMapDeviceToTextureResources[d3d9Device] = textureResources;
  240. return textureResources;
  241. }
  242. void D3D9TextureCore::freeTextureResources(IDirect3DDevice9* d3d9Device, D3D9TextureCore::TextureResources* textureResources)
  243. {
  244. D3D9_DEVICE_ACCESS_CRITICAL_SECTION
  245. // Release surfaces from each mip level.
  246. for(unsigned int i = 0; i < mSurfaceList.size(); ++i)
  247. {
  248. D3D9PixelBuffer* pixelBuffer = static_cast<D3D9PixelBuffer*>(mSurfaceList[i].get());
  249. pixelBuffer->releaseSurfaces(d3d9Device);
  250. }
  251. // Release the rest of the resources.
  252. SAFE_RELEASE(textureResources->pBaseTex);
  253. SAFE_RELEASE(textureResources->pNormTex);
  254. SAFE_RELEASE(textureResources->pCubeTex);
  255. SAFE_RELEASE(textureResources->pVolumeTex);
  256. SAFE_RELEASE(textureResources->pMultisampleSurface);
  257. SAFE_RELEASE(textureResources->pDepthStencilSurface);
  258. }
  259. UINT32 D3D9TextureCore::calculateSize() const
  260. {
  261. UINT32 instanceSize = mProperties.getNumFaces() *
  262. PixelUtil::getMemorySize(mProperties.getWidth(), mProperties.getHeight(),
  263. mProperties.getDepth(), mProperties.getFormat());
  264. return instanceSize * (UINT32)mMapDeviceToTextureResources.size();
  265. }
  266. void D3D9TextureCore::determinePool()
  267. {
  268. if (useDefaultPool())
  269. mD3DPool = D3DPOOL_DEFAULT;
  270. else
  271. mD3DPool = D3DPOOL_MANAGED;
  272. }
  273. void D3D9TextureCore::createInternalResources(IDirect3DDevice9* d3d9Device)
  274. {
  275. switch (mProperties.getTextureType())
  276. {
  277. case TEX_TYPE_1D:
  278. case TEX_TYPE_2D:
  279. createNormTex(d3d9Device);
  280. break;
  281. case TEX_TYPE_CUBE_MAP:
  282. createCubeTex(d3d9Device);
  283. break;
  284. case TEX_TYPE_3D:
  285. createVolumeTex(d3d9Device);
  286. break;
  287. default:
  288. BS_EXCEPT(InternalErrorException, "Unknown texture type.");
  289. }
  290. }
  291. void D3D9TextureCore::createNormTex(IDirect3DDevice9* d3d9Device)
  292. {
  293. UINT32 width = mProperties.getWidth();
  294. UINT32 height = mProperties.getHeight();
  295. int texUsage = mProperties.getUsage();
  296. UINT32 origNumMips = mProperties.getNumMipmaps();
  297. PixelFormat format = mProperties.getFormat();
  298. bool hwGamma = mProperties.isHardwareGammaEnabled();
  299. UINT32 sampleCount = mProperties.getMultisampleCount();
  300. assert(width > 0 || height > 0);
  301. D3DFORMAT d3dPF = chooseD3DFormat(d3d9Device);
  302. if (format != D3D9Mappings::_getPF(d3dPF))
  303. {
  304. BS_EXCEPT(RenderingAPIException, "Provided pixel format is not supported by the driver: " + toString(format));
  305. }
  306. // Use D3DX to help us create the texture, this way it can adjust any relevant sizes
  307. UINT numMips = (origNumMips == MIP_UNLIMITED) ? D3DX_DEFAULT : origNumMips + 1;
  308. DWORD usage = 0;
  309. if ((texUsage & TU_RENDERTARGET) != 0)
  310. usage = D3DUSAGE_RENDERTARGET;
  311. else if ((texUsage & TU_DEPTHSTENCIL) != 0)
  312. usage = D3DUSAGE_DEPTHSTENCIL;
  313. // Check dynamic textures
  314. if (texUsage & TU_DYNAMIC)
  315. {
  316. if (canUseDynamicTextures(d3d9Device, usage, D3DRTYPE_TEXTURE, d3dPF))
  317. {
  318. usage |= D3DUSAGE_DYNAMIC;
  319. mDynamicTextures = true;
  320. }
  321. else
  322. {
  323. mDynamicTextures = false;
  324. }
  325. }
  326. // Check sRGB support
  327. if (hwGamma)
  328. {
  329. mHwGammaReadSupported = canUseHardwareGammaCorrection(d3d9Device, usage, D3DRTYPE_TEXTURE, d3dPF, false);
  330. if (texUsage & TU_RENDERTARGET)
  331. mHwGammaWriteSupported = canUseHardwareGammaCorrection(d3d9Device, usage, D3DRTYPE_TEXTURE, d3dPF, true);
  332. }
  333. // Check multisample level
  334. if ((texUsage & TU_RENDERTARGET) != 0 || (texUsage & TU_DEPTHSTENCIL) != 0)
  335. {
  336. D3D9RenderSystem* rsys = static_cast<D3D9RenderSystem*>(BansheeEngine::RenderSystem::instancePtr());
  337. rsys->determineMultisampleSettings(d3d9Device, sampleCount, d3dPF, false, &mMultisampleType, &mMultisampleQuality);
  338. }
  339. else
  340. {
  341. mMultisampleType = D3DMULTISAMPLE_NONE;
  342. mMultisampleQuality = 0;
  343. }
  344. D3D9Device* device = D3D9RenderSystem::getDeviceManager()->getDeviceFromD3D9Device(d3d9Device);
  345. const D3DCAPS9& rkCurCaps = device->getD3D9DeviceCaps();
  346. // Check if mip maps are supported on hardware
  347. if (numMips > 1 && (!(rkCurCaps.TextureCaps & D3DPTEXTURECAPS_MIPMAP) || (texUsage & TU_RENDERTARGET) != 0 || (texUsage & TU_DEPTHSTENCIL) != 0))
  348. {
  349. BS_EXCEPT(InvalidParametersException, "Invalid number of mipmaps. Maximum allowed is: 0");
  350. }
  351. determinePool();
  352. TextureResources* textureResources;
  353. // Get or create new texture resources structure.
  354. textureResources = getTextureResources(d3d9Device);
  355. if (textureResources != NULL)
  356. freeTextureResources(d3d9Device, textureResources);
  357. else
  358. textureResources = allocateTextureResources(d3d9Device);
  359. if ((texUsage & TU_RENDERTARGET) != 0 && (mMultisampleType != D3DMULTISAMPLE_NONE))
  360. {
  361. // Create AA surface
  362. HRESULT hr = d3d9Device->CreateRenderTarget(width, height, d3dPF,
  363. mMultisampleType, mMultisampleQuality,
  364. FALSE,
  365. &textureResources->pMultisampleSurface, NULL);
  366. if (FAILED(hr))
  367. BS_EXCEPT(RenderingAPIException, "Unable to create AA render target: " + String(DXGetErrorDescription(hr)));
  368. D3DSURFACE_DESC desc;
  369. hr = textureResources->pMultisampleSurface->GetDesc(&desc);
  370. if (FAILED(hr))
  371. {
  372. BS_EXCEPT(RenderingAPIException, "Can't get texture description: " + String(DXGetErrorDescription(hr)));
  373. }
  374. setFinalAttributes(d3d9Device, textureResources, desc.Width, desc.Height, 1, D3D9Mappings::_getPF(desc.Format));
  375. mIsBindableAsShaderResource = false; // Cannot bind AA surfaces
  376. }
  377. else if ((texUsage & TU_DEPTHSTENCIL) != 0 && (mMultisampleType != D3DMULTISAMPLE_NONE))
  378. {
  379. // Create AA depth stencil surface
  380. HRESULT hr = d3d9Device->CreateDepthStencilSurface(width, height, d3dPF,
  381. mMultisampleType, mMultisampleQuality,
  382. FALSE,
  383. &textureResources->pDepthStencilSurface, NULL);
  384. if (FAILED(hr))
  385. BS_EXCEPT(RenderingAPIException, "Unable to create AA depth stencil render target: " + String(DXGetErrorDescription(hr)));
  386. // Update final parameters as they may differ from requested ones
  387. D3DSURFACE_DESC desc;
  388. hr = textureResources->pDepthStencilSurface->GetDesc(&desc);
  389. if (FAILED(hr))
  390. {
  391. BS_EXCEPT(RenderingAPIException, "Can't get texture description: " + String(DXGetErrorDescription(hr)));
  392. }
  393. setFinalAttributes(d3d9Device, textureResources, desc.Width, desc.Height, 1, D3D9Mappings::_getPF(desc.Format));
  394. mIsBindableAsShaderResource = false; // Cannot bind AA depth buffer
  395. }
  396. else
  397. {
  398. // Create normal texture
  399. HRESULT hr = D3DXCreateTexture(d3d9Device, (UINT)width, (UINT)height, numMips,
  400. usage, d3dPF, mD3DPool, &textureResources->pNormTex);
  401. if (FAILED(hr))
  402. {
  403. BS_EXCEPT(RenderingAPIException, "Error creating texture: " + String(DXGetErrorDescription(hr)));
  404. }
  405. hr = textureResources->pNormTex->QueryInterface(IID_IDirect3DBaseTexture9, (void **)&textureResources->pBaseTex);
  406. if (FAILED(hr))
  407. {
  408. BS_EXCEPT(RenderingAPIException, "Can't get base texture: " + String(DXGetErrorDescription(hr)));
  409. }
  410. // Update final parameters as they may differ from requested ones
  411. D3DSURFACE_DESC desc;
  412. hr = textureResources->pNormTex->GetLevelDesc(0, &desc);
  413. if (FAILED(hr))
  414. {
  415. BS_EXCEPT(RenderingAPIException, "Can't get texture description: " + String(DXGetErrorDescription(hr)));
  416. }
  417. setFinalAttributes(d3d9Device, textureResources, desc.Width, desc.Height, 1, D3D9Mappings::_getPF(desc.Format));
  418. }
  419. }
  420. void D3D9TextureCore::createCubeTex(IDirect3DDevice9* d3d9Device)
  421. {
  422. UINT32 width = mProperties.getWidth();
  423. UINT32 height = mProperties.getHeight();
  424. int texUsage = mProperties.getUsage();
  425. UINT32 origNumMips = mProperties.getNumMipmaps();
  426. PixelFormat format = mProperties.getFormat();
  427. bool hwGamma = mProperties.isHardwareGammaEnabled();
  428. assert(width > 0 || height > 0);
  429. D3DFORMAT d3dPF = chooseD3DFormat(d3d9Device);
  430. if (format != D3D9Mappings::_getPF(d3dPF))
  431. {
  432. BS_EXCEPT(RenderingAPIException, "Provided pixel format is not supported by the driver: " + toString(format));
  433. }
  434. // Use D3DX to help us create the texture, this way it can adjust any relevant sizes
  435. DWORD usage = (texUsage & TU_RENDERTARGET) ? D3DUSAGE_RENDERTARGET : 0;
  436. usage |= (texUsage & TU_DEPTHSTENCIL) ? D3DUSAGE_DEPTHSTENCIL : 0;
  437. UINT numMips = (origNumMips == MIP_UNLIMITED) ? D3DX_DEFAULT : origNumMips + 1;
  438. // Check dynamic textures
  439. if (texUsage & TU_DYNAMIC)
  440. {
  441. if (canUseDynamicTextures(d3d9Device, usage, D3DRTYPE_CUBETEXTURE, d3dPF))
  442. {
  443. usage |= D3DUSAGE_DYNAMIC;
  444. mDynamicTextures = true;
  445. }
  446. else
  447. {
  448. mDynamicTextures = false;
  449. }
  450. }
  451. // Check sRGB support
  452. if (hwGamma)
  453. {
  454. mHwGammaReadSupported = canUseHardwareGammaCorrection(d3d9Device, usage, D3DRTYPE_CUBETEXTURE, d3dPF, false);
  455. if (texUsage & TU_RENDERTARGET)
  456. mHwGammaWriteSupported = canUseHardwareGammaCorrection(d3d9Device, usage, D3DRTYPE_CUBETEXTURE, d3dPF, true);
  457. }
  458. // No multisampling on cube textures
  459. mMultisampleType = D3DMULTISAMPLE_NONE;
  460. mMultisampleQuality = 0;
  461. D3D9Device* device = D3D9RenderSystem::getDeviceManager()->getDeviceFromD3D9Device(d3d9Device);
  462. const D3DCAPS9& deviceCaps = device->getD3D9DeviceCaps();
  463. // Check if mip map cube textures are supported
  464. if (numMips > 1 && !(deviceCaps.TextureCaps & D3DPTEXTURECAPS_MIPCUBEMAP))
  465. {
  466. BS_EXCEPT(InvalidParametersException, "Invalid number of mipmaps. Maximum allowed is: 0");
  467. }
  468. determinePool();
  469. TextureResources* textureResources;
  470. // Get or create new texture resources structure.
  471. textureResources = getTextureResources(d3d9Device);
  472. if (textureResources != NULL)
  473. freeTextureResources(d3d9Device, textureResources);
  474. else
  475. textureResources = allocateTextureResources(d3d9Device);
  476. // Create the texture
  477. HRESULT hr = D3DXCreateCubeTexture(d3d9Device, (UINT)width, numMips,
  478. usage, d3dPF, mD3DPool, &textureResources->pCubeTex);
  479. if (FAILED(hr))
  480. {
  481. BS_EXCEPT(RenderingAPIException, "Error creating texture: " + String(DXGetErrorDescription(hr)));
  482. }
  483. hr = textureResources->pCubeTex->QueryInterface(IID_IDirect3DBaseTexture9, (void **)&textureResources->pBaseTex);
  484. if (FAILED(hr))
  485. {
  486. BS_EXCEPT(RenderingAPIException, "Can't get base texture: " + String(DXGetErrorDescription(hr)));
  487. }
  488. // Update final parameters as they may differ from requested ones
  489. D3DSURFACE_DESC desc;
  490. hr = textureResources->pCubeTex->GetLevelDesc(0, &desc);
  491. if (FAILED(hr))
  492. {
  493. BS_EXCEPT(RenderingAPIException, "Can't get texture description: " + String(DXGetErrorDescription(hr)));
  494. }
  495. setFinalAttributes(d3d9Device, textureResources, desc.Width, desc.Height, 1, D3D9Mappings::_getPF(desc.Format));
  496. }
  497. void D3D9TextureCore::createVolumeTex(IDirect3DDevice9* d3d9Device)
  498. {
  499. UINT32 width = mProperties.getWidth();
  500. UINT32 height = mProperties.getHeight();
  501. UINT32 depth = mProperties.getDepth();
  502. int texUsage = mProperties.getUsage();
  503. UINT32 origNumMips = mProperties.getNumMipmaps();
  504. PixelFormat format = mProperties.getFormat();
  505. bool hwGamma = mProperties.isHardwareGammaEnabled();
  506. assert(width > 0 && height > 0 && depth > 0);
  507. if (texUsage & TU_RENDERTARGET)
  508. BS_EXCEPT(RenderingAPIException, "D3D9 Volume texture can not be created as render target !!");
  509. if (texUsage & TU_DEPTHSTENCIL)
  510. BS_EXCEPT(RenderingAPIException, "D3D9 Volume texture can not be created as a depth stencil target !!");
  511. D3DFORMAT d3dPF = chooseD3DFormat(d3d9Device);
  512. if(format != D3D9Mappings::_getPF(d3dPF))
  513. {
  514. BS_EXCEPT(RenderingAPIException, "Provided pixel format is not supported by the driver: " + toString(format));
  515. }
  516. // Use D3DX to help us create the texture, this way it can adjust any relevant sizes
  517. DWORD usage = (texUsage & TU_RENDERTARGET) ? D3DUSAGE_RENDERTARGET : 0;
  518. UINT numMips = (origNumMips == MIP_UNLIMITED) ? D3DX_DEFAULT : origNumMips + 1;
  519. // Check dynamic textures
  520. if (texUsage & TU_DYNAMIC)
  521. {
  522. if (canUseDynamicTextures(d3d9Device, usage, D3DRTYPE_VOLUMETEXTURE, d3dPF))
  523. {
  524. usage |= D3DUSAGE_DYNAMIC;
  525. mDynamicTextures = true;
  526. }
  527. else
  528. {
  529. mDynamicTextures = false;
  530. }
  531. }
  532. // Check sRGB support
  533. if (hwGamma)
  534. {
  535. mHwGammaReadSupported = canUseHardwareGammaCorrection(d3d9Device, usage, D3DRTYPE_VOLUMETEXTURE, d3dPF, false);
  536. if (texUsage & TU_RENDERTARGET)
  537. mHwGammaWriteSupported = canUseHardwareGammaCorrection(d3d9Device, usage, D3DRTYPE_VOLUMETEXTURE, d3dPF, true);
  538. }
  539. D3D9Device* device = D3D9RenderSystem::getDeviceManager()->getDeviceFromD3D9Device(d3d9Device);
  540. const D3DCAPS9& rkCurCaps = device->getD3D9DeviceCaps();
  541. // Check if mip map volume textures are supported
  542. if (numMips > 1 && !(rkCurCaps.TextureCaps & D3DPTEXTURECAPS_MIPVOLUMEMAP))
  543. {
  544. BS_EXCEPT(InvalidParametersException, "Invalid number of mipmaps. Maximum allowed is: 0");
  545. }
  546. determinePool();
  547. TextureResources* textureResources;
  548. // Get or create new texture resources structure.
  549. textureResources = getTextureResources(d3d9Device);
  550. if (textureResources != NULL)
  551. freeTextureResources(d3d9Device, textureResources);
  552. else
  553. textureResources = allocateTextureResources(d3d9Device);
  554. // Create the texture
  555. HRESULT hr = D3DXCreateVolumeTexture(d3d9Device, (UINT)width, (UINT)height, (UINT)depth,
  556. numMips, usage, d3dPF, mD3DPool, &textureResources->pVolumeTex);
  557. if (FAILED(hr))
  558. {
  559. BS_EXCEPT(RenderingAPIException, "Error creating texture: " + String(DXGetErrorDescription(hr)));
  560. }
  561. hr = textureResources->pVolumeTex->QueryInterface(IID_IDirect3DBaseTexture9, (void**)&textureResources->pBaseTex);
  562. if (FAILED(hr))
  563. {
  564. BS_EXCEPT(RenderingAPIException, "Can't get base texture: " + String(DXGetErrorDescription(hr)));
  565. }
  566. // Update final parameters as they may differ from requested ones
  567. D3DVOLUME_DESC desc;
  568. hr = textureResources->pVolumeTex->GetLevelDesc(0, &desc);
  569. if (FAILED(hr))
  570. {
  571. BS_EXCEPT(RenderingAPIException, "Can't get texture description: " + String(DXGetErrorDescription(hr)));
  572. }
  573. setFinalAttributes(d3d9Device, textureResources, desc.Width, desc.Height, desc.Depth, D3D9Mappings::_getPF(desc.Format));
  574. }
  575. void D3D9TextureCore::setFinalAttributes(IDirect3DDevice9* d3d9Device, TextureResources* textureResources,
  576. UINT32 width, UINT32 height, UINT32 depth, PixelFormat format)
  577. {
  578. if(width != mProperties.getWidth() || height != mProperties.getHeight() || depth != mProperties.getDepth())
  579. {
  580. BS_EXCEPT(InternalErrorException, "Wanted and created textures sizes don't match!" \
  581. "Width: " + toString(width) + "/" + toString(mProperties.getWidth()) +
  582. "Height: " + toString(height) + "/" + toString(mProperties.getHeight()) +
  583. "Depth: " + toString(depth) + "/" + toString(mProperties.getDepth()));
  584. }
  585. if(format != mProperties.getFormat())
  586. {
  587. BS_EXCEPT(InternalErrorException, "Wanted and created texture formats don't match! " +
  588. toString(format) + "/" + toString(mProperties.getFormat()));
  589. }
  590. createSurfaceList(d3d9Device, textureResources);
  591. }
  592. D3DTEXTUREFILTERTYPE D3D9TextureCore::getBestFilterMethod(IDirect3DDevice9* d3d9Device)
  593. {
  594. D3D9Device* device = D3D9RenderSystem::getDeviceManager()->getDeviceFromD3D9Device(d3d9Device);
  595. const D3DCAPS9& deviceCaps = device->getD3D9DeviceCaps();
  596. DWORD filterCaps = 0;
  597. switch (mProperties.getTextureType())
  598. {
  599. case TEX_TYPE_1D:
  600. // Same as 2D
  601. case TEX_TYPE_2D:
  602. filterCaps = deviceCaps.TextureFilterCaps;
  603. break;
  604. case TEX_TYPE_3D:
  605. filterCaps = deviceCaps.VolumeTextureFilterCaps;
  606. break;
  607. case TEX_TYPE_CUBE_MAP:
  608. filterCaps = deviceCaps.CubeTextureFilterCaps;
  609. break;
  610. }
  611. if(filterCaps & D3DPTFILTERCAPS_MINFGAUSSIANQUAD)
  612. return D3DTEXF_GAUSSIANQUAD;
  613. if(filterCaps & D3DPTFILTERCAPS_MINFPYRAMIDALQUAD)
  614. return D3DTEXF_PYRAMIDALQUAD;
  615. if(filterCaps & D3DPTFILTERCAPS_MINFANISOTROPIC)
  616. return D3DTEXF_ANISOTROPIC;
  617. if(filterCaps & D3DPTFILTERCAPS_MINFLINEAR)
  618. return D3DTEXF_LINEAR;
  619. if(filterCaps & D3DPTFILTERCAPS_MINFPOINT)
  620. return D3DTEXF_POINT;
  621. return D3DTEXF_POINT;
  622. }
  623. bool D3D9TextureCore::canUseDynamicTextures(IDirect3DDevice9* d3d9Device, DWORD srcUsage, D3DRESOURCETYPE srcType,
  624. D3DFORMAT srcFormat)
  625. {
  626. IDirect3D9* pD3D = nullptr;
  627. HRESULT hr = d3d9Device->GetDirect3D(&pD3D);
  628. if (FAILED(hr))
  629. BS_EXCEPT(InvalidParametersException, "GetDirect3D failed !!!");
  630. if (pD3D != nullptr)
  631. pD3D->Release();
  632. D3D9Device* device = D3D9RenderSystem::getDeviceManager()->getDeviceFromD3D9Device(d3d9Device);
  633. const D3DCAPS9& deviceCaps = device->getD3D9DeviceCaps();
  634. D3DFORMAT backBufferFormat = device->getBackBufferFormat();
  635. hr = pD3D->CheckDeviceFormat(deviceCaps.AdapterOrdinal, deviceCaps.DeviceType,
  636. backBufferFormat, srcUsage | D3DUSAGE_DYNAMIC, srcType, srcFormat);
  637. return hr == D3D_OK;
  638. }
  639. bool D3D9TextureCore::canUseHardwareGammaCorrection(IDirect3DDevice9* d3d9Device, DWORD srcUsage,
  640. D3DRESOURCETYPE srcType, D3DFORMAT srcFormat, bool forwriting)
  641. {
  642. IDirect3D9* pD3D = nullptr;
  643. HRESULT hr = d3d9Device->GetDirect3D(&pD3D);
  644. if (FAILED(hr))
  645. {
  646. BS_EXCEPT(InvalidParametersException, "GetDirect3D failed !!!" );
  647. }
  648. if (pD3D != nullptr)
  649. pD3D->Release();
  650. D3D9Device* device = D3D9RenderSystem::getDeviceManager()->getDeviceFromD3D9Device(d3d9Device);
  651. const D3DCAPS9& deviceCaps = device->getD3D9DeviceCaps();
  652. D3DFORMAT backBufferFormat = device->getBackBufferFormat();
  653. if (forwriting)
  654. srcUsage |= D3DUSAGE_QUERY_SRGBWRITE;
  655. else
  656. srcUsage |= D3DUSAGE_QUERY_SRGBREAD;
  657. hr = pD3D->CheckDeviceFormat(deviceCaps.AdapterOrdinal, deviceCaps.DeviceType,
  658. backBufferFormat, srcUsage, srcType, srcFormat);
  659. return hr == D3D_OK;
  660. }
  661. bool D3D9TextureCore::canAutoGenMipmaps(IDirect3DDevice9* d3d9Device, DWORD srcUsage, D3DRESOURCETYPE srcType, D3DFORMAT srcFormat)
  662. {
  663. IDirect3D9* pD3D = nullptr;
  664. HRESULT hr = d3d9Device->GetDirect3D(&pD3D);
  665. if (FAILED(hr))
  666. {
  667. BS_EXCEPT(InvalidParametersException, "GetDirect3D failed.");
  668. }
  669. if (pD3D != nullptr)
  670. pD3D->Release();
  671. D3D9Device* device = D3D9RenderSystem::getDeviceManager()->getDeviceFromD3D9Device(d3d9Device);
  672. const D3DCAPS9& deviceCaps = device->getD3D9DeviceCaps();
  673. D3DFORMAT backBufferFormat = device->getBackBufferFormat();
  674. if (deviceCaps.Caps2 & D3DCAPS2_CANAUTOGENMIPMAP)
  675. {
  676. hr = pD3D->CheckDeviceFormat(deviceCaps.AdapterOrdinal, deviceCaps.DeviceType,
  677. backBufferFormat, srcUsage | D3DUSAGE_AUTOGENMIPMAP, srcType, srcFormat);
  678. return hr == D3D_OK;
  679. }
  680. else
  681. return false;
  682. }
  683. D3DFORMAT D3D9TextureCore::chooseD3DFormat(IDirect3DDevice9* d3d9Device)
  684. {
  685. // Choose frame buffer pixel format in case PF_UNKNOWN was requested
  686. if(mProperties.getFormat() == PF_UNKNOWN)
  687. {
  688. D3D9Device* device = D3D9RenderSystem::getDeviceManager()->getDeviceFromD3D9Device(d3d9Device);
  689. if((mProperties.getUsage() & TU_DEPTHSTENCIL) != 0)
  690. return device->getDepthStencilFormat();
  691. else
  692. return device->getBackBufferFormat();
  693. }
  694. // Choose closest supported D3D format as a D3D format
  695. return D3D9Mappings::_getPF(D3D9Mappings::_getClosestSupportedPF(mProperties.getFormat()));
  696. }
  697. void D3D9TextureCore::createSurfaceList(IDirect3DDevice9* d3d9Device, TextureResources* textureResources)
  698. {
  699. int texUsage = mProperties.getUsage();
  700. TextureType texType = mProperties.getTextureType();
  701. UINT32 numMips = mProperties.getNumMipmaps();
  702. assert(textureResources != nullptr);
  703. // Need to know static / dynamic
  704. UINT32 usage;
  705. if ((texUsage & TU_DYNAMIC) && mDynamicTextures)
  706. {
  707. usage = GBU_DYNAMIC;
  708. }
  709. else
  710. {
  711. usage = GBU_STATIC;
  712. }
  713. if (texUsage & TU_RENDERTARGET)
  714. {
  715. usage |= TU_RENDERTARGET;
  716. }
  717. else if (texUsage & TU_DEPTHSTENCIL)
  718. {
  719. usage |= TU_RENDERTARGET;
  720. }
  721. UINT32 surfaceCount = static_cast<UINT32>((mProperties.getNumFaces() * (numMips + 1)));
  722. bool updateOldList = mSurfaceList.size() == surfaceCount;
  723. if(!updateOldList)
  724. {
  725. mSurfaceList.clear();
  726. for (UINT32 face = 0; face < mProperties.getNumFaces(); face++)
  727. {
  728. for (UINT32 mip = 0; mip <= numMips; mip++)
  729. {
  730. mSurfaceList.push_back(bs_shared_ptr<D3D9PixelBuffer>((GpuBufferUsage)usage, this));
  731. }
  732. }
  733. }
  734. IDirect3DSurface9* surface = nullptr;
  735. IDirect3DVolume9* volume = nullptr;
  736. if ((texUsage & TU_RENDERTARGET) != 0 && (mMultisampleType != D3DMULTISAMPLE_NONE))
  737. {
  738. assert(textureResources->pMultisampleSurface);
  739. assert(texUsage == TEX_TYPE_2D);
  740. D3D9PixelBuffer* currPixelBuffer = static_cast<D3D9PixelBuffer*>(mSurfaceList[0].get());
  741. currPixelBuffer->bind(d3d9Device, textureResources->pMultisampleSurface, textureResources->pBaseTex);
  742. }
  743. else if ((texUsage & TU_DEPTHSTENCIL) != 0 && (mMultisampleType != D3DMULTISAMPLE_NONE))
  744. {
  745. assert(textureResources->pDepthStencilSurface);
  746. assert(texUsage == TEX_TYPE_2D);
  747. D3D9PixelBuffer* currPixelBuffer = static_cast<D3D9PixelBuffer*>(mSurfaceList[0].get());
  748. currPixelBuffer->bind(d3d9Device, textureResources->pDepthStencilSurface, textureResources->pBaseTex);
  749. }
  750. else
  751. {
  752. assert(textureResources->pBaseTex);
  753. UINT32 numCreatedMips = textureResources->pBaseTex->GetLevelCount() - 1;
  754. if (numCreatedMips != numMips)
  755. {
  756. BS_EXCEPT(InternalErrorException, "Number of created and wanted mip map levels doesn't match: " +
  757. toString(numCreatedMips) + "/" + toString(numMips));
  758. }
  759. switch(texType)
  760. {
  761. case TEX_TYPE_2D:
  762. case TEX_TYPE_1D:
  763. assert(textureResources->pNormTex);
  764. for (UINT32 mip = 0; mip <= numMips; mip++)
  765. {
  766. if(textureResources->pNormTex->GetSurfaceLevel(static_cast<UINT>(mip), &surface) != D3D_OK)
  767. BS_EXCEPT(RenderingAPIException, "Get surface level failed");
  768. D3D9PixelBuffer* currPixelBuffer = static_cast<D3D9PixelBuffer*>(mSurfaceList[mip].get());
  769. currPixelBuffer->bind(d3d9Device, surface, textureResources->pBaseTex);
  770. surface->Release();
  771. }
  772. break;
  773. case TEX_TYPE_CUBE_MAP:
  774. assert(textureResources->pCubeTex);
  775. for(UINT32 face = 0; face < 6; face++)
  776. {
  777. for (UINT32 mip = 0; mip <= numMips; mip++)
  778. {
  779. if(textureResources->pCubeTex->GetCubeMapSurface((D3DCUBEMAP_FACES)face, static_cast<UINT>(mip), &surface) != D3D_OK)
  780. BS_EXCEPT(RenderingAPIException, "Get cubemap surface failed");
  781. UINT32 idx = face*(numMips + 1) + mip;
  782. D3D9PixelBuffer* currPixelBuffer = static_cast<D3D9PixelBuffer*>(mSurfaceList[idx].get());
  783. currPixelBuffer->bind(d3d9Device, surface, textureResources->pBaseTex);
  784. surface->Release();
  785. }
  786. }
  787. break;
  788. case TEX_TYPE_3D:
  789. assert(textureResources->pVolumeTex);
  790. for (UINT32 mip = 0; mip <= numMips; mip++)
  791. {
  792. if(textureResources->pVolumeTex->GetVolumeLevel(static_cast<UINT>(mip), &volume) != D3D_OK)
  793. BS_EXCEPT(RenderingAPIException, "Get volume level failed");
  794. D3D9PixelBuffer* currPixelBuffer = static_cast<D3D9PixelBuffer*>(mSurfaceList[mip].get());
  795. currPixelBuffer->bind(d3d9Device, volume, textureResources->pBaseTex);
  796. volume->Release();
  797. }
  798. break;
  799. };
  800. }
  801. }
  802. PixelBufferPtr D3D9TextureCore::getBuffer(UINT32 face, UINT32 mipmap)
  803. {
  804. THROW_IF_NOT_CORE_THREAD;
  805. if(face >= mProperties.getNumFaces())
  806. BS_EXCEPT(InvalidParametersException, "A three dimensional cube has six faces");
  807. if (mipmap > mProperties.getNumMipmaps())
  808. BS_EXCEPT(InvalidParametersException, "Mipmap index out of range");
  809. UINT32 idx = face*(mProperties.getNumMipmaps() + 1) + mipmap;
  810. IDirect3DDevice9* d3d9Device = D3D9RenderSystem::getActiveD3D9Device();
  811. TextureResources* textureResources = getTextureResources(d3d9Device);
  812. if (textureResources == nullptr || textureResources->pBaseTex == nullptr)
  813. {
  814. createInternalResources(d3d9Device);
  815. textureResources = getTextureResources(d3d9Device);
  816. }
  817. assert(textureResources != nullptr);
  818. assert(idx < mSurfaceList.size());
  819. return mSurfaceList[idx];
  820. }
  821. bool D3D9TextureCore::useDefaultPool()
  822. {
  823. int usage = mProperties.getUsage();
  824. return (usage & TU_RENDERTARGET) || (usage & TU_DEPTHSTENCIL) || ((usage & TU_DYNAMIC) && mDynamicTextures);
  825. }
  826. void D3D9TextureCore::notifyOnDeviceCreate(IDirect3DDevice9* d3d9Device)
  827. {
  828. D3D9_DEVICE_ACCESS_CRITICAL_SECTION
  829. if (D3D9RenderSystem::getResourceManager()->getCreationPolicy() == RCP_CREATE_ON_ALL_DEVICES)
  830. createInternalResources(d3d9Device);
  831. }
  832. void D3D9TextureCore::notifyOnDeviceDestroy(IDirect3DDevice9* d3d9Device)
  833. {
  834. D3D9_DEVICE_ACCESS_CRITICAL_SECTION
  835. auto iterFind = mMapDeviceToTextureResources.find(d3d9Device);
  836. if (iterFind != mMapDeviceToTextureResources.end())
  837. {
  838. TextureResources* textureResource = iterFind->second;
  839. for(unsigned int i = 0; i < mSurfaceList.size(); ++i)
  840. {
  841. D3D9PixelBuffer* pixelBuffer = static_cast<D3D9PixelBuffer*>(mSurfaceList[i].get());
  842. pixelBuffer->destroyBufferResources(d3d9Device);
  843. }
  844. freeTextureResources(d3d9Device, textureResource);
  845. if(textureResource != nullptr)
  846. bs_delete(textureResource);
  847. mMapDeviceToTextureResources.erase(iterFind);
  848. }
  849. }
  850. void D3D9TextureCore::notifyOnDeviceLost(IDirect3DDevice9* d3d9Device)
  851. {
  852. D3D9_DEVICE_ACCESS_CRITICAL_SECTION
  853. if(mD3DPool == D3DPOOL_DEFAULT)
  854. {
  855. auto iterFind = mMapDeviceToTextureResources.find(d3d9Device);
  856. if (iterFind != mMapDeviceToTextureResources.end())
  857. {
  858. TextureResources* textureResource = iterFind->second;
  859. freeTextureResources(d3d9Device, textureResource);
  860. }
  861. }
  862. }
  863. void D3D9TextureCore::notifyOnDeviceReset(IDirect3DDevice9* d3d9Device)
  864. {
  865. D3D9_DEVICE_ACCESS_CRITICAL_SECTION
  866. if(mD3DPool == D3DPOOL_DEFAULT)
  867. {
  868. createInternalResources(d3d9Device);
  869. }
  870. }
  871. IDirect3DBaseTexture9* D3D9TextureCore::getTexture_internal()
  872. {
  873. THROW_IF_NOT_CORE_THREAD;
  874. TextureResources* textureResources;
  875. IDirect3DDevice9* d3d9Device = D3D9RenderSystem::getActiveD3D9Device();
  876. textureResources = getTextureResources(d3d9Device);
  877. if (textureResources == nullptr || textureResources->pBaseTex == nullptr)
  878. {
  879. createInternalResources(d3d9Device);
  880. textureResources = getTextureResources(d3d9Device);
  881. }
  882. assert(textureResources);
  883. assert(textureResources->pBaseTex);
  884. return textureResources->pBaseTex;
  885. }
  886. IDirect3DTexture9* D3D9TextureCore::getNormTexture_internal()
  887. {
  888. THROW_IF_NOT_CORE_THREAD;
  889. TextureResources* textureResources;
  890. IDirect3DDevice9* d3d9Device = D3D9RenderSystem::getActiveD3D9Device();
  891. textureResources = getTextureResources(d3d9Device);
  892. if (textureResources == nullptr || textureResources->pNormTex == nullptr)
  893. {
  894. createInternalResources(d3d9Device);
  895. textureResources = getTextureResources(d3d9Device);
  896. }
  897. assert(textureResources);
  898. assert(textureResources->pNormTex);
  899. return textureResources->pNormTex;
  900. }
  901. IDirect3DCubeTexture9* D3D9TextureCore::getCubeTexture_internal()
  902. {
  903. THROW_IF_NOT_CORE_THREAD;
  904. TextureResources* textureResources;
  905. IDirect3DDevice9* d3d9Device = D3D9RenderSystem::getActiveD3D9Device();
  906. textureResources = getTextureResources(d3d9Device);
  907. if (textureResources == nullptr || textureResources->pCubeTex)
  908. {
  909. createInternalResources(d3d9Device);
  910. textureResources = getTextureResources(d3d9Device);
  911. }
  912. assert(textureResources);
  913. assert(textureResources->pCubeTex);
  914. return textureResources->pCubeTex;
  915. }
  916. }