OgreD3D9RenderWindow.cpp 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891
  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 "OgreD3D9RenderWindow.h"
  25. #include "OgreViewport.h"
  26. #include "OgreException.h"
  27. #include "OgreD3D9RenderSystem.h"
  28. #include "OgreRenderSystem.h"
  29. #include "OgreBitwise.h"
  30. #include "OgreStringConverter.h"
  31. #include "OgreWindowEventUtilities.h"
  32. #include "OgreD3D9DeviceManager.h"
  33. namespace Ogre
  34. {
  35. D3D9RenderWindow::D3D9RenderWindow(HINSTANCE instance)
  36. : mInstance(instance)
  37. {
  38. mDevice = NULL;
  39. mIsFullScreen = false;
  40. mIsExternal = false;
  41. mHWnd = 0;
  42. mActive = false;
  43. mClosed = false;
  44. mSwitchingFullscreen = false;
  45. mDisplayFrequency = 0;
  46. mDeviceValid = false;
  47. mUseNVPerfHUD = false;
  48. }
  49. D3D9RenderWindow::~D3D9RenderWindow()
  50. {
  51. destroy();
  52. }
  53. void D3D9RenderWindow::create(const String& name, unsigned int width, unsigned int height,
  54. bool fullScreen, const NameValuePairList *miscParams)
  55. {
  56. HINSTANCE hInst = mInstance;
  57. HWND parentHWnd = 0;
  58. HWND externalHandle = 0;
  59. mFSAAType = D3DMULTISAMPLE_NONE;
  60. mFSAAQuality = 0;
  61. mFSAA = 0;
  62. mVSync = false;
  63. mVSyncInterval = 1;
  64. String title = name;
  65. unsigned int colourDepth = 32;
  66. int left = INT_MAX; // Defaults to screen center
  67. int top = INT_MAX; // Defaults to screen center
  68. bool depthBuffer = true;
  69. String border = "";
  70. bool outerSize = false;
  71. mUseNVPerfHUD = false;
  72. size_t fsaaSamples = 0;
  73. String fsaaHint;
  74. int monitorIndex = -1; //Default by detecting the adapter from left / top position
  75. if(miscParams)
  76. {
  77. // Get variable-length params
  78. NameValuePairList::const_iterator opt;
  79. // left (x)
  80. opt = miscParams->find("left");
  81. if(opt != miscParams->end())
  82. left = StringConverter::parseInt(opt->second);
  83. // top (y)
  84. opt = miscParams->find("top");
  85. if(opt != miscParams->end())
  86. top = StringConverter::parseInt(opt->second);
  87. // Window title
  88. opt = miscParams->find("title");
  89. if(opt != miscParams->end())
  90. title = opt->second;
  91. // parentWindowHandle -> parentHWnd
  92. opt = miscParams->find("parentWindowHandle");
  93. if(opt != miscParams->end())
  94. parentHWnd = (HWND)StringConverter::parseUnsignedInt(opt->second);
  95. // externalWindowHandle -> externalHandle
  96. opt = miscParams->find("externalWindowHandle");
  97. if(opt != miscParams->end())
  98. externalHandle = (HWND)StringConverter::parseUnsignedInt(opt->second);
  99. // vsync [parseBool]
  100. opt = miscParams->find("vsync");
  101. if(opt != miscParams->end())
  102. mVSync = StringConverter::parseBool(opt->second);
  103. // vsyncInterval [parseUnsignedInt]
  104. opt = miscParams->find("vsyncInterval");
  105. if(opt != miscParams->end())
  106. mVSyncInterval = StringConverter::parseUnsignedInt(opt->second);
  107. // displayFrequency
  108. opt = miscParams->find("displayFrequency");
  109. if(opt != miscParams->end())
  110. mDisplayFrequency = StringConverter::parseUnsignedInt(opt->second);
  111. // colourDepth
  112. opt = miscParams->find("colourDepth");
  113. if(opt != miscParams->end())
  114. colourDepth = StringConverter::parseUnsignedInt(opt->second);
  115. // depthBuffer [parseBool]
  116. opt = miscParams->find("depthBuffer");
  117. if(opt != miscParams->end())
  118. depthBuffer = StringConverter::parseBool(opt->second);
  119. // FSAA settings
  120. opt = miscParams->find("FSAA");
  121. if(opt != miscParams->end())
  122. {
  123. mFSAA = StringConverter::parseUnsignedInt(opt->second);
  124. }
  125. opt = miscParams->find("FSAAHint");
  126. if(opt != miscParams->end())
  127. {
  128. mFSAAHint = opt->second;
  129. }
  130. // window border style
  131. opt = miscParams->find("border");
  132. if(opt != miscParams->end())
  133. border = opt->second;
  134. // set outer dimensions?
  135. opt = miscParams->find("outerDimensions");
  136. if(opt != miscParams->end())
  137. outerSize = StringConverter::parseBool(opt->second);
  138. // NV perf HUD?
  139. opt = miscParams->find("useNVPerfHUD");
  140. if(opt != miscParams->end())
  141. mUseNVPerfHUD = StringConverter::parseBool(opt->second);
  142. // sRGB?
  143. opt = miscParams->find("gamma");
  144. if(opt != miscParams->end())
  145. mHwGamma = StringConverter::parseBool(opt->second);
  146. // monitor index
  147. opt = miscParams->find("monitorIndex");
  148. if(opt != miscParams->end())
  149. monitorIndex = StringConverter::parseInt(opt->second);
  150. }
  151. // Destroy current window if any
  152. if( mHWnd )
  153. destroy();
  154. if (!externalHandle)
  155. {
  156. DWORD dwStyle = WS_VISIBLE | WS_CLIPCHILDREN;
  157. DWORD dwStyleEx = 0;
  158. HMONITOR hMonitor = NULL;
  159. MONITORINFO monitorInfo;
  160. RECT rc;
  161. // If we specified which adapter we want to use - find it's monitor.
  162. if (monitorIndex != -1)
  163. {
  164. IDirect3D9* direct3D9 = D3D9RenderSystem::getDirect3D9();
  165. for (uint i=0; i < direct3D9->GetAdapterCount(); ++i)
  166. {
  167. if (i == monitorIndex)
  168. {
  169. hMonitor = direct3D9->GetAdapterMonitor(i);
  170. break;
  171. }
  172. }
  173. }
  174. // If we didn't specified the adapter index, or if it didn't find it
  175. if (hMonitor == NULL)
  176. {
  177. POINT windowAnchorPoint;
  178. // Fill in anchor point.
  179. windowAnchorPoint.x = left;
  180. windowAnchorPoint.y = top;
  181. // Get the nearest monitor to this window.
  182. hMonitor = MonitorFromPoint(windowAnchorPoint, MONITOR_DEFAULTTONEAREST);
  183. }
  184. // Get the target monitor info
  185. memset(&monitorInfo, 0, sizeof(MONITORINFO));
  186. monitorInfo.cbSize = sizeof(MONITORINFO);
  187. GetMonitorInfo(hMonitor, &monitorInfo);
  188. unsigned int winWidth, winHeight;
  189. winWidth = width;
  190. winHeight = height;
  191. // No specified top left -> Center the window in the middle of the monitor
  192. if (left == INT_MAX || top == INT_MAX)
  193. {
  194. int screenw = monitorInfo.rcWork.right - monitorInfo.rcWork.left;
  195. int screenh = monitorInfo.rcWork.bottom - monitorInfo.rcWork.top;
  196. // clamp window dimensions to screen size
  197. int outerw = (winWidth < screenw)? winWidth : screenw;
  198. int outerh = (winHeight < screenh)? winHeight : screenh;
  199. if (left == INT_MAX)
  200. left = monitorInfo.rcWork.left + (screenw - outerw) / 2;
  201. else if (monitorIndex != -1)
  202. left += monitorInfo.rcWork.left;
  203. if (top == INT_MAX)
  204. top = monitorInfo.rcWork.top + (screenh - outerh) / 2;
  205. else if (monitorIndex != -1)
  206. top += monitorInfo.rcWork.top;
  207. }
  208. else if (monitorIndex != -1)
  209. {
  210. left += monitorInfo.rcWork.left;
  211. top += monitorInfo.rcWork.top;
  212. }
  213. mWidth = mDesiredWidth = width;
  214. mHeight = mDesiredHeight = height;
  215. mTop = top;
  216. mLeft = left;
  217. if (fullScreen)
  218. {
  219. dwStyleEx |= WS_EX_TOPMOST;
  220. dwStyle |= WS_POPUP;
  221. mTop = monitorInfo.rcMonitor.top;
  222. mLeft = monitorInfo.rcMonitor.left;
  223. }
  224. else
  225. {
  226. if (parentHWnd)
  227. {
  228. dwStyle |= WS_CHILD;
  229. }
  230. else
  231. {
  232. if (border == "none")
  233. dwStyle |= WS_POPUP;
  234. else if (border == "fixed")
  235. dwStyle |= WS_OVERLAPPED | WS_BORDER | WS_CAPTION |
  236. WS_SYSMENU | WS_MINIMIZEBOX;
  237. else
  238. dwStyle |= WS_OVERLAPPEDWINDOW;
  239. }
  240. adjustWindow(width, height, dwStyle, &winWidth, &winHeight);
  241. if (!outerSize)
  242. {
  243. // Calculate window dimensions required
  244. // to get the requested client area
  245. SetRect(&rc, 0, 0, mWidth, mHeight);
  246. AdjustWindowRect(&rc, dwStyle, false);
  247. mWidth = rc.right - rc.left;
  248. mHeight = rc.bottom - rc.top;
  249. // Clamp window rect to the nearest display monitor.
  250. if (mLeft < monitorInfo.rcWork.left)
  251. mLeft = monitorInfo.rcWork.left;
  252. if (mTop < monitorInfo.rcWork.top)
  253. mTop = monitorInfo.rcWork.top;
  254. if (static_cast<int>(winWidth) > monitorInfo.rcWork.right - mLeft)
  255. winWidth = monitorInfo.rcWork.right - mLeft;
  256. if (static_cast<int>(winHeight) > monitorInfo.rcWork.bottom - mTop)
  257. winHeight = monitorInfo.rcWork.bottom - mTop;
  258. }
  259. }
  260. // Register the window class
  261. // NB allow 4 bytes of window data for D3D9RenderWindow pointer
  262. WNDCLASS wc = { 0, WindowEventUtilities::_WndProc, 0, 0, hInst,
  263. LoadIcon(0, IDI_APPLICATION), LoadCursor(NULL, IDC_ARROW),
  264. (HBRUSH)GetStockObject(BLACK_BRUSH), 0, "OgreD3D9Wnd" };
  265. RegisterClass(&wc);
  266. // Create our main window
  267. // Pass pointer to self
  268. mIsExternal = false;
  269. mHWnd = CreateWindowEx(dwStyleEx, "OgreD3D9Wnd", title.c_str(), dwStyle,
  270. mLeft, mTop, winWidth, winHeight, parentHWnd, 0, hInst, this);
  271. mStyle = dwStyle;
  272. WindowEventUtilities::_addRenderWindow(this);
  273. }
  274. else
  275. {
  276. mHWnd = externalHandle;
  277. mIsExternal = true;
  278. }
  279. RECT rc;
  280. // top and left represent outer window coordinates
  281. GetWindowRect(mHWnd, &rc);
  282. mTop = rc.top;
  283. mLeft = rc.left;
  284. // width and height represent interior drawable area
  285. GetClientRect(mHWnd, &rc);
  286. mWidth = rc.right;
  287. mHeight = rc.bottom;
  288. mName = name;
  289. mIsDepthBuffered = depthBuffer;
  290. mIsFullScreen = fullScreen;
  291. mColourDepth = colourDepth;
  292. mActive = true;
  293. mClosed = false;
  294. }
  295. void D3D9RenderWindow::setFullscreen(bool fullScreen, unsigned int width, unsigned int height)
  296. {
  297. if (fullScreen != mIsFullScreen || width != mWidth || height != mHeight)
  298. {
  299. if (fullScreen != mIsFullScreen)
  300. mSwitchingFullscreen = true;
  301. mStyle = WS_VISIBLE | WS_CLIPCHILDREN;
  302. bool oldFullscreen = mIsFullScreen;
  303. mIsFullScreen = fullScreen;
  304. mWidth = mDesiredWidth = width;
  305. mHeight = mDesiredHeight = height;
  306. if (fullScreen)
  307. {
  308. mStyle |= WS_POPUP;
  309. // Get the nearest monitor to this window.
  310. HMONITOR hMonitor = MonitorFromWindow(mHWnd, MONITOR_DEFAULTTONEAREST);
  311. // Get monitor info
  312. MONITORINFO monitorInfo;
  313. memset(&monitorInfo, 0, sizeof(MONITORINFO));
  314. monitorInfo.cbSize = sizeof(MONITORINFO);
  315. GetMonitorInfo(hMonitor, &monitorInfo);
  316. mTop = monitorInfo.rcMonitor.top;
  317. mLeft = monitorInfo.rcMonitor.left;
  318. // need different ordering here
  319. if (oldFullscreen)
  320. {
  321. // was previously fullscreen, just changing the resolution
  322. SetWindowPos(mHWnd, HWND_TOPMOST, mLeft, mTop, width, height, SWP_NOACTIVATE);
  323. }
  324. else
  325. {
  326. SetWindowPos(mHWnd, HWND_TOPMOST, mLeft, mTop, width, height, SWP_NOACTIVATE);
  327. //MoveWindow(mHWnd, mLeft, mTop, mWidth, mHeight, FALSE);
  328. SetWindowLong(mHWnd, GWL_STYLE, mStyle);
  329. SetWindowPos(mHWnd, 0, 0,0, 0,0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
  330. }
  331. }
  332. else
  333. {
  334. mStyle |= WS_OVERLAPPEDWINDOW;
  335. // Calculate window dimensions required
  336. // to get the requested client area
  337. unsigned int winWidth, winHeight;
  338. adjustWindow(mWidth, mHeight, mStyle, &winWidth, &winHeight);
  339. SetWindowLong(mHWnd, GWL_STYLE, mStyle);
  340. SetWindowPos(mHWnd, HWND_NOTOPMOST, 0, 0, winWidth, winHeight,
  341. SWP_DRAWFRAME | SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOACTIVATE);
  342. // Note that we also set the position in the restoreLostDevice method
  343. // via _finishSwitchingFullScreen
  344. }
  345. // Have to release & trigger device reset
  346. // NB don't use windowMovedOrResized since Win32 doesn't know
  347. // about the size change yet
  348. mDevice->invalidate(this);
  349. // Notify viewports of resize
  350. ViewportList::iterator it = mViewportList.begin();
  351. while(it != mViewportList.end()) (*it++).second->_updateDimensions();
  352. }
  353. }
  354. void D3D9RenderWindow::adjustWindow(unsigned int clientWidth, unsigned int clientHeight,
  355. DWORD style, unsigned int* winWidth, unsigned int* winHeight)
  356. {
  357. // NB only call this for non full screen
  358. RECT rc;
  359. SetRect(&rc, 0, 0, clientWidth, clientHeight);
  360. AdjustWindowRect(&rc, style, false);
  361. *winWidth = rc.right - rc.left;
  362. *winHeight = rc.bottom - rc.top;
  363. // adjust to monitor
  364. HMONITOR hMonitor = MonitorFromWindow(mHWnd, MONITOR_DEFAULTTONEAREST);
  365. // Get monitor info
  366. MONITORINFO monitorInfo;
  367. memset(&monitorInfo, 0, sizeof(MONITORINFO));
  368. monitorInfo.cbSize = sizeof(MONITORINFO);
  369. GetMonitorInfo(hMonitor, &monitorInfo);
  370. LONG maxW = monitorInfo.rcWork.right - monitorInfo.rcWork.left;
  371. LONG maxH = monitorInfo.rcWork.bottom - monitorInfo.rcWork.top;
  372. if (*winWidth > (unsigned int)maxW)
  373. *winWidth = maxW;
  374. if (*winHeight > (unsigned int)maxH)
  375. *winHeight = maxH;
  376. }
  377. void D3D9RenderWindow::_finishSwitchingFullscreen()
  378. {
  379. if(mIsFullScreen)
  380. {
  381. // Need to reset the region on the window sometimes, when the
  382. // windowed mode was constrained by desktop
  383. HRGN hRgn = CreateRectRgn(0,0,mWidth, mHeight);
  384. SetWindowRgn(mHWnd, hRgn, FALSE);
  385. }
  386. else
  387. {
  388. // When switching back to windowed mode, need to reset window size
  389. // after device has been restored
  390. // We may have had a resize event which polluted our desired sizes
  391. unsigned int winWidth, winHeight;
  392. adjustWindow(mDesiredWidth, mDesiredHeight, mStyle, &winWidth, &winHeight);
  393. // deal with centreing when switching down to smaller resolution
  394. HMONITOR hMonitor = MonitorFromWindow(mHWnd, MONITOR_DEFAULTTONEAREST);
  395. MONITORINFO monitorInfo;
  396. memset(&monitorInfo, 0, sizeof(MONITORINFO));
  397. monitorInfo.cbSize = sizeof(MONITORINFO);
  398. GetMonitorInfo(hMonitor, &monitorInfo);
  399. LONG screenw = monitorInfo.rcWork.right - monitorInfo.rcWork.left;
  400. LONG screenh = monitorInfo.rcWork.bottom - monitorInfo.rcWork.top;
  401. int left = screenw > winWidth ? ((screenw - winWidth) / 2) : 0;
  402. int top = screenh > winHeight ? ((screenh - winHeight) / 2) : 0;
  403. SetWindowPos(mHWnd, HWND_NOTOPMOST, left, top, winWidth, winHeight,
  404. SWP_DRAWFRAME | SWP_FRAMECHANGED | SWP_NOACTIVATE);
  405. if (mWidth != mDesiredWidth ||
  406. mHeight != mDesiredHeight)
  407. {
  408. mWidth = mDesiredWidth;
  409. mHeight = mDesiredHeight;
  410. // Notify viewports of resize
  411. ViewportList::iterator it = mViewportList.begin();
  412. while( it != mViewportList.end() )
  413. (*it++).second->_updateDimensions();
  414. }
  415. }
  416. mSwitchingFullscreen = false;
  417. }
  418. void D3D9RenderWindow::buildPresentParameters(D3DPRESENT_PARAMETERS* presentParams)
  419. {
  420. // Set up the presentation parameters
  421. IDirect3D9* pD3D = D3D9RenderSystem::getDirect3D9();
  422. D3DDEVTYPE devType = D3DDEVTYPE_HAL;
  423. if (mDevice != NULL)
  424. devType = mDevice->getDeviceType();
  425. ZeroMemory( presentParams, sizeof(D3DPRESENT_PARAMETERS) );
  426. presentParams->Windowed = !mIsFullScreen;
  427. presentParams->SwapEffect = D3DSWAPEFFECT_DISCARD;
  428. // triple buffer if VSync is on
  429. presentParams->BackBufferCount = mVSync ? 2 : 1;
  430. presentParams->EnableAutoDepthStencil = mIsDepthBuffered;
  431. presentParams->hDeviceWindow = mHWnd;
  432. presentParams->BackBufferWidth = mWidth;
  433. presentParams->BackBufferHeight = mHeight;
  434. presentParams->FullScreen_RefreshRateInHz = mIsFullScreen ? mDisplayFrequency : 0;
  435. if (presentParams->BackBufferWidth == 0)
  436. presentParams->BackBufferWidth = 1;
  437. if (presentParams->BackBufferHeight == 0)
  438. presentParams->BackBufferHeight = 1;
  439. if (mVSync)
  440. {
  441. // D3D9 only seems to support 2-4 presentation intervals in fullscreen
  442. if (mIsFullScreen)
  443. {
  444. switch(mVSyncInterval)
  445. {
  446. case 1:
  447. default:
  448. presentParams->PresentationInterval = D3DPRESENT_INTERVAL_ONE;
  449. break;
  450. case 2:
  451. presentParams->PresentationInterval = D3DPRESENT_INTERVAL_TWO;
  452. break;
  453. case 3:
  454. presentParams->PresentationInterval = D3DPRESENT_INTERVAL_THREE;
  455. break;
  456. case 4:
  457. presentParams->PresentationInterval = D3DPRESENT_INTERVAL_FOUR;
  458. break;
  459. };
  460. // check that the interval was supported, revert to 1 to be safe otherwise
  461. D3DCAPS9 caps;
  462. pD3D->GetDeviceCaps(mDevice->getAdapterNumber(), devType, &caps);
  463. if (!(caps.PresentationIntervals & presentParams->PresentationInterval))
  464. presentParams->PresentationInterval = D3DPRESENT_INTERVAL_ONE;
  465. }
  466. else
  467. {
  468. presentParams->PresentationInterval = D3DPRESENT_INTERVAL_ONE;
  469. }
  470. }
  471. else
  472. {
  473. // NB not using vsync in windowed mode in D3D9 can cause jerking at low
  474. // frame rates no matter what buffering modes are used (odd - perhaps a
  475. // timer issue in D3D9 since GL doesn't suffer from this)
  476. // low is < 200fps in this context
  477. if (!mIsFullScreen)
  478. {
  479. // TODO PORT - Enable this warning later?
  480. //LogManager::getSingleton().logMessage("D3D9 : WARNING - "
  481. // "disabling VSync in windowed mode can cause timing issues at lower "
  482. // "frame rates, turn VSync on if you observe this problem.");
  483. }
  484. presentParams->PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
  485. }
  486. presentParams->BackBufferFormat = D3DFMT_R5G6B5;
  487. if( mColourDepth > 16 )
  488. presentParams->BackBufferFormat = D3DFMT_X8R8G8B8;
  489. if (mColourDepth > 16 )
  490. {
  491. // Try to create a 32-bit depth, 8-bit stencil
  492. if( FAILED( pD3D->CheckDeviceFormat(mDevice->getAdapterNumber(),
  493. devType, presentParams->BackBufferFormat, D3DUSAGE_DEPTHSTENCIL,
  494. D3DRTYPE_SURFACE, D3DFMT_D24S8 )))
  495. {
  496. // Bugger, no 8-bit hardware stencil, just try 32-bit zbuffer
  497. if( FAILED( pD3D->CheckDeviceFormat(mDevice->getAdapterNumber(),
  498. devType, presentParams->BackBufferFormat, D3DUSAGE_DEPTHSTENCIL,
  499. D3DRTYPE_SURFACE, D3DFMT_D32 )))
  500. {
  501. // Jeez, what a naff card. Fall back on 16-bit depth buffering
  502. presentParams->AutoDepthStencilFormat = D3DFMT_D16;
  503. }
  504. else
  505. presentParams->AutoDepthStencilFormat = D3DFMT_D32;
  506. }
  507. else
  508. {
  509. // Woohoo!
  510. if( SUCCEEDED( pD3D->CheckDepthStencilMatch( mDevice->getAdapterNumber(), devType,
  511. presentParams->BackBufferFormat, presentParams->BackBufferFormat, D3DFMT_D24S8 ) ) )
  512. {
  513. presentParams->AutoDepthStencilFormat = D3DFMT_D24S8;
  514. }
  515. else
  516. presentParams->AutoDepthStencilFormat = D3DFMT_D24X8;
  517. }
  518. }
  519. else
  520. // 16-bit depth, software stencil
  521. presentParams->AutoDepthStencilFormat = D3DFMT_D16;
  522. // TODO PORT - Enable this once I have RenderSystem singleton set up. For now set no FSAA
  523. //D3D9RenderSystem* rsys = static_cast<D3D9RenderSystem*>(Root::getSingleton().getRenderSystem());
  524. //
  525. //rsys->determineFSAASettings(mDevice->getD3D9Device(),
  526. // mFSAA, mFSAAHint, presentParams->BackBufferFormat, mIsFullScreen,
  527. // &mFSAAType, &mFSAAQuality);
  528. mFSAAType = D3DMULTISAMPLE_NONE;
  529. mFSAAQuality = 0;
  530. presentParams->MultiSampleType = mFSAAType;
  531. presentParams->MultiSampleQuality = (mFSAAQuality == 0) ? 0 : mFSAAQuality;
  532. // Check sRGB
  533. if (mHwGamma)
  534. {
  535. /* hmm, this never succeeds even when device does support??
  536. if(FAILED(pD3D->CheckDeviceFormat(mDriver->getAdapterNumber(),
  537. devType, presentParams->BackBufferFormat, D3DUSAGE_QUERY_SRGBWRITE,
  538. D3DRTYPE_SURFACE, presentParams->BackBufferFormat )))
  539. {
  540. // disable - not supported
  541. mHwGamma = false;
  542. }
  543. */
  544. }
  545. }
  546. void D3D9RenderWindow::destroy()
  547. {
  548. if (mDevice != NULL)
  549. {
  550. mDevice->detachRenderWindow(this);
  551. mDevice = NULL;
  552. }
  553. if (mHWnd && !mIsExternal)
  554. {
  555. WindowEventUtilities::_removeRenderWindow(this);
  556. DestroyWindow(mHWnd);
  557. }
  558. mHWnd = 0;
  559. mActive = false;
  560. mClosed = true;
  561. }
  562. bool D3D9RenderWindow::isActive() const
  563. {
  564. if (isFullScreen())
  565. return isVisible();
  566. return mActive && isVisible();
  567. }
  568. bool D3D9RenderWindow::isVisible() const
  569. {
  570. return (mHWnd && !IsIconic(mHWnd));
  571. }
  572. void D3D9RenderWindow::reposition(int top, int left)
  573. {
  574. if (mHWnd && !mIsFullScreen)
  575. {
  576. SetWindowPos(mHWnd, 0, top, left, 0, 0,
  577. SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
  578. }
  579. }
  580. void D3D9RenderWindow::resize(unsigned int width, unsigned int height)
  581. {
  582. if (mHWnd && !mIsFullScreen)
  583. {
  584. unsigned int winWidth, winHeight;
  585. adjustWindow(width, height, mStyle, &winWidth, &winHeight);
  586. SetWindowPos(mHWnd, 0, 0, 0, winWidth, winHeight,
  587. SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
  588. }
  589. }
  590. void D3D9RenderWindow::windowMovedOrResized()
  591. {
  592. if (!mHWnd || IsIconic(mHWnd))
  593. return;
  594. updateWindowRect();
  595. }
  596. void D3D9RenderWindow::swapBuffers( bool waitForVSync )
  597. {
  598. if (mDeviceValid)
  599. mDevice->present(this);
  600. }
  601. void D3D9RenderWindow::getCustomAttribute( const String& name, void* pData )
  602. {
  603. // Valid attributes and their equvalent native functions:
  604. // D3DDEVICE : getD3DDevice
  605. // WINDOW : getWindowHandle
  606. if( name == "D3DDEVICE" )
  607. {
  608. IDirect3DDevice9* *pDev = (IDirect3DDevice9**)pData;
  609. *pDev = getD3D9Device();
  610. return;
  611. }
  612. else if( name == "WINDOW" )
  613. {
  614. HWND *pHwnd = (HWND*)pData;
  615. *pHwnd = getWindowHandle();
  616. return;
  617. }
  618. else if( name == "isTexture" )
  619. {
  620. bool *b = reinterpret_cast< bool * >( pData );
  621. *b = false;
  622. return;
  623. }
  624. else if( name == "D3DZBUFFER" )
  625. {
  626. IDirect3DSurface9* *pSurf = (IDirect3DSurface9**)pData;
  627. *pSurf = mDevice->getDepthBuffer(this);
  628. return;
  629. }
  630. else if( name == "DDBACKBUFFER" )
  631. {
  632. IDirect3DSurface9* *pSurf = (IDirect3DSurface9**)pData;
  633. *pSurf = mDevice->getBackBuffer(this);
  634. return;
  635. }
  636. else if( name == "DDFRONTBUFFER" )
  637. {
  638. IDirect3DSurface9* *pSurf = (IDirect3DSurface9**)pData;
  639. *pSurf = mDevice->getBackBuffer(this);
  640. return;
  641. }
  642. }
  643. void D3D9RenderWindow::copyContentsToMemory(const PixelBox &dst, FrameBuffer buffer)
  644. {
  645. mDevice->copyContentsToMemory(this, dst, buffer);
  646. }
  647. //-----------------------------------------------------------------------------
  648. void D3D9RenderWindow::_beginUpdate()
  649. {
  650. // External windows should update per frame
  651. // since it dosen't get the window resize/move messages.
  652. if (mIsExternal)
  653. {
  654. updateWindowRect();
  655. }
  656. if (mWidth == 0 || mHeight == 0)
  657. {
  658. mDeviceValid = false;
  659. return;
  660. }
  661. D3D9RenderSystem::getDeviceManager()->setActiveRenderTargetDevice(mDevice);
  662. // Check that device can be used for rendering operations.
  663. mDeviceValid = mDevice->validate(this);
  664. if (mDeviceValid)
  665. {
  666. // Finish window / fullscreen mode switch.
  667. if (_getSwitchingFullscreen())
  668. {
  669. _finishSwitchingFullscreen();
  670. // have to re-validate since this may have altered dimensions
  671. mDeviceValid = mDevice->validate(this);
  672. }
  673. }
  674. RenderWindow::_beginUpdate();
  675. }
  676. //---------------------------------------------------------------------
  677. void D3D9RenderWindow::_updateViewport(Viewport* viewport, bool updateStatistics)
  678. {
  679. if (mDeviceValid)
  680. {
  681. RenderWindow::_updateViewport(viewport, updateStatistics);
  682. }
  683. }
  684. //---------------------------------------------------------------------
  685. void D3D9RenderWindow::_endUpdate()
  686. {
  687. RenderWindow::_endUpdate();
  688. D3D9RenderSystem::getDeviceManager()->setActiveRenderTargetDevice(NULL);
  689. }
  690. //-----------------------------------------------------------------------------
  691. IDirect3DDevice9* D3D9RenderWindow::getD3D9Device()
  692. {
  693. return mDevice->getD3D9Device();
  694. }
  695. //-----------------------------------------------------------------------------
  696. IDirect3DSurface9* D3D9RenderWindow::getRenderSurface()
  697. {
  698. return mDevice->getBackBuffer(this);
  699. }
  700. //-----------------------------------------------------------------------------
  701. bool D3D9RenderWindow::_getSwitchingFullscreen() const
  702. {
  703. return mSwitchingFullscreen;
  704. }
  705. //-----------------------------------------------------------------------------
  706. D3D9Device* D3D9RenderWindow::getDevice()
  707. {
  708. return mDevice;
  709. }
  710. //-----------------------------------------------------------------------------
  711. void D3D9RenderWindow::setDevice(D3D9Device* device)
  712. {
  713. mDevice = device;
  714. mDeviceValid = false;
  715. }
  716. //-----------------------------------------------------------------------------
  717. bool D3D9RenderWindow::isDepthBuffered() const
  718. {
  719. return mIsDepthBuffered;
  720. }
  721. //-----------------------------------------------------------------------------
  722. void D3D9RenderWindow::updateWindowRect()
  723. {
  724. RECT rc;
  725. BOOL result;
  726. // Update top left parameters
  727. result = GetWindowRect(mHWnd, &rc);
  728. if (result == FALSE)
  729. {
  730. mTop = 0;
  731. mLeft = 0;
  732. mWidth = 0;
  733. mHeight = 0;
  734. return;
  735. }
  736. mTop = rc.top;
  737. mLeft = rc.left;
  738. // width and height represent drawable area only
  739. result = GetClientRect(mHWnd, &rc);
  740. if (result == FALSE)
  741. {
  742. mTop = 0;
  743. mLeft = 0;
  744. mWidth = 0;
  745. mHeight = 0;
  746. return;
  747. }
  748. unsigned int width = rc.right - rc.left;
  749. unsigned int height = rc.bottom - rc.top;
  750. // Case window resized.
  751. if (width != mWidth || height != mHeight)
  752. {
  753. mWidth = rc.right - rc.left;
  754. mHeight = rc.bottom - rc.top;
  755. // Notify viewports of resize
  756. ViewportList::iterator it = mViewportList.begin();
  757. while( it != mViewportList.end() )
  758. (*it++).second->_updateDimensions();
  759. }
  760. }
  761. //-----------------------------------------------------------------------------
  762. bool D3D9RenderWindow::isNvPerfHUDEnable() const
  763. {
  764. return mUseNVPerfHUD;
  765. }
  766. //---------------------------------------------------------------------
  767. bool D3D9RenderWindow::_validateDevice()
  768. {
  769. mDeviceValid = mDevice->validate(this);
  770. return mDeviceValid;
  771. }
  772. }