BsD3D11RenderWindow.cpp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797
  1. //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
  2. //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
  3. #include "BsD3D11RenderWindow.h"
  4. #include "CoreThread/BsCoreThread.h"
  5. #include "Private/Win32/BsWin32Platform.h"
  6. #include "BsD3D11RenderAPI.h"
  7. #include "BsD3D11Device.h"
  8. #include "BsD3D11RenderTexture.h"
  9. #include "BsD3D11TextureView.h"
  10. #include "Managers/BsTextureManager.h"
  11. #include "BsD3D11DriverList.h"
  12. #include "BsD3D11Driver.h"
  13. #include "BsD3D11VideoModeInfo.h"
  14. #include "Profiling/BsRenderStats.h"
  15. #include "Input/BsInput.h"
  16. #include "Error/BsException.h"
  17. #include "Managers/BsRenderWindowManager.h"
  18. #include "Math/BsMath.h"
  19. #include "Private/Win32/BsWin32Window.h"
  20. namespace bs
  21. {
  22. D3D11RenderWindow::D3D11RenderWindow(const RENDER_WINDOW_DESC& desc, UINT32 windowId, ct::D3D11Device& device,
  23. IDXGIFactory* DXGIFactory)
  24. :RenderWindow(desc, windowId), mProperties(desc), mDevice(device), mDXGIFactory(DXGIFactory)
  25. {
  26. }
  27. void D3D11RenderWindow::getCustomAttribute(const String& name, void* pData) const
  28. {
  29. if (name == "WINDOW")
  30. {
  31. UINT64 *pHwnd = (UINT64*)pData;
  32. *pHwnd = (UINT64)getHWnd();
  33. return;
  34. }
  35. }
  36. Vector2I D3D11RenderWindow::screenToWindowPos(const Vector2I& screenPos) const
  37. {
  38. POINT pos;
  39. pos.x = screenPos.x;
  40. pos.y = screenPos.y;
  41. ScreenToClient(getHWnd(), &pos);
  42. return Vector2I(pos.x, pos.y);
  43. }
  44. Vector2I D3D11RenderWindow::windowToScreenPos(const Vector2I& windowPos) const
  45. {
  46. POINT pos;
  47. pos.x = windowPos.x;
  48. pos.y = windowPos.y;
  49. ClientToScreen(getHWnd(), &pos);
  50. return Vector2I(pos.x, pos.y);
  51. }
  52. SPtr<ct::D3D11RenderWindow> D3D11RenderWindow::getCore() const
  53. {
  54. return std::static_pointer_cast<ct::D3D11RenderWindow>(mCoreSpecific);
  55. }
  56. HWND D3D11RenderWindow::getHWnd() const
  57. {
  58. blockUntilCoreInitialized();
  59. return getCore()->_getWindowHandle();
  60. }
  61. void D3D11RenderWindow::syncProperties()
  62. {
  63. ScopedSpinLock lock(getCore()->mLock);
  64. mProperties = getCore()->mSyncedProperties;
  65. }
  66. namespace ct
  67. {
  68. D3D11RenderWindow::D3D11RenderWindow(const RENDER_WINDOW_DESC& desc, UINT32 windowId, D3D11Device& device, IDXGIFactory* DXGIFactory)
  69. : RenderWindow(desc, windowId), mProperties(desc), mSyncedProperties(desc), mDevice(device), mDXGIFactory(DXGIFactory),
  70. mSizing(false), mRenderTargetView(nullptr), mBackBuffer(nullptr), mSwapChain(nullptr), mDepthStencilView(nullptr), mIsChild(false),
  71. mRefreshRateNumerator(0), mRefreshRateDenominator(0), mShowOnSwap(false), mWindow(nullptr)
  72. { }
  73. D3D11RenderWindow::~D3D11RenderWindow()
  74. {
  75. RenderWindowProperties& props = mProperties;
  76. if (props.isFullScreen)
  77. mSwapChain->SetFullscreenState(false, nullptr);
  78. SAFE_RELEASE(mSwapChain);
  79. BS_INC_RENDER_STAT_CAT(ResDestroyed, RenderStatObject_SwapChain);
  80. if (mWindow != nullptr)
  81. {
  82. bs_delete(mWindow);
  83. mWindow = nullptr;
  84. }
  85. destroySizeDependedD3DResources();
  86. Platform::resetNonClientAreas(*this);
  87. }
  88. void D3D11RenderWindow::initialize()
  89. {
  90. ZeroMemory(&mSwapChainDesc, sizeof(DXGI_SWAP_CHAIN_DESC));
  91. RenderWindowProperties& props = mProperties;
  92. mMultisampleType.Count = 1;
  93. mMultisampleType.Quality = 0;
  94. WINDOW_DESC windowDesc;
  95. windowDesc.showTitleBar = mDesc.showTitleBar;
  96. windowDesc.showBorder = mDesc.showBorder;
  97. windowDesc.allowResize = mDesc.allowResize;
  98. windowDesc.enableDoubleClick = true;
  99. windowDesc.fullscreen = mDesc.fullscreen;
  100. windowDesc.width = mDesc.videoMode.getWidth();
  101. windowDesc.height = mDesc.videoMode.getHeight();
  102. windowDesc.hidden = mDesc.hidden || mDesc.hideUntilSwap;
  103. windowDesc.left = mDesc.left;
  104. windowDesc.top = mDesc.top;
  105. windowDesc.outerDimensions = false;
  106. windowDesc.title = mDesc.title;
  107. windowDesc.toolWindow = mDesc.toolWindow;
  108. windowDesc.creationParams = this;
  109. windowDesc.modal = mDesc.modal;
  110. windowDesc.wndProc = &Win32Platform::_win32WndProc;
  111. #ifdef BS_STATIC_LIB
  112. windowDesc.module = GetModuleHandle(NULL);
  113. #else
  114. windowDesc.module = GetModuleHandle("BansheeD3D11RenderAPI.dll");
  115. #endif
  116. NameValuePairList::const_iterator opt;
  117. opt = mDesc.platformSpecific.find("parentWindowHandle");
  118. if (opt != mDesc.platformSpecific.end())
  119. windowDesc.parent = (HWND)parseUINT64(opt->second);
  120. opt = mDesc.platformSpecific.find("externalWindowHandle");
  121. if (opt != mDesc.platformSpecific.end())
  122. windowDesc.external = (HWND)parseUINT64(opt->second);
  123. mIsChild = windowDesc.parent != nullptr;
  124. props.isFullScreen = mDesc.fullscreen && !mIsChild;
  125. if (mDesc.videoMode.isCustom())
  126. {
  127. mRefreshRateNumerator = Math::roundToInt(mDesc.videoMode.getRefreshRate());
  128. mRefreshRateDenominator = 1;
  129. }
  130. else
  131. {
  132. const D3D11VideoMode& d3d11videoMode = static_cast<const D3D11VideoMode&>(mDesc.videoMode);
  133. mRefreshRateNumerator = d3d11videoMode.getRefreshRateNumerator();
  134. mRefreshRateDenominator = d3d11videoMode.getRefreshRateDenominator();
  135. }
  136. const D3D11VideoOutputInfo* outputInfo = nullptr;
  137. const D3D11VideoModeInfo& videoModeInfo = static_cast<const D3D11VideoModeInfo&>(RenderAPI::instance().getVideoModeInfo());
  138. UINT32 numOutputs = videoModeInfo.getNumOutputs();
  139. if (numOutputs > 0)
  140. {
  141. UINT32 actualMonitorIdx = std::min(mDesc.videoMode.getOutputIdx(), numOutputs - 1);
  142. outputInfo = static_cast<const D3D11VideoOutputInfo*>(&videoModeInfo.getOutputInfo(actualMonitorIdx));
  143. DXGI_OUTPUT_DESC desc;
  144. outputInfo->getDXGIOutput()->GetDesc(&desc);
  145. windowDesc.monitor = desc.Monitor;
  146. }
  147. if (!windowDesc.external)
  148. {
  149. mShowOnSwap = mDesc.hideUntilSwap;
  150. props.isHidden = mDesc.hideUntilSwap || mDesc.hidden;
  151. }
  152. mWindow = bs_new<Win32Window>(windowDesc);
  153. props.width = mWindow->getWidth();
  154. props.height = mWindow->getHeight();
  155. props.top = mWindow->getTop();
  156. props.left = mWindow->getLeft();
  157. createSwapChain();
  158. if (props.isFullScreen)
  159. {
  160. if (outputInfo != nullptr)
  161. mSwapChain->SetFullscreenState(true, outputInfo->getDXGIOutput());
  162. else
  163. mSwapChain->SetFullscreenState(true, nullptr);
  164. }
  165. createSizeDependedD3DResources();
  166. mDXGIFactory->MakeWindowAssociation(mWindow->getHWnd(), NULL);
  167. {
  168. ScopedSpinLock lock(mLock);
  169. mSyncedProperties = props;
  170. }
  171. bs::RenderWindowManager::instance().notifySyncDataDirty(this);
  172. RenderWindow::initialize();
  173. }
  174. void D3D11RenderWindow::swapBuffers(UINT32 syncMask)
  175. {
  176. THROW_IF_NOT_CORE_THREAD;
  177. if (mShowOnSwap)
  178. setHidden(false);
  179. if(mDevice.getD3D11Device() != nullptr)
  180. {
  181. HRESULT hr = mSwapChain->Present(getProperties().vsync ? getProperties().vsyncInterval : 0, 0);
  182. if( FAILED(hr) )
  183. BS_EXCEPT(RenderingAPIException, "Error Presenting surfaces");
  184. }
  185. }
  186. void D3D11RenderWindow::move(INT32 left, INT32 top)
  187. {
  188. THROW_IF_NOT_CORE_THREAD;
  189. RenderWindowProperties& props = mProperties;
  190. if (!props.isFullScreen)
  191. {
  192. mWindow->move(left, top);
  193. props.top = mWindow->getTop();
  194. props.left = mWindow->getLeft();
  195. {
  196. ScopedSpinLock lock(mLock);
  197. mSyncedProperties.top = props.top;
  198. mSyncedProperties.left = props.left;
  199. }
  200. bs::RenderWindowManager::instance().notifySyncDataDirty(this);
  201. }
  202. }
  203. void D3D11RenderWindow::resize(UINT32 width, UINT32 height)
  204. {
  205. THROW_IF_NOT_CORE_THREAD;
  206. RenderWindowProperties& props = mProperties;
  207. if (!props.isFullScreen)
  208. {
  209. mWindow->resize(width, height);
  210. props.width = mWindow->getWidth();
  211. props.height = mWindow->getHeight();
  212. {
  213. ScopedSpinLock lock(mLock);
  214. mSyncedProperties.width = props.width;
  215. mSyncedProperties.height = props.height;
  216. }
  217. bs::RenderWindowManager::instance().notifySyncDataDirty(this);
  218. }
  219. }
  220. void D3D11RenderWindow::setActive(bool state)
  221. {
  222. THROW_IF_NOT_CORE_THREAD;
  223. RenderWindowProperties& props = mProperties;
  224. mWindow->setActive(state);
  225. if (mSwapChain)
  226. {
  227. if (state)
  228. mSwapChain->SetFullscreenState(props.isFullScreen, nullptr);
  229. else
  230. mSwapChain->SetFullscreenState(FALSE, nullptr);
  231. }
  232. RenderWindow::setActive(state);
  233. }
  234. void D3D11RenderWindow::setHidden(bool hidden)
  235. {
  236. THROW_IF_NOT_CORE_THREAD;
  237. mShowOnSwap = false;
  238. mWindow->setHidden(hidden);
  239. RenderWindow::setHidden(hidden);
  240. }
  241. void D3D11RenderWindow::minimize()
  242. {
  243. THROW_IF_NOT_CORE_THREAD;
  244. mWindow->minimize();
  245. }
  246. void D3D11RenderWindow::maximize()
  247. {
  248. THROW_IF_NOT_CORE_THREAD;
  249. mWindow->maximize();
  250. }
  251. void D3D11RenderWindow::restore()
  252. {
  253. THROW_IF_NOT_CORE_THREAD;
  254. mWindow->restore();
  255. }
  256. void D3D11RenderWindow::setFullscreen(UINT32 width, UINT32 height, float refreshRate, UINT32 monitorIdx)
  257. {
  258. THROW_IF_NOT_CORE_THREAD;
  259. if (mIsChild)
  260. return;
  261. const D3D11VideoModeInfo& videoModeInfo = static_cast<const D3D11VideoModeInfo&>(RenderAPI::instance().getVideoModeInfo());
  262. UINT32 numOutputs = videoModeInfo.getNumOutputs();
  263. if (numOutputs == 0)
  264. return;
  265. UINT32 actualMonitorIdx = std::min(monitorIdx, numOutputs - 1);
  266. const D3D11VideoOutputInfo& outputInfo = static_cast<const D3D11VideoOutputInfo&>(videoModeInfo.getOutputInfo(actualMonitorIdx));
  267. DXGI_MODE_DESC modeDesc;
  268. ZeroMemory(&modeDesc, sizeof(modeDesc));
  269. modeDesc.Width = width;
  270. modeDesc.Height = height;
  271. modeDesc.RefreshRate.Numerator = Math::roundToInt(refreshRate);
  272. modeDesc.RefreshRate.Denominator = 1;
  273. modeDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
  274. modeDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
  275. modeDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
  276. DXGI_MODE_DESC nearestMode;
  277. ZeroMemory(&nearestMode, sizeof(nearestMode));
  278. outputInfo.getDXGIOutput()->FindClosestMatchingMode(&modeDesc, &nearestMode, nullptr);
  279. mProperties.isFullScreen = true;
  280. mProperties.width = width;
  281. mProperties.height = height;
  282. mSwapChain->ResizeTarget(&nearestMode);
  283. mSwapChain->SetFullscreenState(true, outputInfo.getDXGIOutput());
  284. {
  285. ScopedSpinLock lock(mLock);
  286. mSyncedProperties.top = mProperties.top;
  287. mSyncedProperties.left = mProperties.left;
  288. mSyncedProperties.width = mProperties.width;
  289. mSyncedProperties.height = mProperties.height;
  290. }
  291. bs::RenderWindowManager::instance().notifySyncDataDirty(this);
  292. bs::RenderWindowManager::instance().notifyMovedOrResized(this);
  293. }
  294. void D3D11RenderWindow::setFullscreen(const VideoMode& mode)
  295. {
  296. THROW_IF_NOT_CORE_THREAD;
  297. if (mIsChild)
  298. return;
  299. if (mode.isCustom())
  300. {
  301. setFullscreen(mode.getWidth(), mode.getHeight(), mode.getRefreshRate(), mode.getOutputIdx());
  302. return;
  303. }
  304. const D3D11VideoModeInfo& videoModeInfo = static_cast<const D3D11VideoModeInfo&>(RenderAPI::instance().getVideoModeInfo());
  305. UINT32 numOutputs = videoModeInfo.getNumOutputs();
  306. if (numOutputs == 0)
  307. return;
  308. UINT32 actualMonitorIdx = std::min(mode.getOutputIdx(), numOutputs - 1);
  309. const D3D11VideoOutputInfo& outputInfo = static_cast<const D3D11VideoOutputInfo&>(videoModeInfo.getOutputInfo(actualMonitorIdx));
  310. const D3D11VideoMode& videoMode = static_cast<const D3D11VideoMode&>(mode);
  311. mProperties.isFullScreen = true;
  312. mProperties.width = mode.getWidth();
  313. mProperties.height = mode.getHeight();
  314. mSwapChain->ResizeTarget(&videoMode.getDXGIModeDesc());
  315. mSwapChain->SetFullscreenState(true, outputInfo.getDXGIOutput());
  316. {
  317. ScopedSpinLock lock(mLock);
  318. mSyncedProperties.top = mProperties.top;
  319. mSyncedProperties.left = mProperties.left;
  320. mSyncedProperties.width = mProperties.width;
  321. mSyncedProperties.height = mProperties.height;
  322. }
  323. bs::RenderWindowManager::instance().notifySyncDataDirty(this);
  324. bs::RenderWindowManager::instance().notifyMovedOrResized(this);
  325. }
  326. void D3D11RenderWindow::setWindowed(UINT32 width, UINT32 height)
  327. {
  328. THROW_IF_NOT_CORE_THREAD;
  329. mProperties.width = width;
  330. mProperties.height = height;
  331. mProperties.isFullScreen = false;
  332. mSwapChainDesc.Windowed = true;
  333. mSwapChainDesc.BufferDesc.RefreshRate.Numerator = 0;
  334. mSwapChainDesc.BufferDesc.RefreshRate.Denominator = 0;
  335. mSwapChainDesc.BufferDesc.Width = width;
  336. mSwapChainDesc.BufferDesc.Height = height;
  337. DXGI_MODE_DESC modeDesc;
  338. ZeroMemory(&modeDesc, sizeof(modeDesc));
  339. modeDesc.Width = width;
  340. modeDesc.Height = height;
  341. modeDesc.RefreshRate.Numerator = 0;
  342. modeDesc.RefreshRate.Denominator = 0;
  343. modeDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
  344. mSwapChain->SetFullscreenState(false, nullptr);
  345. mSwapChain->ResizeTarget(&modeDesc);
  346. {
  347. ScopedSpinLock lock(mLock);
  348. mSyncedProperties.top = mProperties.top;
  349. mSyncedProperties.left = mProperties.left;
  350. mSyncedProperties.width = mProperties.width;
  351. mSyncedProperties.height = mProperties.height;
  352. }
  353. bs::RenderWindowManager::instance().notifySyncDataDirty(this);
  354. bs::RenderWindowManager::instance().notifyMovedOrResized(this);
  355. }
  356. void D3D11RenderWindow::setVSync(bool enabled, UINT32 interval)
  357. {
  358. mProperties.vsync = enabled;
  359. mProperties.vsyncInterval = interval;
  360. {
  361. ScopedSpinLock lock(mLock);
  362. mSyncedProperties.vsync = enabled;
  363. mSyncedProperties.vsyncInterval = interval;
  364. }
  365. bs::RenderWindowManager::instance().notifySyncDataDirty(this);
  366. }
  367. HWND D3D11RenderWindow::_getWindowHandle() const
  368. {
  369. return mWindow->getHWnd();
  370. }
  371. void D3D11RenderWindow::getCustomAttribute(const String& name, void* pData) const
  372. {
  373. if(name == "WINDOW")
  374. {
  375. UINT64 *pWnd = (UINT64*)pData;
  376. *pWnd = (UINT64)mWindow->getHWnd();
  377. return;
  378. }
  379. if(name == "RTV")
  380. {
  381. *static_cast<ID3D11RenderTargetView**>(pData) = mRenderTargetView;
  382. return;
  383. }
  384. else if(name == "DSV")
  385. {
  386. if (mDepthStencilView != nullptr)
  387. {
  388. D3D11TextureView* d3d11TextureView = static_cast<D3D11TextureView*>(mDepthStencilView.get());
  389. *static_cast<ID3D11DepthStencilView**>(pData) = d3d11TextureView->getDSV(false, false);
  390. }
  391. else
  392. {
  393. *static_cast<ID3D11DepthStencilView**>(pData) = nullptr;
  394. }
  395. return;
  396. }
  397. else if (name == "RODSV")
  398. {
  399. if (mDepthStencilView != nullptr)
  400. {
  401. D3D11TextureView* d3d11TextureView = static_cast<D3D11TextureView*>(mDepthStencilView.get());
  402. *static_cast<ID3D11DepthStencilView**>(pData) = d3d11TextureView->getDSV(true, true);
  403. }
  404. else
  405. {
  406. *static_cast<ID3D11DepthStencilView**>(pData) = nullptr;
  407. }
  408. return;
  409. }
  410. else if (name == "RODWSV")
  411. {
  412. if (mDepthStencilView != nullptr)
  413. {
  414. D3D11TextureView* d3d11TextureView = static_cast<D3D11TextureView*>(mDepthStencilView.get());
  415. *static_cast<ID3D11DepthStencilView**>(pData) = d3d11TextureView->getDSV(true, false);
  416. }
  417. else
  418. {
  419. *static_cast<ID3D11DepthStencilView**>(pData) = nullptr;
  420. }
  421. return;
  422. }
  423. else if (name == "WDROSV")
  424. {
  425. if (mDepthStencilView != nullptr)
  426. {
  427. D3D11TextureView* d3d11TextureView = static_cast<D3D11TextureView*>(mDepthStencilView.get());
  428. *static_cast<ID3D11DepthStencilView**>(pData) = d3d11TextureView->getDSV(false, true);
  429. }
  430. else
  431. {
  432. *static_cast<ID3D11DepthStencilView**>(pData) = nullptr;
  433. }
  434. return;
  435. }
  436. RenderWindow::getCustomAttribute(name, pData);
  437. }
  438. void D3D11RenderWindow::copyToMemory(PixelData &dst, FrameBuffer buffer)
  439. {
  440. THROW_IF_NOT_CORE_THREAD;
  441. if(mBackBuffer == nullptr)
  442. return;
  443. // Get the backbuffer desc
  444. D3D11_TEXTURE2D_DESC BBDesc;
  445. mBackBuffer->GetDesc(&BBDesc);
  446. ID3D11Texture2D* backbuffer = nullptr;
  447. if(BBDesc.SampleDesc.Quality > 0)
  448. {
  449. D3D11_TEXTURE2D_DESC desc = BBDesc;
  450. desc.Usage = D3D11_USAGE_DEFAULT;
  451. desc.CPUAccessFlags = 0;
  452. desc.BindFlags = 0;
  453. desc.SampleDesc.Quality = 0;
  454. desc.SampleDesc.Count = 1;
  455. HRESULT hr = mDevice.getD3D11Device()->CreateTexture2D(&desc, nullptr, &backbuffer);
  456. if (FAILED(hr) || mDevice.hasError())
  457. {
  458. String errorDescription = mDevice.getErrorDescription();
  459. BS_EXCEPT(RenderingAPIException, "Error creating texture\nError Description:" + errorDescription);
  460. }
  461. mDevice.getImmediateContext()->ResolveSubresource(backbuffer, D3D11CalcSubresource(0, 0, 1), mBackBuffer, D3D11CalcSubresource(0, 0, 1), desc.Format);
  462. }
  463. // Change the parameters of the texture so we can read it
  464. BBDesc.Usage = D3D11_USAGE_STAGING;
  465. BBDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
  466. BBDesc.BindFlags = 0;
  467. BBDesc.SampleDesc.Quality = 0;
  468. BBDesc.SampleDesc.Count = 1;
  469. // Create a temp buffer to copy to
  470. ID3D11Texture2D* tempTexture;
  471. HRESULT hr = mDevice.getD3D11Device()->CreateTexture2D(&BBDesc, nullptr, &tempTexture);
  472. if (FAILED(hr) || mDevice.hasError())
  473. {
  474. String errorDescription = mDevice.getErrorDescription();
  475. BS_EXCEPT(RenderingAPIException, "Error creating texture\nError Description:" + errorDescription);
  476. }
  477. // Copy the back buffer
  478. mDevice.getImmediateContext()->CopyResource(tempTexture, backbuffer != NULL ? backbuffer : mBackBuffer);
  479. // Map the copied texture
  480. D3D11_MAPPED_SUBRESOURCE mappedTex2D;
  481. mDevice.getImmediateContext()->Map(tempTexture, 0,D3D11_MAP_READ, 0, &mappedTex2D);
  482. // Copy the the texture to the dest
  483. PixelData src(getProperties().width, getProperties().height, 1, PF_RGBA8);
  484. src.setExternalBuffer((UINT8*)mappedTex2D.pData);
  485. PixelUtil::bulkPixelConversion(src, dst);
  486. // Unmap the temp buffer
  487. mDevice.getImmediateContext()->Unmap(tempTexture, 0);
  488. // Release the temp buffer
  489. SAFE_RELEASE(tempTexture);
  490. SAFE_RELEASE(backbuffer);
  491. }
  492. void D3D11RenderWindow::_windowMovedOrResized()
  493. {
  494. THROW_IF_NOT_CORE_THREAD;
  495. if (!mWindow)
  496. return;
  497. mWindow->_windowMovedOrResized();
  498. RenderWindowProperties& props = mProperties;
  499. if (props.isFullScreen) // Fullscreen is handled directly by this object
  500. {
  501. resizeSwapChainBuffers(props.width, props.height);
  502. }
  503. else
  504. {
  505. resizeSwapChainBuffers(mWindow->getWidth(), mWindow->getHeight());
  506. props.width = mWindow->getWidth();
  507. props.height = mWindow->getHeight();
  508. props.top = mWindow->getTop();
  509. props.left = mWindow->getLeft();
  510. }
  511. }
  512. void D3D11RenderWindow::createSwapChain()
  513. {
  514. ZeroMemory(&mSwapChainDesc, sizeof(DXGI_SWAP_CHAIN_DESC));
  515. RenderWindowProperties& props = mProperties;
  516. IDXGIDevice* pDXGIDevice = queryDxgiDevice();
  517. ZeroMemory(&mSwapChainDesc, sizeof(DXGI_SWAP_CHAIN_DESC));
  518. DXGI_FORMAT format = DXGI_FORMAT_R8G8B8A8_UNORM;
  519. mSwapChainDesc.OutputWindow = mWindow->getHWnd();
  520. mSwapChainDesc.BufferDesc.Width = props.width;
  521. mSwapChainDesc.BufferDesc.Height = props.height;
  522. mSwapChainDesc.BufferDesc.Format = format;
  523. if (props.isFullScreen)
  524. {
  525. mSwapChainDesc.BufferDesc.RefreshRate.Numerator = mRefreshRateNumerator;
  526. mSwapChainDesc.BufferDesc.RefreshRate.Denominator = mRefreshRateDenominator;
  527. }
  528. else
  529. {
  530. mSwapChainDesc.BufferDesc.RefreshRate.Numerator = 0;
  531. mSwapChainDesc.BufferDesc.RefreshRate.Denominator = 0;
  532. }
  533. mSwapChainDesc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
  534. mSwapChainDesc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
  535. mSwapChainDesc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH ;
  536. mSwapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
  537. mSwapChainDesc.BufferCount = 1;
  538. mSwapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD ;
  539. mSwapChainDesc.Windowed = true;
  540. D3D11RenderAPI* rs = static_cast<D3D11RenderAPI*>(RenderAPI::instancePtr());
  541. rs->determineMultisampleSettings(props.multisampleCount, format, &mMultisampleType);
  542. mSwapChainDesc.SampleDesc.Count = mMultisampleType.Count;
  543. mSwapChainDesc.SampleDesc.Quality = mMultisampleType.Quality;
  544. HRESULT hr;
  545. // Create swap chain
  546. hr = mDXGIFactory->CreateSwapChain(pDXGIDevice, &mSwapChainDesc, &mSwapChain);
  547. if (FAILED(hr))
  548. {
  549. // Try a second time, may fail the first time due to back buffer count,
  550. // which will be corrected by the runtime
  551. hr = mDXGIFactory->CreateSwapChain(pDXGIDevice, &mSwapChainDesc, &mSwapChain);
  552. }
  553. SAFE_RELEASE(pDXGIDevice);
  554. if (FAILED(hr))
  555. BS_EXCEPT(RenderingAPIException, "Unable to create swap chain. Error code: " + toString(hr));
  556. BS_INC_RENDER_STAT_CAT(ResCreated, RenderStatObject_SwapChain);
  557. }
  558. void D3D11RenderWindow::createSizeDependedD3DResources()
  559. {
  560. SAFE_RELEASE(mBackBuffer);
  561. HRESULT hr = mSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&mBackBuffer);
  562. if(FAILED(hr))
  563. BS_EXCEPT(RenderingAPIException, "Unable to Get Back Buffer for swap chain");
  564. assert(mBackBuffer && !mRenderTargetView);
  565. D3D11_TEXTURE2D_DESC BBDesc;
  566. mBackBuffer->GetDesc(&BBDesc);
  567. D3D11_RENDER_TARGET_VIEW_DESC RTVDesc;
  568. ZeroMemory( &RTVDesc, sizeof(RTVDesc) );
  569. RTVDesc.Format = BBDesc.Format;
  570. RTVDesc.ViewDimension = getProperties().multisampleCount > 1 ? D3D11_RTV_DIMENSION_TEXTURE2DMS : D3D11_RTV_DIMENSION_TEXTURE2D;
  571. RTVDesc.Texture2D.MipSlice = 0;
  572. hr = mDevice.getD3D11Device()->CreateRenderTargetView(mBackBuffer, &RTVDesc, &mRenderTargetView);
  573. if(FAILED(hr))
  574. {
  575. String errorDescription = mDevice.getErrorDescription();
  576. BS_EXCEPT(RenderingAPIException, "Unable to create rendertagert view\nError Description:" + errorDescription);
  577. }
  578. mDepthStencilView = nullptr;
  579. if (mDesc.depthBuffer)
  580. {
  581. TEXTURE_DESC texDesc;
  582. texDesc.type = TEX_TYPE_2D;
  583. texDesc.width = BBDesc.Width;
  584. texDesc.height = BBDesc.Height;
  585. texDesc.format = PF_D32_S8X24;
  586. texDesc.usage = TU_DEPTHSTENCIL;
  587. texDesc.numSamples = getProperties().multisampleCount;
  588. mDepthStencilBuffer = Texture::create(texDesc);
  589. mDepthStencilView = mDepthStencilBuffer->requestView(0, 1, 0, 1, GVU_DEPTHSTENCIL);
  590. }
  591. else
  592. mDepthStencilBuffer = nullptr;
  593. }
  594. void D3D11RenderWindow::destroySizeDependedD3DResources()
  595. {
  596. SAFE_RELEASE(mBackBuffer);
  597. SAFE_RELEASE(mRenderTargetView);
  598. mDepthStencilBuffer = nullptr;
  599. }
  600. void D3D11RenderWindow::resizeSwapChainBuffers(UINT32 width, UINT32 height)
  601. {
  602. destroySizeDependedD3DResources();
  603. UINT Flags = mProperties.isFullScreen ? DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH : 0;
  604. HRESULT hr = mSwapChain->ResizeBuffers(mSwapChainDesc.BufferCount, width, height, mSwapChainDesc.BufferDesc.Format, Flags);
  605. if(hr != S_OK)
  606. BS_EXCEPT(InternalErrorException, "Call to ResizeBuffers failed.");
  607. mSwapChain->GetDesc(&mSwapChainDesc);
  608. mProperties.width = mSwapChainDesc.BufferDesc.Width;
  609. mProperties.height = mSwapChainDesc.BufferDesc.Height;
  610. mProperties.isFullScreen = (0 == mSwapChainDesc.Windowed); // Alt-Enter together with SetWindowAssociation() can change this state
  611. createSizeDependedD3DResources();
  612. mDevice.getImmediateContext()->OMSetRenderTargets(0, 0, 0);
  613. }
  614. IDXGIDevice* D3D11RenderWindow::queryDxgiDevice()
  615. {
  616. if (mDevice.getD3D11Device() == nullptr)
  617. {
  618. BS_EXCEPT(RenderingAPIException, "D3D11Device is null.");
  619. }
  620. IDXGIDevice* pDXGIDevice = nullptr;
  621. HRESULT hr = mDevice.getD3D11Device()->QueryInterface(__uuidof(IDXGIDevice), (void**)&pDXGIDevice);
  622. if(FAILED(hr))
  623. BS_EXCEPT(RenderingAPIException, "Unable to query a DXGIDevice.");
  624. return pDXGIDevice;
  625. }
  626. void D3D11RenderWindow::syncProperties()
  627. {
  628. ScopedSpinLock lock(mLock);
  629. mProperties = mSyncedProperties;
  630. }
  631. }
  632. }