CmD3D9RenderWindow.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757
  1. #include "CmD3D9RenderWindow.h"
  2. #include "CmInput.h"
  3. #include "CmCoreThread.h"
  4. #include "CmViewport.h"
  5. #include "CmException.h"
  6. #include "CmD3D9RenderSystem.h"
  7. #include "CmRenderSystem.h"
  8. #include "CmBitwise.h"
  9. #include "Win32/CmPlatformWndProc.h"
  10. #include "CmD3D9VideoModeInfo.h"
  11. #include "CmD3D9DeviceManager.h"
  12. namespace BansheeEngine
  13. {
  14. D3D9RenderWindow::D3D9RenderWindow(const RENDER_WINDOW_DESC& desc, HINSTANCE instance)
  15. : RenderWindow(desc), mInstance(instance), mIsDepthBuffered(true), mIsChild(false)
  16. {
  17. mDevice = NULL;
  18. mIsFullScreen = false;
  19. mIsExternal = false;
  20. mHWnd = 0;
  21. mActive = false;
  22. mClosed = false;
  23. mSwitchingFullscreen = false;
  24. mDisplayFrequency = 0;
  25. mDeviceValid = false;
  26. }
  27. D3D9RenderWindow::~D3D9RenderWindow()
  28. { }
  29. void D3D9RenderWindow::initialize_internal()
  30. {
  31. HINSTANCE hInst = mInstance;
  32. mFSAAType = D3DMULTISAMPLE_NONE;
  33. mFSAAQuality = 0;
  34. mFSAA = mDesc.FSAA;
  35. mVSync = mDesc.vsync;
  36. mVSyncInterval = mDesc.vsyncInterval;
  37. HWND parentHWnd = 0;
  38. HWND externalHandle = 0;
  39. NameValuePairList::const_iterator opt;
  40. // parentWindowHandle -> parentHWnd
  41. opt = mDesc.platformSpecific.find("parentWindowHandle");
  42. if(opt != mDesc.platformSpecific.end())
  43. parentHWnd = (HWND)parseUnsignedInt(opt->second);
  44. // externalWindowHandle -> externalHandle
  45. opt = mDesc.platformSpecific.find("externalWindowHandle");
  46. if(opt != mDesc.platformSpecific.end())
  47. externalHandle = (HWND)parseUnsignedInt(opt->second);
  48. mIsChild = parentHWnd != 0;
  49. if (!externalHandle)
  50. {
  51. DWORD dwStyle = WS_VISIBLE | WS_CLIPCHILDREN;
  52. DWORD dwStyleEx = 0;
  53. HMONITOR hMonitor = NULL;
  54. MONITORINFO monitorInfo;
  55. RECT rc;
  56. // If we specified which adapter we want to use - find it's monitor.
  57. if (mDesc.monitorIndex != -1)
  58. {
  59. IDirect3D9* direct3D9 = D3D9RenderSystem::getDirect3D9();
  60. for (UINT32 i=0; i < direct3D9->GetAdapterCount(); ++i)
  61. {
  62. if (i == mDesc.monitorIndex)
  63. {
  64. hMonitor = direct3D9->GetAdapterMonitor(i);
  65. break;
  66. }
  67. }
  68. }
  69. // If we didn't specified the adapter index, or if it didn't find it
  70. if (hMonitor == NULL)
  71. {
  72. POINT windowAnchorPoint;
  73. // Fill in anchor point.
  74. windowAnchorPoint.x = mDesc.left;
  75. windowAnchorPoint.y = mDesc.top;
  76. // Get the nearest monitor to this window.
  77. hMonitor = MonitorFromPoint(windowAnchorPoint, MONITOR_DEFAULTTOPRIMARY);
  78. }
  79. // Get the target monitor info
  80. memset(&monitorInfo, 0, sizeof(MONITORINFO));
  81. monitorInfo.cbSize = sizeof(MONITORINFO);
  82. GetMonitorInfo(hMonitor, &monitorInfo);
  83. unsigned int winWidth, winHeight;
  84. winWidth = mDesc.width;
  85. winHeight = mDesc.height;
  86. UINT32 left = mDesc.left;
  87. UINT32 top = mDesc.top;
  88. // No specified top left -> Center the window in the middle of the monitor
  89. if (left == -1 || top == -1)
  90. {
  91. int screenw = monitorInfo.rcWork.right - monitorInfo.rcWork.left;
  92. int screenh = monitorInfo.rcWork.bottom - monitorInfo.rcWork.top;
  93. // clamp window dimensions to screen size
  94. int outerw = (int(winWidth) < screenw)? int(winWidth) : screenw;
  95. int outerh = (int(winHeight) < screenh)? int(winHeight) : screenh;
  96. if (left == -1)
  97. left = monitorInfo.rcWork.left + (screenw - outerw) / 2;
  98. else if (mDesc.monitorIndex != -1)
  99. left += monitorInfo.rcWork.left;
  100. if (top == -1)
  101. top = monitorInfo.rcWork.top + (screenh - outerh) / 2;
  102. else if (mDesc.monitorIndex != -1)
  103. top += monitorInfo.rcWork.top;
  104. }
  105. else if (mDesc.monitorIndex != -1)
  106. {
  107. left += monitorInfo.rcWork.left;
  108. top += monitorInfo.rcWork.top;
  109. }
  110. mWidth = mDesiredWidth = mDesc.width;
  111. mHeight = mDesiredHeight = mDesc.height;
  112. mTop = top;
  113. mLeft = left;
  114. if (mDesc.fullscreen && !mIsChild)
  115. {
  116. dwStyleEx |= WS_EX_TOPMOST;
  117. dwStyle |= WS_POPUP;
  118. mTop = monitorInfo.rcMonitor.top;
  119. mLeft = monitorInfo.rcMonitor.left;
  120. }
  121. else
  122. {
  123. if (parentHWnd)
  124. {
  125. if(mDesc.toolWindow)
  126. dwStyleEx = WS_EX_TOOLWINDOW;
  127. else
  128. dwStyle |= WS_CHILD;
  129. }
  130. if (!parentHWnd || mDesc.toolWindow)
  131. {
  132. if (mDesc.border == WindowBorder::None)
  133. dwStyle |= WS_POPUP;
  134. else if (mDesc.border == WindowBorder::Fixed)
  135. dwStyle |= WS_OVERLAPPED | WS_BORDER | WS_CAPTION |
  136. WS_SYSMENU | WS_MINIMIZEBOX;
  137. else
  138. dwStyle |= WS_OVERLAPPEDWINDOW;
  139. }
  140. _adjustWindow(mDesc.width, mDesc.height, dwStyle, &winWidth, &winHeight);
  141. if (!mDesc.outerDimensions)
  142. {
  143. // Calculate window dimensions required
  144. // to get the requested client area
  145. SetRect(&rc, 0, 0, mWidth, mHeight);
  146. AdjustWindowRect(&rc, dwStyle, false);
  147. mWidth = rc.right - rc.left;
  148. mHeight = rc.bottom - rc.top;
  149. // Clamp window rect to the nearest display monitor.
  150. if (mLeft < monitorInfo.rcWork.left)
  151. mLeft = monitorInfo.rcWork.left;
  152. if (mTop < monitorInfo.rcWork.top)
  153. mTop = monitorInfo.rcWork.top;
  154. if (static_cast<int>(winWidth) > monitorInfo.rcWork.right - mLeft)
  155. winWidth = monitorInfo.rcWork.right - mLeft;
  156. if (static_cast<int>(winHeight) > monitorInfo.rcWork.bottom - mTop)
  157. winHeight = monitorInfo.rcWork.bottom - mTop;
  158. }
  159. }
  160. // Register the window class
  161. // NB allow 4 bytes of window data for D3D9RenderWindow pointer
  162. WNDCLASS wc = { 0, PlatformWndProc::_win32WndProc, 0, 0, hInst,
  163. LoadIcon(0, IDI_APPLICATION), LoadCursor(NULL, IDC_ARROW),
  164. (HBRUSH)GetStockObject(BLACK_BRUSH), 0, "D3D9Wnd" };
  165. RegisterClass(&wc);
  166. // Create our main window
  167. // Pass pointer to self
  168. mIsExternal = false;
  169. mHWnd = CreateWindowEx(dwStyleEx, "D3D9Wnd", mDesc.title.c_str(), dwStyle,
  170. mLeft, mTop, winWidth, winHeight, parentHWnd, 0, hInst, this);
  171. mStyle = dwStyle;
  172. }
  173. else
  174. {
  175. mHWnd = externalHandle;
  176. mIsExternal = true;
  177. }
  178. RECT rc;
  179. // top and left represent outer window coordinates
  180. GetWindowRect(mHWnd, &rc);
  181. mTop = rc.top;
  182. mLeft = rc.left;
  183. // width and height represent interior drawable area
  184. GetClientRect(mHWnd, &rc);
  185. mWidth = rc.right;
  186. mHeight = rc.bottom;
  187. mName = mDesc.title;
  188. mIsDepthBuffered = mDesc.depthBuffer;
  189. mIsFullScreen = mDesc.fullscreen && !mIsChild;
  190. mColorDepth = mDesc.colorDepth;
  191. mActive = true;
  192. mClosed = false;
  193. D3D9RenderSystem* rs = static_cast<D3D9RenderSystem*>(RenderSystem::instancePtr());
  194. rs->registerWindow(*this);
  195. RenderWindow::initialize_internal();
  196. }
  197. void D3D9RenderWindow::destroy_internal()
  198. {
  199. if (mDevice != NULL)
  200. {
  201. mDevice->detachRenderWindow(this);
  202. mDevice = NULL;
  203. }
  204. if (mHWnd && !mIsExternal)
  205. {
  206. DestroyWindow(mHWnd);
  207. }
  208. mHWnd = 0;
  209. mActive = false;
  210. mClosed = true;
  211. RenderWindow::destroy_internal();
  212. }
  213. void D3D9RenderWindow::setFullscreen(UINT32 width, UINT32 height, float refreshRate, UINT32 monitorIdx)
  214. {
  215. THROW_IF_NOT_CORE_THREAD;
  216. if (mIsChild)
  217. return;
  218. const D3D9VideoModeInfo& videoModeInfo = static_cast<const D3D9VideoModeInfo&>(RenderSystem::instance().getVideoModeInfo());
  219. UINT32 numOutputs = videoModeInfo.getNumOutputs();
  220. if (numOutputs == 0)
  221. return;
  222. UINT32 actualMonitorIdx = std::min(monitorIdx, numOutputs - 1);
  223. const D3D9VideoOutputInfo& outputInfo = static_cast<const D3D9VideoOutputInfo&>(videoModeInfo.getOutputInfo(actualMonitorIdx));
  224. bool oldFullscreen = mIsFullScreen;
  225. mStyle = WS_VISIBLE | WS_CLIPCHILDREN | WS_POPUP;
  226. mWidth = width;
  227. mHeight = height;
  228. mDisplayFrequency = Math::roundToInt(refreshRate);
  229. mIsFullScreen = true;
  230. mSwitchingFullscreen = true;
  231. HMONITOR hMonitor = outputInfo.getMonitorHandle();
  232. MONITORINFO monitorInfo;
  233. memset(&monitorInfo, 0, sizeof(MONITORINFO));
  234. monitorInfo.cbSize = sizeof(MONITORINFO);
  235. GetMonitorInfo(hMonitor, &monitorInfo);
  236. mTop = monitorInfo.rcMonitor.top;
  237. mLeft = monitorInfo.rcMonitor.left;
  238. if (oldFullscreen) // Was previously fullscreen, just changing the resolution
  239. {
  240. SetWindowPos(mHWnd, HWND_TOPMOST, mLeft, mTop, mWidth, mHeight, SWP_NOACTIVATE);
  241. }
  242. else
  243. {
  244. SetWindowPos(mHWnd, HWND_TOPMOST, mLeft, mTop, mWidth, mHeight, SWP_NOACTIVATE);
  245. SetWindowLong(mHWnd, GWL_STYLE, mStyle);
  246. SetWindowPos(mHWnd, 0, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
  247. }
  248. // Invalidate device, which resets it
  249. mDevice->invalidate(this);
  250. }
  251. void D3D9RenderWindow::setFullscreen(const VideoMode& mode, UINT32 refreshRateIdx)
  252. {
  253. THROW_IF_NOT_CORE_THREAD;
  254. const VideoOutputInfo& outputInfo = mode.getParentOutput();
  255. UINT32 monitorIdx = 0;
  256. for (UINT32 i = 0; i < outputInfo.getNumVideoModes(); i++)
  257. {
  258. if (&outputInfo.getVideoMode(i) == &mode)
  259. {
  260. monitorIdx = i;
  261. break;
  262. }
  263. }
  264. setFullscreen(mode.getWidth(), mode.getHeight(), mode.getRefreshRate(refreshRateIdx), monitorIdx);
  265. }
  266. void D3D9RenderWindow::setWindowed()
  267. {
  268. THROW_IF_NOT_CORE_THREAD;
  269. if (!mIsFullScreen)
  270. return;
  271. mIsFullScreen = false;
  272. mSwitchingFullscreen = true;
  273. mStyle = WS_VISIBLE | WS_CLIPCHILDREN | WS_OVERLAPPEDWINDOW;
  274. unsigned int winWidth, winHeight;
  275. _adjustWindow(mWidth, mHeight, mStyle, &winWidth, &winHeight);
  276. SetWindowLong(mHWnd, GWL_STYLE, mStyle);
  277. SetWindowPos(mHWnd, HWND_NOTOPMOST, 0, 0, winWidth, winHeight,
  278. SWP_DRAWFRAME | SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOACTIVATE);
  279. mDevice->invalidate(this);
  280. }
  281. void D3D9RenderWindow::setHidden(bool hidden)
  282. {
  283. THROW_IF_NOT_CORE_THREAD;
  284. mHidden = hidden;
  285. if (!mIsExternal)
  286. {
  287. if (hidden)
  288. ShowWindow(mHWnd, SW_HIDE);
  289. else
  290. ShowWindow(mHWnd, SW_SHOWNORMAL);
  291. }
  292. }
  293. bool D3D9RenderWindow::isActive() const
  294. {
  295. if (isFullScreen())
  296. return isVisible();
  297. return mActive && isVisible();
  298. }
  299. bool D3D9RenderWindow::isVisible() const
  300. {
  301. return (mHWnd && !IsIconic(mHWnd));
  302. }
  303. void D3D9RenderWindow::move(INT32 top, INT32 left)
  304. {
  305. THROW_IF_NOT_CORE_THREAD;
  306. if (mHWnd && !mIsFullScreen)
  307. {
  308. mLeft = left;
  309. mTop = top;
  310. SetWindowPos(mHWnd, 0, top, left, 0, 0,
  311. SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
  312. }
  313. }
  314. void D3D9RenderWindow::resize(UINT32 width, UINT32 height)
  315. {
  316. THROW_IF_NOT_CORE_THREAD;
  317. if (mHWnd && !mIsFullScreen)
  318. {
  319. mWidth = width;
  320. mHeight = height;
  321. unsigned int winWidth, winHeight;
  322. _adjustWindow(width, height, mStyle, &winWidth, &winHeight);
  323. SetWindowPos(mHWnd, 0, 0, 0, winWidth, winHeight,
  324. SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
  325. }
  326. }
  327. void D3D9RenderWindow::getCustomAttribute( const String& name, void* pData ) const
  328. {
  329. // Valid attributes and their equivalent native functions:
  330. // D3DDEVICE : getD3DDevice
  331. // WINDOW : getWindowHandle
  332. if( name == "D3DDEVICE" )
  333. {
  334. IDirect3DDevice9* *pDev = (IDirect3DDevice9**)pData;
  335. *pDev = _getD3D9Device();
  336. return;
  337. }
  338. else if( name == "WINDOW" )
  339. {
  340. HWND *pHwnd = (HWND*)pData;
  341. *pHwnd = _getWindowHandle();
  342. return;
  343. }
  344. else if( name == "isTexture" )
  345. {
  346. bool *b = reinterpret_cast< bool * >( pData );
  347. *b = false;
  348. return;
  349. }
  350. else if( name == "D3DZBUFFER" )
  351. {
  352. IDirect3DSurface9* *pSurf = (IDirect3DSurface9**)pData;
  353. *pSurf = mDevice->getDepthBuffer(this);
  354. return;
  355. }
  356. else if( name == "DDBACKBUFFER" )
  357. {
  358. IDirect3DSurface9* *pSurf = (IDirect3DSurface9**)pData;
  359. *pSurf = mDevice->getBackBuffer(this);
  360. return;
  361. }
  362. else if( name == "DDFRONTBUFFER" )
  363. {
  364. IDirect3DSurface9* *pSurf = (IDirect3DSurface9**)pData;
  365. *pSurf = mDevice->getBackBuffer(this);
  366. return;
  367. }
  368. }
  369. void D3D9RenderWindow::swapBuffers()
  370. {
  371. THROW_IF_NOT_CORE_THREAD;
  372. if (mDeviceValid)
  373. mDevice->present(this);
  374. }
  375. Vector2I D3D9RenderWindow::screenToWindowPos(const Vector2I& screenPos) const
  376. {
  377. POINT pos;
  378. pos.x = screenPos.x;
  379. pos.y = screenPos.y;
  380. ScreenToClient(mHWnd, &pos);
  381. return Vector2I(pos.x, pos.y);
  382. }
  383. Vector2I D3D9RenderWindow::windowToScreenPos(const Vector2I& windowPos) const
  384. {
  385. POINT pos;
  386. pos.x = windowPos.x;
  387. pos.y = windowPos.y;
  388. ClientToScreen(mHWnd, &pos);
  389. return Vector2I(pos.x, pos.y);
  390. }
  391. void D3D9RenderWindow::copyToMemory(const PixelData &dst, FrameBuffer buffer)
  392. {
  393. THROW_IF_NOT_CORE_THREAD;
  394. mDevice->copyContentsToMemory(this, dst, buffer);
  395. }
  396. void D3D9RenderWindow::_windowMovedOrResized()
  397. {
  398. THROW_IF_NOT_CORE_THREAD;
  399. if (!mHWnd || IsIconic(mHWnd))
  400. return;
  401. updateWindowRect();
  402. RenderWindow::_windowMovedOrResized();
  403. }
  404. /************************************************************************/
  405. /* D3D9 IMPLEMENTATION SPECIFIC */
  406. /************************************************************************/
  407. void D3D9RenderWindow::_adjustWindow(unsigned int clientWidth, unsigned int clientHeight,
  408. DWORD style, unsigned int* winWidth, unsigned int* winHeight)
  409. {
  410. // NB only call this for non full screen
  411. RECT rc;
  412. SetRect(&rc, 0, 0, clientWidth, clientHeight);
  413. AdjustWindowRect(&rc, style, false);
  414. *winWidth = rc.right - rc.left;
  415. *winHeight = rc.bottom - rc.top;
  416. // adjust to monitor
  417. HMONITOR hMonitor = MonitorFromWindow(mHWnd, MONITOR_DEFAULTTONEAREST);
  418. // Get monitor info
  419. MONITORINFO monitorInfo;
  420. memset(&monitorInfo, 0, sizeof(MONITORINFO));
  421. monitorInfo.cbSize = sizeof(MONITORINFO);
  422. GetMonitorInfo(hMonitor, &monitorInfo);
  423. LONG maxW = monitorInfo.rcWork.right - monitorInfo.rcWork.left;
  424. LONG maxH = monitorInfo.rcWork.bottom - monitorInfo.rcWork.top;
  425. if (*winWidth > (unsigned int)maxW)
  426. *winWidth = maxW;
  427. if (*winHeight > (unsigned int)maxH)
  428. *winHeight = maxH;
  429. }
  430. void D3D9RenderWindow::_finishSwitchingFullscreen()
  431. {
  432. if(mIsFullScreen)
  433. {
  434. // Need to reset the region on the window sometimes, when the
  435. // windowed mode was constrained by desktop
  436. HRGN hRgn = CreateRectRgn(0,0,mWidth, mHeight);
  437. SetWindowRgn(mHWnd, hRgn, FALSE);
  438. }
  439. else
  440. {
  441. // When switching back to windowed mode, need to reset window size
  442. // after device has been restored
  443. // We may have had a resize event which polluted our desired sizes
  444. unsigned int winWidth, winHeight;
  445. _adjustWindow(mDesiredWidth, mDesiredHeight, mStyle, &winWidth, &winHeight);
  446. // deal with centreing when switching down to smaller resolution
  447. HMONITOR hMonitor = MonitorFromWindow(mHWnd, MONITOR_DEFAULTTONEAREST);
  448. MONITORINFO monitorInfo;
  449. memset(&monitorInfo, 0, sizeof(MONITORINFO));
  450. monitorInfo.cbSize = sizeof(MONITORINFO);
  451. GetMonitorInfo(hMonitor, &monitorInfo);
  452. LONG screenw = monitorInfo.rcWork.right - monitorInfo.rcWork.left;
  453. LONG screenh = monitorInfo.rcWork.bottom - monitorInfo.rcWork.top;
  454. int left = screenw > int(winWidth) ? ((screenw - int(winWidth)) / 2) : 0;
  455. int top = screenh > int(winHeight) ? ((screenh - int(winHeight)) / 2) : 0;
  456. SetWindowPos(mHWnd, HWND_NOTOPMOST, left, top, winWidth, winHeight,
  457. SWP_DRAWFRAME | SWP_FRAMECHANGED | SWP_NOACTIVATE);
  458. if (mWidth != mDesiredWidth ||
  459. mHeight != mDesiredHeight)
  460. {
  461. mWidth = mDesiredWidth;
  462. mHeight = mDesiredHeight;
  463. // TODO - Notify viewports of resize
  464. }
  465. }
  466. mSwitchingFullscreen = false;
  467. }
  468. void D3D9RenderWindow::_buildPresentParameters(D3DPRESENT_PARAMETERS* presentParams) const
  469. {
  470. // Set up the presentation parameters
  471. IDirect3D9* pD3D = D3D9RenderSystem::getDirect3D9();
  472. D3DDEVTYPE devType = D3DDEVTYPE_HAL;
  473. if (mDevice != NULL)
  474. devType = mDevice->getDeviceType();
  475. ZeroMemory( presentParams, sizeof(D3DPRESENT_PARAMETERS) );
  476. presentParams->Windowed = !mIsFullScreen;
  477. presentParams->SwapEffect = D3DSWAPEFFECT_DISCARD;
  478. presentParams->BackBufferCount = 1;
  479. presentParams->EnableAutoDepthStencil = mIsDepthBuffered;
  480. presentParams->hDeviceWindow = mHWnd;
  481. presentParams->BackBufferWidth = mWidth;
  482. presentParams->BackBufferHeight = mHeight;
  483. presentParams->FullScreen_RefreshRateInHz = mIsFullScreen ? mDisplayFrequency : 0;
  484. if (presentParams->BackBufferWidth == 0)
  485. presentParams->BackBufferWidth = 1;
  486. if (presentParams->BackBufferHeight == 0)
  487. presentParams->BackBufferHeight = 1;
  488. if (mVSync)
  489. {
  490. // D3D9 only seems to support 2-4 presentation intervals in fullscreen
  491. if (mIsFullScreen)
  492. {
  493. switch(mVSyncInterval)
  494. {
  495. case 1:
  496. default:
  497. presentParams->PresentationInterval = D3DPRESENT_INTERVAL_ONE;
  498. break;
  499. case 2:
  500. presentParams->PresentationInterval = D3DPRESENT_INTERVAL_TWO;
  501. break;
  502. case 3:
  503. presentParams->PresentationInterval = D3DPRESENT_INTERVAL_THREE;
  504. break;
  505. case 4:
  506. presentParams->PresentationInterval = D3DPRESENT_INTERVAL_FOUR;
  507. break;
  508. };
  509. // check that the interval was supported, revert to 1 to be safe otherwise
  510. D3DCAPS9 caps;
  511. pD3D->GetDeviceCaps(mDevice->getAdapterNumber(), devType, &caps);
  512. if (!(caps.PresentationIntervals & presentParams->PresentationInterval))
  513. presentParams->PresentationInterval = D3DPRESENT_INTERVAL_ONE;
  514. }
  515. else
  516. {
  517. presentParams->PresentationInterval = D3DPRESENT_INTERVAL_ONE;
  518. }
  519. }
  520. else
  521. {
  522. presentParams->PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
  523. }
  524. presentParams->BackBufferFormat = D3DFMT_R5G6B5;
  525. if(mColorDepth > 16)
  526. presentParams->BackBufferFormat = D3DFMT_X8R8G8B8;
  527. if (mColorDepth > 16)
  528. {
  529. if(FAILED( pD3D->CheckDeviceFormat(mDevice->getAdapterNumber(),
  530. devType, presentParams->BackBufferFormat, D3DUSAGE_DEPTHSTENCIL,
  531. D3DRTYPE_SURFACE, D3DFMT_D24S8)))
  532. {
  533. if(FAILED( pD3D->CheckDeviceFormat(mDevice->getAdapterNumber(),
  534. devType, presentParams->BackBufferFormat, D3DUSAGE_DEPTHSTENCIL,
  535. D3DRTYPE_SURFACE, D3DFMT_D32)))
  536. {
  537. presentParams->AutoDepthStencilFormat = D3DFMT_D16;
  538. }
  539. else
  540. {
  541. presentParams->AutoDepthStencilFormat = D3DFMT_D32;
  542. }
  543. }
  544. else
  545. {
  546. if(SUCCEEDED( pD3D->CheckDepthStencilMatch( mDevice->getAdapterNumber(), devType,
  547. presentParams->BackBufferFormat, presentParams->BackBufferFormat, D3DFMT_D24S8)))
  548. {
  549. presentParams->AutoDepthStencilFormat = D3DFMT_D24S8;
  550. }
  551. else
  552. {
  553. presentParams->AutoDepthStencilFormat = D3DFMT_D24X8;
  554. }
  555. }
  556. }
  557. else
  558. presentParams->AutoDepthStencilFormat = D3DFMT_D16;
  559. D3D9RenderSystem* rsys = static_cast<D3D9RenderSystem*>(BansheeEngine::RenderSystem::instancePtr());
  560. D3DMULTISAMPLE_TYPE fsaaType;
  561. DWORD fsaaQuality;
  562. rsys->determineFSAASettings(mDevice->getD3D9Device(),
  563. mFSAA, mFSAAHint, presentParams->BackBufferFormat, mIsFullScreen,
  564. &fsaaType, &fsaaQuality);
  565. presentParams->MultiSampleType = fsaaType;
  566. presentParams->MultiSampleQuality = (fsaaQuality == 0) ? 0 : fsaaQuality;
  567. }
  568. IDirect3DDevice9* D3D9RenderWindow::_getD3D9Device() const
  569. {
  570. return mDevice->getD3D9Device();
  571. }
  572. IDirect3DSurface9* D3D9RenderWindow::_getRenderSurface() const
  573. {
  574. return mDevice->getBackBuffer(this);
  575. }
  576. D3D9Device* D3D9RenderWindow::_getDevice() const
  577. {
  578. return mDevice;
  579. }
  580. void D3D9RenderWindow::_setDevice(D3D9Device* device)
  581. {
  582. mDevice = device;
  583. mDeviceValid = false;
  584. }
  585. bool D3D9RenderWindow::_isDepthBuffered() const
  586. {
  587. return mIsDepthBuffered;
  588. }
  589. void D3D9RenderWindow::updateWindowRect()
  590. {
  591. RECT rc;
  592. BOOL result;
  593. // Update top left parameters
  594. result = GetWindowRect(mHWnd, &rc);
  595. if (result == FALSE)
  596. {
  597. mTop = 0;
  598. mLeft = 0;
  599. mWidth = 0;
  600. mHeight = 0;
  601. return;
  602. }
  603. mTop = rc.top;
  604. mLeft = rc.left;
  605. // width and height represent drawable area only
  606. result = GetClientRect(mHWnd, &rc);
  607. if (result == FALSE)
  608. {
  609. mTop = 0;
  610. mLeft = 0;
  611. mWidth = 0;
  612. mHeight = 0;
  613. return;
  614. }
  615. mWidth = rc.right - rc.left;
  616. mHeight = rc.bottom - rc.top;
  617. }
  618. bool D3D9RenderWindow::_validateDevice()
  619. {
  620. mDeviceValid = mDevice->validate(this);
  621. return mDeviceValid;
  622. }
  623. }