HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
gui_system.hpp
1// Copyright Take Vos 2020.
2// Distributed under the Boost Software License, Version 1.0.
3// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
4
5#pragma once
6
7#include "gui_device.hpp"
8#include "gui_window.hpp"
9#include "gui_window_vulkan_win32.hpp"
10#include "vertical_sync.hpp"
11#include "gui_system_delegate.hpp"
12#include "../unfair_recursive_mutex.hpp"
13#include <span>
14#include <memory>
15#include <mutex>
16#include <thread>
17#include <vector>
18
19namespace tt {
20
25public:
26 static inline std::unique_ptr<gui_system> global;
27
29
31
34
39
40 gui_system(std::weak_ptr<gui_system_delegate> const &delegate) noexcept :
41 delegate(delegate)
42 {
43 verticalSync = std::make_unique<vertical_sync>(_handlevertical_sync, this);
44 }
45
46 virtual ~gui_system() {}
47
48 gui_system(const gui_system &) = delete;
49 gui_system &operator=(const gui_system &) = delete;
50 gui_system(gui_system &&) = delete;
51 gui_system &operator=(gui_system &&) = delete;
52
56 virtual void init() = 0;
57
58 template<typename... Args>
59 gui_window *make_window(Args &&... args)
60 {
61 // This function should be called from the main thread from the main loop,
62 // and therefor should not have a lock on the window.
63 tt_assert(is_main_thread(), "createWindow should be called from the main thread.");
64 tt_axiom(gui_system_mutex.recurse_lock_count() == 0);
65
66 auto window = std::make_shared<gui_window_vulkan_win32>(static_cast<gui_system &>(*this), std::forward<Args>(args)...);
67 auto window_ptr = window.get();
68 window->init();
69
70 ttlet lock = std::scoped_lock(gui_system_mutex);
71 auto device = findBestDeviceForWindow(*window);
72 if (!device) {
73 throw gui_error("Could not find a vulkan-device matching this window");
74 }
75
76 device->add(std::move(window));
77 return window_ptr;
78 }
79
83
84 void render(hires_utc_clock::time_point displayTimePoint) {
85 ttlet lock = std::scoped_lock(gui_system_mutex);
86
87 for (auto &device: devices) {
88 device->render(displayTimePoint);
89 }
90 ttlet currentNumberOfWindows = num_windows();
91 if (currentNumberOfWindows == 0 && currentNumberOfWindows != previousNumberOfWindows) {
92 application::global->run_from_main_loop([this]{
93 if (auto delegate_ = this->delegate.lock()) {
94 delegate_->last_window_closed(*this);
95 }
96 });
97 }
98 previousNumberOfWindows = currentNumberOfWindows;
99 }
100
101 void handlevertical_sync(hires_utc_clock::time_point displayTimePoint)
102 {
103 render(displayTimePoint);
104 }
105
106
107 static void _handlevertical_sync(void *data, hires_utc_clock::time_point displayTimePoint);
108
109protected:
110 gui_device *findBestDeviceForWindow(gui_window const &window);
111};
112
113}
Definition exception.hpp:59
Vulkan gui_device controller.
Definition gui_system.hpp:24
std::vector< std::shared_ptr< gui_device > > devices
List of all devices.
Definition gui_system.hpp:33
virtual void init()=0
Initialize after construction.
ssize_t previousNumberOfWindows
Definition gui_system.hpp:38
ssize_t num_windows()
Definition gui_window.hpp:39
int recurse_lock_count() const noexcept
This function should be used in tt_axiom() to check if the lock is held by current thread.
Definition unfair_recursive_mutex.hpp:60
T lock(T... args)
T move(T... args)