BsD3D9Texture.cpp 37 KB

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