CmD3D9Texture.cpp 42 KB

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