Browse Source

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.
Alex Szpakowski 3 years ago
parent
commit
5864d83c31

+ 32 - 2
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<Renderer> &renderers)
+static std::vector<Renderer> defaultRenderers =
+{
+	RENDERER_METAL,
+	RENDERER_OPENGL,
+};
+
+static std::vector<Renderer> _renderers = defaultRenderers;
+
+const std::vector<Renderer> &getDefaultRenderers()
+{
+	return defaultRenderers;
+}
+
+const std::vector<Renderer> &getRenderers()
+{
+	return _renderers;
+}
+
+void setRenderers(const std::vector<Renderer> &renderers)
+{
+	_renderers = renderers;
+}
+
+Graphics *Graphics::createInstance()
 {
 	Graphics *instance = Module::getInstance<Graphics>(M_GRAPHICS);
 
@@ -118,7 +141,7 @@ Graphics *Graphics::createInstance(const std::vector<Renderer> &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

+ 15 - 9
src/modules/graphics/Graphics.h

@@ -65,6 +65,14 @@ typedef Optional<ColorD> 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<Renderer> &getDefaultRenderers();
+const std::vector<Renderer> &getRenderers();
+void setRenderers(const std::vector<Renderer> &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<Renderer> &renderers);
+	static Graphics *createInstance();
 
 	STRINGMAP_CLASS_DECLARE(DrawMode);
 	STRINGMAP_CLASS_DECLARE(ArcMode);
@@ -1016,6 +1020,8 @@ private:
 
 }; // Graphics
 
+STRINGMAP_DECLARE(Renderer);
+
 } // graphics
 } // love
 

+ 1 - 1
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;
 }

+ 1 - 1
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;
 }

+ 1 - 10
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<Graphics::Renderer> 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)
 	{

+ 4 - 2
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 = {}

+ 41 - 0
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

+ 78 - 0
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<love::graphics::Renderer> 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");
 

+ 9 - 9
src/modules/window/sdl/Window.cpp

@@ -295,7 +295,7 @@ std::vector<Window::ContextAttribs> 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<ContextAttribs> 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
 

+ 2 - 2
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<ContextAttribs> 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;