BsD3D9RenderWindow.cpp 21 KB

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