CmD3D9RenderWindow.cpp 22 KB

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