BsD3D9RenderWindow.cpp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797
  1. #include "BsD3D9RenderWindow.h"
  2. #include "BsInput.h"
  3. #include "BsCoreThread.h"
  4. #include "BsViewport.h"
  5. #include "BsException.h"
  6. #include "BsD3D9RenderAPI.h"
  7. #include "BsRenderAPI.h"
  8. #include "BsBitwise.h"
  9. #include "Win32/BsWin32Platform.h"
  10. #include "BsD3D9VideoModeInfo.h"
  11. #include "BsD3D9DeviceManager.h"
  12. #include "BsRenderWindowManager.h"
  13. namespace BansheeEngine
  14. {
  15. D3D9RenderWindowProperties::D3D9RenderWindowProperties(const RENDER_WINDOW_DESC& desc)
  16. :RenderWindowProperties(desc)
  17. {
  18. }
  19. D3D9RenderWindowCore::D3D9RenderWindowCore(const RENDER_WINDOW_DESC& desc, UINT32 windowId, HINSTANCE instance)
  20. : RenderWindowCore(desc, windowId), mInstance(instance), mProperties(desc), mSyncedProperties(desc), mIsDepthBuffered(true), mIsChild(false), mHWnd(0),
  21. mStyle(0), mWindowedStyle(0), mWindowedStyleEx(0), mDevice(nullptr), mIsExternal(false), mDisplayFrequency(0), mDeviceValid(false)
  22. { }
  23. D3D9RenderWindowCore::~D3D9RenderWindowCore()
  24. {
  25. if (mDevice != nullptr)
  26. {
  27. mDevice->detachRenderWindow(this);
  28. mDevice = nullptr;
  29. }
  30. if (mHWnd && !mIsExternal)
  31. {
  32. DestroyWindow(mHWnd);
  33. }
  34. mHWnd = 0;
  35. mProperties.mActive = false;
  36. }
  37. void D3D9RenderWindowCore::initialize()
  38. {
  39. RenderWindowCore::initialize();
  40. HINSTANCE hInst = mInstance;
  41. mMultisampleType = D3DMULTISAMPLE_NONE;
  42. mMultisampleQuality = 0;
  43. mDisplayFrequency = Math::roundToInt(mDesc.videoMode.getRefreshRate());
  44. HWND parentHWnd = 0;
  45. HWND externalHandle = 0;
  46. NameValuePairList::const_iterator opt;
  47. opt = mDesc.platformSpecific.find("parentWindowHandle");
  48. if (opt != mDesc.platformSpecific.end())
  49. parentHWnd = (HWND)parseUnsignedInt(opt->second);
  50. opt = mDesc.platformSpecific.find("externalWindowHandle");
  51. if (opt != mDesc.platformSpecific.end())
  52. externalHandle = (HWND)parseUnsignedInt(opt->second);
  53. mIsChild = parentHWnd != 0;
  54. mWindowedStyle = WS_VISIBLE | WS_CLIPCHILDREN;
  55. mWindowedStyleEx = 0;
  56. if (!mDesc.fullscreen || mIsChild)
  57. {
  58. if (parentHWnd)
  59. {
  60. if (mDesc.toolWindow)
  61. mWindowedStyleEx = WS_EX_TOOLWINDOW;
  62. else
  63. mWindowedStyle |= WS_CHILD;
  64. }
  65. if (!parentHWnd || mDesc.toolWindow)
  66. {
  67. if (mDesc.border == WindowBorder::None)
  68. mWindowedStyle |= WS_POPUP;
  69. else if (mDesc.border == WindowBorder::Fixed)
  70. mWindowedStyle |= WS_OVERLAPPED | WS_BORDER | WS_CAPTION |
  71. WS_SYSMENU | WS_MINIMIZEBOX;
  72. else
  73. mWindowedStyle |= WS_OVERLAPPEDWINDOW;
  74. }
  75. }
  76. D3D9RenderWindowProperties& props = mProperties;
  77. if (!externalHandle)
  78. {
  79. MONITORINFO monitorInfo;
  80. RECT rc;
  81. HMONITOR hMonitor = NULL;
  82. const D3D9VideoModeInfo& videoModeInfo = static_cast<const D3D9VideoModeInfo&>(RenderAPICore::instance().getVideoModeInfo());
  83. UINT32 numOutputs = videoModeInfo.getNumOutputs();
  84. if (numOutputs > 0)
  85. {
  86. UINT32 actualMonitorIdx = std::min(mDesc.videoMode.getOutputIdx(), numOutputs - 1);
  87. const D3D9VideoOutputInfo& outputInfo = static_cast<const D3D9VideoOutputInfo&>(videoModeInfo.getOutputInfo(actualMonitorIdx));
  88. hMonitor = outputInfo.getMonitorHandle();
  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.videoMode.getWidth();
  106. winHeight = mDesc.videoMode.getHeight();
  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 (hMonitor != NULL)
  120. left += monitorInfo.rcWork.left;
  121. if (top == -1)
  122. top = monitorInfo.rcWork.top + (screenh - outerh) / 2;
  123. else if (hMonitor != NULL)
  124. top += monitorInfo.rcWork.top;
  125. }
  126. else if (hMonitor != NULL)
  127. {
  128. left += monitorInfo.rcWork.left;
  129. top += monitorInfo.rcWork.top;
  130. }
  131. props.mWidth = mDesc.videoMode.getWidth();
  132. props.mHeight = mDesc.videoMode.getHeight();
  133. props.mTop = top;
  134. props.mLeft = left;
  135. DWORD dwStyle = 0;
  136. DWORD dwStyleEx = 0;
  137. if (mDesc.fullscreen && !mIsChild)
  138. {
  139. dwStyle = WS_VISIBLE | WS_CLIPCHILDREN | WS_POPUP;
  140. props.mTop = monitorInfo.rcMonitor.top;
  141. props.mLeft = monitorInfo.rcMonitor.left;
  142. }
  143. else
  144. {
  145. dwStyle = mWindowedStyle;
  146. dwStyleEx = mWindowedStyleEx;
  147. getAdjustedWindowSize(mDesc.videoMode.getWidth(), mDesc.videoMode.getHeight(), dwStyle, &winWidth, &winHeight);
  148. if (!mDesc.outerDimensions)
  149. {
  150. // Calculate window dimensions required
  151. // to get the requested client area
  152. SetRect(&rc, 0, 0, props.mWidth, props.mHeight);
  153. AdjustWindowRect(&rc, dwStyle, false);
  154. props.mWidth = rc.right - rc.left;
  155. props.mHeight = rc.bottom - rc.top;
  156. // Clamp window rect to the nearest display monitor.
  157. if (props.mLeft < monitorInfo.rcWork.left)
  158. props.mLeft = monitorInfo.rcWork.left;
  159. if (props.mTop < monitorInfo.rcWork.top)
  160. props.mTop = monitorInfo.rcWork.top;
  161. if (static_cast<int>(winWidth) > monitorInfo.rcWork.right - props.mLeft)
  162. winWidth = monitorInfo.rcWork.right - props.mLeft;
  163. if (static_cast<int>(winHeight) > monitorInfo.rcWork.bottom - props.mTop)
  164. winHeight = monitorInfo.rcWork.bottom - props.mTop;
  165. }
  166. }
  167. UINT classStyle = 0;
  168. if (mDesc.enableDoubleClick)
  169. classStyle |= CS_DBLCLKS;
  170. // Register the window class
  171. WNDCLASS wc = { classStyle, Win32Platform::_win32WndProc, 0, 0, hInst,
  172. LoadIcon(0, IDI_APPLICATION), LoadCursor(NULL, IDC_ARROW),
  173. (HBRUSH)GetStockObject(BLACK_BRUSH), 0, "D3D9Wnd" };
  174. RegisterClass(&wc);
  175. // Create our main window
  176. // Pass pointer to self
  177. mIsExternal = false;
  178. mHWnd = CreateWindowEx(dwStyleEx, "D3D9Wnd", mDesc.title.c_str(), dwStyle,
  179. props.mLeft, props.mTop, winWidth, winHeight, parentHWnd, 0, hInst, this);
  180. mStyle = dwStyle;
  181. }
  182. else
  183. {
  184. mHWnd = externalHandle;
  185. mIsExternal = true;
  186. }
  187. RECT rc;
  188. GetWindowRect(mHWnd, &rc);
  189. props.mTop = rc.top;
  190. props.mLeft = rc.left;
  191. GetClientRect(mHWnd, &rc);
  192. props.mWidth = rc.right;
  193. props.mHeight = rc.bottom;
  194. mIsDepthBuffered = mDesc.depthBuffer;
  195. props.mIsFullScreen = mDesc.fullscreen && !mIsChild;
  196. props.mColorDepth = 32;
  197. props.mActive = true;
  198. D3D9RenderAPI* rs = static_cast<D3D9RenderAPI*>(RenderAPICore::instancePtr());
  199. rs->registerWindow(*this);
  200. {
  201. ScopedSpinLock lock(mLock);
  202. mSyncedProperties = props;
  203. }
  204. RenderWindowManager::instance().notifySyncDataDirty(this);
  205. }
  206. void D3D9RenderWindowCore::setFullscreen(UINT32 width, UINT32 height, float refreshRate, UINT32 monitorIdx)
  207. {
  208. THROW_IF_NOT_CORE_THREAD;
  209. if (mIsChild)
  210. return;
  211. const D3D9VideoModeInfo& videoModeInfo = static_cast<const D3D9VideoModeInfo&>(RenderAPICore::instance().getVideoModeInfo());
  212. UINT32 numOutputs = videoModeInfo.getNumOutputs();
  213. if (numOutputs == 0)
  214. return;
  215. UINT32 actualMonitorIdx = std::min(monitorIdx, numOutputs - 1);
  216. const D3D9VideoOutputInfo& outputInfo = static_cast<const D3D9VideoOutputInfo&>(videoModeInfo.getOutputInfo(actualMonitorIdx));
  217. D3D9RenderWindowProperties& props = mProperties;
  218. bool oldFullscreen = props.mIsFullScreen;
  219. props.mWidth = width;
  220. props.mHeight = height;
  221. mDisplayFrequency = Math::roundToInt(refreshRate);
  222. props.mIsFullScreen = true;
  223. HMONITOR hMonitor = outputInfo.getMonitorHandle();
  224. MONITORINFO monitorInfo;
  225. memset(&monitorInfo, 0, sizeof(MONITORINFO));
  226. monitorInfo.cbSize = sizeof(MONITORINFO);
  227. GetMonitorInfo(hMonitor, &monitorInfo);
  228. props.mTop = monitorInfo.rcMonitor.top;
  229. props.mLeft = monitorInfo.rcMonitor.left;
  230. // Invalidate device, which resets it
  231. mDevice->invalidate(this);
  232. mDevice->acquire();
  233. {
  234. ScopedSpinLock lock(mLock);
  235. mSyncedProperties.mTop = props.mTop;
  236. mSyncedProperties.mLeft = props.mLeft;
  237. mSyncedProperties.mWidth = props.mWidth;
  238. mSyncedProperties.mHeight = props.mHeight;
  239. }
  240. RenderWindowManager::instance().notifySyncDataDirty(this);
  241. RenderWindowManager::instance().notifyMovedOrResized(this);
  242. }
  243. void D3D9RenderWindowCore::setFullscreen(const VideoMode& mode)
  244. {
  245. THROW_IF_NOT_CORE_THREAD;
  246. setFullscreen(mode.getWidth(), mode.getHeight(), mode.getRefreshRate(), mode.getOutputIdx());
  247. }
  248. void D3D9RenderWindowCore::setWindowed(UINT32 width, UINT32 height)
  249. {
  250. THROW_IF_NOT_CORE_THREAD;
  251. D3D9RenderWindowProperties& props = mProperties;
  252. if (!props.mIsFullScreen)
  253. return;
  254. props.mIsFullScreen = false;
  255. mStyle = mWindowedStyle;
  256. props.mWidth = width;
  257. props.mHeight = height;
  258. unsigned int winWidth, winHeight;
  259. getAdjustedWindowSize(props.mWidth, props.mHeight, mStyle, &winWidth, &winHeight);
  260. // Deal with centering when switching down to smaller resolution
  261. HMONITOR hMonitor = MonitorFromWindow(mHWnd, MONITOR_DEFAULTTONEAREST);
  262. MONITORINFO monitorInfo;
  263. memset(&monitorInfo, 0, sizeof(MONITORINFO));
  264. monitorInfo.cbSize = sizeof(MONITORINFO);
  265. GetMonitorInfo(hMonitor, &monitorInfo);
  266. LONG screenw = monitorInfo.rcWork.right - monitorInfo.rcWork.left;
  267. LONG screenh = monitorInfo.rcWork.bottom - monitorInfo.rcWork.top;
  268. int left = screenw > int(winWidth) ? ((screenw - int(winWidth)) / 2) : 0;
  269. int top = screenh > int(winHeight) ? ((screenh - int(winHeight)) / 2) : 0;
  270. SetWindowLong(mHWnd, GWL_STYLE, mStyle);
  271. SetWindowLong(mHWnd, GWL_EXSTYLE, mWindowedStyleEx);
  272. SetWindowPos(mHWnd, HWND_NOTOPMOST, left, top, winWidth, winHeight,
  273. SWP_DRAWFRAME | SWP_FRAMECHANGED | SWP_NOACTIVATE);
  274. mDevice->invalidate(this);
  275. mDevice->acquire();
  276. {
  277. ScopedSpinLock lock(mLock);
  278. mSyncedProperties.mTop = props.mTop;
  279. mSyncedProperties.mLeft = props.mLeft;
  280. mSyncedProperties.mWidth = props.mWidth;
  281. mSyncedProperties.mHeight = props.mHeight;
  282. }
  283. RenderWindowManager::instance().notifySyncDataDirty(this);
  284. RenderWindowManager::instance().notifyMovedOrResized(this);
  285. }
  286. void D3D9RenderWindowCore::setHidden(bool hidden)
  287. {
  288. THROW_IF_NOT_CORE_THREAD;
  289. D3D9RenderWindowProperties& props = mProperties;
  290. props.mHidden = hidden;
  291. if (!mIsExternal)
  292. {
  293. if (hidden)
  294. ShowWindow(mHWnd, SW_HIDE);
  295. else
  296. ShowWindow(mHWnd, SW_SHOWNORMAL);
  297. }
  298. RenderWindowCore::setHidden(hidden);
  299. }
  300. void D3D9RenderWindowCore::minimize()
  301. {
  302. THROW_IF_NOT_CORE_THREAD;
  303. if (mHWnd)
  304. SendMessage(mHWnd, WM_SYSCOMMAND, SC_MINIMIZE, 0);
  305. }
  306. void D3D9RenderWindowCore::maximize()
  307. {
  308. THROW_IF_NOT_CORE_THREAD;
  309. if (mHWnd)
  310. SendMessage(mHWnd, WM_SYSCOMMAND, SC_MAXIMIZE, 0);
  311. }
  312. void D3D9RenderWindowCore::restore()
  313. {
  314. THROW_IF_NOT_CORE_THREAD;
  315. if (mHWnd)
  316. SendMessage(mHWnd, WM_SYSCOMMAND, SC_RESTORE, 0);
  317. }
  318. void D3D9RenderWindowCore::move(INT32 top, INT32 left)
  319. {
  320. THROW_IF_NOT_CORE_THREAD;
  321. D3D9RenderWindowProperties& props = mProperties;
  322. if (mHWnd && !props.mIsFullScreen)
  323. {
  324. props.mLeft = left;
  325. props.mTop = top;
  326. SetWindowPos(mHWnd, 0, top, left, 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
  327. {
  328. ScopedSpinLock lock(mLock);
  329. mSyncedProperties.mLeft = props.mLeft;
  330. mSyncedProperties.mTop = props.mTop;
  331. }
  332. RenderWindowManager::instance().notifySyncDataDirty(this);
  333. }
  334. }
  335. void D3D9RenderWindowCore::resize(UINT32 width, UINT32 height)
  336. {
  337. THROW_IF_NOT_CORE_THREAD;
  338. D3D9RenderWindowProperties& props = mProperties;
  339. if (mHWnd && !props.mIsFullScreen)
  340. {
  341. props.mWidth = width;
  342. props.mHeight = height;
  343. unsigned int winWidth, winHeight;
  344. getAdjustedWindowSize(width, height, mStyle, &winWidth, &winHeight);
  345. SetWindowPos(mHWnd, 0, 0, 0, winWidth, winHeight,
  346. SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
  347. {
  348. ScopedSpinLock lock(mLock);
  349. mSyncedProperties.mWidth = props.mWidth;
  350. mSyncedProperties.mHeight = props.mHeight;
  351. }
  352. RenderWindowManager::instance().notifySyncDataDirty(this);
  353. }
  354. }
  355. void D3D9RenderWindowCore::getCustomAttribute(const String& name, void* pData) const
  356. {
  357. // Valid attributes and their equivalent native functions:
  358. // D3DDEVICE : getD3DDevice
  359. // WINDOW : getWindowHandle
  360. if( name == "D3DDEVICE" )
  361. {
  362. IDirect3DDevice9* *pDev = (IDirect3DDevice9**)pData;
  363. *pDev = _getD3D9Device();
  364. return;
  365. }
  366. else if( name == "WINDOW" )
  367. {
  368. UINT64 *pHwnd = (UINT64*)pData;
  369. *pHwnd = (UINT64)_getWindowHandle();
  370. return;
  371. }
  372. else if( name == "isTexture" )
  373. {
  374. bool *b = reinterpret_cast< bool * >( pData );
  375. *b = false;
  376. return;
  377. }
  378. else if( name == "D3DZBUFFER" )
  379. {
  380. IDirect3DSurface9* *pSurf = (IDirect3DSurface9**)pData;
  381. *pSurf = mDevice->getDepthBuffer(this);
  382. return;
  383. }
  384. else if( name == "DDBACKBUFFER" )
  385. {
  386. IDirect3DSurface9* *pSurf = (IDirect3DSurface9**)pData;
  387. *pSurf = mDevice->getBackBuffer(this);
  388. return;
  389. }
  390. else if( name == "DDFRONTBUFFER" )
  391. {
  392. IDirect3DSurface9* *pSurf = (IDirect3DSurface9**)pData;
  393. *pSurf = mDevice->getBackBuffer(this);
  394. return;
  395. }
  396. }
  397. void D3D9RenderWindowCore::swapBuffers()
  398. {
  399. THROW_IF_NOT_CORE_THREAD;
  400. if (mDeviceValid)
  401. mDevice->present(this);
  402. }
  403. void D3D9RenderWindowCore::copyToMemory(PixelData &dst, FrameBuffer buffer)
  404. {
  405. THROW_IF_NOT_CORE_THREAD;
  406. mDevice->copyContentsToMemory(this, dst, buffer);
  407. }
  408. void D3D9RenderWindowCore::_windowMovedOrResized()
  409. {
  410. THROW_IF_NOT_CORE_THREAD;
  411. D3D9RenderWindowProperties& props = mProperties;
  412. if (!mHWnd || IsIconic(mHWnd))
  413. return;
  414. updateWindowRect();
  415. RenderWindowCore::_windowMovedOrResized();
  416. }
  417. /************************************************************************/
  418. /* D3D9 IMPLEMENTATION SPECIFIC */
  419. /************************************************************************/
  420. void D3D9RenderWindowCore::getAdjustedWindowSize(UINT32 clientWidth, UINT32 clientHeight,
  421. DWORD style, UINT32* winWidth, UINT32* winHeight)
  422. {
  423. D3D9RenderWindowProperties& props = mProperties;
  424. RECT rc;
  425. SetRect(&rc, 0, 0, clientWidth, clientHeight);
  426. AdjustWindowRect(&rc, style, false);
  427. *winWidth = rc.right - rc.left;
  428. *winHeight = rc.bottom - rc.top;
  429. HMONITOR hMonitor = MonitorFromWindow(mHWnd, MONITOR_DEFAULTTONEAREST);
  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 D3D9RenderWindowCore::_buildPresentParameters(D3DPRESENT_PARAMETERS* presentParams) const
  442. {
  443. const D3D9RenderWindowProperties& props = mProperties;
  444. IDirect3D9* pD3D = D3D9RenderAPI::getDirect3D9();
  445. D3DDEVTYPE devType = D3DDEVTYPE_HAL;
  446. if (mDevice != NULL)
  447. devType = mDevice->getDeviceType();
  448. ZeroMemory( presentParams, sizeof(D3DPRESENT_PARAMETERS) );
  449. presentParams->Windowed = !props.mIsFullScreen;
  450. presentParams->SwapEffect = D3DSWAPEFFECT_DISCARD;
  451. presentParams->BackBufferCount = 1;
  452. presentParams->EnableAutoDepthStencil = mIsDepthBuffered;
  453. presentParams->hDeviceWindow = mHWnd;
  454. presentParams->BackBufferWidth = props.mWidth;
  455. presentParams->BackBufferHeight = props.mHeight;
  456. presentParams->FullScreen_RefreshRateInHz = props.mIsFullScreen ? mDisplayFrequency : 0;
  457. if (presentParams->BackBufferWidth == 0)
  458. presentParams->BackBufferWidth = 1;
  459. if (presentParams->BackBufferHeight == 0)
  460. presentParams->BackBufferHeight = 1;
  461. if (props.getVSync())
  462. {
  463. if (props.isFullScreen())
  464. {
  465. switch(mVSyncInterval)
  466. {
  467. case 1:
  468. default:
  469. presentParams->PresentationInterval = D3DPRESENT_INTERVAL_ONE;
  470. break;
  471. case 2:
  472. presentParams->PresentationInterval = D3DPRESENT_INTERVAL_TWO;
  473. break;
  474. case 3:
  475. presentParams->PresentationInterval = D3DPRESENT_INTERVAL_THREE;
  476. break;
  477. case 4:
  478. presentParams->PresentationInterval = D3DPRESENT_INTERVAL_FOUR;
  479. break;
  480. };
  481. D3DCAPS9 caps;
  482. pD3D->GetDeviceCaps(mDevice->getAdapterNumber(), devType, &caps);
  483. if (!(caps.PresentationIntervals & presentParams->PresentationInterval))
  484. {
  485. presentParams->PresentationInterval = D3DPRESENT_INTERVAL_ONE;
  486. }
  487. }
  488. else
  489. {
  490. presentParams->PresentationInterval = D3DPRESENT_INTERVAL_ONE;
  491. }
  492. }
  493. else
  494. {
  495. presentParams->PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
  496. }
  497. presentParams->BackBufferFormat = D3DFMT_X8R8G8B8;
  498. if (FAILED(pD3D->CheckDeviceFormat(mDevice->getAdapterNumber(),
  499. devType, presentParams->BackBufferFormat, D3DUSAGE_DEPTHSTENCIL,
  500. D3DRTYPE_SURFACE, D3DFMT_D24S8)))
  501. {
  502. if (FAILED(pD3D->CheckDeviceFormat(mDevice->getAdapterNumber(),
  503. devType, presentParams->BackBufferFormat, D3DUSAGE_DEPTHSTENCIL,
  504. D3DRTYPE_SURFACE, D3DFMT_D32)))
  505. {
  506. presentParams->AutoDepthStencilFormat = D3DFMT_D16;
  507. }
  508. else
  509. {
  510. presentParams->AutoDepthStencilFormat = D3DFMT_D32;
  511. }
  512. }
  513. else
  514. {
  515. if (SUCCEEDED(pD3D->CheckDepthStencilMatch(mDevice->getAdapterNumber(), devType,
  516. presentParams->BackBufferFormat, presentParams->BackBufferFormat, D3DFMT_D24S8)))
  517. {
  518. presentParams->AutoDepthStencilFormat = D3DFMT_D24S8;
  519. }
  520. else
  521. {
  522. presentParams->AutoDepthStencilFormat = D3DFMT_D24X8;
  523. }
  524. }
  525. D3D9RenderAPI* rs = static_cast<D3D9RenderAPI*>(BansheeEngine::RenderAPICore::instancePtr());
  526. D3DMULTISAMPLE_TYPE multisampleType;
  527. DWORD multisampleQuality;
  528. rs->determineMultisampleSettings(mDevice->getD3D9Device(), props.getMultisampleCount(),
  529. presentParams->BackBufferFormat, props.isFullScreen(), &multisampleType, &multisampleQuality);
  530. presentParams->MultiSampleType = multisampleType;
  531. presentParams->MultiSampleQuality = (multisampleQuality == 0) ? 0 : multisampleQuality;
  532. }
  533. HWND D3D9RenderWindowCore::_getWindowHandle() const
  534. {
  535. return mHWnd;
  536. }
  537. IDirect3DDevice9* D3D9RenderWindowCore::_getD3D9Device() const
  538. {
  539. return mDevice->getD3D9Device();
  540. }
  541. IDirect3DSurface9* D3D9RenderWindowCore::_getRenderSurface() const
  542. {
  543. return mDevice->getBackBuffer(this);
  544. }
  545. D3D9Device* D3D9RenderWindowCore::_getDevice() const
  546. {
  547. return mDevice;
  548. }
  549. void D3D9RenderWindowCore::_setDevice(D3D9Device* device)
  550. {
  551. mDevice = device;
  552. mDeviceValid = false;
  553. }
  554. bool D3D9RenderWindowCore::_isDepthBuffered() const
  555. {
  556. return mIsDepthBuffered;
  557. }
  558. void D3D9RenderWindowCore::updateWindowRect()
  559. {
  560. RECT rc;
  561. BOOL result;
  562. D3D9RenderWindowProperties& props = mProperties;
  563. // Update top left parameters
  564. result = GetWindowRect(_getWindowHandle(), &rc);
  565. if (result == FALSE)
  566. {
  567. props.mTop = 0;
  568. props.mLeft = 0;
  569. props.mWidth = 0;
  570. props.mHeight = 0;
  571. return;
  572. }
  573. props.mTop = rc.top;
  574. props.mLeft = rc.left;
  575. // Width and height represent drawable area only
  576. result = GetClientRect(_getWindowHandle(), &rc);
  577. if (result == FALSE)
  578. {
  579. props.mTop = 0;
  580. props.mLeft = 0;
  581. props.mWidth = 0;
  582. props.mHeight = 0;
  583. return;
  584. }
  585. props.mWidth = rc.right - rc.left;
  586. props.mHeight = rc.bottom - rc.top;
  587. }
  588. bool D3D9RenderWindowCore::_validateDevice()
  589. {
  590. mDeviceValid = mDevice->validate(this);
  591. return mDeviceValid;
  592. }
  593. void D3D9RenderWindowCore::syncProperties()
  594. {
  595. ScopedSpinLock lock(mLock);
  596. mProperties = mSyncedProperties;
  597. }
  598. D3D9RenderWindow::D3D9RenderWindow(const RENDER_WINDOW_DESC& desc, UINT32 windowId, HINSTANCE instance)
  599. :RenderWindow(desc, windowId), mInstance(instance), mProperties(desc)
  600. {
  601. }
  602. void D3D9RenderWindow::getCustomAttribute(const String& name, void* pData) const
  603. {
  604. if (name == "WINDOW")
  605. {
  606. UINT64 *pHwnd = (UINT64*)pData;
  607. *pHwnd = (UINT64)getHWnd();
  608. return;
  609. }
  610. }
  611. Vector2I D3D9RenderWindow::screenToWindowPos(const Vector2I& screenPos) const
  612. {
  613. POINT pos;
  614. pos.x = screenPos.x;
  615. pos.y = screenPos.y;
  616. ScreenToClient(getHWnd(), &pos);
  617. return Vector2I(pos.x, pos.y);
  618. }
  619. Vector2I D3D9RenderWindow::windowToScreenPos(const Vector2I& windowPos) const
  620. {
  621. POINT pos;
  622. pos.x = windowPos.x;
  623. pos.y = windowPos.y;
  624. ClientToScreen(getHWnd(), &pos);
  625. return Vector2I(pos.x, pos.y);
  626. }
  627. HWND D3D9RenderWindow::getHWnd() const
  628. {
  629. // HACK: I'm accessing core method from sim thread, which means an invalid handle
  630. // could be returned here if requested too soon after initialization.
  631. return getCore()->_getWindowHandle();
  632. }
  633. SPtr<D3D9RenderWindowCore> D3D9RenderWindow::getCore() const
  634. {
  635. return std::static_pointer_cast<D3D9RenderWindowCore>(mCoreSpecific);
  636. }
  637. void D3D9RenderWindow::syncProperties()
  638. {
  639. ScopedSpinLock lock(getCore()->mLock);
  640. mProperties = getCore()->mSyncedProperties;
  641. }
  642. }