BsD3D9Texture.cpp 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140
  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 "BsD3D9RenderAPI.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 < D3D9RenderAPI::getResourceCreationDeviceCount(); ++i)
  43. {
  44. IDirect3DDevice9* d3d9Device = D3D9RenderAPI::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() > 1)
  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() > 1)
  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 = D3D9RenderAPI::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() > 1)
  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. D3DSURFACE_DESC desc;
  205. sourceSurface->GetDesc(&desc);
  206. if (desc.Pool != D3DPOOL_DEFAULT)
  207. BS_EXCEPT(InvalidStateException, "Source surface must be in the default pool.");
  208. destSurface->GetDesc(&desc);
  209. if (desc.Pool != D3DPOOL_DEFAULT)
  210. BS_EXCEPT(InvalidStateException, "Destination surface must be in the default pool.");
  211. if (FAILED(hr = resPair.first->StretchRect(sourceSurface, NULL, destSurface, NULL, D3DTEXF_NONE)))
  212. {
  213. String msg = DXGetErrorDescription(hr);
  214. BS_EXCEPT(RenderingAPIException, "StretchRect failed during copy: " + msg);
  215. }
  216. }
  217. SAFE_RELEASE(sourceSurface);
  218. SAFE_RELEASE(destSurface);
  219. }
  220. }
  221. D3D9TextureCore::TextureResources* D3D9TextureCore::getTextureResources(IDirect3DDevice9* d3d9Device)
  222. {
  223. auto iterFind = mMapDeviceToTextureResources.find(d3d9Device);
  224. if (iterFind == mMapDeviceToTextureResources.end())
  225. return nullptr;
  226. return iterFind->second;
  227. }
  228. D3D9TextureCore::TextureResources* D3D9TextureCore::allocateTextureResources(IDirect3DDevice9* d3d9Device)
  229. {
  230. assert(mMapDeviceToTextureResources.find(d3d9Device) == mMapDeviceToTextureResources.end());
  231. TextureResources* textureResources = bs_new<TextureResources>();
  232. textureResources->pNormTex = nullptr;
  233. textureResources->pCubeTex = nullptr;
  234. textureResources->pVolumeTex = nullptr;
  235. textureResources->pBaseTex = nullptr;
  236. textureResources->pMultisampleSurface = nullptr;
  237. textureResources->pDepthStencilSurface = nullptr;
  238. mMapDeviceToTextureResources[d3d9Device] = textureResources;
  239. return textureResources;
  240. }
  241. void D3D9TextureCore::freeTextureResources(IDirect3DDevice9* d3d9Device, D3D9TextureCore::TextureResources* textureResources)
  242. {
  243. D3D9_DEVICE_ACCESS_CRITICAL_SECTION
  244. // Release surfaces from each mip level.
  245. for(unsigned int i = 0; i < mSurfaceList.size(); ++i)
  246. {
  247. D3D9PixelBuffer* pixelBuffer = static_cast<D3D9PixelBuffer*>(mSurfaceList[i].get());
  248. pixelBuffer->releaseSurfaces(d3d9Device);
  249. }
  250. // Release the rest of the resources.
  251. SAFE_RELEASE(textureResources->pBaseTex);
  252. SAFE_RELEASE(textureResources->pNormTex);
  253. SAFE_RELEASE(textureResources->pCubeTex);
  254. SAFE_RELEASE(textureResources->pVolumeTex);
  255. SAFE_RELEASE(textureResources->pMultisampleSurface);
  256. SAFE_RELEASE(textureResources->pDepthStencilSurface);
  257. }
  258. UINT32 D3D9TextureCore::calculateSize() const
  259. {
  260. UINT32 instanceSize = mProperties.getNumFaces() *
  261. PixelUtil::getMemorySize(mProperties.getWidth(), mProperties.getHeight(),
  262. mProperties.getDepth(), mProperties.getFormat());
  263. return instanceSize * (UINT32)mMapDeviceToTextureResources.size();
  264. }
  265. void D3D9TextureCore::determinePool()
  266. {
  267. if (useDefaultPool())
  268. mD3DPool = D3DPOOL_DEFAULT;
  269. else
  270. mD3DPool = D3DPOOL_MANAGED;
  271. }
  272. void D3D9TextureCore::createInternalResources(IDirect3DDevice9* d3d9Device)
  273. {
  274. switch (mProperties.getTextureType())
  275. {
  276. case TEX_TYPE_1D:
  277. case TEX_TYPE_2D:
  278. createNormTex(d3d9Device);
  279. break;
  280. case TEX_TYPE_CUBE_MAP:
  281. createCubeTex(d3d9Device);
  282. break;
  283. case TEX_TYPE_3D:
  284. createVolumeTex(d3d9Device);
  285. break;
  286. default:
  287. BS_EXCEPT(InternalErrorException, "Unknown texture type.");
  288. }
  289. }
  290. void D3D9TextureCore::createNormTex(IDirect3DDevice9* d3d9Device)
  291. {
  292. UINT32 width = mProperties.getWidth();
  293. UINT32 height = mProperties.getHeight();
  294. int texUsage = mProperties.getUsage();
  295. UINT32 origNumMips = mProperties.getNumMipmaps();
  296. PixelFormat format = mProperties.getFormat();
  297. bool hwGamma = mProperties.isHardwareGammaEnabled();
  298. UINT32 sampleCount = mProperties.getMultisampleCount();
  299. assert(width > 0 || height > 0);
  300. D3DFORMAT d3dPF = chooseD3DFormat(d3d9Device);
  301. if (format != D3D9Mappings::_getPF(d3dPF))
  302. {
  303. BS_EXCEPT(RenderingAPIException, "Provided pixel format is not supported by the driver: " + toString(format));
  304. }
  305. // Use D3DX to help us create the texture, this way it can adjust any relevant sizes
  306. UINT numMips = (origNumMips == MIP_UNLIMITED) ? D3DX_DEFAULT : origNumMips + 1;
  307. DWORD usage = 0;
  308. if ((texUsage & TU_RENDERTARGET) != 0)
  309. usage = D3DUSAGE_RENDERTARGET;
  310. else if ((texUsage & TU_DEPTHSTENCIL) != 0)
  311. usage = D3DUSAGE_DEPTHSTENCIL;
  312. // Check dynamic textures
  313. if (texUsage & TU_DYNAMIC)
  314. {
  315. if (canUseDynamicTextures(d3d9Device, usage, D3DRTYPE_TEXTURE, d3dPF))
  316. {
  317. usage |= D3DUSAGE_DYNAMIC;
  318. mDynamicTextures = true;
  319. }
  320. else
  321. {
  322. mDynamicTextures = false;
  323. }
  324. }
  325. // Check sRGB support
  326. if (hwGamma)
  327. {
  328. mHwGammaReadSupported = canUseHardwareGammaCorrection(d3d9Device, usage, D3DRTYPE_TEXTURE, d3dPF, false);
  329. if (texUsage & TU_RENDERTARGET)
  330. mHwGammaWriteSupported = canUseHardwareGammaCorrection(d3d9Device, usage, D3DRTYPE_TEXTURE, d3dPF, true);
  331. }
  332. // Check multisample level
  333. if ((texUsage & TU_RENDERTARGET) != 0 || (texUsage & TU_DEPTHSTENCIL) != 0)
  334. {
  335. D3D9RenderAPI* rsys = static_cast<D3D9RenderAPI*>(BansheeEngine::RenderAPICore::instancePtr());
  336. rsys->determineMultisampleSettings(d3d9Device, sampleCount, d3dPF, false, &mMultisampleType, &mMultisampleQuality);
  337. }
  338. else
  339. {
  340. mMultisampleType = D3DMULTISAMPLE_NONE;
  341. mMultisampleQuality = 0;
  342. }
  343. D3D9Device* device = D3D9RenderAPI::getDeviceManager()->getDeviceFromD3D9Device(d3d9Device);
  344. const D3DCAPS9& rkCurCaps = device->getD3D9DeviceCaps();
  345. // Check if mip maps are supported on hardware
  346. if (numMips > 1 && (!(rkCurCaps.TextureCaps & D3DPTEXTURECAPS_MIPMAP) || (texUsage & TU_RENDERTARGET) != 0 || (texUsage & TU_DEPTHSTENCIL) != 0))
  347. {
  348. BS_EXCEPT(InvalidParametersException, "Invalid number of mipmaps. Maximum allowed is: 0");
  349. }
  350. determinePool();
  351. TextureResources* textureResources;
  352. // Get or create new texture resources structure.
  353. textureResources = getTextureResources(d3d9Device);
  354. if (textureResources != NULL)
  355. freeTextureResources(d3d9Device, textureResources);
  356. else
  357. textureResources = allocateTextureResources(d3d9Device);
  358. if ((texUsage & TU_RENDERTARGET) != 0 && (mMultisampleType != D3DMULTISAMPLE_NONE))
  359. {
  360. // Create AA surface
  361. HRESULT hr = d3d9Device->CreateRenderTarget(width, height, d3dPF,
  362. mMultisampleType, mMultisampleQuality,
  363. FALSE,
  364. &textureResources->pMultisampleSurface, NULL);
  365. if (FAILED(hr))
  366. BS_EXCEPT(RenderingAPIException, "Unable to create AA render target: " + String(DXGetErrorDescription(hr)));
  367. D3DSURFACE_DESC desc;
  368. hr = textureResources->pMultisampleSurface->GetDesc(&desc);
  369. if (FAILED(hr))
  370. {
  371. BS_EXCEPT(RenderingAPIException, "Can't get texture description: " + String(DXGetErrorDescription(hr)));
  372. }
  373. setFinalAttributes(d3d9Device, textureResources, desc.Width, desc.Height, 1, D3D9Mappings::_getPF(desc.Format));
  374. mIsBindableAsShaderResource = false; // Cannot bind AA surfaces
  375. }
  376. else if ((texUsage & TU_DEPTHSTENCIL) != 0 && (mMultisampleType != D3DMULTISAMPLE_NONE))
  377. {
  378. // Create AA depth stencil surface
  379. HRESULT hr = d3d9Device->CreateDepthStencilSurface(width, height, d3dPF,
  380. mMultisampleType, mMultisampleQuality,
  381. FALSE,
  382. &textureResources->pDepthStencilSurface, NULL);
  383. if (FAILED(hr))
  384. BS_EXCEPT(RenderingAPIException, "Unable to create AA depth stencil render target: " + String(DXGetErrorDescription(hr)));
  385. // Update final parameters as they may differ from requested ones
  386. D3DSURFACE_DESC desc;
  387. hr = textureResources->pDepthStencilSurface->GetDesc(&desc);
  388. if (FAILED(hr))
  389. {
  390. BS_EXCEPT(RenderingAPIException, "Can't get texture description: " + String(DXGetErrorDescription(hr)));
  391. }
  392. setFinalAttributes(d3d9Device, textureResources, desc.Width, desc.Height, 1, D3D9Mappings::_getPF(desc.Format));
  393. mIsBindableAsShaderResource = false; // Cannot bind AA depth buffer
  394. }
  395. else
  396. {
  397. // Create normal texture
  398. HRESULT hr = D3DXCreateTexture(d3d9Device, (UINT)width, (UINT)height, numMips,
  399. usage, d3dPF, mD3DPool, &textureResources->pNormTex);
  400. if (FAILED(hr))
  401. {
  402. BS_EXCEPT(RenderingAPIException, "Error creating texture: " + String(DXGetErrorDescription(hr)));
  403. }
  404. hr = textureResources->pNormTex->QueryInterface(IID_IDirect3DBaseTexture9, (void **)&textureResources->pBaseTex);
  405. if (FAILED(hr))
  406. {
  407. BS_EXCEPT(RenderingAPIException, "Can't get base texture: " + String(DXGetErrorDescription(hr)));
  408. }
  409. // Update final parameters as they may differ from requested ones
  410. D3DSURFACE_DESC desc;
  411. hr = textureResources->pNormTex->GetLevelDesc(0, &desc);
  412. if (FAILED(hr))
  413. {
  414. BS_EXCEPT(RenderingAPIException, "Can't get texture description: " + String(DXGetErrorDescription(hr)));
  415. }
  416. setFinalAttributes(d3d9Device, textureResources, desc.Width, desc.Height, 1, D3D9Mappings::_getPF(desc.Format));
  417. }
  418. }
  419. void D3D9TextureCore::createCubeTex(IDirect3DDevice9* d3d9Device)
  420. {
  421. UINT32 width = mProperties.getWidth();
  422. UINT32 height = mProperties.getHeight();
  423. int texUsage = mProperties.getUsage();
  424. UINT32 origNumMips = mProperties.getNumMipmaps();
  425. PixelFormat format = mProperties.getFormat();
  426. bool hwGamma = mProperties.isHardwareGammaEnabled();
  427. assert(width > 0 || height > 0);
  428. D3DFORMAT d3dPF = chooseD3DFormat(d3d9Device);
  429. if (format != D3D9Mappings::_getPF(d3dPF))
  430. {
  431. BS_EXCEPT(RenderingAPIException, "Provided pixel format is not supported by the driver: " + toString(format));
  432. }
  433. // Use D3DX to help us create the texture, this way it can adjust any relevant sizes
  434. DWORD usage = (texUsage & TU_RENDERTARGET) ? D3DUSAGE_RENDERTARGET : 0;
  435. usage |= (texUsage & TU_DEPTHSTENCIL) ? D3DUSAGE_DEPTHSTENCIL : 0;
  436. UINT numMips = (origNumMips == MIP_UNLIMITED) ? D3DX_DEFAULT : origNumMips + 1;
  437. // Check dynamic textures
  438. if (texUsage & TU_DYNAMIC)
  439. {
  440. if (canUseDynamicTextures(d3d9Device, usage, D3DRTYPE_CUBETEXTURE, d3dPF))
  441. {
  442. usage |= D3DUSAGE_DYNAMIC;
  443. mDynamicTextures = true;
  444. }
  445. else
  446. {
  447. mDynamicTextures = false;
  448. }
  449. }
  450. // Check sRGB support
  451. if (hwGamma)
  452. {
  453. mHwGammaReadSupported = canUseHardwareGammaCorrection(d3d9Device, usage, D3DRTYPE_CUBETEXTURE, d3dPF, false);
  454. if (texUsage & TU_RENDERTARGET)
  455. mHwGammaWriteSupported = canUseHardwareGammaCorrection(d3d9Device, usage, D3DRTYPE_CUBETEXTURE, d3dPF, true);
  456. }
  457. // No multisampling on cube textures
  458. mMultisampleType = D3DMULTISAMPLE_NONE;
  459. mMultisampleQuality = 0;
  460. D3D9Device* device = D3D9RenderAPI::getDeviceManager()->getDeviceFromD3D9Device(d3d9Device);
  461. const D3DCAPS9& deviceCaps = device->getD3D9DeviceCaps();
  462. // Check if mip map cube textures are supported
  463. if (numMips > 1 && !(deviceCaps.TextureCaps & D3DPTEXTURECAPS_MIPCUBEMAP))
  464. {
  465. BS_EXCEPT(InvalidParametersException, "Invalid number of mipmaps. Maximum allowed is: 0");
  466. }
  467. determinePool();
  468. TextureResources* textureResources;
  469. // Get or create new texture resources structure.
  470. textureResources = getTextureResources(d3d9Device);
  471. if (textureResources != NULL)
  472. freeTextureResources(d3d9Device, textureResources);
  473. else
  474. textureResources = allocateTextureResources(d3d9Device);
  475. // Create the texture
  476. HRESULT hr = D3DXCreateCubeTexture(d3d9Device, (UINT)width, numMips,
  477. usage, d3dPF, mD3DPool, &textureResources->pCubeTex);
  478. if (FAILED(hr))
  479. {
  480. BS_EXCEPT(RenderingAPIException, "Error creating texture: " + String(DXGetErrorDescription(hr)));
  481. }
  482. hr = textureResources->pCubeTex->QueryInterface(IID_IDirect3DBaseTexture9, (void **)&textureResources->pBaseTex);
  483. if (FAILED(hr))
  484. {
  485. BS_EXCEPT(RenderingAPIException, "Can't get base texture: " + String(DXGetErrorDescription(hr)));
  486. }
  487. // Update final parameters as they may differ from requested ones
  488. D3DSURFACE_DESC desc;
  489. hr = textureResources->pCubeTex->GetLevelDesc(0, &desc);
  490. if (FAILED(hr))
  491. {
  492. BS_EXCEPT(RenderingAPIException, "Can't get texture description: " + String(DXGetErrorDescription(hr)));
  493. }
  494. setFinalAttributes(d3d9Device, textureResources, desc.Width, desc.Height, 1, D3D9Mappings::_getPF(desc.Format));
  495. }
  496. void D3D9TextureCore::createVolumeTex(IDirect3DDevice9* d3d9Device)
  497. {
  498. UINT32 width = mProperties.getWidth();
  499. UINT32 height = mProperties.getHeight();
  500. UINT32 depth = mProperties.getDepth();
  501. int texUsage = mProperties.getUsage();
  502. UINT32 origNumMips = mProperties.getNumMipmaps();
  503. PixelFormat format = mProperties.getFormat();
  504. bool hwGamma = mProperties.isHardwareGammaEnabled();
  505. assert(width > 0 && height > 0 && depth > 0);
  506. if (texUsage & TU_RENDERTARGET)
  507. BS_EXCEPT(RenderingAPIException, "D3D9 Volume texture can not be created as render target !!");
  508. if (texUsage & TU_DEPTHSTENCIL)
  509. BS_EXCEPT(RenderingAPIException, "D3D9 Volume texture can not be created as a depth stencil target !!");
  510. D3DFORMAT d3dPF = chooseD3DFormat(d3d9Device);
  511. if(format != D3D9Mappings::_getPF(d3dPF))
  512. {
  513. BS_EXCEPT(RenderingAPIException, "Provided pixel format is not supported by the driver: " + toString(format));
  514. }
  515. // Use D3DX to help us create the texture, this way it can adjust any relevant sizes
  516. DWORD usage = (texUsage & TU_RENDERTARGET) ? D3DUSAGE_RENDERTARGET : 0;
  517. UINT numMips = (origNumMips == MIP_UNLIMITED) ? D3DX_DEFAULT : origNumMips + 1;
  518. // Check dynamic textures
  519. if (texUsage & TU_DYNAMIC)
  520. {
  521. if (canUseDynamicTextures(d3d9Device, usage, D3DRTYPE_VOLUMETEXTURE, d3dPF))
  522. {
  523. usage |= D3DUSAGE_DYNAMIC;
  524. mDynamicTextures = true;
  525. }
  526. else
  527. {
  528. mDynamicTextures = false;
  529. }
  530. }
  531. // Check sRGB support
  532. if (hwGamma)
  533. {
  534. mHwGammaReadSupported = canUseHardwareGammaCorrection(d3d9Device, usage, D3DRTYPE_VOLUMETEXTURE, d3dPF, false);
  535. if (texUsage & TU_RENDERTARGET)
  536. mHwGammaWriteSupported = canUseHardwareGammaCorrection(d3d9Device, usage, D3DRTYPE_VOLUMETEXTURE, d3dPF, true);
  537. }
  538. D3D9Device* device = D3D9RenderAPI::getDeviceManager()->getDeviceFromD3D9Device(d3d9Device);
  539. const D3DCAPS9& rkCurCaps = device->getD3D9DeviceCaps();
  540. // Check if mip map volume textures are supported
  541. if (numMips > 1 && !(rkCurCaps.TextureCaps & D3DPTEXTURECAPS_MIPVOLUMEMAP))
  542. {
  543. BS_EXCEPT(InvalidParametersException, "Invalid number of mipmaps. Maximum allowed is: 0");
  544. }
  545. determinePool();
  546. TextureResources* textureResources;
  547. // Get or create new texture resources structure.
  548. textureResources = getTextureResources(d3d9Device);
  549. if (textureResources != NULL)
  550. freeTextureResources(d3d9Device, textureResources);
  551. else
  552. textureResources = allocateTextureResources(d3d9Device);
  553. // Create the texture
  554. HRESULT hr = D3DXCreateVolumeTexture(d3d9Device, (UINT)width, (UINT)height, (UINT)depth,
  555. numMips, usage, d3dPF, mD3DPool, &textureResources->pVolumeTex);
  556. if (FAILED(hr))
  557. {
  558. BS_EXCEPT(RenderingAPIException, "Error creating texture: " + String(DXGetErrorDescription(hr)));
  559. }
  560. hr = textureResources->pVolumeTex->QueryInterface(IID_IDirect3DBaseTexture9, (void**)&textureResources->pBaseTex);
  561. if (FAILED(hr))
  562. {
  563. BS_EXCEPT(RenderingAPIException, "Can't get base texture: " + String(DXGetErrorDescription(hr)));
  564. }
  565. // Update final parameters as they may differ from requested ones
  566. D3DVOLUME_DESC desc;
  567. hr = textureResources->pVolumeTex->GetLevelDesc(0, &desc);
  568. if (FAILED(hr))
  569. {
  570. BS_EXCEPT(RenderingAPIException, "Can't get texture description: " + String(DXGetErrorDescription(hr)));
  571. }
  572. setFinalAttributes(d3d9Device, textureResources, desc.Width, desc.Height, desc.Depth, D3D9Mappings::_getPF(desc.Format));
  573. }
  574. void D3D9TextureCore::setFinalAttributes(IDirect3DDevice9* d3d9Device, TextureResources* textureResources,
  575. UINT32 width, UINT32 height, UINT32 depth, PixelFormat format)
  576. {
  577. if(width != mProperties.getWidth() || height != mProperties.getHeight() || depth != mProperties.getDepth())
  578. {
  579. BS_EXCEPT(InternalErrorException, "Wanted and created textures sizes don't match!" \
  580. "Width: " + toString(width) + "/" + toString(mProperties.getWidth()) +
  581. "Height: " + toString(height) + "/" + toString(mProperties.getHeight()) +
  582. "Depth: " + toString(depth) + "/" + toString(mProperties.getDepth()));
  583. }
  584. if(format != mProperties.getFormat())
  585. {
  586. BS_EXCEPT(InternalErrorException, "Wanted and created texture formats don't match! " +
  587. toString(format) + "/" + toString(mProperties.getFormat()));
  588. }
  589. createSurfaceList(d3d9Device, textureResources);
  590. }
  591. D3DTEXTUREFILTERTYPE D3D9TextureCore::getBestFilterMethod(IDirect3DDevice9* d3d9Device)
  592. {
  593. D3D9Device* device = D3D9RenderAPI::getDeviceManager()->getDeviceFromD3D9Device(d3d9Device);
  594. const D3DCAPS9& deviceCaps = device->getD3D9DeviceCaps();
  595. DWORD filterCaps = 0;
  596. switch (mProperties.getTextureType())
  597. {
  598. case TEX_TYPE_1D:
  599. // Same as 2D
  600. case TEX_TYPE_2D:
  601. filterCaps = deviceCaps.TextureFilterCaps;
  602. break;
  603. case TEX_TYPE_3D:
  604. filterCaps = deviceCaps.VolumeTextureFilterCaps;
  605. break;
  606. case TEX_TYPE_CUBE_MAP:
  607. filterCaps = deviceCaps.CubeTextureFilterCaps;
  608. break;
  609. }
  610. if(filterCaps & D3DPTFILTERCAPS_MINFGAUSSIANQUAD)
  611. return D3DTEXF_GAUSSIANQUAD;
  612. if(filterCaps & D3DPTFILTERCAPS_MINFPYRAMIDALQUAD)
  613. return D3DTEXF_PYRAMIDALQUAD;
  614. if(filterCaps & D3DPTFILTERCAPS_MINFANISOTROPIC)
  615. return D3DTEXF_ANISOTROPIC;
  616. if(filterCaps & D3DPTFILTERCAPS_MINFLINEAR)
  617. return D3DTEXF_LINEAR;
  618. if(filterCaps & D3DPTFILTERCAPS_MINFPOINT)
  619. return D3DTEXF_POINT;
  620. return D3DTEXF_POINT;
  621. }
  622. bool D3D9TextureCore::canUseDynamicTextures(IDirect3DDevice9* d3d9Device, DWORD srcUsage, D3DRESOURCETYPE srcType,
  623. D3DFORMAT srcFormat)
  624. {
  625. IDirect3D9* pD3D = nullptr;
  626. HRESULT hr = d3d9Device->GetDirect3D(&pD3D);
  627. if (FAILED(hr))
  628. BS_EXCEPT(InvalidParametersException, "GetDirect3D failed !!!");
  629. if (pD3D != nullptr)
  630. pD3D->Release();
  631. D3D9Device* device = D3D9RenderAPI::getDeviceManager()->getDeviceFromD3D9Device(d3d9Device);
  632. const D3DCAPS9& deviceCaps = device->getD3D9DeviceCaps();
  633. D3DFORMAT backBufferFormat = device->getBackBufferFormat();
  634. hr = pD3D->CheckDeviceFormat(deviceCaps.AdapterOrdinal, deviceCaps.DeviceType,
  635. backBufferFormat, srcUsage | D3DUSAGE_DYNAMIC, srcType, srcFormat);
  636. return hr == D3D_OK;
  637. }
  638. bool D3D9TextureCore::canUseHardwareGammaCorrection(IDirect3DDevice9* d3d9Device, DWORD srcUsage,
  639. D3DRESOURCETYPE srcType, D3DFORMAT srcFormat, bool forwriting)
  640. {
  641. IDirect3D9* pD3D = nullptr;
  642. HRESULT hr = d3d9Device->GetDirect3D(&pD3D);
  643. if (FAILED(hr))
  644. {
  645. BS_EXCEPT(InvalidParametersException, "GetDirect3D failed !!!" );
  646. }
  647. if (pD3D != nullptr)
  648. pD3D->Release();
  649. D3D9Device* device = D3D9RenderAPI::getDeviceManager()->getDeviceFromD3D9Device(d3d9Device);
  650. const D3DCAPS9& deviceCaps = device->getD3D9DeviceCaps();
  651. D3DFORMAT backBufferFormat = device->getBackBufferFormat();
  652. if (forwriting)
  653. srcUsage |= D3DUSAGE_QUERY_SRGBWRITE;
  654. else
  655. srcUsage |= D3DUSAGE_QUERY_SRGBREAD;
  656. hr = pD3D->CheckDeviceFormat(deviceCaps.AdapterOrdinal, deviceCaps.DeviceType,
  657. backBufferFormat, srcUsage, srcType, srcFormat);
  658. return hr == D3D_OK;
  659. }
  660. bool D3D9TextureCore::canAutoGenMipmaps(IDirect3DDevice9* d3d9Device, DWORD srcUsage, D3DRESOURCETYPE srcType, D3DFORMAT srcFormat)
  661. {
  662. IDirect3D9* pD3D = nullptr;
  663. HRESULT hr = d3d9Device->GetDirect3D(&pD3D);
  664. if (FAILED(hr))
  665. {
  666. BS_EXCEPT(InvalidParametersException, "GetDirect3D failed.");
  667. }
  668. if (pD3D != nullptr)
  669. pD3D->Release();
  670. D3D9Device* device = D3D9RenderAPI::getDeviceManager()->getDeviceFromD3D9Device(d3d9Device);
  671. const D3DCAPS9& deviceCaps = device->getD3D9DeviceCaps();
  672. D3DFORMAT backBufferFormat = device->getBackBufferFormat();
  673. if (deviceCaps.Caps2 & D3DCAPS2_CANAUTOGENMIPMAP)
  674. {
  675. hr = pD3D->CheckDeviceFormat(deviceCaps.AdapterOrdinal, deviceCaps.DeviceType,
  676. backBufferFormat, srcUsage | D3DUSAGE_AUTOGENMIPMAP, srcType, srcFormat);
  677. return hr == D3D_OK;
  678. }
  679. else
  680. return false;
  681. }
  682. D3DFORMAT D3D9TextureCore::chooseD3DFormat(IDirect3DDevice9* d3d9Device)
  683. {
  684. // Choose frame buffer pixel format in case PF_UNKNOWN was requested
  685. if(mProperties.getFormat() == PF_UNKNOWN)
  686. {
  687. D3D9Device* device = D3D9RenderAPI::getDeviceManager()->getDeviceFromD3D9Device(d3d9Device);
  688. if((mProperties.getUsage() & TU_DEPTHSTENCIL) != 0)
  689. return device->getDepthStencilFormat();
  690. else
  691. return device->getBackBufferFormat();
  692. }
  693. // Choose closest supported D3D format as a D3D format
  694. return D3D9Mappings::_getPF(D3D9Mappings::_getClosestSupportedPF(mProperties.getFormat()));
  695. }
  696. void D3D9TextureCore::createSurfaceList(IDirect3DDevice9* d3d9Device, TextureResources* textureResources)
  697. {
  698. int texUsage = mProperties.getUsage();
  699. TextureType texType = mProperties.getTextureType();
  700. UINT32 numMips = mProperties.getNumMipmaps();
  701. assert(textureResources != nullptr);
  702. // Need to know static / dynamic
  703. UINT32 usage;
  704. if ((texUsage & TU_DYNAMIC) && mDynamicTextures)
  705. {
  706. usage = GBU_DYNAMIC;
  707. }
  708. else
  709. {
  710. usage = GBU_STATIC;
  711. }
  712. if (texUsage & TU_RENDERTARGET)
  713. {
  714. usage |= TU_RENDERTARGET;
  715. }
  716. else if (texUsage & TU_DEPTHSTENCIL)
  717. {
  718. usage |= TU_RENDERTARGET;
  719. }
  720. UINT32 surfaceCount = static_cast<UINT32>((mProperties.getNumFaces() * (numMips + 1)));
  721. bool updateOldList = mSurfaceList.size() == surfaceCount;
  722. if(!updateOldList)
  723. {
  724. mSurfaceList.clear();
  725. for (UINT32 face = 0; face < mProperties.getNumFaces(); face++)
  726. {
  727. for (UINT32 mip = 0; mip <= numMips; mip++)
  728. {
  729. mSurfaceList.push_back(bs_shared_ptr_new<D3D9PixelBuffer>((GpuBufferUsage)usage, this));
  730. }
  731. }
  732. }
  733. IDirect3DSurface9* surface = nullptr;
  734. IDirect3DVolume9* volume = nullptr;
  735. if ((texUsage & TU_RENDERTARGET) != 0 && (mMultisampleType != D3DMULTISAMPLE_NONE))
  736. {
  737. assert(textureResources->pMultisampleSurface);
  738. assert(texType == TEX_TYPE_2D);
  739. D3D9PixelBuffer* currPixelBuffer = static_cast<D3D9PixelBuffer*>(mSurfaceList[0].get());
  740. currPixelBuffer->bind(d3d9Device, textureResources->pMultisampleSurface, textureResources->pBaseTex);
  741. }
  742. else if ((texUsage & TU_DEPTHSTENCIL) != 0 && (mMultisampleType != D3DMULTISAMPLE_NONE))
  743. {
  744. assert(textureResources->pDepthStencilSurface);
  745. assert(texType == TEX_TYPE_2D);
  746. D3D9PixelBuffer* currPixelBuffer = static_cast<D3D9PixelBuffer*>(mSurfaceList[0].get());
  747. currPixelBuffer->bind(d3d9Device, textureResources->pDepthStencilSurface, textureResources->pBaseTex);
  748. }
  749. else
  750. {
  751. assert(textureResources->pBaseTex);
  752. UINT32 numCreatedMips = textureResources->pBaseTex->GetLevelCount() - 1;
  753. if (numCreatedMips != numMips)
  754. {
  755. BS_EXCEPT(InternalErrorException, "Number of created and wanted mip map levels doesn't match: " +
  756. toString(numCreatedMips) + "/" + toString(numMips));
  757. }
  758. switch(texType)
  759. {
  760. case TEX_TYPE_2D:
  761. case TEX_TYPE_1D:
  762. assert(textureResources->pNormTex);
  763. for (UINT32 mip = 0; mip <= numMips; mip++)
  764. {
  765. if(textureResources->pNormTex->GetSurfaceLevel(static_cast<UINT>(mip), &surface) != D3D_OK)
  766. BS_EXCEPT(RenderingAPIException, "Get surface level failed");
  767. D3D9PixelBuffer* currPixelBuffer = static_cast<D3D9PixelBuffer*>(mSurfaceList[mip].get());
  768. currPixelBuffer->bind(d3d9Device, surface, textureResources->pBaseTex);
  769. surface->Release();
  770. }
  771. break;
  772. case TEX_TYPE_CUBE_MAP:
  773. assert(textureResources->pCubeTex);
  774. for(UINT32 face = 0; face < 6; face++)
  775. {
  776. for (UINT32 mip = 0; mip <= numMips; mip++)
  777. {
  778. if(textureResources->pCubeTex->GetCubeMapSurface((D3DCUBEMAP_FACES)face, static_cast<UINT>(mip), &surface) != D3D_OK)
  779. BS_EXCEPT(RenderingAPIException, "Get cubemap surface failed");
  780. UINT32 idx = face*(numMips + 1) + mip;
  781. D3D9PixelBuffer* currPixelBuffer = static_cast<D3D9PixelBuffer*>(mSurfaceList[idx].get());
  782. currPixelBuffer->bind(d3d9Device, surface, textureResources->pBaseTex);
  783. surface->Release();
  784. }
  785. }
  786. break;
  787. case TEX_TYPE_3D:
  788. assert(textureResources->pVolumeTex);
  789. for (UINT32 mip = 0; mip <= numMips; mip++)
  790. {
  791. if(textureResources->pVolumeTex->GetVolumeLevel(static_cast<UINT>(mip), &volume) != D3D_OK)
  792. BS_EXCEPT(RenderingAPIException, "Get volume level failed");
  793. D3D9PixelBuffer* currPixelBuffer = static_cast<D3D9PixelBuffer*>(mSurfaceList[mip].get());
  794. currPixelBuffer->bind(d3d9Device, volume, textureResources->pBaseTex);
  795. volume->Release();
  796. }
  797. break;
  798. };
  799. }
  800. }
  801. PixelBufferPtr D3D9TextureCore::getBuffer(UINT32 face, UINT32 mipmap)
  802. {
  803. THROW_IF_NOT_CORE_THREAD;
  804. if(face >= mProperties.getNumFaces())
  805. BS_EXCEPT(InvalidParametersException, "A three dimensional cube has six faces");
  806. if (mipmap > mProperties.getNumMipmaps())
  807. BS_EXCEPT(InvalidParametersException, "Mipmap index out of range");
  808. UINT32 idx = face*(mProperties.getNumMipmaps() + 1) + mipmap;
  809. IDirect3DDevice9* d3d9Device = D3D9RenderAPI::getActiveD3D9Device();
  810. TextureResources* textureResources = getTextureResources(d3d9Device);
  811. if (textureResources == nullptr || textureResources->pBaseTex == nullptr)
  812. {
  813. createInternalResources(d3d9Device);
  814. textureResources = getTextureResources(d3d9Device);
  815. }
  816. assert(textureResources != nullptr);
  817. assert(idx < mSurfaceList.size());
  818. return mSurfaceList[idx];
  819. }
  820. bool D3D9TextureCore::useDefaultPool()
  821. {
  822. int usage = mProperties.getUsage();
  823. return (usage & TU_RENDERTARGET) || (usage & TU_DEPTHSTENCIL) || ((usage & TU_DYNAMIC) && mDynamicTextures);
  824. }
  825. void D3D9TextureCore::notifyOnDeviceCreate(IDirect3DDevice9* d3d9Device)
  826. {
  827. D3D9_DEVICE_ACCESS_CRITICAL_SECTION
  828. if (D3D9RenderAPI::getResourceManager()->getCreationPolicy() == RCP_CREATE_ON_ALL_DEVICES)
  829. createInternalResources(d3d9Device);
  830. }
  831. void D3D9TextureCore::notifyOnDeviceDestroy(IDirect3DDevice9* d3d9Device)
  832. {
  833. D3D9_DEVICE_ACCESS_CRITICAL_SECTION
  834. auto iterFind = mMapDeviceToTextureResources.find(d3d9Device);
  835. if (iterFind != mMapDeviceToTextureResources.end())
  836. {
  837. TextureResources* textureResource = iterFind->second;
  838. for(unsigned int i = 0; i < mSurfaceList.size(); ++i)
  839. {
  840. D3D9PixelBuffer* pixelBuffer = static_cast<D3D9PixelBuffer*>(mSurfaceList[i].get());
  841. pixelBuffer->destroyBufferResources(d3d9Device);
  842. }
  843. freeTextureResources(d3d9Device, textureResource);
  844. if(textureResource != nullptr)
  845. bs_delete(textureResource);
  846. mMapDeviceToTextureResources.erase(iterFind);
  847. }
  848. }
  849. void D3D9TextureCore::notifyOnDeviceLost(IDirect3DDevice9* d3d9Device)
  850. {
  851. D3D9_DEVICE_ACCESS_CRITICAL_SECTION
  852. if(mD3DPool == D3DPOOL_DEFAULT)
  853. {
  854. auto iterFind = mMapDeviceToTextureResources.find(d3d9Device);
  855. if (iterFind != mMapDeviceToTextureResources.end())
  856. {
  857. TextureResources* textureResource = iterFind->second;
  858. freeTextureResources(d3d9Device, textureResource);
  859. }
  860. }
  861. }
  862. void D3D9TextureCore::notifyOnDeviceReset(IDirect3DDevice9* d3d9Device)
  863. {
  864. D3D9_DEVICE_ACCESS_CRITICAL_SECTION
  865. if(mD3DPool == D3DPOOL_DEFAULT)
  866. {
  867. createInternalResources(d3d9Device);
  868. }
  869. }
  870. IDirect3DBaseTexture9* D3D9TextureCore::getTexture_internal()
  871. {
  872. THROW_IF_NOT_CORE_THREAD;
  873. TextureResources* textureResources;
  874. IDirect3DDevice9* d3d9Device = D3D9RenderAPI::getActiveD3D9Device();
  875. textureResources = getTextureResources(d3d9Device);
  876. if (textureResources == nullptr || textureResources->pBaseTex == nullptr)
  877. {
  878. createInternalResources(d3d9Device);
  879. textureResources = getTextureResources(d3d9Device);
  880. }
  881. assert(textureResources);
  882. assert(textureResources->pBaseTex);
  883. return textureResources->pBaseTex;
  884. }
  885. IDirect3DTexture9* D3D9TextureCore::getNormTexture_internal()
  886. {
  887. THROW_IF_NOT_CORE_THREAD;
  888. TextureResources* textureResources;
  889. IDirect3DDevice9* d3d9Device = D3D9RenderAPI::getActiveD3D9Device();
  890. textureResources = getTextureResources(d3d9Device);
  891. if (textureResources == nullptr || textureResources->pNormTex == nullptr)
  892. {
  893. createInternalResources(d3d9Device);
  894. textureResources = getTextureResources(d3d9Device);
  895. }
  896. assert(textureResources);
  897. assert(textureResources->pNormTex);
  898. return textureResources->pNormTex;
  899. }
  900. IDirect3DCubeTexture9* D3D9TextureCore::getCubeTexture_internal()
  901. {
  902. THROW_IF_NOT_CORE_THREAD;
  903. TextureResources* textureResources;
  904. IDirect3DDevice9* d3d9Device = D3D9RenderAPI::getActiveD3D9Device();
  905. textureResources = getTextureResources(d3d9Device);
  906. if (textureResources == nullptr || textureResources->pCubeTex)
  907. {
  908. createInternalResources(d3d9Device);
  909. textureResources = getTextureResources(d3d9Device);
  910. }
  911. assert(textureResources);
  912. assert(textureResources->pCubeTex);
  913. return textureResources->pCubeTex;
  914. }
  915. }