1//************************************ bs::framework - Copyright 2018 Marko Pintera **************************************//
2//*********** Licensed under the MIT license. See LICENSE.md for full terms. This notice is not to be removed. ***********//
3#include "RenderAPI/BsRenderWindow.h"
4#include "CoreThread/BsCoreThread.h"
5#include "Managers/BsRenderWindowManager.h"
6#include "RenderAPI/BsViewport.h"
7#include "Platform/BsPlatform.h"
8#include "Private/RTTI/BsRenderTargetRTTI.h"
9
10namespace bs
11{
12 RenderWindowProperties::RenderWindowProperties(const RENDER_WINDOW_DESC& desc)
13 {
14 width = desc.videoMode.width;
15 height = desc.videoMode.height;
16 hwGamma = desc.gamma;
17 vsync = desc.vsync;
18 vsyncInterval = desc.vsyncInterval;
19 multisampleCount = desc.multisampleCount;
20 left = desc.left;
21 top = desc.top;
22 isFullScreen = desc.fullscreen;
23 isHidden = desc.hidden;
24 isModal = desc.modal;
25 isWindow = true;
26 requiresTextureFlipping = false;
27 }
28
29 void RenderWindow::destroy()
30 {
31 RenderWindowManager::instance().notifyWindowDestroyed(this);
32
33 RenderTarget::destroy();
34 }
35
36 RenderWindow::RenderWindow(const RENDER_WINDOW_DESC& desc, UINT32 windowId)
37 :mDesc(desc), mWindowId(windowId)
38 {
39
40 }
41
42 void RenderWindow::resize(UINT32 width, UINT32 height)
43 {
44 std::function<void(SPtr<ct::RenderWindow>, UINT32, UINT32)> resizeFunc =
45 [](SPtr<ct::RenderWindow> renderWindow, UINT32 width, UINT32 height)
46 {
47 renderWindow->resize(width, height);
48 };
49
50 gCoreThread().queueCommand(std::bind(resizeFunc, getCore(), width, height));
51 gCoreThread().submit(true);
52
53 {
54 ScopedSpinLock lock(getCore()->mLock);
55 const RenderWindowProperties& syncedProps = getCore()->getSyncedProperties();
56 RenderWindowProperties& mutableProps = getMutableProperties();
57
58 mutableProps.width = syncedProps.width;
59 mutableProps.height = syncedProps.height;
60 }
61 }
62
63 void RenderWindow::move(INT32 left, INT32 top)
64 {
65 std::function<void(SPtr<ct::RenderWindow>, INT32, INT32)> moveFunc =
66 [](SPtr<ct::RenderWindow> renderWindow, INT32 left, INT32 top)
67 {
68 renderWindow->move(left, top);
69 };
70
71 gCoreThread().queueCommand(std::bind(moveFunc, getCore(), left, top));
72 gCoreThread().submit(true);
73
74 {
75 ScopedSpinLock lock(getCore()->mLock);
76 const RenderWindowProperties& syncedProps = getCore()->getSyncedProperties();
77 RenderWindowProperties& mutableProps = getMutableProperties();
78
79 mutableProps.left = syncedProps.left;
80 mutableProps.top = syncedProps.top;
81 }
82 }
83
84 void RenderWindow::hide()
85 {
86 std::function<void(SPtr<ct::RenderWindow>)> hideFunc =
87 [](SPtr<ct::RenderWindow> renderWindow)
88 {
89 renderWindow->setHidden(true);
90 };
91
92 getMutableProperties().isHidden = true;
93
94 gCoreThread().queueCommand(std::bind(hideFunc, getCore()));
95 }
96
97 void RenderWindow::show()
98 {
99 std::function<void(SPtr<ct::RenderWindow>)> showFunc =
100 [](SPtr<ct::RenderWindow> renderWindow)
101 {
102 renderWindow->setHidden(false);
103 };
104
105 getMutableProperties().isHidden = false;
106
107 gCoreThread().queueCommand(std::bind(showFunc, getCore()));
108 }
109
110 void RenderWindow::minimize()
111 {
112 std::function<void(SPtr<ct::RenderWindow>)> minimizeFunc =
113 [](SPtr<ct::RenderWindow> renderWindow)
114 {
115 renderWindow->minimize();
116 };
117
118 getMutableProperties().isMaximized = false;
119
120 gCoreThread().queueCommand(std::bind(minimizeFunc, getCore()));
121 }
122
123 void RenderWindow::maximize()
124 {
125 std::function<void(SPtr<ct::RenderWindow>)> maximizeFunc =
126 [](SPtr<ct::RenderWindow> renderWindow)
127 {
128 renderWindow->maximize();
129 };
130
131 getMutableProperties().isMaximized = true;
132
133 gCoreThread().queueCommand(std::bind(maximizeFunc, getCore()));
134 gCoreThread().submit(true);
135
136 {
137 ScopedSpinLock lock(getCore()->mLock);
138 const RenderWindowProperties& syncedProps = getCore()->getSyncedProperties();
139 RenderWindowProperties& mutableProps = getMutableProperties();
140
141 mutableProps.width = syncedProps.width;
142 mutableProps.height = syncedProps.height;
143 }
144 }
145
146 void RenderWindow::restore()
147 {
148 std::function<void(SPtr<ct::RenderWindow>)> restoreFunc =
149 [](SPtr<ct::RenderWindow> renderWindow)
150 {
151 renderWindow->restore();
152 };
153
154 getMutableProperties().isMaximized = false;
155
156 gCoreThread().queueCommand(std::bind(restoreFunc, getCore()));
157 gCoreThread().submit(true);
158
159 {
160 ScopedSpinLock lock(getCore()->mLock);
161 const RenderWindowProperties& syncedProps = getCore()->getSyncedProperties();
162 RenderWindowProperties& mutableProps = getMutableProperties();
163
164 mutableProps.width = syncedProps.width;
165 mutableProps.height = syncedProps.height;
166 }
167 }
168
169 void RenderWindow::setFullscreen(UINT32 width, UINT32 height, float refreshRate, UINT32 monitorIdx)
170 {
171 std::function<void(SPtr<ct::RenderWindow>, UINT32, UINT32, float, UINT32)> fullscreenFunc =
172 [](SPtr<ct::RenderWindow> renderWindow, UINT32 width, UINT32 height, float refreshRate, UINT32 monitorIdx)
173 {
174 renderWindow->setFullscreen(width, height, refreshRate, monitorIdx);
175 };
176
177 gCoreThread().queueCommand(std::bind(fullscreenFunc, getCore(), width, height, refreshRate, monitorIdx));
178 gCoreThread().submit(true);
179
180 {
181 ScopedSpinLock lock(getCore()->mLock);
182 const RenderWindowProperties& syncedProps = getCore()->getSyncedProperties();
183 RenderWindowProperties& mutableProps = getMutableProperties();
184
185 mutableProps.width = syncedProps.width;
186 mutableProps.height = syncedProps.height;
187 }
188 }
189
190 void RenderWindow::setFullscreen(const VideoMode& mode)
191 {
192 std::function<void(SPtr<ct::RenderWindow>, const VideoMode&)> fullscreenFunc =
193 [](SPtr<ct::RenderWindow> renderWindow, const VideoMode& mode)
194 {
195 renderWindow->setFullscreen(mode);
196 };
197
198 gCoreThread().queueCommand(std::bind(fullscreenFunc, getCore(), std::cref(mode)));
199 gCoreThread().submit(true);
200
201 {
202 ScopedSpinLock lock(getCore()->mLock);
203 const RenderWindowProperties& syncedProps = getCore()->getSyncedProperties();
204 RenderWindowProperties& mutableProps = getMutableProperties();
205
206 mutableProps.width = syncedProps.width;
207 mutableProps.height = syncedProps.height;
208 }
209 }
210
211 void RenderWindow::setWindowed(UINT32 width, UINT32 height)
212 {
213 std::function<void(SPtr<ct::RenderWindow>, UINT32, UINT32)> windowedFunc =
214 [](SPtr<ct::RenderWindow> renderWindow, UINT32 width, UINT32 height)
215 {
216 renderWindow->setWindowed(width, height);
217 };
218
219 gCoreThread().queueCommand(std::bind(windowedFunc, getCore(), width, height));
220 gCoreThread().submit(true);
221
222 {
223 ScopedSpinLock lock(getCore()->mLock);
224 const RenderWindowProperties& syncedProps = getCore()->getSyncedProperties();
225 RenderWindowProperties& mutableProps = getMutableProperties();
226
227 mutableProps.width = syncedProps.width;
228 mutableProps.height = syncedProps.height;
229 }
230 }
231
232 SPtr<ct::RenderWindow> RenderWindow::getCore() const
233 {
234 return std::static_pointer_cast<ct::RenderWindow>(mCoreSpecific);
235 }
236
237 SPtr<RenderWindow> RenderWindow::create(RENDER_WINDOW_DESC& desc, SPtr<RenderWindow> parentWindow)
238 {
239 return RenderWindowManager::instance().create(desc, parentWindow);
240 }
241
242 RenderWindowProperties& RenderWindow::getMutableProperties()
243 {
244 return const_cast<RenderWindowProperties&>(getProperties());
245 }
246
247 const RenderWindowProperties& RenderWindow::getProperties() const
248 {
249 return static_cast<const RenderWindowProperties&>(getPropertiesInternal());
250 }
251
252 void RenderWindow::_notifyWindowEvent(WindowEventType type)
253 {
254 THROW_IF_CORE_THREAD;
255
256 ct::RenderWindow* coreWindow = getCore().get();
257 RenderWindowProperties& syncProps = coreWindow->getSyncedProperties();
258 RenderWindowProperties& props = const_cast<RenderWindowProperties&>(getProperties());
259
260 switch(type)
261 {
262 case WindowEventType::Resized:
263 {
264 _windowMovedOrResized();
265
266 {
267 ScopedSpinLock lock(coreWindow->mLock);
268 syncProps.width = props.width;
269 syncProps.height = props.height;
270 }
271
272 ct::RenderWindowManager::instance().notifySyncDataDirty(coreWindow);
273 RenderWindowManager::instance().notifyMovedOrResized(coreWindow);
274
275 break;
276 }
277 case WindowEventType::Moved:
278 {
279 _windowMovedOrResized();
280
281 {
282 ScopedSpinLock lock(coreWindow->mLock);
283 syncProps.top = props.top;
284 syncProps.left = props.left;
285 }
286
287 ct::RenderWindowManager::instance().notifySyncDataDirty(coreWindow);
288 RenderWindowManager::instance().notifyMovedOrResized(coreWindow);
289
290 break;
291 }
292 case WindowEventType::FocusReceived:
293 {
294 {
295 ScopedSpinLock lock(coreWindow->mLock);
296 syncProps.hasFocus = true;
297 }
298
299 props.hasFocus = true;
300
301 ct::RenderWindowManager::instance().notifySyncDataDirty(coreWindow);
302 RenderWindowManager::instance().notifyFocusReceived(coreWindow);
303 break;
304 }
305 case WindowEventType::FocusLost:
306 {
307 {
308 ScopedSpinLock lock(coreWindow->mLock);
309 syncProps.hasFocus = false;
310 }
311
312 props.hasFocus = false;
313
314 ct::RenderWindowManager::instance().notifySyncDataDirty(coreWindow);
315 RenderWindowManager::instance().notifyFocusLost(coreWindow);
316 break;
317 }
318 case WindowEventType::Minimized:
319 {
320 {
321 ScopedSpinLock lock(coreWindow->mLock);
322 syncProps.isMaximized = false;
323 }
324
325 props.isMaximized = false;
326
327 ct::RenderWindowManager::instance().notifySyncDataDirty(coreWindow);
328 break;
329 }
330 case WindowEventType::Maximized:
331 {
332 {
333 ScopedSpinLock lock(coreWindow->mLock);
334 syncProps.isMaximized = true;
335 }
336
337 props.isMaximized = true;
338
339 ct::RenderWindowManager::instance().notifySyncDataDirty(coreWindow);
340 break;
341 }
342 case WindowEventType::Restored:
343 {
344 {
345 ScopedSpinLock lock(coreWindow->mLock);
346 syncProps.isMaximized = false;
347 }
348
349 props.isMaximized = false;
350
351 ct::RenderWindowManager::instance().notifySyncDataDirty(coreWindow);
352 break;
353 }
354 case WindowEventType::MouseLeft:
355 {
356 RenderWindowManager::instance().notifyMouseLeft(coreWindow);
357 break;
358 }
359 case WindowEventType::CloseRequested:
360 {
361 RenderWindowManager::instance().notifyCloseRequested(coreWindow);
362 break;
363 }
364 }
365 }
366
367 /************************************************************************/
368 /* SERIALIZATION */
369 /************************************************************************/
370
371 RTTITypeBase* RenderWindow::getRTTIStatic()
372 {
373 return RenderWindowRTTI::instance();
374 }
375
376 RTTITypeBase* RenderWindow::getRTTI() const
377 {
378 return RenderWindow::getRTTIStatic();
379 }
380
381 namespace ct
382 {
383 RenderWindow::RenderWindow(const RENDER_WINDOW_DESC& desc, UINT32 windowId)
384 :mDesc(desc), mWindowId(windowId)
385 {
386 RenderWindowManager::instance().windowCreated(this);
387 }
388
389 RenderWindow::~RenderWindow()
390 {
391 RenderWindowManager::instance().windowDestroyed(this);
392 }
393
394 void RenderWindow::setHidden(bool hidden)
395 {
396 THROW_IF_NOT_CORE_THREAD;
397
398 RenderWindowProperties& props = const_cast<RenderWindowProperties&>(getProperties());
399
400 props.isHidden = hidden;
401 {
402 ScopedSpinLock lock(mLock);
403 getSyncedProperties().isHidden = hidden;
404 }
405
406 bs::RenderWindowManager::instance().notifySyncDataDirty(this);
407 }
408
409 void RenderWindow::setActive(bool state)
410 {
411 THROW_IF_NOT_CORE_THREAD;
412 }
413
414 void RenderWindow::_notifyWindowEvent(WindowEventType type)
415 {
416 THROW_IF_NOT_CORE_THREAD;
417
418 RenderWindowProperties& syncProps = getSyncedProperties();
419 RenderWindowProperties& props = const_cast<RenderWindowProperties&>(getProperties());
420
421 switch(type)
422 {
423 case WindowEventType::Resized:
424 {
425 _windowMovedOrResized();
426
427 {
428 ScopedSpinLock lock(mLock);
429 syncProps.width = props.width;
430 syncProps.height = props.height;
431 }
432
433 bs::RenderWindowManager::instance().notifySyncDataDirty(this);
434 bs::RenderWindowManager::instance().notifyMovedOrResized(this);
435
436 break;
437 }
438 case WindowEventType::Moved:
439 {
440 _windowMovedOrResized();
441
442 {
443 ScopedSpinLock lock(mLock);
444 syncProps.top = props.top;
445 syncProps.left = props.left;
446 }
447
448 bs::RenderWindowManager::instance().notifySyncDataDirty(this);
449 bs::RenderWindowManager::instance().notifyMovedOrResized(this);
450
451 break;
452 }
453 case WindowEventType::FocusReceived:
454 {
455 {
456 ScopedSpinLock lock(mLock);
457 syncProps.hasFocus = true;
458 }
459
460 props.hasFocus = true;
461
462 bs::RenderWindowManager::instance().notifySyncDataDirty(this);
463 bs::RenderWindowManager::instance().notifyFocusReceived(this);
464 break;
465 }
466 case WindowEventType::FocusLost:
467 {
468 {
469 ScopedSpinLock lock(mLock);
470 syncProps.hasFocus = false;
471 }
472
473 props.hasFocus = false;
474
475 bs::RenderWindowManager::instance().notifySyncDataDirty(this);
476 bs::RenderWindowManager::instance().notifyFocusLost(this);
477 break;
478 }
479 case WindowEventType::Minimized:
480 {
481 {
482 ScopedSpinLock lock(mLock);
483 syncProps.isMaximized = false;
484 }
485
486 props.isMaximized = false;
487
488 bs::RenderWindowManager::instance().notifySyncDataDirty(this);
489 break;
490 }
491 case WindowEventType::Maximized:
492 {
493 {
494 ScopedSpinLock lock(mLock);
495 syncProps.isMaximized = true;
496 }
497
498 props.isMaximized = true;
499
500 bs::RenderWindowManager::instance().notifySyncDataDirty(this);
501 break;
502 }
503 case WindowEventType::Restored:
504 {
505 {
506 ScopedSpinLock lock(mLock);
507 syncProps.isMaximized = false;
508 }
509
510 props.isMaximized = false;
511
512 bs::RenderWindowManager::instance().notifySyncDataDirty(this);
513 break;
514 }
515 case WindowEventType::MouseLeft:
516 {
517 bs::RenderWindowManager::instance().notifyMouseLeft(this);
518 break;
519 }
520 case WindowEventType::CloseRequested:
521 {
522 bs::RenderWindowManager::instance().notifyCloseRequested(this);
523 break;
524 }
525 }
526 }
527
528 const RenderWindowProperties& RenderWindow::getProperties() const
529 {
530 return static_cast<const RenderWindowProperties&>(getPropertiesInternal());
531 }
532 }
533}
534