diff --git a/src/modules/graphics/Graphics.cpp b/src/modules/graphics/Graphics.cpp index 225080a38..ca57be5d8 100644 --- a/src/modules/graphics/Graphics.cpp +++ b/src/modules/graphics/Graphics.cpp @@ -36,6 +36,7 @@ // C++ #include +#include #include namespace love @@ -106,12 +107,12 @@ bool isDebugEnabled() love::Type Graphics::type("graphics", &Module::type); -namespace opengl { extern love::graphics::Graphics *createInstance(); } +namespace opengl { extern std::tuple createInstance(); } #ifdef LOVE_GRAPHICS_METAL -namespace metal { extern love::graphics::Graphics *createInstance(); } +namespace metal { extern std::tuple createInstance(); } #endif #ifdef LOVE_GRAPHICS_VULKAN -namespace vulkan { extern love::graphics::Graphics *createInstance(); } +namespace vulkan { extern std::tuple createInstance(); } #endif static const Renderer rendererOrder[] = { @@ -164,6 +165,7 @@ bool isLowPowerPreferred() Graphics *Graphics::createInstance() { Graphics *instance = Module::getInstance(M_GRAPHICS); + std::string errors; if (instance != nullptr) instance->retain(); @@ -171,25 +173,39 @@ Graphics *Graphics::createInstance() { for (auto r : rendererOrder) { - if (std::find(_renderers.begin(), _renderers.end(), r) == _renderers.end()) continue; + std::string err; + #ifdef LOVE_GRAPHICS_VULKAN if (r == RENDERER_VULKAN) - instance = vulkan::createInstance(); + std::tie(instance, err) = vulkan::createInstance(); #endif if (r == RENDERER_OPENGL) - instance = opengl::createInstance(); + std::tie(instance, err) = opengl::createInstance(); #ifdef LOVE_GRAPHICS_METAL if (r == RENDERER_METAL) - instance = metal::createInstance(); + std::tie(instance, err) = metal::createInstance(); #endif + + if (!err.empty()) + { + errors += err; + if (isDebugEnabled()) + ::printf("%s", err.c_str()); + } + if (instance != nullptr) break; } } + if (instance == nullptr) + { + throw love::Exception("Cannot create graphics: no supported renderer on this system.\n%s", errors.c_str()); + } + return instance; } diff --git a/src/modules/graphics/metal/Graphics.mm b/src/modules/graphics/metal/Graphics.mm index 4966e1804..c0b8cdcc3 100644 --- a/src/modules/graphics/metal/Graphics.mm +++ b/src/modules/graphics/metal/Graphics.mm @@ -29,6 +29,8 @@ #include "image/Image.h" #include "common/memory.h" +#include + #import #ifdef LOVE_MACOS @@ -239,9 +241,10 @@ static inline void setSampler(id encoder, Graphics::Re } } -love::graphics::Graphics *createInstance() +std::tuple createInstance() { love::graphics::Graphics *instance = nullptr; + std::string err; try { @@ -249,10 +252,10 @@ love::graphics::Graphics *createInstance() } catch (love::Exception &e) { - printf("Cannot create Metal renderer: %s\n", e.what()); + err = "Cannot create Metal renderer: " + std::string(e.what()) + "\n"; } - return instance; + return { instance, err }; } struct DefaultVertexAttributes diff --git a/src/modules/graphics/opengl/Graphics.cpp b/src/modules/graphics/opengl/Graphics.cpp index 5ba3060f8..c66d137d1 100644 --- a/src/modules/graphics/opengl/Graphics.cpp +++ b/src/modules/graphics/opengl/Graphics.cpp @@ -39,6 +39,7 @@ #include #include #include +#include // C #include @@ -89,9 +90,10 @@ static GLenum getGLBlendFactor(BlendFactor factor) return 0; } -love::graphics::Graphics *createInstance() +std::tuple createInstance() { love::graphics::Graphics *instance = nullptr; + std::string err; try { @@ -99,10 +101,10 @@ love::graphics::Graphics *createInstance() } catch (love::Exception &e) { - printf("Cannot create OpenGL renderer: %s\n", e.what()); + err = "Cannot create OpenGL renderer: " + std::string(e.what()) + "\n"; } - return instance; + return { instance, err }; } Graphics::Graphics() diff --git a/src/modules/graphics/vulkan/Graphics.cpp b/src/modules/graphics/vulkan/Graphics.cpp index 76a38dae0..f2baf7312 100644 --- a/src/modules/graphics/vulkan/Graphics.cpp +++ b/src/modules/graphics/vulkan/Graphics.cpp @@ -39,6 +39,7 @@ #include #include #include +#include #define VOLK_IMPLEMENTATION #include "libraries/volk/volk.h" @@ -3603,9 +3604,10 @@ void Graphics::recreateSwapChain() transitionColorDepthLayouts = true; } -love::graphics::Graphics *createInstance() +std::tuple createInstance() { love::graphics::Graphics *instance = nullptr; + std::string err; try { @@ -3613,11 +3615,10 @@ love::graphics::Graphics *createInstance() } catch (love::Exception &e) { - if (isDebugEnabled()) - printf("Cannot create Vulkan renderer: %s\n", e.what()); + err = "Cannot create Vulkan renderer: " + std::string(e.what()) + "\n"; } - return instance; + return { instance, err }; } } // vulkan diff --git a/src/modules/graphics/wrap_Graphics.cpp b/src/modules/graphics/wrap_Graphics.cpp index 1822a12d8..349927c3a 100644 --- a/src/modules/graphics/wrap_Graphics.cpp +++ b/src/modules/graphics/wrap_Graphics.cpp @@ -4208,13 +4208,8 @@ static const lua_CFunction types[] = extern "C" int luaopen_love_graphics(lua_State *L) { - Graphics *instance = Graphics::createInstance(); - - if (instance == nullptr) - { - printf("Cannot create graphics: no supported renderer on this system.\n"); - return luaL_error(L, "Cannot create graphics: no supported renderer on this system."); - } + Graphics *instance = nullptr; + luax_catchexcept(L, [&]() { instance = Graphics::createInstance(); }); WrappedModule w; w.module = instance; diff --git a/src/modules/love/callbacks.lua b/src/modules/love/callbacks.lua index 3dc12576f..eaf53c4ce 100644 --- a/src/modules/love/callbacks.lua +++ b/src/modules/love/callbacks.lua @@ -223,13 +223,17 @@ function love.errorhandler(msg) error_printer(msg, 2) - if not love.window or not love.graphics or not love.event then + if not love.window then return end - if not love.graphics.isCreated() or not love.window.isOpen() then - local success, status = pcall(love.window.setMode, 800, 600) + if not love.graphics or not love.event or not love.graphics.isCreated() or not love.window.isOpen() then + local success, status + if love.graphics and love.event then + success, status = pcall(love.window.setMode, 800, 600) + end if not success or not status then + love.window.showMessageBox("Error during startup", msg, "error", false) return end end