CmD3D11RenderWindow.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644
  1. #include "CmD3D11RenderWindow.h"
  2. #include "CmWindowEventUtilities.h"
  3. #include "CmD3D11RenderSystem.h"
  4. #include "CmD3D11Device.h"
  5. #include "CmD3D11RenderTexture.h"
  6. #include "CmD3D11TextureView.h"
  7. #include "CmTextureManager.h"
  8. #include "CmException.h"
  9. namespace CamelotEngine
  10. {
  11. D3D11RenderWindow::D3D11RenderWindow(const RENDER_WINDOW_DESC& desc,D3D11Device& device, IDXGIFactory* DXGIFactory)
  12. : RenderWindow(desc)
  13. , mDevice(device)
  14. , mDXGIFactory(DXGIFactory)
  15. , mIsExternal(false)
  16. , mSizing(false)
  17. , mClosed(false)
  18. , mHidden(false)
  19. , mSwitchingFullscreen(false)
  20. , mDisplayFrequency(0)
  21. , mRenderTargetView(nullptr)
  22. , mBackBuffer(nullptr)
  23. , mSwapChain(nullptr)
  24. , mHWnd(0)
  25. , mDepthStencilView(nullptr)
  26. {
  27. ZeroMemory(&mSwapChainDesc, sizeof(DXGI_SWAP_CHAIN_DESC));
  28. }
  29. D3D11RenderWindow::~D3D11RenderWindow()
  30. {
  31. }
  32. void D3D11RenderWindow::initialize_internal()
  33. {
  34. mFSAAType.Count = 1;
  35. mFSAAType.Quality = 0;
  36. mFSAA = 0;
  37. mFSAAHint = "";
  38. mVSync = false;
  39. mVSyncInterval = 1;
  40. HWND parentHWnd = 0;
  41. HWND externalHandle = 0;
  42. // Get variable-length params
  43. NameValuePairList::const_iterator opt;
  44. // parentWindowHandle -> parentHWnd
  45. opt = mDesc.platformSpecific.find("parentWindowHandle");
  46. if(opt != mDesc.platformSpecific.end())
  47. parentHWnd = (HWND)parseUnsignedInt(opt->second);
  48. // externalWindowHandle -> externalHandle
  49. opt = mDesc.platformSpecific.find("externalWindowHandle");
  50. if(opt != mDesc.platformSpecific.end())
  51. externalHandle = (HWND)parseUnsignedInt(opt->second);
  52. mName = mDesc.title;
  53. mIsFullScreen = mDesc.fullscreen;
  54. mColorDepth = mDesc.colorDepth;
  55. mWidth = mHeight = mLeft = mTop = 0;
  56. mActive = true;
  57. mClosed = false;
  58. if (!externalHandle)
  59. {
  60. DWORD dwStyle = (mHidden ? 0 : WS_VISIBLE) | WS_CLIPCHILDREN;
  61. RECT rc;
  62. mWidth = mDesc.width;
  63. mHeight = mDesc.height;
  64. mTop = mDesc.top;
  65. mLeft = mDesc.left;
  66. if (!mDesc.fullscreen)
  67. {
  68. if (parentHWnd)
  69. {
  70. dwStyle |= WS_CHILD;
  71. }
  72. else
  73. {
  74. if (mDesc.border == "none")
  75. dwStyle |= WS_POPUP;
  76. else if (mDesc.border == "fixed")
  77. dwStyle |= WS_OVERLAPPED | WS_BORDER | WS_CAPTION |
  78. WS_SYSMENU | WS_MINIMIZEBOX;
  79. else
  80. dwStyle |= WS_OVERLAPPEDWINDOW;
  81. }
  82. if (!mDesc.outerDimensions)
  83. {
  84. // Calculate window dimensions required
  85. // to get the requested client area
  86. SetRect(&rc, 0, 0, mWidth, mHeight);
  87. AdjustWindowRect(&rc, dwStyle, false);
  88. mWidth = rc.right - rc.left;
  89. mHeight = rc.bottom - rc.top;
  90. // Clamp width and height to the desktop dimensions
  91. int screenw = GetSystemMetrics(SM_CXSCREEN);
  92. int screenh = GetSystemMetrics(SM_CYSCREEN);
  93. if ((int)mWidth > screenw)
  94. mWidth = screenw;
  95. if ((int)mHeight > screenh)
  96. mHeight = screenh;
  97. if (mLeft < 0)
  98. mLeft = (screenw - mWidth) / 2;
  99. if (mTop < 0)
  100. mTop = (screenh - mHeight) / 2;
  101. }
  102. }
  103. else
  104. {
  105. dwStyle |= WS_POPUP;
  106. mTop = mLeft = 0;
  107. }
  108. UINT classStyle = 0;
  109. if (mDesc.enableDoubleClick)
  110. classStyle |= CS_DBLCLKS;
  111. HINSTANCE hInst = NULL;
  112. // Register the window class
  113. // Allow 4 bytes of window data for D3D11RenderWindow pointer
  114. WNDCLASS wc = { classStyle, WindowEventUtilities::_WndProc, 0, 0, hInst,
  115. LoadIcon(0, IDI_APPLICATION), LoadCursor(NULL, IDC_ARROW),
  116. (HBRUSH)GetStockObject(BLACK_BRUSH), 0, "D3D11Wnd" };
  117. RegisterClass(&wc);
  118. // Create our main window
  119. // Pass pointer to self
  120. mIsExternal = false;
  121. mHWnd = CreateWindow("D3D11Wnd", mDesc.title.c_str(), dwStyle,
  122. mLeft, mTop, mWidth, mHeight, parentHWnd, 0, hInst, this);
  123. WindowEventUtilities::_addRenderWindow(this);
  124. }
  125. else
  126. {
  127. mHWnd = externalHandle;
  128. mIsExternal = true;
  129. }
  130. RECT rc;
  131. // top and left represent outer window coordinates
  132. GetWindowRect(mHWnd, &rc);
  133. mTop = rc.top;
  134. mLeft = rc.left;
  135. // width and height represent interior drawable area
  136. GetClientRect(mHWnd, &rc);
  137. mWidth = rc.right;
  138. mHeight = rc.bottom;
  139. _createSwapChain();
  140. _createSizeDependedD3DResources();
  141. mDXGIFactory->MakeWindowAssociation(mHWnd, NULL);
  142. setHidden(mHidden);
  143. RenderSystem* rs = RenderSystem::instancePtr();
  144. D3D11RenderSystem* d3d11rs = static_cast<D3D11RenderSystem*>(rs);
  145. d3d11rs->_notifyWindowCreated(*this);
  146. RenderWindow::initialize_internal();
  147. }
  148. void D3D11RenderWindow::destroy_internal()
  149. {
  150. mActive = false;
  151. mClosed = true;
  152. SAFE_RELEASE(mSwapChain);
  153. if (mHWnd && !mIsExternal)
  154. {
  155. WindowEventUtilities::_removeRenderWindow(this);
  156. DestroyWindow(mHWnd);
  157. }
  158. if(mDepthStencilView != nullptr)
  159. {
  160. Texture::releaseView(mDepthStencilView);
  161. mDepthStencilView = nullptr;
  162. }
  163. mHWnd = nullptr;
  164. _destroySizeDependedD3DResources();
  165. RenderWindow::destroy_internal();
  166. }
  167. void D3D11RenderWindow::swapBuffers_internal()
  168. {
  169. if(mDevice.getD3D11Device() != nullptr)
  170. {
  171. HRESULT hr = mSwapChain->Present(mVSync ? mVSyncInterval : 0, 0);
  172. if( FAILED(hr) )
  173. CM_EXCEPT(RenderingAPIException, "Error Presenting surfaces");
  174. }
  175. }
  176. void D3D11RenderWindow::reposition(int top, int left)
  177. {
  178. if (mHWnd && !mIsFullScreen)
  179. {
  180. SetWindowPos(mHWnd, 0, top, left, 0, 0,
  181. SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
  182. }
  183. }
  184. void D3D11RenderWindow::resize(unsigned int width, unsigned int height)
  185. {
  186. if (mHWnd && !mIsFullScreen)
  187. {
  188. RECT rc = { 0, 0, width, height };
  189. AdjustWindowRect(&rc, GetWindowLong(mHWnd, GWL_STYLE), false);
  190. width = rc.right - rc.left;
  191. height = rc.bottom - rc.top;
  192. SetWindowPos(mHWnd, 0, 0, 0, width, height,
  193. SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
  194. }
  195. }
  196. void D3D11RenderWindow::windowMovedOrResized()
  197. {
  198. if (!mHWnd || IsIconic(mHWnd))
  199. return;
  200. RECT rc;
  201. // top and left represent outer window position
  202. GetWindowRect(mHWnd, &rc);
  203. mTop = rc.top;
  204. mLeft = rc.left;
  205. // width and height represent drawable area only
  206. GetClientRect(mHWnd, &rc);
  207. unsigned int width = rc.right - rc.left;
  208. unsigned int height = rc.bottom - rc.top;
  209. if (width == 0)
  210. width = 1;
  211. if (height == 0)
  212. height = 1;
  213. if (mWidth == width && mHeight == height)
  214. return;
  215. _resizeSwapChainBuffers(width, height);
  216. }
  217. void D3D11RenderWindow::setActive(bool state)
  218. {
  219. if (mHWnd && mSwapChain)
  220. {
  221. if (state)
  222. {
  223. ShowWindow(mHWnd, SW_RESTORE);
  224. mSwapChain->SetFullscreenState(mIsFullScreen, nullptr);
  225. }
  226. else
  227. {
  228. ShowWindow(mHWnd, SW_SHOWMINIMIZED);
  229. mSwapChain->SetFullscreenState(FALSE, nullptr);
  230. }
  231. }
  232. RenderWindow::setActive(state);
  233. }
  234. void D3D11RenderWindow::setHidden(bool hidden)
  235. {
  236. mHidden = hidden;
  237. if (!mIsExternal)
  238. {
  239. if (hidden)
  240. ShowWindow(mHWnd, SW_HIDE);
  241. else
  242. ShowWindow(mHWnd, SW_SHOWNORMAL);
  243. }
  244. }
  245. void D3D11RenderWindow::setFullscreen(bool fullScreen, unsigned int width, unsigned int height)
  246. {
  247. if (fullScreen != mIsFullScreen || width != mWidth || height != mHeight)
  248. {
  249. if (fullScreen != mIsFullScreen)
  250. mSwitchingFullscreen = true;
  251. DWORD dwStyle = WS_VISIBLE | WS_CLIPCHILDREN;
  252. bool oldFullscreen = mIsFullScreen;
  253. mIsFullScreen = fullScreen;
  254. if (fullScreen)
  255. {
  256. dwStyle |= WS_POPUP;
  257. mTop = mLeft = 0;
  258. mWidth = width;
  259. mHeight = height;
  260. // need different ordering here
  261. if (oldFullscreen)
  262. {
  263. // was previously fullscreen, just changing the resolution
  264. SetWindowPos(mHWnd, HWND_TOPMOST, 0, 0, width, height, SWP_NOACTIVATE);
  265. }
  266. else
  267. {
  268. SetWindowPos(mHWnd, HWND_TOPMOST, 0, 0, width, height, SWP_NOACTIVATE);
  269. //MoveWindow(mHWnd, mLeft, mTop, mWidth, mHeight, FALSE);
  270. SetWindowLong(mHWnd, GWL_STYLE, dwStyle);
  271. SetWindowPos(mHWnd, 0, 0,0, 0,0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER);
  272. }
  273. }
  274. else
  275. {
  276. dwStyle |= WS_OVERLAPPEDWINDOW;
  277. // Calculate window dimensions required
  278. // to get the requested client area
  279. RECT rc;
  280. SetRect(&rc, 0, 0, width, height);
  281. AdjustWindowRect(&rc, dwStyle, false);
  282. unsigned int winWidth = rc.right - rc.left;
  283. unsigned int winHeight = rc.bottom - rc.top;
  284. SetWindowLong(mHWnd, GWL_STYLE, dwStyle);
  285. SetWindowPos(mHWnd, HWND_NOTOPMOST, 0, 0, winWidth, winHeight,
  286. SWP_DRAWFRAME | SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOACTIVATE);
  287. // Note that we also set the position in the restoreLostDevice method
  288. // via _finishSwitchingFullScreen
  289. }
  290. mSwapChainDesc.Windowed = !fullScreen;
  291. mSwapChainDesc.BufferDesc.RefreshRate.Numerator = 0;
  292. mSwapChainDesc.BufferDesc.RefreshRate.Denominator=0;
  293. mSwapChainDesc.BufferDesc.Height = height;
  294. mSwapChainDesc.BufferDesc.Width = width;
  295. }
  296. }
  297. void D3D11RenderWindow::getCustomAttribute( const String& name, void* pData )
  298. {
  299. if(name == "WINDOW")
  300. {
  301. HWND *pWnd = (HWND*)pData;
  302. *pWnd = mHWnd;
  303. return;
  304. }
  305. if(name == "RTV")
  306. {
  307. *static_cast<ID3D11RenderTargetView**>(pData) = mRenderTargetView;
  308. return;
  309. }
  310. else if(name == "DSV")
  311. {
  312. D3D11TextureView* d3d11TextureView = static_cast<D3D11TextureView*>(mDepthStencilView.get());
  313. *static_cast<ID3D11DepthStencilView**>(pData) = d3d11TextureView->getDSV();
  314. return;
  315. }
  316. RenderWindow::getCustomAttribute(name, pData);
  317. }
  318. void D3D11RenderWindow::copyContentsToMemory(const PixelData &dst, FrameBuffer buffer)
  319. {
  320. if(mBackBuffer == nullptr)
  321. return;
  322. // get the backbuffer desc
  323. D3D11_TEXTURE2D_DESC BBDesc;
  324. mBackBuffer->GetDesc(&BBDesc);
  325. ID3D11Texture2D *backbuffer = nullptr;
  326. if(BBDesc.SampleDesc.Quality > 0)
  327. {
  328. D3D11_TEXTURE2D_DESC desc = BBDesc;
  329. desc.Usage = D3D11_USAGE_DEFAULT;
  330. desc.CPUAccessFlags = 0;
  331. desc.BindFlags = 0;
  332. desc.SampleDesc.Quality = 0;
  333. desc.SampleDesc.Count = 1;
  334. HRESULT hr = mDevice.getD3D11Device()->CreateTexture2D(
  335. &desc,
  336. NULL,
  337. &backbuffer);
  338. if (FAILED(hr) || mDevice.hasError())
  339. {
  340. String errorDescription = mDevice.getErrorDescription();
  341. CM_EXCEPT(RenderingAPIException,
  342. "Error creating texture\nError Description:" + errorDescription);
  343. }
  344. mDevice.getImmediateContext()->ResolveSubresource(backbuffer, D3D11CalcSubresource(0, 0, 1), mBackBuffer, D3D11CalcSubresource(0, 0, 1), desc.Format);
  345. }
  346. // change the parameters of the texture so we can read it
  347. BBDesc.Usage = D3D11_USAGE_STAGING;
  348. BBDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
  349. BBDesc.BindFlags = 0;
  350. BBDesc.SampleDesc.Quality = 0;
  351. BBDesc.SampleDesc.Count = 1;
  352. // create a temp buffer to copy to
  353. ID3D11Texture2D * pTempTexture2D;
  354. HRESULT hr = mDevice.getD3D11Device()->CreateTexture2D(
  355. &BBDesc,
  356. NULL,
  357. &pTempTexture2D);
  358. if (FAILED(hr) || mDevice.hasError())
  359. {
  360. String errorDescription = mDevice.getErrorDescription();
  361. CM_EXCEPT(RenderingAPIException,
  362. "Error creating texture\nError Description:" + errorDescription);
  363. }
  364. // copy the back buffer
  365. mDevice.getImmediateContext()->CopyResource(pTempTexture2D, backbuffer != NULL ? backbuffer : mBackBuffer);
  366. // map the copied texture
  367. D3D11_MAPPED_SUBRESOURCE mappedTex2D;
  368. mDevice.getImmediateContext()->Map(pTempTexture2D, 0,D3D11_MAP_READ, 0, &mappedTex2D);
  369. // copy the the texture to the dest
  370. PixelUtil::bulkPixelConversion(PixelData(mWidth, mHeight, 1, PF_A8B8G8R8, mappedTex2D.pData), dst);
  371. // unmap the temp buffer
  372. mDevice.getImmediateContext()->Unmap(pTempTexture2D, 0);
  373. // Release the temp buffer
  374. SAFE_RELEASE(pTempTexture2D);
  375. SAFE_RELEASE(backbuffer);
  376. }
  377. void D3D11RenderWindow::_createSwapChain()
  378. {
  379. ZeroMemory(&mSwapChainDesc, sizeof(DXGI_SWAP_CHAIN_DESC));
  380. // get the dxgi device
  381. IDXGIDevice* pDXGIDevice = _queryDxgiDevice();
  382. ZeroMemory(&mSwapChainDesc, sizeof(DXGI_SWAP_CHAIN_DESC));
  383. DXGI_FORMAT format = DXGI_FORMAT_R8G8B8A8_UNORM;
  384. mSwapChainDesc.OutputWindow = mHWnd;
  385. mSwapChainDesc.BufferDesc.Width = mWidth;
  386. mSwapChainDesc.BufferDesc.Height = mHeight;
  387. mSwapChainDesc.BufferDesc.Format = format;
  388. mSwapChainDesc.BufferDesc.RefreshRate.Numerator=0;
  389. mSwapChainDesc.BufferDesc.RefreshRate.Denominator = 0;
  390. mSwapChainDesc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
  391. mSwapChainDesc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
  392. mSwapChainDesc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH ;
  393. // triple buffer if VSync is on
  394. mSwapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
  395. mSwapChainDesc.BufferCount = mVSync ? 2 : 1;
  396. mSwapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD ;
  397. mSwapChainDesc.OutputWindow = mHWnd;
  398. mSwapChainDesc.Windowed = !mIsFullScreen;
  399. D3D11RenderSystem* rs = static_cast<D3D11RenderSystem*>(RenderSystem::instancePtr());
  400. rs->determineFSAASettings(mFSAA, mFSAAHint, format, &mFSAAType);
  401. mSwapChainDesc.SampleDesc.Count = mFSAAType.Count;
  402. mSwapChainDesc.SampleDesc.Quality = mFSAAType.Quality;
  403. HRESULT hr;
  404. // Create swap chain
  405. hr = mDXGIFactory->CreateSwapChain(pDXGIDevice, &mSwapChainDesc, &mSwapChain);
  406. if (FAILED(hr))
  407. {
  408. // Try a second time, may fail the first time due to back buffer count,
  409. // which will be corrected by the runtime
  410. hr = mDXGIFactory->CreateSwapChain(pDXGIDevice, &mSwapChainDesc, &mSwapChain);
  411. }
  412. SAFE_RELEASE(pDXGIDevice);
  413. if (FAILED(hr))
  414. CM_EXCEPT(RenderingAPIException, "Unable to create swap chain");
  415. }
  416. void D3D11RenderWindow::_createSizeDependedD3DResources()
  417. {
  418. // obtain back buffer
  419. SAFE_RELEASE(mBackBuffer);
  420. HRESULT hr = mSwapChain->GetBuffer(0, __uuidof( ID3D11Texture2D ), (LPVOID*)&mBackBuffer);
  421. if( FAILED(hr) )
  422. CM_EXCEPT(RenderingAPIException, "Unable to Get Back Buffer for swap chain");
  423. // create all other size depended resources
  424. assert(mBackBuffer && !mRenderTargetView);
  425. // get the backbuffer desc
  426. D3D11_TEXTURE2D_DESC BBDesc;
  427. mBackBuffer->GetDesc(&BBDesc);
  428. // create the render target view
  429. D3D11_RENDER_TARGET_VIEW_DESC RTVDesc;
  430. ZeroMemory( &RTVDesc, sizeof(RTVDesc) );
  431. RTVDesc.Format = BBDesc.Format;
  432. RTVDesc.ViewDimension = mFSAA ? D3D11_RTV_DIMENSION_TEXTURE2DMS : D3D11_RTV_DIMENSION_TEXTURE2D;
  433. RTVDesc.Texture2D.MipSlice = 0;
  434. hr = mDevice.getD3D11Device()->CreateRenderTargetView(mBackBuffer, &RTVDesc, &mRenderTargetView);
  435. if( FAILED(hr) )
  436. {
  437. String errorDescription = mDevice.getErrorDescription();
  438. CM_EXCEPT(RenderingAPIException, "Unable to create rendertagert view\nError Description:" + errorDescription);
  439. }
  440. mDepthStencilBuffer = TextureManager::instance().createTexture(TEX_TYPE_2D,
  441. BBDesc.Width, BBDesc.Height, 0, PF_D24S8, TU_DEPTHSTENCIL, false, mFSAA, mFSAAHint);
  442. if(mDepthStencilView != nullptr)
  443. {
  444. Texture::releaseView(mDepthStencilView);
  445. mDepthStencilView = nullptr;
  446. }
  447. mDepthStencilView = Texture::requestView(mDepthStencilBuffer, 0, 1, 0, 1, GVU_DEPTHSTENCIL);
  448. }
  449. void D3D11RenderWindow::_destroySizeDependedD3DResources()
  450. {
  451. SAFE_RELEASE(mBackBuffer);
  452. SAFE_RELEASE(mRenderTargetView);
  453. mDepthStencilBuffer = nullptr;
  454. }
  455. void D3D11RenderWindow::_resizeSwapChainBuffers(unsigned width, unsigned height)
  456. {
  457. _destroySizeDependedD3DResources();
  458. // width and height can be zero to autodetect size, therefore do not rely on them
  459. UINT Flags = mIsFullScreen ? DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH : 0;
  460. mSwapChain->ResizeBuffers(mSwapChainDesc.BufferCount, width, height, mSwapChainDesc.BufferDesc.Format, Flags);
  461. mSwapChain->GetDesc(&mSwapChainDesc);
  462. mWidth = mSwapChainDesc.BufferDesc.Width;
  463. mHeight = mSwapChainDesc.BufferDesc.Height;
  464. mIsFullScreen = (0 == mSwapChainDesc.Windowed); // Alt-Enter together with SetWindowAssociation() can change this state
  465. _createSizeDependedD3DResources();
  466. mDevice.getImmediateContext()->OMSetRenderTargets(0, 0, 0);
  467. // Additional swap chains need their own depth buffer
  468. // to support resizing them
  469. HRESULT hr = mSwapChain->GetBuffer( 0, __uuidof( ID3D11Texture2D ), (LPVOID*)&mBackBuffer );
  470. if( FAILED(hr) )
  471. {
  472. CM_EXCEPT(RenderingAPIException,
  473. "Unable to Get Back Buffer for swap chain");
  474. }
  475. // get the backbuffer desc
  476. D3D11_TEXTURE2D_DESC BBDesc;
  477. mBackBuffer->GetDesc(&BBDesc);
  478. // create the render target view
  479. D3D11_RENDER_TARGET_VIEW_DESC RTVDesc;
  480. ZeroMemory( &RTVDesc, sizeof(RTVDesc) );
  481. RTVDesc.Format = BBDesc.Format;
  482. RTVDesc.ViewDimension = mFSAA ? D3D11_RTV_DIMENSION_TEXTURE2DMS : D3D11_RTV_DIMENSION_TEXTURE2D;
  483. RTVDesc.Texture2D.MipSlice = 0;
  484. hr = mDevice.getD3D11Device()->CreateRenderTargetView(mBackBuffer, &RTVDesc, &mRenderTargetView);
  485. if(FAILED(hr))
  486. {
  487. String errorDescription = mDevice.getErrorDescription();
  488. CM_EXCEPT(RenderingAPIException,
  489. "Unable to create rendertagert view\nError Description:" + errorDescription);
  490. }
  491. }
  492. IDXGIDevice* D3D11RenderWindow::_queryDxgiDevice()
  493. {
  494. if (mDevice.getD3D11Device() == nullptr)
  495. {
  496. CM_EXCEPT(RenderingAPIException, "D3D11Device is NULL!");
  497. }
  498. IDXGIDevice* pDXGIDevice = nullptr;
  499. HRESULT hr = mDevice.getD3D11Device()->QueryInterface(__uuidof(IDXGIDevice), (void**)&pDXGIDevice);
  500. if(FAILED(hr))
  501. CM_EXCEPT(RenderingAPIException, "Unable to query a DXGIDevice");
  502. return pDXGIDevice;
  503. }
  504. void D3D11RenderWindow::_finishSwitchingFullscreen()
  505. {
  506. if(mIsFullScreen)
  507. {
  508. // Need to reset the region on the window sometimes, when the
  509. // windowed mode was constrained by desktop
  510. HRGN hRgn = CreateRectRgn(0, 0, mSwapChainDesc.BufferDesc.Width, mSwapChainDesc.BufferDesc.Height);
  511. SetWindowRgn(mHWnd, hRgn, FALSE);
  512. }
  513. else
  514. {
  515. // When switching back to windowed mode, need to reset window size
  516. // after device has been restored
  517. RECT rc;
  518. SetRect(&rc, 0, 0, mSwapChainDesc.BufferDesc.Width, mSwapChainDesc.BufferDesc.Height);
  519. AdjustWindowRect(&rc, GetWindowLong(mHWnd, GWL_STYLE), false);
  520. unsigned int winWidth = rc.right - rc.left;
  521. unsigned int winHeight = rc.bottom - rc.top;
  522. int screenw = GetSystemMetrics(SM_CXSCREEN);
  523. int screenh = GetSystemMetrics(SM_CYSCREEN);
  524. int left = (screenw - winWidth) / 2;
  525. int top = (screenh - winHeight) / 2;
  526. SetWindowPos(mHWnd, HWND_NOTOPMOST, left, top, winWidth, winHeight,
  527. SWP_DRAWFRAME | SWP_FRAMECHANGED | SWP_NOACTIVATE);
  528. }
  529. mSwapChain->SetFullscreenState(mIsFullScreen, NULL);
  530. mSwitchingFullscreen = false;
  531. }
  532. bool D3D11RenderWindow::_checkMultiSampleQuality(UINT SampleCount, UINT *outQuality, DXGI_FORMAT format)
  533. {
  534. if (SUCCEEDED(mDevice.getD3D11Device()->CheckMultisampleQualityLevels(format, SampleCount, outQuality)))
  535. return true;
  536. else
  537. return false;
  538. }
  539. }