浏览代码

Merge branch 'inject_renderer_impl' into batching

* inject_renderer_impl:
  Add Unit Tests for injecting renderers with a string id.
  Use string id instead of enumeration.
  Update schemas...
  refactor(renderer_impl): Switch from driver enums to dependency-injection.
Sam Jaffe 6 年之前
父节点
当前提交
0812d82f0c

+ 3 - 0
.gitmodules

@@ -17,3 +17,6 @@
 [submodule "include/scope_guard"]
 	path = include/scope_guard
 	url = freenas:utility/scope_guard
+[submodule "include/resource_factory"]
+	path = include/resource_factory
+	url = freenas:utility/resource_factory.git

+ 3 - 7
engine/engine.xcodeproj/xcshareddata/xcschemes/engine-test.xcscheme

@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <Scheme
-   LastUpgradeVersion = "1030"
+   LastUpgradeVersion = "1110"
    version = "1.3">
    <BuildAction
       parallelizeBuildables = "YES"
@@ -10,9 +10,9 @@
       buildConfiguration = "Debug"
       selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
       selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      shouldUseLaunchSchemeArgsEnv = "YES"
       codeCoverageEnabled = "YES"
-      onlyGenerateCoverageForSpecifiedTargets = "YES"
-      shouldUseLaunchSchemeArgsEnv = "YES">
+      onlyGenerateCoverageForSpecifiedTargets = "YES">
       <CodeCoverageTargets>
          <BuildableReference
             BuildableIdentifier = "primary"
@@ -34,8 +34,6 @@
             </BuildableReference>
          </TestableReference>
       </Testables>
-      <AdditionalOptions>
-      </AdditionalOptions>
    </TestAction>
    <LaunchAction
       buildConfiguration = "Debug"
@@ -47,8 +45,6 @@
       debugDocumentVersioning = "YES"
       debugServiceExtension = "internal"
       allowLocationSimulation = "YES">
-      <AdditionalOptions>
-      </AdditionalOptions>
    </LaunchAction>
    <ProfileAction
       buildConfiguration = "Release"

+ 148 - 10
graphics/graphics.xcodeproj/project.pbxproj

@@ -9,19 +9,25 @@
 /* Begin PBXBuildFile section */
 		CD1C82BD22988EC700825C4E /* matrix.cxx in Sources */ = {isa = PBXBuildFile; fileRef = CD1C82BC22988EC700825C4E /* matrix.cxx */; };
 		CD1C83E922998E2600825C4E /* manager.cxx in Sources */ = {isa = PBXBuildFile; fileRef = CD1C83E722998E2600825C4E /* manager.cxx */; settings = {COMPILER_FLAGS = "-fvisibility=default"; }; };
-		CD1C840F2299B81500825C4E /* error_formatter.cxx in Sources */ = {isa = PBXBuildFile; fileRef = CD1C840D2299B81500825C4E /* error_formatter.cxx */; };
 		CD3AC6F21D2C03B7002B4BB0 /* material.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CD3AC6F01D2C03B7002B4BB0 /* material.cpp */; };
 		CD3AC6F81D2C0518002B4BB0 /* texture.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CD3AC6F61D2C0518002B4BB0 /* texture.cpp */; };
 		CD3AC6FD1D2C06B5002B4BB0 /* shader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CD3AC6FB1D2C06B5002B4BB0 /* shader.cpp */; };
 		CD3AC7191D2C0950002B4BB0 /* shader_program.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CD3AC7171D2C0950002B4BB0 /* shader_program.cpp */; };
 		CD3AC7261D2C0C63002B4BB0 /* object.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CD3AC7241D2C0C63002B4BB0 /* object.cpp */; settings = {COMPILER_FLAGS = "-fvisibility=default"; }; };
 		CD62FCF72290DC9000376440 /* helper.hpp in Headers */ = {isa = PBXBuildFile; fileRef = CD62FCF52290DC9000376440 /* helper.hpp */; };
-		CD62FCF82290DC9000376440 /* opengl_manager.cxx in Sources */ = {isa = PBXBuildFile; fileRef = CD62FCF62290DC9000376440 /* opengl_manager.cxx */; };
-		CD62FCFA2290E2E500376440 /* OpenGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CD62FCF92290E2E500376440 /* OpenGL.framework */; };
 		CD62FD062291970F00376440 /* libgameutils.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = CD62FD052291970F00376440 /* libgameutils.dylib */; };
 		CD62FD1E2292412900376440 /* renderer.cxx in Sources */ = {isa = PBXBuildFile; fileRef = CD62FD1C2292412900376440 /* renderer.cxx */; settings = {COMPILER_FLAGS = "-fvisibility=default"; }; };
 		CD62FD222292C76B00376440 /* renderer_impl.hpp in Headers */ = {isa = PBXBuildFile; fileRef = CD62FD202292C76B00376440 /* renderer_impl.hpp */; };
-		CD62FD232292C76B00376440 /* opengl_renderer.cxx in Sources */ = {isa = PBXBuildFile; fileRef = CD62FD212292C76B00376440 /* opengl_renderer.cxx */; };
+		CD6CDB68234EA31F00D76C1A /* opengl_renderer.cxx in Sources */ = {isa = PBXBuildFile; fileRef = CD62FD212292C76B00376440 /* opengl_renderer.cxx */; };
+		CD6CDB69234EA32300D76C1A /* opengl_manager.cxx in Sources */ = {isa = PBXBuildFile; fileRef = CD62FCF62290DC9000376440 /* opengl_manager.cxx */; };
+		CD6CDB6A234EA32300D76C1A /* error_formatter.cxx in Sources */ = {isa = PBXBuildFile; fileRef = CD1C840D2299B81500825C4E /* error_formatter.cxx */; };
+		CD6CDB6C234EA6CE00D76C1A /* OpenGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CD62FCF92290E2E500376440 /* OpenGL.framework */; };
+		CD6CDB6D234EA6DC00D76C1A /* libgameutils.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = CD62FD052291970F00376440 /* libgameutils.dylib */; };
+		CD6CDB6E234EA6DC00D76C1A /* libgameutils.dylib in Embed Libraries */ = {isa = PBXBuildFile; fileRef = CD62FD052291970F00376440 /* libgameutils.dylib */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
+		CD6CDB6F234EA6DC00D76C1A /* libmath.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = CDA34D9922517A3D008036A7 /* libmath.dylib */; };
+		CD6CDB70234EA6DC00D76C1A /* libmath.dylib in Embed Libraries */ = {isa = PBXBuildFile; fileRef = CDA34D9922517A3D008036A7 /* libmath.dylib */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
+		CD6CDB72234EA70700D76C1A /* libgraphics.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = CD3AC6E21D2C0364002B4BB0 /* libgraphics.dylib */; };
+		CD6CDB73234EA70700D76C1A /* libgraphics.dylib in Embed Libraries */ = {isa = PBXBuildFile; fileRef = CD3AC6E21D2C0364002B4BB0 /* libgraphics.dylib */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
 		CDA34D9A22517A3D008036A7 /* libmath.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = CDA34D9922517A3D008036A7 /* libmath.dylib */; };
 		CDED9C1922A2D6CE00AE5CE5 /* libgraphics.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = CD3AC6E21D2C0364002B4BB0 /* libgraphics.dylib */; };
 		CDED9C4322A2FACB00AE5CE5 /* renderer_test.cxx in Sources */ = {isa = PBXBuildFile; fileRef = CDED9C4222A2FACB00AE5CE5 /* renderer_test.cxx */; };
@@ -62,6 +68,13 @@
 			remoteGlobalIDString = 05818F901A685AEA0072A469;
 			remoteInfo = GoogleMockTests;
 		};
+		CD6CDB74234EA70700D76C1A /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = CD3AC6DA1D2C0364002B4BB0 /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = CD3AC6E11D2C0364002B4BB0;
+			remoteInfo = graphics;
+		};
 		CDED9C1A22A2D6CE00AE5CE5 /* PBXContainerItemProxy */ = {
 			isa = PBXContainerItemProxy;
 			containerPortal = CD3AC6DA1D2C0364002B4BB0 /* Project object */;
@@ -78,6 +91,22 @@
 		};
 /* End PBXContainerItemProxy section */
 
+/* Begin PBXCopyFilesBuildPhase section */
+		CD6CDB71234EA6DC00D76C1A /* Embed Libraries */ = {
+			isa = PBXCopyFilesBuildPhase;
+			buildActionMask = 2147483647;
+			dstPath = "";
+			dstSubfolderSpec = 10;
+			files = (
+				CD6CDB73234EA70700D76C1A /* libgraphics.dylib in Embed Libraries */,
+				CD6CDB70234EA6DC00D76C1A /* libmath.dylib in Embed Libraries */,
+				CD6CDB6E234EA6DC00D76C1A /* libgameutils.dylib in Embed Libraries */,
+			);
+			name = "Embed Libraries";
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXCopyFilesBuildPhase section */
+
 /* Begin PBXFileReference section */
 		CD1C82B722988E4E00825C4E /* matrix.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = matrix.hpp; sourceTree = "<group>"; };
 		CD1C82BC22988EC700825C4E /* matrix.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = matrix.cxx; sourceTree = "<group>"; };
@@ -97,6 +126,7 @@
 		CD62FD1C2292412900376440 /* renderer.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = renderer.cxx; sourceTree = "<group>"; };
 		CD62FD202292C76B00376440 /* renderer_impl.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = renderer_impl.hpp; sourceTree = "<group>"; };
 		CD62FD212292C76B00376440 /* opengl_renderer.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = opengl_renderer.cxx; sourceTree = "<group>"; };
+		CD6CDB61234EA31500D76C1A /* libopengl_graphics.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = libopengl_graphics.dylib; sourceTree = BUILT_PRODUCTS_DIR; };
 		CDA34D86225171AA008036A7 /* game */ = {isa = PBXFileReference; lastKnownFileType = folder; name = game; path = include/game; sourceTree = "<group>"; };
 		CDA34D9922517A3D008036A7 /* libmath.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; path = libmath.dylib; sourceTree = BUILT_PRODUCTS_DIR; };
 		CDED9C1422A2D6CD00AE5CE5 /* graphics-test.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "graphics-test.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -113,11 +143,21 @@
 			buildActionMask = 2147483647;
 			files = (
 				CD62FD062291970F00376440 /* libgameutils.dylib in Frameworks */,
-				CD62FCFA2290E2E500376440 /* OpenGL.framework in Frameworks */,
 				CDA34D9A22517A3D008036A7 /* libmath.dylib in Frameworks */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
+		CD6CDB5F234EA31500D76C1A /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				CD6CDB6D234EA6DC00D76C1A /* libgameutils.dylib in Frameworks */,
+				CD6CDB6C234EA6CE00D76C1A /* OpenGL.framework in Frameworks */,
+				CD6CDB6F234EA6DC00D76C1A /* libmath.dylib in Frameworks */,
+				CD6CDB72234EA70700D76C1A /* libgraphics.dylib in Frameworks */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
 		CDED9C1122A2D6CD00AE5CE5 /* Frameworks */ = {
 			isa = PBXFrameworksBuildPhase;
 			buildActionMask = 2147483647;
@@ -161,6 +201,7 @@
 			children = (
 				CD3AC6E21D2C0364002B4BB0 /* libgraphics.dylib */,
 				CDED9C1422A2D6CD00AE5CE5 /* graphics-test.xctest */,
+				CD6CDB61234EA31500D76C1A /* libopengl_graphics.dylib */,
 			);
 			name = Products;
 			sourceTree = "<group>";
@@ -252,6 +293,13 @@
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
+		CD6CDB5D234EA31500D76C1A /* Headers */ = {
+			isa = PBXHeadersBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
 /* End PBXHeadersBuildPhase section */
 
 /* Begin PBXNativeTarget section */
@@ -273,6 +321,25 @@
 			productReference = CD3AC6E21D2C0364002B4BB0 /* libgraphics.dylib */;
 			productType = "com.apple.product-type.library.dynamic";
 		};
+		CD6CDB60234EA31500D76C1A /* opengl_graphics */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = CD6CDB67234EA31500D76C1A /* Build configuration list for PBXNativeTarget "opengl_graphics" */;
+			buildPhases = (
+				CD6CDB5D234EA31500D76C1A /* Headers */,
+				CD6CDB5E234EA31500D76C1A /* Sources */,
+				CD6CDB5F234EA31500D76C1A /* Frameworks */,
+				CD6CDB71234EA6DC00D76C1A /* Embed Libraries */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+				CD6CDB75234EA70700D76C1A /* PBXTargetDependency */,
+			);
+			name = opengl_graphics;
+			productName = opengl_graphics;
+			productReference = CD6CDB61234EA31500D76C1A /* libopengl_graphics.dylib */;
+			productType = "com.apple.product-type.library.dynamic";
+		};
 		CDED9C1322A2D6CD00AE5CE5 /* graphics-test */ = {
 			isa = PBXNativeTarget;
 			buildConfigurationList = CDED9C2222A2D6CE00AE5CE5 /* Build configuration list for PBXNativeTarget "graphics-test" */;
@@ -304,6 +371,10 @@
 					CD3AC6E11D2C0364002B4BB0 = {
 						CreatedOnToolsVersion = 7.2.1;
 					};
+					CD6CDB60234EA31500D76C1A = {
+						CreatedOnToolsVersion = 11.1;
+						ProvisioningStyle = Automatic;
+					};
 					CDED9C1322A2D6CD00AE5CE5 = {
 						CreatedOnToolsVersion = 10.1;
 						ProvisioningStyle = Automatic;
@@ -331,6 +402,7 @@
 			targets = (
 				CD3AC6E11D2C0364002B4BB0 /* graphics */,
 				CDED9C1322A2D6CD00AE5CE5 /* graphics-test */,
+				CD6CDB60234EA31500D76C1A /* opengl_graphics */,
 			);
 		};
 /* End PBXProject section */
@@ -406,13 +478,20 @@
 				CD3AC7191D2C0950002B4BB0 /* shader_program.cpp in Sources */,
 				CD1C82BD22988EC700825C4E /* matrix.cxx in Sources */,
 				CD3AC6F21D2C03B7002B4BB0 /* material.cpp in Sources */,
-				CD1C840F2299B81500825C4E /* error_formatter.cxx in Sources */,
 				CD62FD1E2292412900376440 /* renderer.cxx in Sources */,
 				CD3AC6F81D2C0518002B4BB0 /* texture.cpp in Sources */,
 				CD3AC7261D2C0C63002B4BB0 /* object.cpp in Sources */,
 				CD1C83E922998E2600825C4E /* manager.cxx in Sources */,
-				CD62FCF82290DC9000376440 /* opengl_manager.cxx in Sources */,
-				CD62FD232292C76B00376440 /* opengl_renderer.cxx in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+		CD6CDB5E234EA31500D76C1A /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				CD6CDB69234EA32300D76C1A /* opengl_manager.cxx in Sources */,
+				CD6CDB68234EA31F00D76C1A /* opengl_renderer.cxx in Sources */,
+				CD6CDB6A234EA32300D76C1A /* error_formatter.cxx in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -428,6 +507,11 @@
 /* End PBXSourcesBuildPhase section */
 
 /* Begin PBXTargetDependency section */
+		CD6CDB75234EA70700D76C1A /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			target = CD3AC6E11D2C0364002B4BB0 /* graphics */;
+			targetProxy = CD6CDB74234EA70700D76C1A /* PBXContainerItemProxy */;
+		};
 		CDED9C1B22A2D6CE00AE5CE5 /* PBXTargetDependency */ = {
 			isa = PBXTargetDependency;
 			target = CD3AC6E11D2C0364002B4BB0 /* graphics */;
@@ -491,7 +575,7 @@
 				MTL_ENABLE_DEBUG_INFO = YES;
 				ONLY_ACTIVE_ARCH = YES;
 				SDKROOT = macosx;
-				USER_HEADER_SEARCH_PATHS = "$(PROJECT_DIR)/include/ $(PROJECT_DIR)/../include/expect/include/ $(PROJECT_DIR)/../math/ $(PROJECT_DIR)/../include/ $(PROJECT_DIR)/../math/include/ $(PROJECT_DIR)/../util/include";
+				USER_HEADER_SEARCH_PATHS = "$(PROJECT_DIR)/include/ $(PROJECT_DIR)/../include/expect/include/ $(PROJECT_DIR)/../math/ $(PROJECT_DIR)/../include/ $(PROJECT_DIR)/../math/include/ $(PROJECT_DIR)/../include/resource_factory/include/ $(PROJECT_DIR)/../util/include";
 			};
 			name = Debug;
 		};
@@ -538,7 +622,7 @@
 				MACOSX_DEPLOYMENT_TARGET = 10.10;
 				MTL_ENABLE_DEBUG_INFO = NO;
 				SDKROOT = macosx;
-				USER_HEADER_SEARCH_PATHS = "$(PROJECT_DIR)/include/ $(PROJECT_DIR)/../include/expect/include/ $(PROJECT_DIR)/../math/ $(PROJECT_DIR)/../include/ $(PROJECT_DIR)/../math/include/ $(PROJECT_DIR)/../util/include";
+				USER_HEADER_SEARCH_PATHS = "$(PROJECT_DIR)/include/ $(PROJECT_DIR)/../include/expect/include/ $(PROJECT_DIR)/../math/ $(PROJECT_DIR)/../include/ $(PROJECT_DIR)/../math/include/ $(PROJECT_DIR)/../include/resource_factory/include/ $(PROJECT_DIR)/../util/include";
 			};
 			name = Release;
 		};
@@ -568,6 +652,51 @@
 			};
 			name = Release;
 		};
+		CD6CDB62234EA31500D76C1A /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				CLANG_ANALYZER_NONNULL = YES;
+				CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+				CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
+				CLANG_ENABLE_OBJC_WEAK = YES;
+				CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+				CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+				CODE_SIGN_STYLE = Automatic;
+				DYLIB_COMPATIBILITY_VERSION = 1;
+				DYLIB_CURRENT_VERSION = 1;
+				EXECUTABLE_PREFIX = lib;
+				GCC_C_LANGUAGE_STANDARD = gnu11;
+				MACOSX_DEPLOYMENT_TARGET = 10.10;
+				MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
+				MTL_FAST_MATH = YES;
+				PRODUCT_NAME = "$(TARGET_NAME)";
+				SKIP_INSTALL = YES;
+			};
+			name = Debug;
+		};
+		CD6CDB63234EA31500D76C1A /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				CLANG_ANALYZER_NONNULL = YES;
+				CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+				CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
+				CLANG_ENABLE_OBJC_WEAK = YES;
+				CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+				CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+				CODE_SIGN_STYLE = Automatic;
+				DYLIB_COMPATIBILITY_VERSION = 1;
+				DYLIB_CURRENT_VERSION = 1;
+				EXECUTABLE_PREFIX = lib;
+				GCC_C_LANGUAGE_STANDARD = gnu11;
+				MACOSX_DEPLOYMENT_TARGET = 10.10;
+				MTL_FAST_MATH = YES;
+				PRODUCT_NAME = "$(TARGET_NAME)";
+				SKIP_INSTALL = YES;
+			};
+			name = Release;
+		};
 		CDED9C1C22A2D6CE00AE5CE5 /* Debug */ = {
 			isa = XCBuildConfiguration;
 			buildSettings = {
@@ -634,6 +763,15 @@
 			defaultConfigurationIsVisible = 0;
 			defaultConfigurationName = Release;
 		};
+		CD6CDB67234EA31500D76C1A /* Build configuration list for PBXNativeTarget "opengl_graphics" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				CD6CDB62234EA31500D76C1A /* Debug */,
+				CD6CDB63234EA31500D76C1A /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
 		CDED9C2222A2D6CE00AE5CE5 /* Build configuration list for PBXNativeTarget "graphics-test" */ = {
 			isa = XCConfigurationList;
 			buildConfigurations = (

+ 3 - 7
graphics/graphics.xcodeproj/xcshareddata/xcschemes/graphics-test.xcscheme

@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <Scheme
-   LastUpgradeVersion = "1030"
+   LastUpgradeVersion = "1110"
    version = "1.3">
    <BuildAction
       parallelizeBuildables = "YES"
@@ -10,9 +10,9 @@
       buildConfiguration = "Debug"
       selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
       selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      shouldUseLaunchSchemeArgsEnv = "YES"
       codeCoverageEnabled = "YES"
-      onlyGenerateCoverageForSpecifiedTargets = "YES"
-      shouldUseLaunchSchemeArgsEnv = "YES">
+      onlyGenerateCoverageForSpecifiedTargets = "YES">
       <CodeCoverageTargets>
          <BuildableReference
             BuildableIdentifier = "primary"
@@ -34,8 +34,6 @@
             </BuildableReference>
          </TestableReference>
       </Testables>
-      <AdditionalOptions>
-      </AdditionalOptions>
    </TestAction>
    <LaunchAction
       buildConfiguration = "Debug"
@@ -47,8 +45,6 @@
       debugDocumentVersioning = "YES"
       debugServiceExtension = "internal"
       allowLocationSimulation = "YES">
-      <AdditionalOptions>
-      </AdditionalOptions>
    </LaunchAction>
    <ProfileAction
       buildConfiguration = "Release"

+ 2 - 2
graphics/include/game/graphics/renderer.hpp

@@ -27,11 +27,11 @@ namespace graphics {
     virtual void flush() = 0;
   };
 
-  enum class driver { openGL };
+  enum class driver {}; // Dummy class...
 
   class direct_renderer : public renderer {
   public:
-    direct_renderer(driver d);
+    direct_renderer(std::string const & driver_id);
     direct_renderer(class renderer_impl * pi);
     std::shared_ptr<class manager const> manager() const override;
     void draw(object const & obj) override;

+ 6 - 1
graphics/src/openGL/opengl_renderer.cxx

@@ -114,7 +114,12 @@ void opengl_renderer::activate(material const & mat) {
   glActiveTexture(GL_TEXTURE0);
 }
 
-template <> renderer_impl * graphics::get_renderer_impl<driver::openGL>() {
+renderer_impl * get_openGL() {
   static opengl_renderer impl;
   return &impl;
 }
+
+namespace {
+  bool _ =
+      graphics::renderer_impl_factory::instance().bind("openGL", &get_openGL);
+}

+ 1 - 1
graphics/src/openGL/opengl_renderer.h

@@ -9,9 +9,9 @@
 #pragma once
 
 #include "../helper.hpp"
+#include "../renderer_impl.hpp"
 #include "game/graphics/manager.hpp"
 #include "game/util/identity.hpp"
-#include "renderer_impl.hpp"
 
 #include "matrix/matrix.hpp"
 #include "matrix/matrix_helpers.hpp"

+ 7 - 8
graphics/src/renderer.cxx

@@ -18,20 +18,19 @@
 
 using namespace graphics;
 
-renderer_impl * get_renderer_impl(driver d) {
-  switch (d) {
-  case driver::openGL:
-    return get_renderer_impl<driver::openGL>();
-  default:
-    throw unmapped_enum<driver>(d);
-  }
+INSTANTIATE_PROTOTYPE_FACTORY(renderer_impl *);
+renderer_impl * get_renderer_impl(std::string const & id) {
+  renderer_impl * rval = renderer_impl_factory::instance().get(id);
+  if (rval == nullptr) throw unmapped_enum<driver>(id);
+  return rval;
 }
 
 namespace {
   const math::matr4 identity4 = math::matrix::identity<float, 4>();
 }
 
-direct_renderer::direct_renderer(driver d) : pimpl(::get_renderer_impl(d)) {}
+direct_renderer::direct_renderer(std::string const & driver_id)
+    : direct_renderer(::get_renderer_impl(driver_id)) {}
 
 direct_renderer::direct_renderer(renderer_impl * pi) : pimpl(pi) {}
 

+ 3 - 1
graphics/src/renderer_impl.hpp

@@ -12,8 +12,10 @@
 #include "game/graphics/renderer.hpp"
 #include "game/math/math_fwd.hpp"
 
+#include "resource_factory/prototype_factory.hpp"
+
 namespace graphics {
-  template <driver> renderer_impl * get_renderer_impl();
+  using renderer_impl_factory = objects::prototype::factory<renderer_impl *>;
 
   struct renderer_impl {
     virtual ~renderer_impl() {}

+ 39 - 0
graphics/test/renderer_test.cxx

@@ -9,6 +9,7 @@
 #include <gmock/gmock.h>
 
 #include "../src/renderer_impl.hpp"
+#include "game/graphics/exception.h"
 #include "game/graphics/object.hpp"
 #include "game/graphics/renderer.hpp"
 #include "game/graphics/vertex.h"
@@ -157,3 +158,41 @@ TEST_F(BatchRendererTest, BatchLimitingCanSplitTheWrites) {
   renderer->draw(DemoObject(2));
   renderer->draw(DemoObject(2));
 }
+
+struct InjectRendererTest : testing::Test {
+protected:
+  void SetUp() override;
+  void TearDown() override;
+  mock_renderer_impl * mock;
+
+private:
+  graphics::renderer_impl_factory::scoped_binding scope_;
+};
+
+void InjectRendererTest::SetUp() {
+  mock = new mock_renderer_impl;
+  auto & factory = graphics::renderer_impl_factory::instance();
+  scope_ = factory.bind_scoped("mock", [this]() { return mock; });
+}
+
+void InjectRendererTest::TearDown() { delete mock; }
+
+TEST_F(InjectRendererTest, ThrowsOnRequestOfBlank) {
+  EXPECT_THROW(graphics::direct_renderer(""),
+               graphics::unmapped_enum<graphics::driver>);
+}
+
+TEST(UnboundRendererTest, ThrowsOnRequestOfUnboundDriver) {
+  EXPECT_THROW(graphics::direct_renderer("mock"),
+               graphics::unmapped_enum<graphics::driver>);
+}
+
+TEST_F(InjectRendererTest, SuccessfulConstructionWithBoundImpl) {
+  EXPECT_NO_THROW(graphics::direct_renderer("mock"));
+}
+
+TEST_F(InjectRendererTest, BoundImplIsSamePointed) {
+  graphics::direct_renderer renderer("mock");
+  EXPECT_CALL(*mock, draw(cast(1), math::matr4(), IsEmpty())).Times(1);
+  renderer.draw(cast(1), math::matr4(), {});
+}

+ 1 - 0
include/resource_factory

@@ -0,0 +1 @@
+Subproject commit 5131e8ab6f8ec488d9e9fc9d82aac6f5ba09c620

+ 3 - 7
math/math.xcodeproj/xcshareddata/xcschemes/math-test.xcscheme

@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <Scheme
-   LastUpgradeVersion = "1030"
+   LastUpgradeVersion = "1110"
    version = "1.3">
    <BuildAction
       parallelizeBuildables = "YES"
@@ -10,9 +10,9 @@
       buildConfiguration = "Debug"
       selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
       selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      shouldUseLaunchSchemeArgsEnv = "YES"
       codeCoverageEnabled = "YES"
-      onlyGenerateCoverageForSpecifiedTargets = "YES"
-      shouldUseLaunchSchemeArgsEnv = "YES">
+      onlyGenerateCoverageForSpecifiedTargets = "YES">
       <CodeCoverageTargets>
          <BuildableReference
             BuildableIdentifier = "primary"
@@ -34,8 +34,6 @@
             </BuildableReference>
          </TestableReference>
       </Testables>
-      <AdditionalOptions>
-      </AdditionalOptions>
    </TestAction>
    <LaunchAction
       buildConfiguration = "Debug"
@@ -47,8 +45,6 @@
       debugDocumentVersioning = "YES"
       debugServiceExtension = "internal"
       allowLocationSimulation = "YES">
-      <AdditionalOptions>
-      </AdditionalOptions>
    </LaunchAction>
    <ProfileAction
       buildConfiguration = "Release"