aboutsummaryrefslogtreecommitdiff
path: root/src/core/application.cpp
diff options
context:
space:
mode:
authorhachem <im@hachem.wtf>2026-09-22 06:57:16 +0200
committerhachem <im@hachem.wtf>2026-09-22 06:57:16 +0200
commitd7c1ced08d5d78fcb239550404db4e67d4357a19 (patch)
tree9c0e218b096d138075cbf6a48e2562d33a8f94ed /src/core/application.cpp
parent270eda6f558c972ec86ad0580f1d3d18afc83a94 (diff)
fix: windows supportHEADmain
Diffstat (limited to 'src/core/application.cpp')
-rw-r--r--src/core/application.cpp56
1 files changed, 51 insertions, 5 deletions
diff --git a/src/core/application.cpp b/src/core/application.cpp
index e53e420..de318fb 100644
--- a/src/core/application.cpp
+++ b/src/core/application.cpp
@@ -4,10 +4,13 @@
#include "settings_manager.h"
#include "platform/opengl/opengl_device.h"
-#include "platform/vulkan/vulkan_device.h"
+#ifndef DONUT_NO_VULKAN
+ #include "platform/vulkan/vulkan_device.h"
+#endif
#include <GLFW/glfw3.h>
#include <imgui.h>
+#include <imgui_impl_glfw.h> // ImGui_ImplGlfw_GetContentScaleForWindow
#include <glm/glm.hpp>
#include <algorithm>
#include <thread>
@@ -29,6 +32,7 @@ namespace Donut
}
Application::Application(const std::string& name, int width, int height)
+ : m_title(name), m_init_w(width), m_init_h(height)
{
s_instance = this;
@@ -42,11 +46,31 @@ namespace Donut
? RendererAPI::API::Vulkan : RendererAPI::API::OpenGL);
}
+#ifdef DONUT_NO_VULKAN
+ // generated without a Vulkan SDK, so the backend isn't in this binary at all
+ if (RendererAPI::get_api() == RendererAPI::API::Vulkan)
+ {
+ DONUT_WARN("built without the Vulkan backend, falling back to OpenGL");
+ RendererAPI::set_api(RendererAPI::API::OpenGL);
+ }
+#else
+ if (RendererAPI::get_api() == RendererAPI::API::Vulkan && !RHI::vulkan_runtime_available())
+ {
+ DONUT_WARN("no Vulkan runtime on this machine (vulkan-1.dll), falling back to OpenGL");
+ RendererAPI::set_api(RendererAPI::API::OpenGL);
+ }
if (RendererAPI::get_api() == RendererAPI::API::Vulkan)
RHI::vulkan_prepare_glfw(); // must precede glfwInit() inside the Window ctor
+#endif
m_window = create_scope<Window>(name, width, height);
m_window->set_event_callback([this](Event& event) { on_event(event); });
+ if (!m_window->get_native_window())
+ {
+ DONUT_ERROR("no window, no app (GLFW said why above)");
+ m_running = false;
+ return;
+ }
on_init();
}
@@ -62,15 +86,33 @@ namespace Donut
int w = 0, h = 0;
glfwGetFramebufferSize((GLFWwindow*)m_window->get_native_window(), &w, &h);
+#ifndef DONUT_NO_VULKAN
if (RendererAPI::get_api() == RendererAPI::API::Vulkan)
m_device = RHI::create_vulkan_device();
else
+#endif
m_device = RHI::create_opengl_device();
RHI::NativeWindow native{ m_window->get_native_window(), w, h };
if (!m_device->init(native))
{
+ m_device->shutdown();
+ m_device.reset();
+#ifndef DONUT_NO_VULKAN
+ // a Vulkan window can't host a GL context (GLFW_NO_API), so rebuild it
+ // and try once more on OpenGL. the saved setting stays as the user left it.
+ if (RendererAPI::get_api() == RendererAPI::API::Vulkan)
+ {
+ DONUT_WARN("Vulkan device init failed (see above), falling back to OpenGL");
+ RendererAPI::set_api(RendererAPI::API::OpenGL);
+ m_window.reset();
+ m_window = create_scope<Window>(m_title, m_init_w, m_init_h);
+ m_window->set_event_callback([this](Event& event) { on_event(event); });
+ if (m_window->get_native_window()) { on_init(); return; }
+ }
+#endif
DONUT_ERROR("RHI device initialization failed");
+ m_running = false; // nothing to draw with; run() just returns
return;
}
@@ -80,9 +122,13 @@ namespace Donut
m_ui = create_scope<UILayer>();
m_device->init_imgui();
+ // windows hands out physical pixels with no scaling, so a 4k desktop at 200%
+ // would get a half-size ui. the glfw backend reports 1.0 on macos (retina
+ // scaling lives in the framebuffer there), so the mac is untouched.
+ const float dpi = ImGui_ImplGlfw_GetContentScaleForWindow((GLFWwindow*)m_window->get_native_window());
// the UI layer owns its typography and its imgui.ini section; both go into
// the device-created ImGui context before its first NewFrame reads the ini.
- m_ui->init();
+ m_ui->init(dpi);
g_prev_scroll = glfwSetScrollCallback((GLFWwindow*)m_window->get_native_window(), donut_scroll_callback);
@@ -99,8 +145,8 @@ namespace Donut
{
double frame_start = glfwGetTime();
glfwPollEvents();
- if (!m_minimized && m_device)
- render_frame();
+ if (m_minimized) { glfwWaitEventsTimeout(0.1); continue; } // nothing to draw, so don't spin a core
+ if (m_device) render_frame();
// with vsync off, cap to the target FPS (vsync itself paces otherwise).
if (!SettingsManager::get_v_sync_enabled())
@@ -179,7 +225,7 @@ namespace Donut
{
ExportConfig cfg;
cfg.width = 1280; cfg.height = 720;
- int written = export_frame(cfg);
+ [[maybe_unused]] const int written = export_frame(cfg); // only the debug log reads it
DONUT_INFO("autoexport wrote {} file(s)", written);
close();
}