CmD3D11RenderWindow.cpp 18 KB

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