BsD3D9RenderWindow.cpp 21 KB

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