From 5864d83c312fe25df5a354c9e1f8f5002204b054 Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Tue, 4 Jan 2022 21:29:56 -0400 Subject: [PATCH] Add ability to configure which renderers are used by love.graphics. - Add t.renderers and t.excluderenderers love.conf fields. They can be an array of renderer names. - Add --renderers a,list,of,renderernames and --excluderenderers more,renderers argument options. --- src/modules/graphics/Graphics.cpp | 34 ++++++++++- src/modules/graphics/Graphics.h | 24 +++++--- src/modules/graphics/metal/Graphics.mm | 2 +- src/modules/graphics/opengl/Graphics.cpp | 2 +- src/modules/graphics/wrap_Graphics.cpp | 11 +--- src/modules/love/arg.lua | 6 +- src/modules/love/boot.lua | 41 +++++++++++++ src/modules/love/love.cpp | 78 ++++++++++++++++++++++++ src/modules/window/sdl/Window.cpp | 18 +++--- src/modules/window/sdl/Window.h | 4 +- 10 files changed, 184 insertions(+), 36 deletions(-) diff --git a/src/modules/graphics/Graphics.cpp b/src/modules/graphics/Graphics.cpp index 9ca953c49..70f0d5a2b 100644 --- a/src/modules/graphics/Graphics.cpp +++ b/src/modules/graphics/Graphics.cpp @@ -110,7 +110,30 @@ namespace opengl { extern love::graphics::Graphics *createInstance(); } namespace metal { extern love::graphics::Graphics *createInstance(); } #endif -Graphics *Graphics::createInstance(const std::vector &renderers) +static std::vector defaultRenderers = +{ + RENDERER_METAL, + RENDERER_OPENGL, +}; + +static std::vector _renderers = defaultRenderers; + +const std::vector &getDefaultRenderers() +{ + return defaultRenderers; +} + +const std::vector &getRenderers() +{ + return _renderers; +} + +void setRenderers(const std::vector &renderers) +{ + _renderers = renderers; +} + +Graphics *Graphics::createInstance() { Graphics *instance = Module::getInstance(M_GRAPHICS); @@ -118,7 +141,7 @@ Graphics *Graphics::createInstance(const std::vector &renderers) instance->retain(); else { - for (auto renderer : renderers) + for (auto renderer : _renderers) { if (renderer == RENDERER_OPENGL) instance = opengl::createInstance(); @@ -2147,5 +2170,12 @@ STRINGMAP_CLASS_BEGIN(Graphics, Graphics::StackType, Graphics::STACK_MAX_ENUM, s } STRINGMAP_CLASS_END(Graphics, Graphics::StackType, Graphics::STACK_MAX_ENUM, stackType) +STRINGMAP_BEGIN(Renderer, RENDERER_MAX_ENUM, renderer) +{ + { "opengl", RENDERER_OPENGL }, + { "metal", RENDERER_METAL }, +} +STRINGMAP_END(Renderer, RENDERER_MAX_ENUM, renderer) + } // graphics } // love diff --git a/src/modules/graphics/Graphics.h b/src/modules/graphics/Graphics.h index 56119b96c..9172ed25c 100644 --- a/src/modules/graphics/Graphics.h +++ b/src/modules/graphics/Graphics.h @@ -65,6 +65,14 @@ typedef Optional OptionalColorD; const int MAX_COLOR_RENDER_TARGETS = 8; +enum Renderer +{ + RENDERER_NONE, + RENDERER_OPENGL, + RENDERER_METAL, + RENDERER_MAX_ENUM +}; + /** * Globally sets whether gamma correction is enabled. Ideally this should be set * prior to using any Graphics module function. @@ -95,6 +103,10 @@ Colorf unGammaCorrectColor(const Colorf &c); bool isDebugEnabled(); +const std::vector &getDefaultRenderers(); +const std::vector &getRenderers(); +void setRenderers(const std::vector &renderers); + class Graphics : public Module { public: @@ -151,14 +163,6 @@ public: FEATURE_MAX_ENUM }; - enum Renderer - { - RENDERER_NONE, - RENDERER_OPENGL, - RENDERER_METAL, - RENDERER_MAX_ENUM - }; - enum SystemLimit { LIMIT_POINT_SIZE, @@ -860,7 +864,7 @@ public: return (T *) scratchBuffer.data(); } - static Graphics *createInstance(const std::vector &renderers); + static Graphics *createInstance(); STRINGMAP_CLASS_DECLARE(DrawMode); STRINGMAP_CLASS_DECLARE(ArcMode); @@ -1016,6 +1020,8 @@ private: }; // Graphics +STRINGMAP_DECLARE(Renderer); + } // graphics } // love diff --git a/src/modules/graphics/metal/Graphics.mm b/src/modules/graphics/metal/Graphics.mm index eb42048e8..1ffdffe6c 100644 --- a/src/modules/graphics/metal/Graphics.mm +++ b/src/modules/graphics/metal/Graphics.mm @@ -2016,7 +2016,7 @@ bool Graphics::isPixelFormatSupported(PixelFormat format, PixelFormatUsageFlags return (usage & flags) == usage; } -Graphics::Renderer Graphics::getRenderer() const +Renderer Graphics::getRenderer() const { return RENDERER_METAL; } diff --git a/src/modules/graphics/opengl/Graphics.cpp b/src/modules/graphics/opengl/Graphics.cpp index 95d11176d..2d3e61ca3 100644 --- a/src/modules/graphics/opengl/Graphics.cpp +++ b/src/modules/graphics/opengl/Graphics.cpp @@ -1599,7 +1599,7 @@ void Graphics::releaseBufferMapMemory(void *mem) free(mem); } -Graphics::Renderer Graphics::getRenderer() const +Renderer Graphics::getRenderer() const { return RENDERER_OPENGL; } diff --git a/src/modules/graphics/wrap_Graphics.cpp b/src/modules/graphics/wrap_Graphics.cpp index fb398de03..9ae5ec50f 100644 --- a/src/modules/graphics/wrap_Graphics.cpp +++ b/src/modules/graphics/wrap_Graphics.cpp @@ -3697,16 +3697,7 @@ static const lua_CFunction types[] = extern "C" int luaopen_love_graphics(lua_State *L) { - Graphics *instance = nullptr; - - { - std::vector renderers; -#if defined(LOVE_MACOS) || defined(LOVE_IOS) - renderers.push_back(Graphics::RENDERER_METAL); -#endif - renderers.push_back(Graphics::RENDERER_OPENGL); - instance = Graphics::createInstance(renderers); - } + Graphics *instance = Graphics::createInstance(); if (instance == nullptr) { diff --git a/src/modules/love/arg.lua b/src/modules/love/arg.lua index d3e133553..dd0f0be5d 100644 --- a/src/modules/love/arg.lua +++ b/src/modules/love/arg.lua @@ -114,8 +114,10 @@ end love.arg.options = { console = { a = 0 }, - fused = {a = 0 }, - game = { a = 1 } + fused = { a = 0 }, + game = { a = 1 }, + renderers = { a = 1 }, + excluderenderers = { a = 1 }, } love.arg.optionIndices = {} diff --git a/src/modules/love/boot.lua b/src/modules/love/boot.lua index bf293325c..013dba52c 100644 --- a/src/modules/love/boot.lua +++ b/src/modules/love/boot.lua @@ -184,6 +184,8 @@ function love.init() accelerometerjoystick = true, -- Only relevant for Android / iOS. gammacorrect = false, highdpi = false, + renderers = nil, + excluderenderers = nil, } -- Console hack, part 1. @@ -221,6 +223,45 @@ function love.init() love._setGammaCorrect(c.gammacorrect) end + if love._setRenderers then + local renderers = love._getDefaultRenderers() + if type(c.renderers) == "table" then + renderers = {} + for i,v in ipairs(c.renderers) do + renderers[i] = v + end + end + + if love.arg.options.renderers.set then + local renderersstr = love.arg.options.renderers.arg[1] + renderers = {} + for r in renderersstr:gmatch("[^,]+") do + table.insert(renderers, r) + end + end + local excluderenderers = c.excluderenderers + if love.arg.options.excluderenderers.set then + local excludestr = love.arg.options.excluderenderers.arg[1] + excluderenderers = {} + for r in excludestr:gmatch("[^,]+") do + table.insert(excluderenderers, r) + end + end + + if type(excluderenderers) == "table" then + for i,v in ipairs(excluderenderers) do + for j=#renderers, 1, -1 do + if renderers[j] == v then + table.remove(renderers, j) + break + end + end + end + end + + love._setRenderers(renderers) + end + if love._setHighDPIAllowed then love._setHighDPIAllowed(c.highdpi) end diff --git a/src/modules/love/love.cpp b/src/modules/love/love.cpp index b04b532bc..86880e8ec 100644 --- a/src/modules/love/love.cpp +++ b/src/modules/love/love.cpp @@ -356,6 +356,75 @@ static int w__setGammaCorrect(lua_State *L) return 0; } +static int w__getDefaultRenderers(lua_State *L) +{ +#ifdef LOVE_ENABLE_GRAPHICS + const auto &renderers = love::graphics::getDefaultRenderers(); + + lua_createtable(L, (int) renderers.size(), 0); + + int n = 1; + for (auto r : renderers) + { + const char *str = nullptr; + if (love::graphics::getConstant(r, str)) + { + lua_pushstring(L, str); + lua_rawseti(L, -2, n++); + } + } +#else + lua_createtable(L, 0, 0); +#endif + return 1; +} + +static int w__getRenderers(lua_State *L) +{ +#ifdef LOVE_ENABLE_GRAPHICS + const auto &renderers = love::graphics::getRenderers(); + + lua_createtable(L, (int) renderers.size(), 0); + + int n = 1; + for (auto r : renderers) + { + const char *str = nullptr; + if (love::graphics::getConstant(r, str)) + { + lua_pushstring(L, str); + lua_rawseti(L, -2, n++); + } + } +#else + lua_createtable(L, 0, 0); +#endif + return 1; +} + +static int w__setRenderers(lua_State *L) +{ +#ifdef LOVE_ENABLE_GRAPHICS + std::vector renderers; + + luaL_checktype(L, 1, LUA_TTABLE); + for (size_t i = 1; i <= love::luax_objlen(L, 1); i++) + { + lua_rawgeti(L, -1, (int) i); + const char *str = luaL_checkstring(L, -1); + + love::graphics::Renderer r; + if (love::graphics::getConstant(str, r)) + renderers.push_back(r); + + lua_pop(L, 1); + } + + love::graphics::setRenderers(renderers); +#endif + return 0; +} + static int w__setHighDPIAllowed(lua_State *L) { #ifdef LOVE_ENABLE_WINDOW @@ -491,6 +560,15 @@ int luaopen_love(lua_State *L) lua_pushcfunction(L, w__setGammaCorrect); lua_setfield(L, -2, "_setGammaCorrect"); + lua_pushcfunction(L, w__getDefaultRenderers); + lua_setfield(L, -2, "_getDefaultRenderers"); + + lua_pushcfunction(L, w__getRenderers); + lua_setfield(L, -2, "_getRenderers"); + + lua_pushcfunction(L, w__setRenderers); + lua_setfield(L, -2, "_setRenderers"); + lua_pushcfunction(L, w__setHighDPIAllowed); lua_setfield(L, -2, "_setHighDPIAllowed"); diff --git a/src/modules/window/sdl/Window.cpp b/src/modules/window/sdl/Window.cpp index d917f514e..b7bcd6d38 100644 --- a/src/modules/window/sdl/Window.cpp +++ b/src/modules/window/sdl/Window.cpp @@ -295,7 +295,7 @@ std::vector Window::getContextAttribsList() const return attribslist; } -bool Window::createWindowAndContext(int x, int y, int w, int h, Uint32 windowflags, graphics::Graphics::Renderer renderer) +bool Window::createWindowAndContext(int x, int y, int w, int h, Uint32 windowflags, graphics::Renderer renderer) { bool needsglcontext = (windowflags & SDL_WINDOW_OPENGL) != 0; #ifdef LOVE_GRAPHICS_METAL @@ -368,7 +368,7 @@ bool Window::createWindowAndContext(int x, int y, int w, int h, Uint32 windowfla return true; }; - if (renderer == graphics::Graphics::RENDERER_OPENGL) + if (renderer == graphics::RENDERER_OPENGL) { std::vector attribslist = getContextAttribsList(); @@ -404,7 +404,7 @@ bool Window::createWindowAndContext(int x, int y, int w, int h, Uint32 windowfla } } #ifdef LOVE_GRAPHICS_METAL - else if (renderer == graphics::Graphics::RENDERER_METAL) + else if (renderer == graphics::RENDERER_METAL) { if (create(nullptr) && window != nullptr) metalView = SDL_Metal_CreateView(window); @@ -465,7 +465,7 @@ bool Window::setWindow(int width, int height, WindowSettings *settings) if (graphics.get() && graphics->isRenderTargetActive()) throw love::Exception("love.window.setMode cannot be called while a render target is active in love.graphics."); - auto renderer = graphics != nullptr ? graphics->getRenderer() : graphics::Graphics::RENDERER_NONE; + auto renderer = graphics != nullptr ? graphics->getRenderer() : graphics::RENDERER_NONE; if (isOpen()) updateSettings(this->settings, false); @@ -557,7 +557,7 @@ bool Window::setWindow(int width, int height, WindowSettings *settings) if (isOpen()) { - if (SDL_SetWindowFullscreen(window, sdlflags) == 0 && renderer == graphics::Graphics::RENDERER_OPENGL) + if (SDL_SetWindowFullscreen(window, sdlflags) == 0 && renderer == graphics::RENDERER_OPENGL) SDL_GL_MakeCurrent(window, glcontext); if (!f.fullscreen) @@ -575,11 +575,11 @@ bool Window::setWindow(int width, int height, WindowSettings *settings) } else { - if (renderer == graphics::Graphics::RENDERER_OPENGL) + if (renderer == graphics::RENDERER_OPENGL) sdlflags |= SDL_WINDOW_OPENGL; #ifdef LOVE_GRAPHICS_METAL - if (renderer == graphics::Graphics::RENDERER_METAL) + if (renderer == graphics::RENDERER_METAL) sdlflags |= SDL_WINDOW_METAL; #endif @@ -626,10 +626,10 @@ bool Window::setWindow(int width, int height, WindowSettings *settings) if (needsetmode) { void *context = nullptr; - if (renderer == graphics::Graphics::RENDERER_OPENGL) + if (renderer == graphics::RENDERER_OPENGL) context = (void *) glcontext; #ifdef LOVE_GRAPHICS_METAL - if (renderer == graphics::Graphics::RENDERER_METAL && metalView) + if (renderer == graphics::RENDERER_METAL && metalView) context = (void *) SDL_Metal_GetLayer(metalView); #endif diff --git a/src/modules/window/sdl/Window.h b/src/modules/window/sdl/Window.h index 7d96915ea..f93770f26 100644 --- a/src/modules/window/sdl/Window.h +++ b/src/modules/window/sdl/Window.h @@ -145,7 +145,7 @@ private: void setGLContextAttributes(const ContextAttribs &attribs); bool checkGLVersion(const ContextAttribs &attribs, std::string &outversion); std::vector getContextAttribsList() const; - bool createWindowAndContext(int x, int y, int w, int h, Uint32 windowflags, graphics::Graphics::Renderer renderer); + bool createWindowAndContext(int x, int y, int w, int h, Uint32 windowflags, graphics::Renderer renderer); // Update the saved window settings based on the window's actual state. void updateSettings(const WindowSettings &newsettings, bool updateGraphicsViewport); @@ -172,7 +172,7 @@ private: SDL_MetalView metalView; #endif - graphics::Graphics::Renderer windowRenderer = graphics::Graphics::RENDERER_NONE; + graphics::Renderer windowRenderer = graphics::RENDERER_NONE; bool displayedWindowError; bool hasSDL203orEarlier;