Skip to main content

GLFWApplication.ixx File

GLFW-specific Application implementation. More...

Included Headers

#include <glad/gl.h> #include <glfw/glfw3.h> #include <memory> #include <vector> #include <stdexcept> #include <format> #include <helios.ext.glfw.app.GLFWRAIIGuard> #include <helios.rendering.RenderTarget> #include <helios.event.EventManager> #include <helios.ext.glfw.window.GLFWWindow> #include <helios.rendering.RenderingDevice> #include <helios.ext.glfw.window.GLFWWindowConfig> #include <helios.input.InputManager> #include <helios.window.Window> #include <helios.window.WindowConfig> #include <helios.app.Application>

Namespaces Index

namespacehelios
namespaceext

Platform-specific extensions and backend implementations. More...

namespaceglfw

GLFW-specific implementations. More...

namespaceapp

GLFW application infrastructure. More...

Classes Index

classGLFWApplication

An Application implementation for glfw-based environments. More...

Description

GLFW-specific Application implementation.

File Listing

The file content with the documentation metadata removed is:

1/**
2 * @file GLFWApplication.ixx
3 * @brief GLFW-specific Application implementation.
4 */
5module;
6
7#include <glad/gl.h>
8#include <glfw/glfw3.h>
9#include <memory>
10#include <vector>
11#include <stdexcept>
12#include <format>
13
14
15export module helios.ext.glfw.app.GLFWApplication;
16
17import helios.app.Application;
18import helios.window.Window;
19import helios.window.WindowConfig;
20import helios.input.InputManager;
21import helios.rendering.RenderingDevice;
22import helios.event.EventManager;
23import helios.ext.glfw.window.GLFWWindow;
24import helios.ext.glfw.window.GLFWWindowConfig;
25import helios.rendering.RenderTarget;
26
27import helios.ext.glfw.app.GLFWRAIIGuard;
28
29export namespace helios::ext::glfw::app {
30
31 /**
32 * @brief An Application implementation for glfw-based environments.
33 *
34 * This application owns a `GLFWRAIIGuard`.
35 */
37
38 private:
39 /**
40 * @brief A pointer to the currently active window of the Application, or `nullptr`
41 * if there is no currently active window.
42 */
43 helios::window::Window* current_ = nullptr;
44
45 /**
46 * @brief RAII Guard for glfw initialization and termination.
47 */
48 GLFWRAIIGuard glfwRaiiGuard_;
49
50 public:
51 /**
52 * @brief Constructs a new `GLFWApplication` instance.
53 *
54 * @param renderingDevice Unique rendering device owned by the application.
55 * @param inputManager Unique input manager instance.
56 * @param eventManager Unique event manager instance.
57 */
59 std::unique_ptr<helios::rendering::RenderingDevice> renderingDevice,
60 std::unique_ptr<helios::input::InputManager> inputManager,
61 std::unique_ptr<helios::event::EventManager> eventManager)
63 std::move(renderingDevice),
64 std::move(inputManager),
65 std::move(eventManager)),
66 glfwRaiiGuard_() {}
67
68
69 /**
70 * @copydoc helios::app::Application::init()
71 */
72 void init() override {
73 Application::init();
74
75 glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
76 glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 6);
77 glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
78 }
79
80
81 /**
82 * @brief Creates a new GLFWWindow and add it to this Application's windows collection.
83 * The Application takes ownership of the window.
84 *
85 * Delegates to Window::show() for showing the window and initializes the associated rendering
86 * device if necessary, e.g. for glfw an additional `glfwMakeContextCurrent()` is called
87 * so the rendering device can be safely initialized, then immediately passes a
88 * `nullptr` to the `glfwMakeContextCurrent()` to force calling APIs to explicitly
89 * call setCurrent() on the constructed window.
90 * The render target size is synced to the current framebuffer dimensions reported by
91 * `glfwGetFramebufferSize()`.
92 *
93 * @return Reference to the created window instance.
94 *
95 * @see https://www.glfw.org/docs/latest/group__window.html#ga0e2637a4161afb283f5300c7f94785c9
96 * @return A ref to the window created.
97 */
99 std::unique_ptr<helios::rendering::RenderTarget> renderTarget,
101 ) {
102 auto window = std::make_unique<helios::ext::glfw::window::GLFWWindow>(std::move(renderTarget), cfg);
103
104 if (const auto glfw_window = window.get()) {
105 if (!glfw_window->show()) {
106 const std::string msg = "Cannot show window.";
107 logger_.error(msg);
108 throw std::runtime_error(msg);
109 }
110
111 // the first window inits the rendering device in this case, since glad requires
112 // context created by glfw window
113 if (!renderingDevice_->initialized()) {
114 glfwMakeContextCurrent(glfw_window->nativeHandle());
115 renderingDevice_->init();
116 // we intentionally set the previous context to NULL
117 // to enforce call to setCurrent()
118 glfwMakeContextCurrent(nullptr);
119 }
120 int width, height;
121 glfwGetFramebufferSize(glfw_window->nativeHandle(), &width, &height);
122 glfw_window->renderTarget().setSize(width, height);
123
124 } else {
125 throw std::runtime_error("Cannot create: Missing GLFWWindow.");
126 }
127
128 windowList_.emplace_back(std::move(window));
129
130 return *dynamic_cast<helios::ext::glfw::window::GLFWWindow*>(windowList_.back().get());
131 }
132
133
134 /**
135 * @copydoc helios::app::Application::createWindow()
136 */
138 std::unique_ptr<helios::rendering::RenderTarget> renderTarget,
140 ) override {
141 auto const* tmp_cfg = dynamic_cast<helios::ext::glfw::window::GLFWWindowConfig const*>(&cfg);
142 if (!tmp_cfg) {
143 std::string msg = "GLFWApplication requires GLFWWindowConfig";
144 logger_.error(msg);
145 throw std::invalid_argument(msg);
146 }
147
148 return createWindow(std::move(renderTarget), *tmp_cfg);
149 }
150
151
152 /**
153 * @brief Sets the current window for this application.
154 *
155 * Ensures `glfwMakeContextCurrent()` is called to bind the correct context for
156 * subsequent glfw operations and re-registers the framebuffer size callback on
157 * the targeted window.
158 *
159 * @param win Reference to the window that becomes the current context owner.
160 *
161 * @throws std::invalid_argument If `win` is not a `GLFWWindow` or not owned by this application.
162 */
163 void setCurrent(helios::window::Window& win) override {
164 if (!hasWindow(win)) {
165 const std::string msg = "Window is not owned by this Application.";
166 logger_.error(msg);
167 throw std::runtime_error(msg);
168 }
169
170 if (const auto glfw_window = dynamic_cast<helios::ext::glfw::window::GLFWWindow*>(&win)) {
171 logger_.info(std::format("Setting Window {0} as current", win.guid().value()));
172 // 1 makes the context of the specified window current
173 // for the calling thread (@todo extract?)
174 glfwMakeContextCurrent(glfw_window->nativeHandle());
175
176 // 2 set the framebuffersize callback
177 glfwSetFramebufferSizeCallback(
178 glfw_window->nativeHandle(),
179 glfw_window->frameBufferSizeCallback()
180 );
181
182 } else {
183 const std::string msg = "Cannot init: Missing GLFWWindow.";
184 logger_.error(msg);
185 throw std::runtime_error(msg);
186 }
187
188 inputManager_->observe(win);
189 current_ = &win;
190 }
191
192 /**
193 * @copydoc helios::app::Application::current()
194 */
195 [[nodiscard]] helios::window::Window* current() const noexcept override {
196 return current_;
197 }
198
199 };
200
201
202}

Generated via doxygen2docusaurus 2.0.0 by Doxygen 1.15.0.