CmD3D9RenderWindow.cpp 21 KB

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