OgreD3D9Device.cpp 45 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448
  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 "OgreD3D9Device.h"
  25. #include "OgreD3D9DeviceManager.h"
  26. #include "OgreD3D9Driver.h"
  27. #include "OgreD3D9RenderSystem.h"
  28. #include "OgreD3D9ResourceManager.h"
  29. #include "OgreD3D9RenderWindow.h"
  30. #include "OgreHardwareBufferManager.h"
  31. #include "OgreException.h"
  32. #include "CmRenderSystemManager.h"
  33. namespace Ogre
  34. {
  35. HWND D3D9Device::msSharedFocusWindow = NULL;
  36. //---------------------------------------------------------------------
  37. D3D9Device::D3D9Device(D3D9DeviceManager* deviceManager,
  38. UINT adapterNumber,
  39. HMONITOR hMonitor,
  40. D3DDEVTYPE devType,
  41. DWORD behaviorFlags)
  42. {
  43. mpDeviceManager = deviceManager;
  44. mpDevice = NULL;
  45. mAdapterNumber = adapterNumber;
  46. mMonitor = hMonitor;
  47. mDeviceType = devType;
  48. mFocusWindow = NULL;
  49. mBehaviorFlags = behaviorFlags;
  50. mD3D9DeviceCapsValid = false;
  51. mDeviceLost = false;
  52. mPresentationParamsCount = 0;
  53. mPresentationParams = NULL;
  54. memset(&mD3D9DeviceCaps, 0, sizeof(mD3D9DeviceCaps));
  55. memset(&mCreationParams, 0, sizeof(mCreationParams));
  56. }
  57. //---------------------------------------------------------------------
  58. D3D9Device::~D3D9Device()
  59. {
  60. }
  61. //---------------------------------------------------------------------
  62. D3D9Device::RenderWindowToResorucesIterator D3D9Device::getRenderWindowIterator(D3D9RenderWindow* renderWindow)
  63. {
  64. RenderWindowToResorucesIterator it = mMapRenderWindowToResoruces.find(renderWindow);
  65. if (it == mMapRenderWindowToResoruces.end())
  66. {
  67. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR,
  68. "Render window was not attached to this device !!",
  69. "D3D9Device::getRenderWindowIterator" );
  70. }
  71. return it;
  72. }
  73. //---------------------------------------------------------------------
  74. void D3D9Device::attachRenderWindow(D3D9RenderWindow* renderWindow)
  75. {
  76. RenderWindowToResorucesIterator it = mMapRenderWindowToResoruces.find(renderWindow);
  77. if (it == mMapRenderWindowToResoruces.end())
  78. {
  79. RenderWindowResources* renderWindowResources = new RenderWindowResources;
  80. memset(renderWindowResources, 0, sizeof(RenderWindowResources));
  81. renderWindowResources->adapterOrdinalInGroupIndex = 0;
  82. renderWindowResources->acquired = false;
  83. mMapRenderWindowToResoruces[renderWindow] = renderWindowResources;
  84. }
  85. updateRenderWindowsIndices();
  86. }
  87. //---------------------------------------------------------------------
  88. void D3D9Device::detachRenderWindow(D3D9RenderWindow* renderWindow)
  89. {
  90. RenderWindowToResorucesIterator it = mMapRenderWindowToResoruces.find(renderWindow);
  91. if (it != mMapRenderWindowToResoruces.end())
  92. {
  93. // The focus window in which the d3d9 device created on is detached.
  94. // resources must be acquired again.
  95. if (mFocusWindow == renderWindow->getWindowHandle())
  96. {
  97. mFocusWindow = NULL;
  98. }
  99. // Case this is the shared focus window.
  100. if (renderWindow->getWindowHandle() == msSharedFocusWindow)
  101. setSharedWindowHandle(NULL);
  102. RenderWindowResources* renderWindowResources = it->second;
  103. releaseRenderWindowResources(renderWindowResources);
  104. SAFE_DELETE(renderWindowResources);
  105. mMapRenderWindowToResoruces.erase(it);
  106. }
  107. updateRenderWindowsIndices();
  108. }
  109. //---------------------------------------------------------------------
  110. bool D3D9Device::acquire()
  111. {
  112. updatePresentationParameters();
  113. bool resetDevice = false;
  114. // Create device if need to.
  115. if (mpDevice == NULL)
  116. {
  117. createD3D9Device();
  118. }
  119. // Case device already exists.
  120. else
  121. {
  122. RenderWindowToResorucesIterator itPrimary = getRenderWindowIterator(getPrimaryWindow());
  123. if (itPrimary->second->swapChain != NULL)
  124. {
  125. D3DPRESENT_PARAMETERS currentPresentParams;
  126. HRESULT hr;
  127. hr = itPrimary->second->swapChain->GetPresentParameters(&currentPresentParams);
  128. if (FAILED(hr))
  129. {
  130. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR,
  131. "GetPresentParameters failed",
  132. "D3D9RenderWindow::acquire");
  133. }
  134. // Desired parameters are different then current parameters.
  135. // Possible scenario is that primary window resized and in the mean while another
  136. // window attached to this device.
  137. if (memcmp(&currentPresentParams, &mPresentationParams[0], sizeof(D3DPRESENT_PARAMETERS)) != 0)
  138. {
  139. resetDevice = true;
  140. }
  141. }
  142. // Make sure depth stencil is set to valid surface. It is going to be
  143. // grabbed by the primary window using the GetDepthStencilSurface method.
  144. if (resetDevice == false)
  145. {
  146. mpDevice->SetDepthStencilSurface(itPrimary->second->depthBuffer);
  147. }
  148. }
  149. // Reset device will update all render window resources.
  150. if (resetDevice)
  151. {
  152. reset();
  153. }
  154. // No need to reset -> just acquire resources.
  155. else
  156. {
  157. // Update resources of each window.
  158. RenderWindowToResorucesIterator it = mMapRenderWindowToResoruces.begin();
  159. while (it != mMapRenderWindowToResoruces.end())
  160. {
  161. acquireRenderWindowResources(it);
  162. ++it;
  163. }
  164. }
  165. return true;
  166. }
  167. //---------------------------------------------------------------------
  168. void D3D9Device::release()
  169. {
  170. if (mpDevice != NULL)
  171. {
  172. D3D9RenderSystem* renderSystem = static_cast<D3D9RenderSystem*>(CamelotEngine::RenderSystemManager::getActive());
  173. //// Clean up depth stencil surfaces
  174. //renderSystem->_cleanupDepthStencils(mpDevice);
  175. RenderWindowToResorucesIterator it = mMapRenderWindowToResoruces.begin();
  176. while (it != mMapRenderWindowToResoruces.end())
  177. {
  178. RenderWindowResources* renderWindowResources = it->second;
  179. releaseRenderWindowResources(renderWindowResources);
  180. ++it;
  181. }
  182. releaseD3D9Device();
  183. }
  184. }
  185. //---------------------------------------------------------------------
  186. bool D3D9Device::acquire(D3D9RenderWindow* renderWindow)
  187. {
  188. RenderWindowToResorucesIterator it = getRenderWindowIterator(renderWindow);
  189. acquireRenderWindowResources(it);
  190. return true;
  191. }
  192. //---------------------------------------------------------------------
  193. void D3D9Device::notifyDeviceLost()
  194. {
  195. // Case this device is already in lost state.
  196. if (mDeviceLost)
  197. return;
  198. // Case we just moved from valid state to lost state.
  199. mDeviceLost = true;
  200. D3D9RenderSystem* renderSystem = static_cast<D3D9RenderSystem*>(CamelotEngine::RenderSystemManager::getActive());
  201. renderSystem->notifyOnDeviceLost(this);
  202. }
  203. //---------------------------------------------------------------------
  204. IDirect3DSurface9* D3D9Device::getDepthBuffer(D3D9RenderWindow* renderWindow)
  205. {
  206. RenderWindowToResorucesIterator it = getRenderWindowIterator(renderWindow);
  207. return it->second->depthBuffer;
  208. }
  209. //---------------------------------------------------------------------
  210. IDirect3DSurface9* D3D9Device::getBackBuffer(D3D9RenderWindow* renderWindow)
  211. {
  212. RenderWindowToResorucesIterator it = getRenderWindowIterator(renderWindow);
  213. return it->second->backBuffer;
  214. }
  215. //---------------------------------------------------------------------
  216. uint D3D9Device::getRenderWindowCount() const
  217. {
  218. return static_cast<uint>(mMapRenderWindowToResoruces.size());
  219. }
  220. //---------------------------------------------------------------------
  221. D3D9RenderWindow* D3D9Device::getRenderWindow(uint index)
  222. {
  223. if (index >= mMapRenderWindowToResoruces.size())
  224. {
  225. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR,
  226. "Index of render window is out of bounds!",
  227. "D3D9RenderWindow::getRenderWindow");
  228. }
  229. RenderWindowToResorucesIterator it = mMapRenderWindowToResoruces.begin();
  230. while (it != mMapRenderWindowToResoruces.end())
  231. {
  232. if (index == 0)
  233. break;
  234. --index;
  235. ++it;
  236. }
  237. return it->first;
  238. }
  239. //---------------------------------------------------------------------
  240. void D3D9Device::setAdapterOrdinalIndex(D3D9RenderWindow* renderWindow, uint adapterOrdinalInGroupIndex)
  241. {
  242. RenderWindowToResorucesIterator it = getRenderWindowIterator(renderWindow);
  243. it->second->adapterOrdinalInGroupIndex = adapterOrdinalInGroupIndex;
  244. updateRenderWindowsIndices();
  245. }
  246. //---------------------------------------------------------------------
  247. void D3D9Device::destroy()
  248. {
  249. // Lock access to rendering device.
  250. D3D9RenderSystem::getResourceManager()->lockDeviceAccess();
  251. release();
  252. RenderWindowToResorucesIterator it = mMapRenderWindowToResoruces.begin();
  253. if (it != mMapRenderWindowToResoruces.end())
  254. {
  255. if (it->first->getWindowHandle() == msSharedFocusWindow)
  256. setSharedWindowHandle(NULL);
  257. SAFE_DELETE(it->second);
  258. ++it;
  259. }
  260. mMapRenderWindowToResoruces.clear();
  261. // Reset dynamic attributes.
  262. mFocusWindow = NULL;
  263. mD3D9DeviceCapsValid = false;
  264. SAFE_DELETE_ARRAY(mPresentationParams);
  265. mPresentationParamsCount = 0;
  266. // Notify the device manager on this instance destruction.
  267. mpDeviceManager->notifyOnDeviceDestroy(this);
  268. // UnLock access to rendering device.
  269. D3D9RenderSystem::getResourceManager()->unlockDeviceAccess();
  270. }
  271. //---------------------------------------------------------------------
  272. bool D3D9Device::isDeviceLost()
  273. {
  274. HRESULT hr;
  275. hr = mpDevice->TestCooperativeLevel();
  276. if (hr == D3DERR_DEVICELOST ||
  277. hr == D3DERR_DEVICENOTRESET)
  278. {
  279. return true;
  280. }
  281. return false;
  282. }
  283. //---------------------------------------------------------------------
  284. bool D3D9Device::reset()
  285. {
  286. HRESULT hr;
  287. // Check that device is in valid state for reset.
  288. hr = mpDevice->TestCooperativeLevel();
  289. if (hr == D3DERR_DEVICELOST ||
  290. hr == D3DERR_DRIVERINTERNALERROR)
  291. {
  292. return false;
  293. }
  294. // Lock access to rendering device.
  295. D3D9RenderSystem::getResourceManager()->lockDeviceAccess();
  296. D3D9RenderSystem* renderSystem = static_cast<D3D9RenderSystem*>(CamelotEngine::RenderSystemManager::getActive());
  297. // Inform all resources that device lost.
  298. D3D9RenderSystem::getResourceManager()->notifyOnDeviceLost(mpDevice);
  299. // TODO PORT - Make sure to call this once rendersystem is active
  300. // Notify all listener before device is rested
  301. //renderSystem->notifyOnDeviceLost(this);
  302. // Release all automatic temporary buffers and free unused
  303. // temporary buffers, so we doesn't need to recreate them,
  304. // and they will reallocate on demand. This save a lot of
  305. // release/recreate of non-managed vertex buffers which
  306. // wasn't need at all.
  307. HardwareBufferManager::getSingleton()._releaseBufferCopies(true);
  308. // TODO PORT - Make sure to call this once rendersystem is active
  309. // Cleanup depth stencils surfaces.
  310. //renderSystem->_cleanupDepthStencils(mpDevice);
  311. updatePresentationParameters();
  312. RenderWindowToResorucesIterator it = mMapRenderWindowToResoruces.begin();
  313. while (it != mMapRenderWindowToResoruces.end())
  314. {
  315. RenderWindowResources* renderWindowResources = it->second;
  316. releaseRenderWindowResources(renderWindowResources);
  317. ++it;
  318. }
  319. clearDeviceStreams();
  320. // Reset the device using the presentation parameters.
  321. hr = mpDevice->Reset(mPresentationParams);
  322. if (hr == D3DERR_DEVICELOST)
  323. {
  324. // UnLock access to rendering device.
  325. D3D9RenderSystem::getResourceManager()->unlockDeviceAccess();
  326. // Don't continue
  327. return false;
  328. }
  329. else if (FAILED(hr))
  330. {
  331. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR,
  332. "Cannot reset device!",
  333. "D3D9RenderWindow::reset");
  334. }
  335. mDeviceLost = false;
  336. // Initialize device states.
  337. setupDeviceStates();
  338. // Update resources of each window.
  339. it = mMapRenderWindowToResoruces.begin();
  340. while (it != mMapRenderWindowToResoruces.end())
  341. {
  342. acquireRenderWindowResources(it);
  343. ++it;
  344. }
  345. D3D9Device* pCurActiveDevice = mpDeviceManager->getActiveDevice();
  346. mpDeviceManager->setActiveDevice(this);
  347. // Inform all resources that device has been reset.
  348. D3D9RenderSystem::getResourceManager()->notifyOnDeviceReset(mpDevice);
  349. mpDeviceManager->setActiveDevice(pCurActiveDevice);
  350. // TODO PORT - Make sure to call this once rendersystem is active
  351. //renderSystem->notifyOnDeviceReset(this);
  352. // UnLock access to rendering device.
  353. D3D9RenderSystem::getResourceManager()->unlockDeviceAccess();
  354. return true;
  355. }
  356. //---------------------------------------------------------------------
  357. bool D3D9Device::isAutoDepthStencil() const
  358. {
  359. const D3DPRESENT_PARAMETERS& primaryPresentationParams = mPresentationParams[0];
  360. // Check if auto depth stencil can be used.
  361. for (unsigned int i = 1; i < mPresentationParamsCount; i++)
  362. {
  363. // disable AutoDepthStencil if these parameters are not all the same.
  364. if(primaryPresentationParams.BackBufferHeight != mPresentationParams[i].BackBufferHeight ||
  365. primaryPresentationParams.BackBufferWidth != mPresentationParams[i].BackBufferWidth ||
  366. primaryPresentationParams.BackBufferFormat != mPresentationParams[i].BackBufferFormat ||
  367. primaryPresentationParams.AutoDepthStencilFormat != mPresentationParams[i].AutoDepthStencilFormat ||
  368. primaryPresentationParams.MultiSampleQuality != mPresentationParams[i].MultiSampleQuality ||
  369. primaryPresentationParams.MultiSampleType != mPresentationParams[i].MultiSampleType)
  370. {
  371. return false;
  372. }
  373. }
  374. return true;
  375. }
  376. //---------------------------------------------------------------------
  377. const D3DCAPS9& D3D9Device::getD3D9DeviceCaps() const
  378. {
  379. if (mD3D9DeviceCapsValid == false)
  380. {
  381. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR,
  382. "Device caps are invalid!",
  383. "D3D9Device::getD3D9DeviceCaps" );
  384. }
  385. return mD3D9DeviceCaps;
  386. }
  387. //---------------------------------------------------------------------
  388. D3DFORMAT D3D9Device::getBackBufferFormat() const
  389. {
  390. if (mPresentationParams == NULL || mPresentationParamsCount == 0)
  391. {
  392. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR,
  393. "Presentation parameters are invalid!",
  394. "D3D9Device::getBackBufferFormat" );
  395. }
  396. return mPresentationParams[0].BackBufferFormat;
  397. }
  398. //---------------------------------------------------------------------
  399. IDirect3DDevice9* D3D9Device::getD3D9Device()
  400. {
  401. return mpDevice;
  402. }
  403. //---------------------------------------------------------------------
  404. void D3D9Device::updatePresentationParameters()
  405. {
  406. // Clear old presentation parameters.
  407. SAFE_DELETE_ARRAY(mPresentationParams);
  408. mPresentationParamsCount = 0;
  409. if (mMapRenderWindowToResoruces.size() > 0)
  410. {
  411. mPresentationParams = new D3DPRESENT_PARAMETERS[mMapRenderWindowToResoruces.size()];
  412. RenderWindowToResorucesIterator it = mMapRenderWindowToResoruces.begin();
  413. while (it != mMapRenderWindowToResoruces.end())
  414. {
  415. D3D9RenderWindow* renderWindow = it->first;
  416. RenderWindowResources* renderWindowResources = it->second;
  417. // Ask the render window to build it's own parameters.
  418. renderWindow->buildPresentParameters(&renderWindowResources->presentParameters);
  419. // Update shared focus window handle.
  420. if (renderWindow->isFullScreen() &&
  421. renderWindowResources->presentParametersIndex == 0 &&
  422. msSharedFocusWindow == NULL)
  423. setSharedWindowHandle(renderWindow->getWindowHandle());
  424. // This is the primary window or a full screen window that is part of multi head device.
  425. if (renderWindowResources->presentParametersIndex == 0 ||
  426. renderWindow->isFullScreen())
  427. {
  428. mPresentationParams[renderWindowResources->presentParametersIndex] = renderWindowResources->presentParameters;
  429. mPresentationParamsCount++;
  430. }
  431. ++it;
  432. }
  433. }
  434. // Case we have to cancel auto depth stencil.
  435. if (isMultihead() && isAutoDepthStencil() == false)
  436. {
  437. for(unsigned int i = 0; i < mPresentationParamsCount; i++)
  438. {
  439. mPresentationParams[i].EnableAutoDepthStencil = false;
  440. }
  441. }
  442. }
  443. //---------------------------------------------------------------------
  444. UINT D3D9Device::getAdapterNumber() const
  445. {
  446. return mAdapterNumber;
  447. }
  448. //---------------------------------------------------------------------
  449. D3DDEVTYPE D3D9Device::getDeviceType() const
  450. {
  451. return mDeviceType;
  452. }
  453. //---------------------------------------------------------------------
  454. bool D3D9Device::isMultihead() const
  455. {
  456. RenderWindowToResorucesMap::const_iterator it = mMapRenderWindowToResoruces.begin();
  457. while (it != mMapRenderWindowToResoruces.end())
  458. {
  459. RenderWindowResources* renderWindowResources = it->second;
  460. if (renderWindowResources->adapterOrdinalInGroupIndex > 0 &&
  461. it->first->isFullScreen())
  462. {
  463. return true;
  464. }
  465. ++it;
  466. }
  467. return false;
  468. }
  469. //---------------------------------------------------------------------
  470. void D3D9Device::clearDeviceStreams()
  471. {
  472. D3D9RenderSystem* renderSystem = static_cast<D3D9RenderSystem*>(CamelotEngine::RenderSystemManager::getActive());
  473. // Set all texture units to nothing to release texture surfaces
  474. for (DWORD stage = 0; stage < mD3D9DeviceCaps.MaxSimultaneousTextures; ++stage)
  475. {
  476. DWORD dwCurValue = D3DTOP_FORCE_DWORD;
  477. HRESULT hr;
  478. hr = mpDevice->SetTexture(stage, NULL);
  479. if( hr != S_OK )
  480. {
  481. String str = "Unable to disable texture '" + StringConverter::toString((unsigned int)stage) + "' in D3D9";
  482. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, str, "D3D9Device::clearDeviceStreams" );
  483. }
  484. mpDevice->GetTextureStageState(static_cast<DWORD>(stage), D3DTSS_COLOROP, &dwCurValue);
  485. if (dwCurValue != D3DTOP_DISABLE)
  486. {
  487. hr = mpDevice->SetTextureStageState(static_cast<DWORD>(stage), D3DTSS_COLOROP, D3DTOP_DISABLE);
  488. if( hr != S_OK )
  489. {
  490. String str = "Unable to disable texture '" + StringConverter::toString((unsigned)stage) + "' in D3D9";
  491. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, str, "D3D9Device::clearDeviceStreams" );
  492. }
  493. }
  494. // TODO PORT - Make sure to call this once rendersystem is active
  495. // set stage desc. to defaults
  496. //renderSystem->mTexStageDesc[stage].pTex = 0;
  497. //renderSystem->mTexStageDesc[stage].autoTexCoordType = TEXCALC_NONE;
  498. //renderSystem->mTexStageDesc[stage].coordIndex = 0;
  499. //renderSystem->mTexStageDesc[stage].texType = D3D9Mappings::D3D_TEX_TYPE_NORMAL;
  500. }
  501. // Unbind any vertex streams to avoid memory leaks
  502. for (unsigned int i = 0; i < mD3D9DeviceCaps.MaxStreams; ++i)
  503. {
  504. mpDevice->SetStreamSource(i, NULL, 0, 0);
  505. }
  506. }
  507. //---------------------------------------------------------------------
  508. void D3D9Device::createD3D9Device()
  509. {
  510. // Update focus window.
  511. D3D9RenderWindow* primaryRenderWindow = getPrimaryWindow();
  512. // Case we have to share the same focus window.
  513. if (msSharedFocusWindow != NULL)
  514. mFocusWindow = msSharedFocusWindow;
  515. else
  516. mFocusWindow = primaryRenderWindow->getWindowHandle();
  517. IDirect3D9* pD3D9 = D3D9RenderSystem::getDirect3D9();
  518. HRESULT hr;
  519. if (isMultihead())
  520. {
  521. mBehaviorFlags |= D3DCREATE_ADAPTERGROUP_DEVICE;
  522. }
  523. else
  524. {
  525. mBehaviorFlags &= ~D3DCREATE_ADAPTERGROUP_DEVICE;
  526. }
  527. // Try to create the device with hardware vertex processing.
  528. mBehaviorFlags |= D3DCREATE_HARDWARE_VERTEXPROCESSING;
  529. hr = pD3D9->CreateDevice(mAdapterNumber, mDeviceType, mFocusWindow,
  530. mBehaviorFlags, mPresentationParams, &mpDevice);
  531. if (FAILED(hr))
  532. {
  533. // Try a second time, may fail the first time due to back buffer count,
  534. // which will be corrected down to 1 by the runtime
  535. hr = pD3D9->CreateDevice(mAdapterNumber, mDeviceType, mFocusWindow,
  536. mBehaviorFlags, mPresentationParams, &mpDevice);
  537. }
  538. // Case hardware vertex processing failed.
  539. if( FAILED( hr ) )
  540. {
  541. // Try to create the device with mixed vertex processing.
  542. mBehaviorFlags &= ~D3DCREATE_HARDWARE_VERTEXPROCESSING;
  543. mBehaviorFlags |= D3DCREATE_MIXED_VERTEXPROCESSING;
  544. hr = pD3D9->CreateDevice(mAdapterNumber, mDeviceType, mFocusWindow,
  545. mBehaviorFlags, mPresentationParams, &mpDevice);
  546. }
  547. if( FAILED( hr ) )
  548. {
  549. // try to create the device with software vertex processing.
  550. mBehaviorFlags &= ~D3DCREATE_MIXED_VERTEXPROCESSING;
  551. mBehaviorFlags |= D3DCREATE_SOFTWARE_VERTEXPROCESSING;
  552. hr = pD3D9->CreateDevice(mAdapterNumber, mDeviceType, mFocusWindow,
  553. mBehaviorFlags, mPresentationParams, &mpDevice);
  554. }
  555. if ( FAILED( hr ) )
  556. {
  557. // try reference device
  558. mDeviceType = D3DDEVTYPE_REF;
  559. hr = pD3D9->CreateDevice(mAdapterNumber, mDeviceType, mFocusWindow,
  560. mBehaviorFlags, mPresentationParams, &mpDevice);
  561. if ( FAILED( hr ) )
  562. {
  563. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR,
  564. "Cannot create device!",
  565. "D3D9Device::createD3D9Device" );
  566. }
  567. }
  568. // Get current device caps.
  569. hr = mpDevice->GetDeviceCaps(&mD3D9DeviceCaps);
  570. if( FAILED( hr ) )
  571. {
  572. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR,
  573. "Cannot get device caps!",
  574. "D3D9Device::createD3D9Device" );
  575. }
  576. // Get current creation parameters caps.
  577. hr = mpDevice->GetCreationParameters(&mCreationParams);
  578. if ( FAILED(hr) )
  579. {
  580. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR,
  581. "Error Get Creation Parameters",
  582. "D3D9Device:createD3D9Device" );
  583. }
  584. mD3D9DeviceCapsValid = true;
  585. // Initialize device states.
  586. setupDeviceStates();
  587. // Lock access to rendering device.
  588. D3D9RenderSystem::getResourceManager()->lockDeviceAccess();
  589. D3D9Device* pCurActiveDevice = mpDeviceManager->getActiveDevice();
  590. mpDeviceManager->setActiveDevice(this);
  591. // Inform all resources that new device created.
  592. D3D9RenderSystem::getResourceManager()->notifyOnDeviceCreate(mpDevice);
  593. mpDeviceManager->setActiveDevice(pCurActiveDevice);
  594. // UnLock access to rendering device.
  595. D3D9RenderSystem::getResourceManager()->unlockDeviceAccess();
  596. }
  597. //---------------------------------------------------------------------
  598. void D3D9Device::releaseD3D9Device()
  599. {
  600. if (mpDevice != NULL)
  601. {
  602. // Lock access to rendering device.
  603. D3D9RenderSystem::getResourceManager()->lockDeviceAccess();
  604. D3D9Device* pCurActiveDevice = mpDeviceManager->getActiveDevice();
  605. mpDeviceManager->setActiveDevice(this);
  606. // Inform all resources that device is going to be destroyed.
  607. D3D9RenderSystem::getResourceManager()->notifyOnDeviceDestroy(mpDevice);
  608. mpDeviceManager->setActiveDevice(pCurActiveDevice);
  609. clearDeviceStreams();
  610. // Release device.
  611. SAFE_RELEASE(mpDevice);
  612. // UnLock access to rendering device.
  613. D3D9RenderSystem::getResourceManager()->unlockDeviceAccess();
  614. }
  615. }
  616. //---------------------------------------------------------------------
  617. void D3D9Device::releaseRenderWindowResources(RenderWindowResources* renderWindowResources)
  618. {
  619. SAFE_RELEASE(renderWindowResources->backBuffer);
  620. SAFE_RELEASE(renderWindowResources->depthBuffer);
  621. SAFE_RELEASE(renderWindowResources->swapChain);
  622. renderWindowResources->acquired = false;
  623. }
  624. //---------------------------------------------------------------------
  625. void D3D9Device::invalidate(D3D9RenderWindow* renderWindow)
  626. {
  627. RenderWindowToResorucesIterator it = getRenderWindowIterator(renderWindow);
  628. it->second->acquired = false;
  629. }
  630. //---------------------------------------------------------------------
  631. bool D3D9Device::validate(D3D9RenderWindow* renderWindow)
  632. {
  633. // Validate that the render window should run on this device.
  634. if (false == validateDisplayMonitor(renderWindow))
  635. return false;
  636. // Validate that this device created on the correct target focus window handle
  637. validateFocusWindow();
  638. // Validate that the render window dimensions matches to back buffer dimensions.
  639. validateBackBufferSize(renderWindow);
  640. // Validate that this device is in valid rendering state.
  641. if (false == validateDeviceState(renderWindow))
  642. return false;
  643. return true;
  644. }
  645. //---------------------------------------------------------------------
  646. void D3D9Device::validateFocusWindow()
  647. {
  648. // Focus window changed -> device should be re-acquired.
  649. if ((msSharedFocusWindow != NULL && mCreationParams.hFocusWindow != msSharedFocusWindow) ||
  650. (msSharedFocusWindow == NULL && mCreationParams.hFocusWindow != getPrimaryWindow()->getWindowHandle()))
  651. {
  652. // Lock access to rendering device.
  653. D3D9RenderSystem::getResourceManager()->lockDeviceAccess();
  654. release();
  655. acquire();
  656. // UnLock access to rendering device.
  657. D3D9RenderSystem::getResourceManager()->unlockDeviceAccess();
  658. }
  659. }
  660. //---------------------------------------------------------------------
  661. bool D3D9Device::validateDeviceState(D3D9RenderWindow* renderWindow)
  662. {
  663. RenderWindowToResorucesIterator it = getRenderWindowIterator(renderWindow);
  664. RenderWindowResources* renderWindowResources = it->second;
  665. HRESULT hr;
  666. hr = mpDevice->TestCooperativeLevel();
  667. // Case device is not valid for rendering.
  668. if (FAILED(hr))
  669. {
  670. // device lost, and we can't reset
  671. // can't do anything about it here, wait until we get
  672. // D3DERR_DEVICENOTRESET; rendering calls will silently fail until
  673. // then (except Present, but we ignore device lost there too)
  674. if (hr == D3DERR_DEVICELOST)
  675. {
  676. releaseRenderWindowResources(renderWindowResources);
  677. notifyDeviceLost();
  678. return false;
  679. }
  680. // device lost, and we can reset
  681. else if (hr == D3DERR_DEVICENOTRESET)
  682. {
  683. bool deviceRestored = reset();
  684. // Device was not restored yet.
  685. if (deviceRestored == false)
  686. {
  687. // Wait a while
  688. Sleep(50);
  689. return false;
  690. }
  691. }
  692. }
  693. // Render window resources explicitly invalidated. (Resize or window mode switch)
  694. if (renderWindowResources->acquired == false)
  695. {
  696. if (getPrimaryWindow() == renderWindow)
  697. {
  698. bool deviceRestored = reset();
  699. // Device was not restored yet.
  700. if (deviceRestored == false)
  701. {
  702. // Wait a while
  703. Sleep(50);
  704. return false;
  705. }
  706. }
  707. else
  708. {
  709. acquire(renderWindow);
  710. }
  711. }
  712. return true;
  713. }
  714. //---------------------------------------------------------------------
  715. void D3D9Device::validateBackBufferSize(D3D9RenderWindow* renderWindow)
  716. {
  717. RenderWindowToResorucesIterator it = getRenderWindowIterator(renderWindow);
  718. RenderWindowResources* renderWindowResources = it->second;
  719. // Case size has been changed.
  720. if (renderWindow->getWidth() != renderWindowResources->presentParameters.BackBufferWidth ||
  721. renderWindow->getHeight() != renderWindowResources->presentParameters.BackBufferHeight)
  722. {
  723. if (renderWindow->getWidth() > 0)
  724. renderWindowResources->presentParameters.BackBufferWidth = renderWindow->getWidth();
  725. if (renderWindow->getHeight() > 0)
  726. renderWindowResources->presentParameters.BackBufferHeight = renderWindow->getHeight();
  727. invalidate(renderWindow);
  728. }
  729. }
  730. //---------------------------------------------------------------------
  731. bool D3D9Device::validateDisplayMonitor(D3D9RenderWindow* renderWindow)
  732. {
  733. // Ignore full screen since it doesn't really move and it is possible
  734. // that it created using multi-head adapter so for a subordinate the
  735. // native monitor handle and this device handle will be different.
  736. if (renderWindow->isFullScreen())
  737. return true;
  738. RenderWindowToResorucesIterator it = getRenderWindowIterator(renderWindow);
  739. HMONITOR hRenderWindowMonitor = NULL;
  740. // Find the monitor this render window belongs to.
  741. hRenderWindowMonitor = MonitorFromWindow(renderWindow->getWindowHandle(), MONITOR_DEFAULTTONULL);
  742. // This window doesn't intersect with any of the display monitor
  743. if (hRenderWindowMonitor == NULL)
  744. return false;
  745. // Case this window changed monitor.
  746. if (hRenderWindowMonitor != mMonitor)
  747. {
  748. // Lock access to rendering device.
  749. D3D9RenderSystem::getResourceManager()->lockDeviceAccess();
  750. mpDeviceManager->linkRenderWindow(renderWindow);
  751. // UnLock access to rendering device.
  752. D3D9RenderSystem::getResourceManager()->unlockDeviceAccess();
  753. return false;
  754. }
  755. return true;
  756. }
  757. //---------------------------------------------------------------------
  758. void D3D9Device::present(D3D9RenderWindow* renderWindow)
  759. {
  760. RenderWindowToResorucesIterator it = getRenderWindowIterator(renderWindow);
  761. RenderWindowResources* renderWindowResources = it->second;
  762. // Skip present while current device state is invalid.
  763. if (mDeviceLost ||
  764. renderWindowResources->acquired == false ||
  765. isDeviceLost())
  766. return;
  767. HRESULT hr;
  768. if (isMultihead())
  769. {
  770. // Only the master will call present method results in synchronized
  771. // buffer swap for the rest of the implicit swap chain.
  772. if (getPrimaryWindow() == renderWindow)
  773. hr = mpDevice->Present( NULL, NULL, NULL, NULL );
  774. else
  775. hr = S_OK;
  776. }
  777. else
  778. {
  779. hr = renderWindowResources->swapChain->Present(NULL, NULL, NULL, NULL, 0);
  780. }
  781. if( D3DERR_DEVICELOST == hr)
  782. {
  783. releaseRenderWindowResources(renderWindowResources);
  784. notifyDeviceLost();
  785. }
  786. else if( FAILED(hr) )
  787. {
  788. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR,
  789. "Error Presenting surfaces",
  790. "D3D9Device::present" );
  791. }
  792. else
  793. {
  794. // TODO PORT - What is this used for? In any case I don't have Root so just set it to 0
  795. //mLastPresentFrame = Root::getSingleton().getNextFrameNumber();
  796. mLastPresentFrame = 0;
  797. }
  798. }
  799. //---------------------------------------------------------------------
  800. void D3D9Device::acquireRenderWindowResources(RenderWindowToResorucesIterator it)
  801. {
  802. RenderWindowResources* renderWindowResources = it->second;
  803. D3D9RenderWindow* renderWindow = it->first;
  804. releaseRenderWindowResources(renderWindowResources);
  805. // Create additional swap chain
  806. if (isSwapChainWindow(renderWindow) && !isMultihead())
  807. {
  808. // Create swap chain
  809. HRESULT hr = mpDevice->CreateAdditionalSwapChain(&renderWindowResources->presentParameters,
  810. &renderWindowResources->swapChain);
  811. if (FAILED(hr))
  812. {
  813. // Try a second time, may fail the first time due to back buffer count,
  814. // which will be corrected by the runtime
  815. hr = mpDevice->CreateAdditionalSwapChain(&renderWindowResources->presentParameters,
  816. &renderWindowResources->swapChain);
  817. }
  818. if (FAILED(hr))
  819. {
  820. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR,
  821. "Unable to create an additional swap chain",
  822. "D3D9RenderWindow::acquireRenderWindowResources");
  823. }
  824. }
  825. else
  826. {
  827. // The swap chain is already created by the device
  828. HRESULT hr = mpDevice->GetSwapChain(renderWindowResources->presentParametersIndex,
  829. &renderWindowResources->swapChain);
  830. if (FAILED(hr))
  831. {
  832. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR,
  833. "Unable to get the swap chain",
  834. "D3D9RenderWindow::acquireRenderWindowResources");
  835. }
  836. }
  837. // Store references to buffers for convenience
  838. renderWindowResources->swapChain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO,
  839. &renderWindowResources->backBuffer);
  840. // Additional swap chains need their own depth buffer
  841. // to support resizing them
  842. if (renderWindow->isDepthBuffered())
  843. {
  844. // if multihead is enabled, depth buffer can be created automatically for
  845. // all the adapters. if multihead is not enabled, depth buffer is just
  846. // created for the main swap chain
  847. if (isMultihead() && isAutoDepthStencil() ||
  848. isMultihead() == false && isSwapChainWindow(renderWindow) == false)
  849. {
  850. mpDevice->GetDepthStencilSurface(&renderWindowResources->depthBuffer);
  851. }
  852. else
  853. {
  854. uint targetWidth = renderWindow->getWidth();
  855. uint targetHeight = renderWindow->getHeight();
  856. if (targetWidth == 0)
  857. targetWidth = 1;
  858. if (targetHeight == 0)
  859. targetHeight = 1;
  860. HRESULT hr = mpDevice->CreateDepthStencilSurface(
  861. targetWidth, targetHeight,
  862. renderWindowResources->presentParameters.AutoDepthStencilFormat,
  863. renderWindowResources->presentParameters.MultiSampleType,
  864. renderWindowResources->presentParameters.MultiSampleQuality,
  865. (renderWindowResources->presentParameters.Flags & D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL),
  866. &renderWindowResources->depthBuffer, NULL
  867. );
  868. if (FAILED(hr))
  869. {
  870. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR,
  871. "Unable to create a depth buffer for the swap chain",
  872. "D3D9RenderWindow::acquireRenderWindowResources");
  873. }
  874. if (isSwapChainWindow(renderWindow) == false)
  875. {
  876. mpDevice->SetDepthStencilSurface(renderWindowResources->depthBuffer);
  877. }
  878. }
  879. }
  880. renderWindowResources->acquired = true;
  881. }
  882. //---------------------------------------------------------------------
  883. void D3D9Device::setupDeviceStates()
  884. {
  885. HRESULT hr = mpDevice->SetRenderState(D3DRS_SPECULARENABLE, TRUE);
  886. if (FAILED(hr))
  887. {
  888. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR,
  889. "Unable to apply render state: D3DRS_SPECULARENABLE <- TRUE",
  890. "D3D9Device::setupDeviceStates");
  891. }
  892. }
  893. //---------------------------------------------------------------------
  894. bool D3D9Device::isSwapChainWindow(D3D9RenderWindow* renderWindow)
  895. {
  896. RenderWindowToResorucesIterator it = getRenderWindowIterator(renderWindow);
  897. if (it->second->presentParametersIndex == 0 || renderWindow->isFullScreen())
  898. return false;
  899. return true;
  900. }
  901. //---------------------------------------------------------------------
  902. D3D9RenderWindow* D3D9Device::getPrimaryWindow()
  903. {
  904. RenderWindowToResorucesIterator it = mMapRenderWindowToResoruces.begin();
  905. while (it != mMapRenderWindowToResoruces.end() && it->second->presentParametersIndex != 0)
  906. ++it;
  907. assert(it != mMapRenderWindowToResoruces.end());
  908. return it->first;
  909. }
  910. //---------------------------------------------------------------------
  911. void D3D9Device::setSharedWindowHandle(HWND hSharedHWND)
  912. {
  913. if (hSharedHWND != msSharedFocusWindow)
  914. msSharedFocusWindow = hSharedHWND;
  915. }
  916. //---------------------------------------------------------------------
  917. void D3D9Device::updateRenderWindowsIndices()
  918. {
  919. // Update present parameters index attribute per render window.
  920. if (isMultihead())
  921. {
  922. RenderWindowToResorucesIterator it = mMapRenderWindowToResoruces.begin();
  923. // Multi head device case -
  924. // Present parameter index is based on adapter ordinal in group index.
  925. while (it != mMapRenderWindowToResoruces.end())
  926. {
  927. it->second->presentParametersIndex = it->second->adapterOrdinalInGroupIndex;
  928. ++it;
  929. }
  930. }
  931. else
  932. {
  933. // Single head device case -
  934. // Just assign index in incremental order -
  935. // NOTE: It suppose to cover both cases that possible here:
  936. // 1. Single full screen window - only one allowed per device (this is not multi-head case).
  937. // 2. Multiple window mode windows.
  938. uint nextPresParamIndex = 0;
  939. RenderWindowToResorucesIterator it;
  940. D3D9RenderWindow* deviceFocusWindow = NULL;
  941. // In case a d3d9 device exists - try to keep the present parameters order
  942. // so that the window that the device is focused on will stay the same and we
  943. // will avoid device re-creation.
  944. if (mpDevice != NULL)
  945. {
  946. it = mMapRenderWindowToResoruces.begin();
  947. while (it != mMapRenderWindowToResoruces.end())
  948. {
  949. if (it->first->getWindowHandle() == mCreationParams.hFocusWindow)
  950. {
  951. deviceFocusWindow = it->first;
  952. it->second->presentParametersIndex = nextPresParamIndex;
  953. ++nextPresParamIndex;
  954. break;
  955. }
  956. ++it;
  957. }
  958. }
  959. it = mMapRenderWindowToResoruces.begin();
  960. while (it != mMapRenderWindowToResoruces.end())
  961. {
  962. if (it->first != deviceFocusWindow)
  963. {
  964. it->second->presentParametersIndex = nextPresParamIndex;
  965. ++nextPresParamIndex;
  966. }
  967. ++it;
  968. }
  969. }
  970. }
  971. //---------------------------------------------------------------------
  972. void D3D9Device::copyContentsToMemory(D3D9RenderWindow* renderWindow,
  973. const PixelBox &dst, RenderTarget::FrameBuffer buffer)
  974. {
  975. RenderWindowToResorucesIterator it = getRenderWindowIterator(renderWindow);
  976. RenderWindowResources* resources = it->second;
  977. bool swapChain = isSwapChainWindow(renderWindow);
  978. if ((dst.left < 0) || (dst.right > renderWindow->getWidth()) ||
  979. (dst.top < 0) || (dst.bottom > renderWindow->getHeight()) ||
  980. (dst.front != 0) || (dst.back != 1))
  981. {
  982. OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS,
  983. "Invalid box.",
  984. "D3D9Device::copyContentsToMemory" );
  985. }
  986. HRESULT hr;
  987. IDirect3DSurface9* pSurf = NULL;
  988. IDirect3DSurface9* pTempSurf = NULL;
  989. D3DSURFACE_DESC desc;
  990. D3DLOCKED_RECT lockedRect;
  991. if (buffer == RenderTarget::FB_AUTO)
  992. {
  993. //buffer = mIsFullScreen? FB_FRONT : FB_BACK;
  994. buffer = RenderTarget::FB_FRONT;
  995. }
  996. if (buffer == RenderTarget::FB_FRONT)
  997. {
  998. D3DDISPLAYMODE dm;
  999. if (FAILED(hr = mpDevice->GetDisplayMode(0, &dm)))
  1000. {
  1001. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR,
  1002. "Can't get display mode: TODO PORT NO ERROR", // TODO PORT - Translate HR to error
  1003. "D3D9Device::copyContentsToMemory");
  1004. }
  1005. desc.Width = dm.Width;
  1006. desc.Height = dm.Height;
  1007. desc.Format = D3DFMT_A8R8G8B8;
  1008. if (FAILED(hr = mpDevice->CreateOffscreenPlainSurface(desc.Width, desc.Height,
  1009. desc.Format,
  1010. D3DPOOL_SYSTEMMEM,
  1011. &pTempSurf,
  1012. 0)))
  1013. {
  1014. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR,
  1015. "Can't create offscreen buffer: TODO PORT NO ERROR", // TODO PORT - Translate HR to error
  1016. "D3D9Device::copyContentsToMemory");
  1017. }
  1018. if (FAILED(hr = swapChain ? resources->swapChain->GetFrontBufferData(pTempSurf) :
  1019. mpDevice->GetFrontBufferData(0, pTempSurf)))
  1020. {
  1021. SAFE_RELEASE(pTempSurf);
  1022. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR,
  1023. "Can't get front buffer: TODO PORT NO ERROR", // TODO PORT - Translate HR to error
  1024. "D3D9Device::copyContentsToMemory");
  1025. }
  1026. if(renderWindow->isFullScreen())
  1027. {
  1028. if ((dst.left == 0) && (dst.right == renderWindow->getWidth()) && (dst.top == 0) && (dst.bottom == renderWindow->getHeight()))
  1029. {
  1030. hr = pTempSurf->LockRect(&lockedRect, 0, D3DLOCK_READONLY | D3DLOCK_NOSYSLOCK);
  1031. }
  1032. else
  1033. {
  1034. RECT rect;
  1035. rect.left = static_cast<LONG>(dst.left);
  1036. rect.right = static_cast<LONG>(dst.right);
  1037. rect.top = static_cast<LONG>(dst.top);
  1038. rect.bottom = static_cast<LONG>(dst.bottom);
  1039. hr = pTempSurf->LockRect(&lockedRect, &rect, D3DLOCK_READONLY | D3DLOCK_NOSYSLOCK);
  1040. }
  1041. if (FAILED(hr))
  1042. {
  1043. SAFE_RELEASE(pTempSurf);
  1044. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR,
  1045. "Can't lock rect: TODO PORT NO ERROR", // TODO PORT - Translate HR to error
  1046. "D3D9Device::copyContentsToMemory");
  1047. }
  1048. }
  1049. else
  1050. {
  1051. RECT srcRect;
  1052. //GetClientRect(mHWnd, &srcRect);
  1053. srcRect.left = static_cast<LONG>(dst.left);
  1054. srcRect.top = static_cast<LONG>(dst.top);
  1055. srcRect.right = static_cast<LONG>(dst.right);
  1056. srcRect.bottom = static_cast<LONG>(dst.bottom);
  1057. POINT point;
  1058. point.x = srcRect.left;
  1059. point.y = srcRect.top;
  1060. ClientToScreen(renderWindow->getWindowHandle(), &point);
  1061. srcRect.top = point.y;
  1062. srcRect.left = point.x;
  1063. srcRect.bottom += point.y;
  1064. srcRect.right += point.x;
  1065. desc.Width = srcRect.right - srcRect.left;
  1066. desc.Height = srcRect.bottom - srcRect.top;
  1067. if (FAILED(hr = pTempSurf->LockRect(&lockedRect, &srcRect, D3DLOCK_READONLY | D3DLOCK_NOSYSLOCK)))
  1068. {
  1069. SAFE_RELEASE(pTempSurf);
  1070. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR,
  1071. "Can't lock rect: TODO PORT NO ERROR", // TODO PORT - Translate HR to error
  1072. "D3D9Device::copyContentsToMemory");
  1073. }
  1074. }
  1075. }
  1076. else
  1077. {
  1078. SAFE_RELEASE(pSurf);
  1079. if(FAILED(hr = swapChain? resources->swapChain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &pSurf) :
  1080. mpDevice->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &pSurf)))
  1081. {
  1082. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR,
  1083. "Can't get back buffer: TODO PORT NO ERROR", // TODO PORT - Translate HR to error
  1084. "D3D9Device::copyContentsToMemory");
  1085. }
  1086. if(FAILED(hr = pSurf->GetDesc(&desc)))
  1087. {
  1088. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR,
  1089. "Can't get description: TODO PORT NO ERROR", // TODO PORT - Translate HR to error
  1090. "D3D9Device::copyContentsToMemory");
  1091. }
  1092. if (FAILED(hr = mpDevice->CreateOffscreenPlainSurface(desc.Width, desc.Height,
  1093. desc.Format,
  1094. D3DPOOL_SYSTEMMEM,
  1095. &pTempSurf,
  1096. 0)))
  1097. {
  1098. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR,
  1099. "Can't create offscreen surface: TODO PORT NO ERROR", // TODO PORT - Translate HR to error
  1100. "D3D9Device::copyContentsToMemory");
  1101. }
  1102. if (desc.MultiSampleType == D3DMULTISAMPLE_NONE)
  1103. {
  1104. if (FAILED(hr = mpDevice->GetRenderTargetData(pSurf, pTempSurf)))
  1105. {
  1106. SAFE_RELEASE(pTempSurf);
  1107. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR,
  1108. "Can't get render target data: TODO PORT NO ERROR", // TODO PORT - Translate HR to error
  1109. "D3D9Device::copyContentsToMemory");
  1110. }
  1111. }
  1112. else
  1113. {
  1114. IDirect3DSurface9* pStretchSurf = 0;
  1115. if (FAILED(hr = mpDevice->CreateRenderTarget(desc.Width, desc.Height,
  1116. desc.Format,
  1117. D3DMULTISAMPLE_NONE,
  1118. 0,
  1119. false,
  1120. &pStretchSurf,
  1121. 0)))
  1122. {
  1123. SAFE_RELEASE(pTempSurf);
  1124. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR,
  1125. "Can't create render target: TODO PORT NO ERROR", // TODO PORT - Translate HR to error
  1126. "D3D9Device::copyContentsToMemory");
  1127. }
  1128. if (FAILED(hr = mpDevice->StretchRect(pSurf, 0, pStretchSurf, 0, D3DTEXF_NONE)))
  1129. {
  1130. SAFE_RELEASE(pTempSurf);
  1131. SAFE_RELEASE(pStretchSurf);
  1132. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR,
  1133. "Can't stretch rect: TODO PORT NO ERROR", // TODO PORT - Translate HR to error
  1134. "D3D9Device::copyContentsToMemory");
  1135. }
  1136. if (FAILED(hr = mpDevice->GetRenderTargetData(pStretchSurf, pTempSurf)))
  1137. {
  1138. SAFE_RELEASE(pTempSurf);
  1139. SAFE_RELEASE(pStretchSurf);
  1140. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR,
  1141. "Can't get render target data: TODO PORT NO ERROR", // TODO PORT - Translate HR to error
  1142. "D3D9Device::copyContentsToMemory");
  1143. }
  1144. SAFE_RELEASE(pStretchSurf);
  1145. }
  1146. if ((dst.left == 0) && (dst.right == renderWindow->getWidth()) && (dst.top == 0) && (dst.bottom == renderWindow->getHeight()))
  1147. {
  1148. hr = pTempSurf->LockRect(&lockedRect, 0, D3DLOCK_READONLY | D3DLOCK_NOSYSLOCK);
  1149. }
  1150. else
  1151. {
  1152. RECT rect;
  1153. rect.left = static_cast<LONG>(dst.left);
  1154. rect.right = static_cast<LONG>(dst.right);
  1155. rect.top = static_cast<LONG>(dst.top);
  1156. rect.bottom = static_cast<LONG>(dst.bottom);
  1157. hr = pTempSurf->LockRect(&lockedRect, &rect, D3DLOCK_READONLY | D3DLOCK_NOSYSLOCK);
  1158. }
  1159. if (FAILED(hr))
  1160. {
  1161. SAFE_RELEASE(pTempSurf);
  1162. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR,
  1163. "Can't lock rect: TODO PORT NO ERROR", // TODO PORT - Translate HR to error
  1164. "D3D9Device::copyContentsToMemory");
  1165. }
  1166. }
  1167. PixelFormat format = Ogre::D3D9Mappings::_getPF(desc.Format);
  1168. if (format == PF_UNKNOWN)
  1169. {
  1170. SAFE_RELEASE(pTempSurf);
  1171. OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR,
  1172. "Unsupported format", "D3D9Device::copyContentsToMemory");
  1173. }
  1174. PixelBox src(dst.getWidth(), dst.getHeight(), 1, format, lockedRect.pBits);
  1175. src.rowPitch = lockedRect.Pitch / PixelUtil::getNumElemBytes(format);
  1176. src.slicePitch = desc.Height * src.rowPitch;
  1177. PixelUtil::bulkPixelConversion(src, dst);
  1178. SAFE_RELEASE(pTempSurf);
  1179. SAFE_RELEASE(pSurf);
  1180. }
  1181. }