CmD3D9Texture.cpp 41 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280
  1. /*
  2. -----------------------------------------------------------------------------
  3. This source file is part of OGRE
  4. (Object-oriented Graphics Rendering Engine)
  5. For the latest info, see http://www.ogre3d.org/
  6. Copyright (c) 2000-2011 Torus Knot Software Ltd
  7. Permission is hereby granted, free of charge, to any person obtaining a copy
  8. of this software and associated documentation files (the "Software"), to deal
  9. in the Software without restriction, including without limitation the rights
  10. to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  11. copies of the Software, and to permit persons to whom the Software is
  12. furnished to do so, subject to the following conditions:
  13. The above copyright notice and this permission notice shall be included in
  14. all copies or substantial portions of the Software.
  15. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  20. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  21. THE SOFTWARE.
  22. -----------------------------------------------------------------------------
  23. */
  24. #include "CmCoreThread.h"
  25. #include "CmD3D9Texture.h"
  26. #include "CmD3D9PixelBuffer.h"
  27. #include "CmException.h"
  28. #include "CmBitwise.h"
  29. #include "CmD3D9Mappings.h"
  30. #include "CmD3D9RenderSystem.h"
  31. #include "CmD3D9TextureManager.h"
  32. #include "CmD3D9Device.h"
  33. #include "CmD3D9DeviceManager.h"
  34. #include "CmD3D9ResourceManager.h"
  35. namespace CamelotFramework
  36. {
  37. D3D9Texture::D3D9Texture()
  38. :Texture(),
  39. mD3DPool(D3DPOOL_MANAGED),
  40. mDynamicTextures(false),
  41. mHwGammaReadSupported(false),
  42. mHwGammaWriteSupported(false),
  43. mFSAAType(D3DMULTISAMPLE_NONE),
  44. mFSAAQuality(0),
  45. mIsBindableAsShaderResource(true)
  46. {
  47. }
  48. D3D9Texture::~D3D9Texture()
  49. {
  50. }
  51. PixelData D3D9Texture::lockImpl(GpuLockOptions options, UINT32 mipLevel, UINT32 face)
  52. {
  53. if(mLockedBuffer != nullptr)
  54. CM_EXCEPT(InternalErrorException, "Trying to lock a buffer that's already locked.");
  55. if(getUsage() == TU_DEPTHSTENCIL)
  56. CM_EXCEPT(InternalErrorException, "Cannot lock a depth stencil texture.");
  57. UINT32 mipWidth = mWidth >> mipLevel;
  58. UINT32 mipHeight = mHeight >> mipLevel;
  59. UINT32 mipDepth = mDepth >> mipLevel;
  60. PixelData lockedArea(mipWidth, mipHeight, mipDepth, mFormat);
  61. mLockedBuffer = getBuffer(face, mipLevel);
  62. lockedArea.setExternalBuffer((UINT8*)mLockedBuffer->lock(options));
  63. return lockedArea;
  64. }
  65. void D3D9Texture::unlockImpl()
  66. {
  67. if(mLockedBuffer == nullptr)
  68. CM_EXCEPT(InternalErrorException, "Trying to unlock a buffer that's not locked.");
  69. mLockedBuffer->unlock();
  70. mLockedBuffer = nullptr;
  71. }
  72. void D3D9Texture::readData(PixelData& dest, UINT32 mipLevel, UINT32 face)
  73. {
  74. PixelData myData = lock(GBL_READ_ONLY, mipLevel, face);
  75. #if CM_DEBUG_MODE
  76. if(dest.getConsecutiveSize() != myData.getConsecutiveSize())
  77. {
  78. unlock();
  79. CM_EXCEPT(InternalErrorException, "Buffer sizes don't match");
  80. }
  81. #endif
  82. PixelUtil::bulkPixelConversion(myData, dest);
  83. unlock();
  84. }
  85. void D3D9Texture::writeData(const PixelData& src, UINT32 mipLevel, UINT32 face, bool discardWholeBuffer)
  86. {
  87. if(mUsage == TU_DYNAMIC || mUsage == TU_STATIC)
  88. {
  89. PixelData myData = lock(discardWholeBuffer ? GBL_WRITE_ONLY_DISCARD : GBL_WRITE_ONLY, mipLevel, face);
  90. PixelUtil::bulkPixelConversion(src, myData);
  91. unlock();
  92. }
  93. else
  94. {
  95. CM_EXCEPT(RenderingAPIException, "Trying to write into a buffer with unsupported usage: " + toString(mUsage));
  96. }
  97. }
  98. void D3D9Texture::copyImpl(TexturePtr& target)
  99. {
  100. THROW_IF_NOT_CORE_THREAD;
  101. // check if this & target are the same format and type
  102. // blitting from or to cube textures is not supported yet
  103. if (target->getUsage() != getUsage() ||
  104. target->getTextureType() != getTextureType())
  105. {
  106. CM_EXCEPT(InvalidParametersException,
  107. "Src. and dest. textures must be of same type and must have the same usage !!!");
  108. }
  109. HRESULT hr;
  110. D3D9Texture *other;
  111. // get the target
  112. other = reinterpret_cast< D3D9Texture * >( target.get() );
  113. // target rectangle (whole surface)
  114. RECT dstRC = {0, 0, static_cast<LONG>(other->getWidth()), static_cast<LONG>(other->getHeight())};
  115. DeviceToTextureResourcesIterator it = mMapDeviceToTextureResources.begin();
  116. while (it != mMapDeviceToTextureResources.end())
  117. {
  118. TextureResources* srcTextureResource = it->second;
  119. TextureResources* dstTextureResource = other->getTextureResources(it->first);
  120. // do it plain for normal texture
  121. if (getTextureType() == TEX_TYPE_2D &&
  122. srcTextureResource->pNormTex &&
  123. dstTextureResource->pNormTex)
  124. {
  125. // get our source surface
  126. IDirect3DSurface9 *pSrcSurface = 0;
  127. if( FAILED( hr = srcTextureResource->pNormTex->GetSurfaceLevel(0, &pSrcSurface) ) )
  128. {
  129. String msg = DXGetErrorDescription(hr);
  130. CM_EXCEPT(RenderingAPIException, "Couldn't blit : " + msg);
  131. }
  132. // get our target surface
  133. IDirect3DSurface9 *pDstSurface = 0;
  134. if( FAILED( hr = dstTextureResource->pNormTex->GetSurfaceLevel(0, &pDstSurface) ) )
  135. {
  136. String msg = DXGetErrorDescription(hr);
  137. SAFE_RELEASE(pSrcSurface);
  138. CM_EXCEPT(RenderingAPIException, "Couldn't blit : " + msg );
  139. }
  140. // do the blit, it's called StretchRect in D3D9 :)
  141. if( FAILED( hr = it->first->StretchRect( pSrcSurface, NULL, pDstSurface, &dstRC, D3DTEXF_NONE) ) )
  142. {
  143. String msg = DXGetErrorDescription(hr);
  144. SAFE_RELEASE(pSrcSurface);
  145. SAFE_RELEASE(pDstSurface);
  146. CM_EXCEPT(RenderingAPIException, "Couldn't blit : " + msg);
  147. }
  148. // release temp. surfaces
  149. SAFE_RELEASE(pSrcSurface);
  150. SAFE_RELEASE(pDstSurface);
  151. }
  152. else if (getTextureType() == TEX_TYPE_CUBE_MAP &&
  153. srcTextureResource->pCubeTex &&
  154. dstTextureResource->pCubeTex)
  155. {
  156. // blit to 6 cube faces
  157. for (UINT32 face = 0; face < 6; face++)
  158. {
  159. // get our source surface
  160. IDirect3DSurface9 *pSrcSurface = 0;
  161. if( FAILED( hr =srcTextureResource->pCubeTex->GetCubeMapSurface((D3DCUBEMAP_FACES)face, 0, &pSrcSurface) ) )
  162. {
  163. String msg = DXGetErrorDescription(hr);
  164. CM_EXCEPT(RenderingAPIException, "Couldn't blit : " + msg);
  165. }
  166. // get our target surface
  167. IDirect3DSurface9 *pDstSurface = 0;
  168. if( FAILED( hr = dstTextureResource->pCubeTex->GetCubeMapSurface((D3DCUBEMAP_FACES)face, 0, &pDstSurface) ) )
  169. {
  170. String msg = DXGetErrorDescription(hr);
  171. SAFE_RELEASE(pSrcSurface);
  172. CM_EXCEPT(RenderingAPIException, "Couldn't blit : " + msg);
  173. }
  174. // do the blit, it's called StretchRect in D3D9 :)
  175. if( FAILED( hr = it->first->StretchRect( pSrcSurface, NULL, pDstSurface, &dstRC, D3DTEXF_NONE) ) )
  176. {
  177. String msg = DXGetErrorDescription(hr);
  178. SAFE_RELEASE(pSrcSurface);
  179. SAFE_RELEASE(pDstSurface);
  180. CM_EXCEPT(RenderingAPIException, "Couldn't blit : " + msg);
  181. }
  182. // release temp. surfaces
  183. SAFE_RELEASE(pSrcSurface);
  184. SAFE_RELEASE(pDstSurface);
  185. }
  186. }
  187. else
  188. {
  189. CM_EXCEPT(NotImplementedException, "Copy to texture is implemented only for 2D and cube textures !!!");
  190. }
  191. ++it;
  192. }
  193. }
  194. void D3D9Texture::initialize_internal()
  195. {
  196. THROW_IF_NOT_CORE_THREAD;
  197. for (UINT32 i = 0; i < D3D9RenderSystem::getResourceCreationDeviceCount(); ++i)
  198. {
  199. IDirect3DDevice9* d3d9Device = D3D9RenderSystem::getResourceCreationDevice(i);
  200. createInternalResources(d3d9Device);
  201. }
  202. Texture::initialize_internal();
  203. }
  204. void D3D9Texture::destroy_internal()
  205. {
  206. THROW_IF_NOT_CORE_THREAD;
  207. DeviceToTextureResourcesIterator it = mMapDeviceToTextureResources.begin();
  208. while (it != mMapDeviceToTextureResources.end())
  209. {
  210. TextureResources* textureResource = it->second;
  211. freeTextureResources(it->first, textureResource);
  212. ++it;
  213. }
  214. it = mMapDeviceToTextureResources.begin();
  215. while (it != mMapDeviceToTextureResources.end())
  216. {
  217. TextureResources* textureResource = it->second;
  218. if(textureResource != nullptr)
  219. cm_delete<PoolAlloc>(textureResource);
  220. ++it;
  221. }
  222. mMapDeviceToTextureResources.clear();
  223. mSurfaceList.clear();
  224. clearBufferViews();
  225. Texture::destroy_internal();
  226. }
  227. D3D9Texture::TextureResources* D3D9Texture::getTextureResources(IDirect3DDevice9* d3d9Device)
  228. {
  229. DeviceToTextureResourcesIterator it = mMapDeviceToTextureResources.find(d3d9Device);
  230. if (it == mMapDeviceToTextureResources.end())
  231. return NULL;
  232. return it->second;
  233. }
  234. D3D9Texture::TextureResources* D3D9Texture::allocateTextureResources(IDirect3DDevice9* d3d9Device)
  235. {
  236. assert(mMapDeviceToTextureResources.find(d3d9Device) == mMapDeviceToTextureResources.end());
  237. TextureResources* textureResources = cm_new<TextureResources, PoolAlloc>();
  238. textureResources->pNormTex = NULL;
  239. textureResources->pCubeTex = NULL;
  240. textureResources->pVolumeTex = NULL;
  241. textureResources->pBaseTex = NULL;
  242. textureResources->pFSAASurface = NULL;
  243. textureResources->pDepthStencilSurface = NULL;
  244. mMapDeviceToTextureResources[d3d9Device] = textureResources;
  245. return textureResources;
  246. }
  247. void D3D9Texture::createTextureResources(IDirect3DDevice9* d3d9Device)
  248. {
  249. D3D9_DEVICE_ACCESS_CRITICAL_SECTION
  250. /* prepareImpl();
  251. loadImpl(d3d9Device);
  252. postLoadImpl(); */
  253. }
  254. void D3D9Texture::freeTextureResources(IDirect3DDevice9* d3d9Device, D3D9Texture::TextureResources* textureResources)
  255. {
  256. D3D9_DEVICE_ACCESS_CRITICAL_SECTION
  257. // Release surfaces from each mip level.
  258. for(unsigned int i = 0; i < mSurfaceList.size(); ++i)
  259. {
  260. D3D9PixelBuffer* pixelBuffer = static_cast<D3D9PixelBuffer*>(mSurfaceList[i].get());
  261. pixelBuffer->releaseSurfaces(d3d9Device);
  262. }
  263. // Release the rest of the resources.
  264. SAFE_RELEASE(textureResources->pBaseTex);
  265. SAFE_RELEASE(textureResources->pNormTex);
  266. SAFE_RELEASE(textureResources->pCubeTex);
  267. SAFE_RELEASE(textureResources->pVolumeTex);
  268. SAFE_RELEASE(textureResources->pFSAASurface);
  269. SAFE_RELEASE(textureResources->pDepthStencilSurface);
  270. }
  271. UINT32 D3D9Texture::calculateSize(void) const
  272. {
  273. UINT32 instanceSize = getNumFaces() * PixelUtil::getMemorySize(mWidth, mHeight, mDepth, mFormat);
  274. return instanceSize * (UINT32)mMapDeviceToTextureResources.size();
  275. }
  276. void D3D9Texture::determinePool()
  277. {
  278. if (useDefaultPool())
  279. {
  280. mD3DPool = D3DPOOL_DEFAULT;
  281. }
  282. else
  283. {
  284. mD3DPool = D3DPOOL_MANAGED;
  285. }
  286. }
  287. void D3D9Texture::createInternalResources(IDirect3DDevice9* d3d9Device)
  288. {
  289. TextureResources* textureResources;
  290. // Check if resources already exist.
  291. textureResources = getTextureResources(d3d9Device);
  292. if (textureResources != NULL && textureResources->pBaseTex != NULL)
  293. return;
  294. // load based on tex.type
  295. switch (getTextureType())
  296. {
  297. case TEX_TYPE_1D:
  298. case TEX_TYPE_2D:
  299. _createNormTex(d3d9Device);
  300. break;
  301. case TEX_TYPE_CUBE_MAP:
  302. _createCubeTex(d3d9Device);
  303. break;
  304. case TEX_TYPE_3D:
  305. _createVolumeTex(d3d9Device);
  306. break;
  307. default:
  308. destroy_internal();
  309. CM_EXCEPT(InternalErrorException, "Unknown texture type");
  310. }
  311. }
  312. void D3D9Texture::_createNormTex(IDirect3DDevice9* d3d9Device)
  313. {
  314. // we must have those defined here
  315. assert(mWidth > 0 || mHeight > 0);
  316. // determine wich D3D9 pixel format we'll use
  317. HRESULT hr;
  318. D3DFORMAT d3dPF = _chooseD3DFormat(d3d9Device);
  319. if(mFormat != D3D9Mappings::_getPF(d3dPF))
  320. {
  321. CM_EXCEPT(RenderingAPIException, "Provided pixel format is not supported by the driver: " + toString(mFormat));
  322. }
  323. // Use D3DX to help us create the texture, this way it can adjust any relevant sizes
  324. UINT numMips = (mNumMipmaps == MIP_UNLIMITED) ? D3DX_DEFAULT : mNumMipmaps + 1;
  325. DWORD usage = 0;
  326. if((mUsage & TU_RENDERTARGET) != 0)
  327. usage = D3DUSAGE_RENDERTARGET;
  328. else if((mUsage & TU_DEPTHSTENCIL) != 0)
  329. usage = D3DUSAGE_DEPTHSTENCIL;
  330. // Check dynamic textures
  331. if (mUsage & TU_DYNAMIC)
  332. {
  333. if (_canUseDynamicTextures(d3d9Device, usage, D3DRTYPE_TEXTURE, d3dPF))
  334. {
  335. usage |= D3DUSAGE_DYNAMIC;
  336. mDynamicTextures = true;
  337. }
  338. else
  339. {
  340. mDynamicTextures = false;
  341. }
  342. }
  343. // Check sRGB support
  344. if (mHwGamma)
  345. {
  346. mHwGammaReadSupported = _canUseHardwareGammaCorrection(d3d9Device, usage, D3DRTYPE_TEXTURE, d3dPF, false);
  347. if (mUsage & TU_RENDERTARGET)
  348. mHwGammaWriteSupported = _canUseHardwareGammaCorrection(d3d9Device, usage, D3DRTYPE_TEXTURE, d3dPF, true);
  349. }
  350. // Check FSAA level
  351. if ((mUsage & TU_RENDERTARGET) != 0 || (mUsage & TU_DEPTHSTENCIL) != 0)
  352. {
  353. D3D9RenderSystem* rsys = static_cast<D3D9RenderSystem*>(CamelotFramework::RenderSystem::instancePtr());
  354. rsys->determineFSAASettings(d3d9Device, mFSAA, mFSAAHint, d3dPF, false,
  355. &mFSAAType, &mFSAAQuality);
  356. }
  357. else
  358. {
  359. mFSAAType = D3DMULTISAMPLE_NONE;
  360. mFSAAQuality = 0;
  361. }
  362. D3D9Device* device = D3D9RenderSystem::getDeviceManager()->getDeviceFromD3D9Device(d3d9Device);
  363. const D3DCAPS9& rkCurCaps = device->getD3D9DeviceCaps();
  364. // check if mip maps are supported on hardware
  365. if (numMips > 1 && (!(rkCurCaps.TextureCaps & D3DPTEXTURECAPS_MIPMAP) || (mUsage & TU_RENDERTARGET) != 0 || (mUsage & TU_DEPTHSTENCIL) != 0))
  366. {
  367. CM_EXCEPT(InvalidParametersException, "Invalid number of mipmaps. Maximum allowed is: 0");
  368. numMips = 1;
  369. }
  370. // derive the pool to use
  371. determinePool();
  372. TextureResources* textureResources;
  373. // Get or create new texture resources structure.
  374. textureResources = getTextureResources(d3d9Device);
  375. if (textureResources != NULL)
  376. freeTextureResources(d3d9Device, textureResources);
  377. else
  378. textureResources = allocateTextureResources(d3d9Device);
  379. if ((mUsage & TU_RENDERTARGET) != 0 && (mFSAAType != D3DMULTISAMPLE_NONE))
  380. {
  381. // Create AA surface
  382. HRESULT hr = d3d9Device->CreateRenderTarget(mWidth, mHeight, d3dPF,
  383. mFSAAType,
  384. mFSAAQuality,
  385. TRUE, // TODO - Possible performance issues? Need to check
  386. &textureResources->pFSAASurface, NULL);
  387. if (FAILED(hr))
  388. {
  389. CM_EXCEPT(RenderingAPIException, "Unable to create AA render target: " + String(DXGetErrorDescription(hr)));
  390. }
  391. D3DSURFACE_DESC desc;
  392. hr = textureResources->pFSAASurface->GetDesc(&desc);
  393. if (FAILED(hr))
  394. {
  395. destroy_internal();
  396. CM_EXCEPT(RenderingAPIException, "Can't get texture description: " + String(DXGetErrorDescription(hr)));
  397. }
  398. _setFinalAttributes(d3d9Device, textureResources,
  399. desc.Width, desc.Height, 1, D3D9Mappings::_getPF(desc.Format));
  400. mIsBindableAsShaderResource = true; // Cannot bind AA surfaces
  401. }
  402. else if ((mUsage & TU_DEPTHSTENCIL) != 0 && (mFSAAType != D3DMULTISAMPLE_NONE))
  403. {
  404. // Create AA depth stencil surface
  405. HRESULT hr = d3d9Device->CreateDepthStencilSurface(mWidth, mHeight, d3dPF,
  406. mFSAAType,
  407. mFSAAQuality,
  408. TRUE, // TODO - Possible performance issues? Need to check
  409. &textureResources->pDepthStencilSurface, NULL);
  410. if (FAILED(hr))
  411. CM_EXCEPT(RenderingAPIException, "Unable to create AA depth stencil render target: " + String(DXGetErrorDescription(hr)));
  412. D3DSURFACE_DESC desc;
  413. hr = textureResources->pDepthStencilSurface->GetDesc(&desc);
  414. if (FAILED(hr))
  415. {
  416. destroy_internal();
  417. CM_EXCEPT(RenderingAPIException, "Can't get texture description: " + String(DXGetErrorDescription(hr)));
  418. }
  419. _setFinalAttributes(d3d9Device, textureResources, desc.Width, desc.Height, 1, D3D9Mappings::_getPF(desc.Format));
  420. mIsBindableAsShaderResource = true; // Cannot bind AA depth buffer
  421. }
  422. else
  423. {
  424. // create the texture
  425. hr = D3DXCreateTexture(
  426. d3d9Device, // device
  427. static_cast<UINT>(mWidth), // width
  428. static_cast<UINT>(mHeight), // height
  429. numMips, // number of mip map levels
  430. usage, // usage
  431. d3dPF, // pixel format
  432. mD3DPool,
  433. &textureResources->pNormTex); // data pointer
  434. // check result and except if failed
  435. if (FAILED(hr))
  436. {
  437. destroy_internal();
  438. CM_EXCEPT(RenderingAPIException, "Error creating texture: " + String(DXGetErrorDescription(hr)));
  439. }
  440. // set the base texture we'll use in the render system
  441. hr = textureResources->pNormTex->QueryInterface(IID_IDirect3DBaseTexture9, (void **)&textureResources->pBaseTex);
  442. if (FAILED(hr))
  443. {
  444. destroy_internal();
  445. CM_EXCEPT(RenderingAPIException, "Can't get base texture: " + String(DXGetErrorDescription(hr)));
  446. }
  447. // set final tex. attributes from tex. description
  448. // they may differ from the source image !!!
  449. D3DSURFACE_DESC desc;
  450. hr = textureResources->pNormTex->GetLevelDesc(0, &desc);
  451. if (FAILED(hr))
  452. {
  453. destroy_internal();
  454. CM_EXCEPT(RenderingAPIException, "Can't get texture description: " + String(DXGetErrorDescription(hr)));
  455. }
  456. _setFinalAttributes(d3d9Device, textureResources,
  457. desc.Width, desc.Height, 1, D3D9Mappings::_getPF(desc.Format));
  458. }
  459. }
  460. void D3D9Texture::_createCubeTex(IDirect3DDevice9* d3d9Device)
  461. {
  462. // we must have those defined here
  463. assert(mWidth > 0 || mHeight > 0);
  464. if (mUsage & TU_RENDERTARGET)
  465. CM_EXCEPT(RenderingAPIException, "D3D9 Cube texture can not be created as render target !!");
  466. if (mUsage & TU_DEPTHSTENCIL)
  467. CM_EXCEPT(RenderingAPIException, "D3D9 Cube texture can not be created as a depth stencil target !!");
  468. // determine wich D3D9 pixel format we'll use
  469. HRESULT hr;
  470. D3DFORMAT d3dPF = _chooseD3DFormat(d3d9Device);
  471. if(mFormat != D3D9Mappings::_getPF(d3dPF))
  472. {
  473. CM_EXCEPT(RenderingAPIException, "Provided pixel format is not supported by the driver: " + toString(mFormat));
  474. }
  475. // Use D3DX to help us create the texture, this way it can adjust any relevant sizes
  476. DWORD usage = (mUsage & TU_RENDERTARGET) ? D3DUSAGE_RENDERTARGET : 0;
  477. UINT numMips = (mNumMipmaps == MIP_UNLIMITED) ?
  478. D3DX_DEFAULT : mNumMipmaps + 1;
  479. // Check dynamic textures
  480. if (mUsage & TU_DYNAMIC)
  481. {
  482. if (_canUseDynamicTextures(d3d9Device, usage, D3DRTYPE_CUBETEXTURE, d3dPF))
  483. {
  484. usage |= D3DUSAGE_DYNAMIC;
  485. mDynamicTextures = true;
  486. }
  487. else
  488. {
  489. mDynamicTextures = false;
  490. }
  491. }
  492. // Check sRGB support
  493. if (mHwGamma)
  494. {
  495. mHwGammaReadSupported = _canUseHardwareGammaCorrection(d3d9Device, usage, D3DRTYPE_CUBETEXTURE, d3dPF, false);
  496. if (mUsage & TU_RENDERTARGET)
  497. mHwGammaWriteSupported = _canUseHardwareGammaCorrection(d3d9Device, usage, D3DRTYPE_CUBETEXTURE, d3dPF, true);
  498. }
  499. mFSAAType = D3DMULTISAMPLE_NONE;
  500. mFSAAQuality = 0;
  501. D3D9Device* device = D3D9RenderSystem::getDeviceManager()->getDeviceFromD3D9Device(d3d9Device);
  502. const D3DCAPS9& rkCurCaps = device->getD3D9DeviceCaps();
  503. // check if mip map cube textures are supported
  504. if (numMips > 1 && !(rkCurCaps.TextureCaps & D3DPTEXTURECAPS_MIPCUBEMAP))
  505. {
  506. CM_EXCEPT(InvalidParametersException, "Invalid number of mipmaps. Maximum allowed is: 0");
  507. numMips = 1;
  508. }
  509. // derive the pool to use
  510. determinePool();
  511. TextureResources* textureResources;
  512. // Get or create new texture resources structure.
  513. textureResources = getTextureResources(d3d9Device);
  514. if (textureResources != NULL)
  515. freeTextureResources(d3d9Device, textureResources);
  516. else
  517. textureResources = allocateTextureResources(d3d9Device);
  518. // create the texture
  519. hr = D3DXCreateCubeTexture(
  520. d3d9Device, // device
  521. static_cast<UINT>(mWidth), // dimension
  522. numMips, // number of mip map levels
  523. usage, // usage
  524. d3dPF, // pixel format
  525. mD3DPool,
  526. &textureResources->pCubeTex); // data pointer
  527. // check result and except if failed
  528. if (FAILED(hr))
  529. {
  530. destroy_internal();
  531. CM_EXCEPT(RenderingAPIException, "Error creating texture: " + String(DXGetErrorDescription(hr)));
  532. }
  533. // set the base texture we'll use in the render system
  534. hr = textureResources->pCubeTex->QueryInterface(IID_IDirect3DBaseTexture9, (void **)&textureResources->pBaseTex);
  535. if (FAILED(hr))
  536. {
  537. destroy_internal();
  538. CM_EXCEPT(RenderingAPIException, "Can't get base texture: " + String(DXGetErrorDescription(hr)));
  539. }
  540. // set final tex. attributes from tex. description
  541. // they may differ from the source image !!!
  542. D3DSURFACE_DESC desc;
  543. hr = textureResources->pCubeTex->GetLevelDesc(0, &desc);
  544. if (FAILED(hr))
  545. {
  546. destroy_internal();
  547. CM_EXCEPT(RenderingAPIException, "Can't get texture description: " + String(DXGetErrorDescription(hr)));
  548. }
  549. _setFinalAttributes(d3d9Device, textureResources,
  550. desc.Width, desc.Height, 1, D3D9Mappings::_getPF(desc.Format));
  551. }
  552. void D3D9Texture::_createVolumeTex(IDirect3DDevice9* d3d9Device)
  553. {
  554. // we must have those defined here
  555. assert(mWidth > 0 && mHeight > 0 && mDepth>0);
  556. if (mUsage & TU_RENDERTARGET)
  557. CM_EXCEPT(RenderingAPIException, "D3D9 Volume texture can not be created as render target !!");
  558. if (mUsage & TU_DEPTHSTENCIL)
  559. CM_EXCEPT(RenderingAPIException, "D3D9 Volume texture can not be created as a depth stencil target !!");
  560. // determine which D3D9 pixel format we'll use
  561. HRESULT hr;
  562. D3DFORMAT d3dPF = _chooseD3DFormat(d3d9Device);
  563. if(mFormat != D3D9Mappings::_getPF(d3dPF))
  564. {
  565. CM_EXCEPT(RenderingAPIException, "Provided pixel format is not supported by the driver: " + toString(mFormat));
  566. }
  567. // Use D3DX to help us create the texture, this way it can adjust any relevant sizes
  568. DWORD usage = (mUsage & TU_RENDERTARGET) ? D3DUSAGE_RENDERTARGET : 0;
  569. UINT numMips = (mNumMipmaps == MIP_UNLIMITED) ?
  570. D3DX_DEFAULT : mNumMipmaps + 1;
  571. // Check dynamic textures
  572. if (mUsage & TU_DYNAMIC)
  573. {
  574. if (_canUseDynamicTextures(d3d9Device, usage, D3DRTYPE_VOLUMETEXTURE, d3dPF))
  575. {
  576. usage |= D3DUSAGE_DYNAMIC;
  577. mDynamicTextures = true;
  578. }
  579. else
  580. {
  581. mDynamicTextures = false;
  582. }
  583. }
  584. // Check sRGB support
  585. if (mHwGamma)
  586. {
  587. mHwGammaReadSupported = _canUseHardwareGammaCorrection(d3d9Device, usage, D3DRTYPE_VOLUMETEXTURE, d3dPF, false);
  588. if (mUsage & TU_RENDERTARGET)
  589. mHwGammaWriteSupported = _canUseHardwareGammaCorrection(d3d9Device, usage, D3DRTYPE_VOLUMETEXTURE, d3dPF, true);
  590. }
  591. D3D9Device* device = D3D9RenderSystem::getDeviceManager()->getDeviceFromD3D9Device(d3d9Device);
  592. const D3DCAPS9& rkCurCaps = device->getD3D9DeviceCaps();
  593. // check if mip map volume textures are supported
  594. if (numMips > 1 && !(rkCurCaps.TextureCaps & D3DPTEXTURECAPS_MIPVOLUMEMAP))
  595. {
  596. CM_EXCEPT(InvalidParametersException, "Invalid number of mipmaps. Maximum allowed is: 0");
  597. }
  598. // derive the pool to use
  599. determinePool();
  600. TextureResources* textureResources;
  601. // Get or create new texture resources structure.
  602. textureResources = getTextureResources(d3d9Device);
  603. if (textureResources != NULL)
  604. freeTextureResources(d3d9Device, textureResources);
  605. else
  606. textureResources = allocateTextureResources(d3d9Device);
  607. // create the texture
  608. hr = D3DXCreateVolumeTexture(
  609. d3d9Device, // device
  610. static_cast<UINT>(mWidth), // dimension
  611. static_cast<UINT>(mHeight),
  612. static_cast<UINT>(mDepth),
  613. numMips, // number of mip map levels
  614. usage, // usage
  615. d3dPF, // pixel format
  616. mD3DPool,
  617. &textureResources->pVolumeTex); // data pointer
  618. // check result and except if failed
  619. if (FAILED(hr))
  620. {
  621. destroy_internal();
  622. CM_EXCEPT(RenderingAPIException, "Error creating texture: " + String(DXGetErrorDescription(hr)));
  623. }
  624. // set the base texture we'll use in the render system
  625. hr = textureResources->pVolumeTex->QueryInterface(IID_IDirect3DBaseTexture9, (void **)&textureResources->pBaseTex);
  626. if (FAILED(hr))
  627. {
  628. destroy_internal();
  629. CM_EXCEPT(RenderingAPIException, "Can't get base texture: " + String(DXGetErrorDescription(hr)));
  630. }
  631. // set final tex. attributes from tex. description
  632. // they may differ from the source image !!!
  633. D3DVOLUME_DESC desc;
  634. hr = textureResources->pVolumeTex->GetLevelDesc(0, &desc);
  635. if (FAILED(hr))
  636. {
  637. destroy_internal();
  638. CM_EXCEPT(RenderingAPIException, "Can't get texture description: " + String(DXGetErrorDescription(hr)));
  639. }
  640. _setFinalAttributes(d3d9Device, textureResources,
  641. desc.Width, desc.Height, desc.Depth, D3D9Mappings::_getPF(desc.Format));
  642. }
  643. void D3D9Texture::_setFinalAttributes(IDirect3DDevice9* d3d9Device,
  644. TextureResources* textureResources,
  645. unsigned long width, unsigned long height,
  646. unsigned long depth, PixelFormat format)
  647. {
  648. if(width != mWidth || height != mHeight || depth != mDepth)
  649. {
  650. CM_EXCEPT(InternalErrorException, "Wanted and created textures sizes don't match!" \
  651. "Width: " + toString(width) + "/" + toString(mWidth) +
  652. "Height: " + toString(height) + "/" + toString(mHeight) +
  653. "Depth: " + toString(depth) + "/" + toString(mDepth));
  654. }
  655. if(format != mFormat)
  656. {
  657. CM_EXCEPT(InternalErrorException, "Wanted and created texture formats don't match! " + toString(format) + "/" + toString(mFormat));
  658. }
  659. // Create list of subsurfaces for getBuffer()
  660. _createSurfaceList(d3d9Device, textureResources);
  661. }
  662. D3DTEXTUREFILTERTYPE D3D9Texture::_getBestFilterMethod(IDirect3DDevice9* d3d9Device)
  663. {
  664. D3D9Device* device = D3D9RenderSystem::getDeviceManager()->getDeviceFromD3D9Device(d3d9Device);
  665. const D3DCAPS9& rkCurCaps = device->getD3D9DeviceCaps();
  666. DWORD filterCaps = 0;
  667. // Minification filter is used for mipmap generation
  668. // Pick the best one supported for this tex type
  669. switch (getTextureType())
  670. {
  671. case TEX_TYPE_1D: // Same as 2D
  672. case TEX_TYPE_2D: filterCaps = rkCurCaps.TextureFilterCaps; break;
  673. case TEX_TYPE_3D: filterCaps = rkCurCaps.VolumeTextureFilterCaps; break;
  674. case TEX_TYPE_CUBE_MAP: filterCaps = rkCurCaps.CubeTextureFilterCaps; break;
  675. }
  676. if(filterCaps & D3DPTFILTERCAPS_MINFGAUSSIANQUAD)
  677. return D3DTEXF_GAUSSIANQUAD;
  678. if(filterCaps & D3DPTFILTERCAPS_MINFPYRAMIDALQUAD)
  679. return D3DTEXF_PYRAMIDALQUAD;
  680. if(filterCaps & D3DPTFILTERCAPS_MINFANISOTROPIC)
  681. return D3DTEXF_ANISOTROPIC;
  682. if(filterCaps & D3DPTFILTERCAPS_MINFLINEAR)
  683. return D3DTEXF_LINEAR;
  684. if(filterCaps & D3DPTFILTERCAPS_MINFPOINT)
  685. return D3DTEXF_POINT;
  686. return D3DTEXF_POINT;
  687. }
  688. bool D3D9Texture::_canUseDynamicTextures(IDirect3DDevice9* d3d9Device,
  689. DWORD srcUsage,
  690. D3DRESOURCETYPE srcType,
  691. D3DFORMAT srcFormat)
  692. {
  693. HRESULT hr;
  694. IDirect3D9* pD3D = NULL;
  695. hr = d3d9Device->GetDirect3D(&pD3D);
  696. if (FAILED(hr))
  697. {
  698. CM_EXCEPT(InvalidParametersException, "GetDirect3D failed !!!");
  699. }
  700. if (pD3D != NULL)
  701. pD3D->Release();
  702. D3D9Device* device = D3D9RenderSystem::getDeviceManager()->getDeviceFromD3D9Device(d3d9Device);
  703. const D3DCAPS9& rkCurCaps = device->getD3D9DeviceCaps();
  704. D3DFORMAT eBackBufferFormat = device->getBackBufferFormat();
  705. // Check for dynamic texture support
  706. // check for auto gen. mip maps support
  707. hr = pD3D->CheckDeviceFormat(
  708. rkCurCaps.AdapterOrdinal,
  709. rkCurCaps.DeviceType,
  710. eBackBufferFormat,
  711. srcUsage | D3DUSAGE_DYNAMIC,
  712. srcType,
  713. srcFormat);
  714. if (hr == D3D_OK)
  715. return true;
  716. else
  717. return false;
  718. }
  719. bool D3D9Texture::_canUseHardwareGammaCorrection(IDirect3DDevice9* d3d9Device,
  720. DWORD srcUsage,
  721. D3DRESOURCETYPE srcType, D3DFORMAT srcFormat, bool forwriting)
  722. {
  723. HRESULT hr;
  724. IDirect3D9* pD3D = NULL;
  725. hr = d3d9Device->GetDirect3D(&pD3D);
  726. if (FAILED(hr))
  727. {
  728. CM_EXCEPT(InvalidParametersException, "GetDirect3D failed !!!" );
  729. }
  730. if (pD3D != NULL)
  731. pD3D->Release();
  732. D3D9Device* device = D3D9RenderSystem::getDeviceManager()->getDeviceFromD3D9Device(d3d9Device);
  733. const D3DCAPS9& rkCurCaps = device->getD3D9DeviceCaps();
  734. D3DFORMAT eBackBufferFormat = device->getBackBufferFormat();
  735. // Always check 'read' capability here
  736. // We will check 'write' capability only in the context of a render target
  737. if (forwriting)
  738. srcUsage |= D3DUSAGE_QUERY_SRGBWRITE;
  739. else
  740. srcUsage |= D3DUSAGE_QUERY_SRGBREAD;
  741. // Check for sRGB support
  742. // check for auto gen. mip maps support
  743. hr = pD3D->CheckDeviceFormat(
  744. rkCurCaps.AdapterOrdinal,
  745. rkCurCaps.DeviceType,
  746. eBackBufferFormat,
  747. srcUsage,
  748. srcType,
  749. srcFormat);
  750. if (hr == D3D_OK)
  751. return true;
  752. else
  753. return false;
  754. }
  755. bool D3D9Texture::_canAutoGenMipmaps(IDirect3DDevice9* d3d9Device,
  756. DWORD srcUsage, D3DRESOURCETYPE srcType, D3DFORMAT srcFormat)
  757. {
  758. HRESULT hr;
  759. IDirect3D9* pD3D = NULL;
  760. hr = d3d9Device->GetDirect3D(&pD3D);
  761. if (FAILED(hr))
  762. {
  763. CM_EXCEPT(InvalidParametersException, "GetDirect3D failed !!!");
  764. }
  765. if (pD3D != NULL)
  766. pD3D->Release();
  767. D3D9Device* device = D3D9RenderSystem::getDeviceManager()->getDeviceFromD3D9Device(d3d9Device);
  768. const D3DCAPS9& rkCurCaps = device->getD3D9DeviceCaps();
  769. D3DFORMAT eBackBufferFormat = device->getBackBufferFormat();
  770. // Hacky override - many (all?) cards seem to not be able to autogen on
  771. // textures which are not a power of two
  772. // Can we even mipmap on 3D textures? Well
  773. if ((mWidth & mWidth-1) || (mHeight & mHeight-1) || (mDepth & mDepth-1))
  774. return false;
  775. if (rkCurCaps.Caps2 & D3DCAPS2_CANAUTOGENMIPMAP)
  776. {
  777. HRESULT hr;
  778. // check for auto gen. mip maps support
  779. hr = pD3D->CheckDeviceFormat(
  780. rkCurCaps.AdapterOrdinal,
  781. rkCurCaps.DeviceType,
  782. eBackBufferFormat,
  783. srcUsage | D3DUSAGE_AUTOGENMIPMAP,
  784. srcType,
  785. srcFormat);
  786. // this HR could a SUCCES
  787. // but mip maps will not be generated
  788. if (hr == D3D_OK)
  789. return true;
  790. else
  791. return false;
  792. }
  793. else
  794. return false;
  795. }
  796. D3DFORMAT D3D9Texture::_chooseD3DFormat(IDirect3DDevice9* d3d9Device)
  797. {
  798. // Choose frame buffer pixel format in case PF_UNKNOWN was requested
  799. if(mFormat == PF_UNKNOWN)
  800. {
  801. D3D9Device* device = D3D9RenderSystem::getDeviceManager()->getDeviceFromD3D9Device(d3d9Device);
  802. if((mUsage & TU_DEPTHSTENCIL) != 0)
  803. return device->getDepthStencilFormat();
  804. else
  805. return device->getBackBufferFormat();
  806. }
  807. // Choose closest supported D3D format as a D3D format
  808. return D3D9Mappings::_getPF(D3D9Mappings::_getClosestSupportedPF(mFormat));
  809. }
  810. // Macro to hide ugly cast
  811. #define GETLEVEL(face,mip) \
  812. static_cast<D3D9PixelBuffer*>(mSurfaceList[face*(mNumMipmaps+1)+mip].get())
  813. void D3D9Texture::_createSurfaceList(IDirect3DDevice9* d3d9Device, TextureResources* textureResources)
  814. {
  815. IDirect3DSurface9 *surface;
  816. IDirect3DVolume9 *volume;
  817. UINT32 mip, face;
  818. assert(textureResources != NULL);
  819. // Need to know static / dynamic
  820. unsigned int bufusage;
  821. if ((mUsage & TU_DYNAMIC) && mDynamicTextures)
  822. {
  823. bufusage = GBU_DYNAMIC;
  824. }
  825. else
  826. {
  827. bufusage = GBU_STATIC;
  828. }
  829. if (mUsage & TU_RENDERTARGET)
  830. {
  831. bufusage |= TU_RENDERTARGET;
  832. }
  833. else if(mUsage & TU_DEPTHSTENCIL)
  834. {
  835. bufusage |= TU_RENDERTARGET;
  836. }
  837. UINT32 surfaceCount = static_cast<UINT32>((getNumFaces() * (mNumMipmaps + 1)));
  838. bool updateOldList = mSurfaceList.size() == surfaceCount;
  839. if(!updateOldList)
  840. {
  841. // Create new list of surfaces
  842. mSurfaceList.clear();
  843. for(UINT32 face=0; face<getNumFaces(); ++face)
  844. {
  845. for(UINT32 mip=0; mip<=mNumMipmaps; ++mip)
  846. {
  847. mSurfaceList.push_back(cm_shared_ptr<D3D9PixelBuffer, PoolAlloc>((GpuBufferUsage)bufusage, this));
  848. }
  849. }
  850. }
  851. if((mUsage & TU_RENDERTARGET) != 0 && (mFSAAType != D3DMULTISAMPLE_NONE))
  852. {
  853. assert(textureResources->pFSAASurface);
  854. assert(getTextureType() == TEX_TYPE_2D);
  855. D3D9PixelBuffer* currPixelBuffer = GETLEVEL(0, 0);
  856. currPixelBuffer->bind(d3d9Device, textureResources->pFSAASurface,
  857. mHwGammaWriteSupported, mFSAA, "PortNoName", textureResources->pBaseTex);
  858. }
  859. else if((mUsage & TU_DEPTHSTENCIL) != 0 && (mFSAAType != D3DMULTISAMPLE_NONE))
  860. {
  861. assert(textureResources->pDepthStencilSurface);
  862. assert(getTextureType() == TEX_TYPE_2D);
  863. D3D9PixelBuffer* currPixelBuffer = GETLEVEL(0, 0);
  864. currPixelBuffer->bind(d3d9Device, textureResources->pDepthStencilSurface,
  865. mHwGammaWriteSupported, mFSAA, "PortNoName", textureResources->pBaseTex);
  866. }
  867. else
  868. {
  869. assert(textureResources->pBaseTex);
  870. // Make sure number of mips is right
  871. UINT32 numCreatedMips = textureResources->pBaseTex->GetLevelCount() - 1;
  872. if(numCreatedMips != mNumMipmaps)
  873. {
  874. CM_EXCEPT(InternalErrorException, "Number of created and wanted mip map levels doesn't match: " +
  875. toString(numCreatedMips) + "/" + toString(mNumMipmaps));
  876. }
  877. switch(getTextureType())
  878. {
  879. case TEX_TYPE_2D:
  880. case TEX_TYPE_1D:
  881. assert(textureResources->pNormTex);
  882. // For all mipmaps, store surfaces as HardwarePixelBufferPtr
  883. for(mip=0; mip<=mNumMipmaps; ++mip)
  884. {
  885. if(textureResources->pNormTex->GetSurfaceLevel(static_cast<UINT>(mip), &surface) != D3D_OK)
  886. CM_EXCEPT(RenderingAPIException, "Get surface level failed");
  887. D3D9PixelBuffer* currPixelBuffer = GETLEVEL(0, mip);
  888. currPixelBuffer->bind(d3d9Device, surface,
  889. mHwGammaWriteSupported, mFSAA, "PortNoName", textureResources->pBaseTex);
  890. // decrement reference count, the GetSurfaceLevel call increments this
  891. // this is safe because the pixel buffer keeps a reference as well
  892. surface->Release();
  893. }
  894. break;
  895. case TEX_TYPE_CUBE_MAP:
  896. assert(textureResources->pCubeTex);
  897. // For all faces and mipmaps, store surfaces as HardwarePixelBufferPtr
  898. for(face=0; face<6; ++face)
  899. {
  900. for(mip=0; mip<=mNumMipmaps; ++mip)
  901. {
  902. if(textureResources->pCubeTex->GetCubeMapSurface((D3DCUBEMAP_FACES)face, static_cast<UINT>(mip), &surface) != D3D_OK)
  903. CM_EXCEPT(RenderingAPIException, "Get cubemap surface failed");
  904. D3D9PixelBuffer* currPixelBuffer = GETLEVEL(face, mip);
  905. currPixelBuffer->bind(d3d9Device, surface,
  906. mHwGammaWriteSupported, mFSAA, "NoNamePort", textureResources->pBaseTex);
  907. // decrement reference count, the GetSurfaceLevel call increments this
  908. // this is safe because the pixel buffer keeps a reference as well
  909. surface->Release();
  910. }
  911. }
  912. break;
  913. case TEX_TYPE_3D:
  914. assert(textureResources->pVolumeTex);
  915. // For all mipmaps, store surfaces as HardwarePixelBufferPtr
  916. for(mip=0; mip<=mNumMipmaps; ++mip)
  917. {
  918. if(textureResources->pVolumeTex->GetVolumeLevel(static_cast<UINT>(mip), &volume) != D3D_OK)
  919. CM_EXCEPT(RenderingAPIException, "Get volume level failed");
  920. D3D9PixelBuffer* currPixelBuffer = GETLEVEL(0, mip);
  921. currPixelBuffer->bind(d3d9Device, volume, textureResources->pBaseTex);
  922. // decrement reference count, the GetSurfaceLevel call increments this
  923. // this is safe because the pixel buffer keeps a reference as well
  924. volume->Release();
  925. }
  926. break;
  927. };
  928. }
  929. }
  930. #undef GETLEVEL
  931. PixelBufferPtr D3D9Texture::getBuffer(UINT32 face, UINT32 mipmap)
  932. {
  933. THROW_IF_NOT_CORE_THREAD;
  934. if(face >= getNumFaces())
  935. CM_EXCEPT(InvalidParametersException, "A three dimensional cube has six faces");
  936. if(mipmap > mNumMipmaps)
  937. CM_EXCEPT(InvalidParametersException, "Mipmap index out of range");
  938. UINT32 idx = face*(mNumMipmaps+1) + mipmap;
  939. IDirect3DDevice9* d3d9Device = D3D9RenderSystem::getActiveD3D9Device();
  940. TextureResources* textureResources = getTextureResources(d3d9Device);
  941. if (textureResources == NULL || textureResources->pBaseTex == NULL)
  942. {
  943. createTextureResources(d3d9Device);
  944. textureResources = getTextureResources(d3d9Device);
  945. }
  946. assert(textureResources != NULL);
  947. assert(idx < mSurfaceList.size());
  948. return mSurfaceList[idx];
  949. }
  950. //---------------------------------------------------------------------
  951. bool D3D9Texture::useDefaultPool()
  952. {
  953. // Determine D3D pool to use
  954. // Use managed unless we're a render target or user has asked for
  955. // a dynamic texture, and device supports D3DUSAGE_DYNAMIC (because default pool
  956. // resources without the dynamic flag are not lockable)
  957. return (mUsage & TU_RENDERTARGET) || (mUsage & TU_DEPTHSTENCIL) || ((mUsage & TU_DYNAMIC) && mDynamicTextures);
  958. }
  959. //---------------------------------------------------------------------
  960. void D3D9Texture::notifyOnDeviceCreate(IDirect3DDevice9* d3d9Device)
  961. {
  962. D3D9_DEVICE_ACCESS_CRITICAL_SECTION
  963. if (D3D9RenderSystem::getResourceManager()->getCreationPolicy() == RCP_CREATE_ON_ALL_DEVICES)
  964. createTextureResources(d3d9Device);
  965. }
  966. //---------------------------------------------------------------------
  967. void D3D9Texture::notifyOnDeviceDestroy(IDirect3DDevice9* d3d9Device)
  968. {
  969. D3D9_DEVICE_ACCESS_CRITICAL_SECTION
  970. DeviceToTextureResourcesIterator it = mMapDeviceToTextureResources.find(d3d9Device);
  971. if (it != mMapDeviceToTextureResources.end())
  972. {
  973. TextureResources* textureResource = it->second;
  974. // Destroy surfaces from each mip level.
  975. for(unsigned int i = 0; i < mSurfaceList.size(); ++i)
  976. {
  977. D3D9PixelBuffer* pixelBuffer = static_cast<D3D9PixelBuffer*>(mSurfaceList[i].get());
  978. pixelBuffer->destroyBufferResources(d3d9Device);
  979. }
  980. // Just free any internal resources, don't call unload() here
  981. // because we want the un-touched resource to keep its unloaded status
  982. // after device reset.
  983. freeTextureResources(d3d9Device, textureResource);
  984. if(textureResource != nullptr)
  985. cm_delete<PoolAlloc>(textureResource);
  986. mMapDeviceToTextureResources.erase(it);
  987. }
  988. }
  989. //---------------------------------------------------------------------
  990. void D3D9Texture::notifyOnDeviceLost(IDirect3DDevice9* d3d9Device)
  991. {
  992. D3D9_DEVICE_ACCESS_CRITICAL_SECTION
  993. if(mD3DPool == D3DPOOL_DEFAULT)
  994. {
  995. DeviceToTextureResourcesIterator it = mMapDeviceToTextureResources.find(d3d9Device);
  996. if (it != mMapDeviceToTextureResources.end())
  997. {
  998. TextureResources* textureResource = it->second;
  999. // Just free any internal resources, don't call unload() here
  1000. // because we want the un-touched resource to keep its unloaded status
  1001. // after device reset.
  1002. freeTextureResources(d3d9Device, textureResource);
  1003. }
  1004. }
  1005. }
  1006. //---------------------------------------------------------------------
  1007. void D3D9Texture::notifyOnDeviceReset(IDirect3DDevice9* d3d9Device)
  1008. {
  1009. D3D9_DEVICE_ACCESS_CRITICAL_SECTION
  1010. if(mD3DPool == D3DPOOL_DEFAULT)
  1011. {
  1012. createTextureResources(d3d9Device);
  1013. }
  1014. }
  1015. //---------------------------------------------------------------------
  1016. IDirect3DBaseTexture9* D3D9Texture::getTexture_internal()
  1017. {
  1018. THROW_IF_NOT_CORE_THREAD;
  1019. TextureResources* textureResources;
  1020. IDirect3DDevice9* d3d9Device = D3D9RenderSystem::getActiveD3D9Device();
  1021. textureResources = getTextureResources(d3d9Device);
  1022. if (textureResources == NULL || textureResources->pBaseTex == NULL)
  1023. {
  1024. createTextureResources(d3d9Device);
  1025. textureResources = getTextureResources(d3d9Device);
  1026. }
  1027. assert(textureResources);
  1028. assert(textureResources->pBaseTex);
  1029. return textureResources->pBaseTex;
  1030. }
  1031. //---------------------------------------------------------------------
  1032. IDirect3DTexture9* D3D9Texture::getNormTexture_internal()
  1033. {
  1034. THROW_IF_NOT_CORE_THREAD;
  1035. TextureResources* textureResources;
  1036. IDirect3DDevice9* d3d9Device = D3D9RenderSystem::getActiveD3D9Device();
  1037. textureResources = getTextureResources(d3d9Device);
  1038. if (textureResources == NULL || textureResources->pNormTex == NULL)
  1039. {
  1040. createTextureResources(d3d9Device);
  1041. textureResources = getTextureResources(d3d9Device);
  1042. }
  1043. assert(textureResources);
  1044. assert(textureResources->pNormTex);
  1045. return textureResources->pNormTex;
  1046. }
  1047. //---------------------------------------------------------------------
  1048. IDirect3DCubeTexture9* D3D9Texture::getCubeTexture_internal()
  1049. {
  1050. THROW_IF_NOT_CORE_THREAD;
  1051. TextureResources* textureResources;
  1052. IDirect3DDevice9* d3d9Device = D3D9RenderSystem::getActiveD3D9Device();
  1053. textureResources = getTextureResources(d3d9Device);
  1054. if (textureResources == NULL || textureResources->pCubeTex)
  1055. {
  1056. createTextureResources(d3d9Device);
  1057. textureResources = getTextureResources(d3d9Device);
  1058. }
  1059. assert(textureResources);
  1060. assert(textureResources->pCubeTex);
  1061. return textureResources->pCubeTex;
  1062. }
  1063. }