diff --git a/Source/Core/Core/CMakeLists.txt b/Source/Core/Core/CMakeLists.txt
index f08080a3e2..5a2d89d518 100644
--- a/Source/Core/Core/CMakeLists.txt
+++ b/Source/Core/Core/CMakeLists.txt
@@ -233,6 +233,7 @@ set(LIBS
${LZO}
sfml-network
sfml-system
+ videonull
videoogl
videosoftware
z
diff --git a/Source/Core/DolphinWX/DolphinWX.vcxproj b/Source/Core/DolphinWX/DolphinWX.vcxproj
index 2f8183249d..ba66d9a20c 100644
--- a/Source/Core/DolphinWX/DolphinWX.vcxproj
+++ b/Source/Core/DolphinWX/DolphinWX.vcxproj
@@ -230,6 +230,9 @@
{a4c423aa-f57c-46c7-a172-d1a777017d29}
+
+ {53A5391B-737E-49A8-BC8F-312ADA00736F}
+
{3de9ee35-3e91-4f27-a014-2866ad8c3fe3}
diff --git a/Source/Core/DolphinWX/Main.cpp b/Source/Core/DolphinWX/Main.cpp
index 81df10255b..96fb4fa7f2 100644
--- a/Source/Core/DolphinWX/Main.cpp
+++ b/Source/Core/DolphinWX/Main.cpp
@@ -558,15 +558,14 @@ void Host_ConnectWiimote(int wm_idx, bool connect)
void Host_ShowVideoConfig(void* parent, const std::string& backend_name,
const std::string& config_name)
{
- if (backend_name == "Direct3D 11" || backend_name == "Direct3D 12 (experimental)" ||
- backend_name == "OpenGL")
- {
- VideoConfigDiag diag((wxWindow*)parent, backend_name, config_name);
- diag.ShowModal();
- }
- else if (backend_name == "Software Renderer")
+ if (backend_name == "Software Renderer")
{
SoftwareVideoConfigDialog diag((wxWindow*)parent, backend_name, config_name);
diag.ShowModal();
}
+ else
+ {
+ VideoConfigDiag diag((wxWindow*)parent, backend_name, config_name);
+ diag.ShowModal();
+ }
}
diff --git a/Source/Core/VideoBackends/CMakeLists.txt b/Source/Core/VideoBackends/CMakeLists.txt
index 1f5772306f..cb41b64b82 100644
--- a/Source/Core/VideoBackends/CMakeLists.txt
+++ b/Source/Core/VideoBackends/CMakeLists.txt
@@ -1,3 +1,4 @@
add_subdirectory(OGL)
+add_subdirectory(Null)
add_subdirectory(Software)
# TODO: Add other backends here!
diff --git a/Source/Core/VideoBackends/Null/CMakeLists.txt b/Source/Core/VideoBackends/Null/CMakeLists.txt
new file mode 100644
index 0000000000..f186da0067
--- /dev/null
+++ b/Source/Core/VideoBackends/Null/CMakeLists.txt
@@ -0,0 +1,14 @@
+set(SRCS
+ NullBackend.cpp
+ Render.cpp
+ VertexManager.cpp
+ ShaderCache.cpp
+)
+
+set(LIBS
+ videocommon
+ common
+)
+
+add_dolphin_library(videonull "${SRCS}" "${LIBS}")
+
diff --git a/Source/Core/VideoBackends/Null/FramebufferManager.h b/Source/Core/VideoBackends/Null/FramebufferManager.h
new file mode 100644
index 0000000000..9d8524b694
--- /dev/null
+++ b/Source/Core/VideoBackends/Null/FramebufferManager.h
@@ -0,0 +1,29 @@
+// Copyright 2015 Dolphin Emulator Project
+// Licensed under GPLv2+
+// Refer to the license.txt file included.
+
+#include "VideoCommon/FramebufferManagerBase.h"
+
+class XFBSource : public XFBSourceBase
+{
+public:
+ void DecodeToTexture(u32 xfb_addr, u32 fb_width, u32 fb_height) override {}
+ void CopyEFB(float gamma) override {}
+};
+
+class FramebufferManager : public FramebufferManagerBase
+{
+public:
+ std::unique_ptr CreateXFBSource(unsigned int target_width,
+ unsigned int target_height,
+ unsigned int layers) override
+ {
+ return std::make_unique();
+ }
+
+ void GetTargetSize(unsigned int* width, unsigned int* height) override {}
+ void CopyToRealXFB(u32 xfb_addr, u32 fb_stride, u32 fb_height, const EFBRectangle& source_rc,
+ float gamma = 1.0f) override
+ {
+ }
+};
diff --git a/Source/Core/VideoBackends/Null/Null.vcxproj b/Source/Core/VideoBackends/Null/Null.vcxproj
new file mode 100644
index 0000000000..7497675a73
--- /dev/null
+++ b/Source/Core/VideoBackends/Null/Null.vcxproj
@@ -0,0 +1,63 @@
+
+
+
+
+ Debug
+ x64
+
+
+ Release
+ x64
+
+
+
+ {53A5391B-737E-49A8-BC8F-312ADA00736F}
+
+
+
+ StaticLibrary
+ v140
+ Unicode
+
+
+ true
+
+
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {3de9ee35-3e91-4f27-a014-2866ad8c3fe3}
+
+
+
+
+
+
diff --git a/Source/Core/VideoBackends/Null/NullBackend.cpp b/Source/Core/VideoBackends/Null/NullBackend.cpp
new file mode 100644
index 0000000000..7a1691b9d5
--- /dev/null
+++ b/Source/Core/VideoBackends/Null/NullBackend.cpp
@@ -0,0 +1,127 @@
+// Copyright 2015 Dolphin Emulator Project
+// Licensed under GPLv2+
+// Refer to the license.txt file included.
+
+// Null Backend Documentation
+
+// This backend tries not to do anything in the backend,
+// but everything in VideoCommon.
+
+#include "Core/Host.h"
+
+#include "VideoBackends/Null/FramebufferManager.h"
+#include "VideoBackends/Null/PerfQuery.h"
+#include "VideoBackends/Null/Render.h"
+#include "VideoBackends/Null/ShaderCache.h"
+#include "VideoBackends/Null/TextureCache.h"
+#include "VideoBackends/Null/VertexManager.h"
+#include "VideoBackends/Null/VideoBackend.h"
+
+#include "VideoCommon/BPStructs.h"
+#include "VideoCommon/CommandProcessor.h"
+#include "VideoCommon/Fifo.h"
+#include "VideoCommon/IndexGenerator.h"
+#include "VideoCommon/OnScreenDisplay.h"
+#include "VideoCommon/OpcodeDecoding.h"
+#include "VideoCommon/PixelEngine.h"
+#include "VideoCommon/PixelShaderManager.h"
+#include "VideoCommon/VertexLoaderManager.h"
+#include "VideoCommon/VertexShaderManager.h"
+#include "VideoCommon/VideoBackendBase.h"
+#include "VideoCommon/VideoConfig.h"
+
+namespace Null
+{
+static void InitBackendInfo()
+{
+ g_Config.backend_info.APIType = API_NONE;
+ g_Config.backend_info.bSupportsExclusiveFullscreen = true;
+ g_Config.backend_info.bSupportsDualSourceBlend = true;
+ g_Config.backend_info.bSupportsEarlyZ = true;
+ g_Config.backend_info.bSupportsPrimitiveRestart = true;
+ g_Config.backend_info.bSupportsOversizedViewports = true;
+ g_Config.backend_info.bSupportsGeometryShaders = true;
+ g_Config.backend_info.bSupports3DVision = false;
+ g_Config.backend_info.bSupportsPostProcessing = false;
+ g_Config.backend_info.bSupportsPaletteConversion = true;
+ g_Config.backend_info.bSupportsClipControl = true;
+
+ // aamodes: We only support 1 sample, so no MSAA
+ g_Config.backend_info.AAModes = {1};
+}
+
+void VideoBackend::ShowConfig(void* parent)
+{
+ InitBackendInfo();
+ Host_ShowVideoConfig(parent, GetDisplayName(), "gfx_null");
+}
+
+bool VideoBackend::Initialize(void* window_handle)
+{
+ InitializeShared();
+ InitBackendInfo();
+
+ // Load Configs
+ g_Config.Load(File::GetUserPath(D_CONFIG_IDX) + "GFX.ini");
+ g_Config.GameIniLoad();
+ g_Config.UpdateProjectionHack();
+ g_Config.VerifyValidity();
+ UpdateActiveConfig();
+
+ // Do our OSD callbacks
+ OSD::DoCallbacks(OSD::CallbackType::Initialization);
+
+ // Initialize VideoCommon
+ CommandProcessor::Init();
+ PixelEngine::Init();
+ BPInit();
+ Fifo::Init();
+ OpcodeDecoder::Init();
+ IndexGenerator::Init();
+ VertexShaderManager::Init();
+ PixelShaderManager::Init();
+ VertexLoaderManager::Init();
+ Host_Message(WM_USER_CREATE);
+
+ return true;
+}
+
+// This is called after Initialize() from the Core
+// Run from the graphics thread
+void VideoBackend::Video_Prepare()
+{
+ g_renderer = std::make_unique();
+ g_vertex_manager = std::make_unique();
+ g_perf_query = std::make_unique();
+ g_framebuffer_manager = std::make_unique();
+ g_texture_cache = std::make_unique();
+ VertexShaderCache::s_instance = std::make_unique();
+ GeometryShaderCache::s_instance = std::make_unique();
+ PixelShaderCache::s_instance = std::make_unique();
+}
+
+void VideoBackend::Shutdown()
+{
+ // Shutdown VideoCommon
+ Fifo::Shutdown();
+ VertexLoaderManager::Shutdown();
+ VertexShaderManager::Shutdown();
+ PixelShaderManager::Shutdown();
+ OpcodeDecoder::Shutdown();
+
+ // Do our OSD callbacks
+ OSD::DoCallbacks(OSD::CallbackType::Shutdown);
+}
+
+void VideoBackend::Video_Cleanup()
+{
+ PixelShaderCache::s_instance.reset();
+ VertexShaderCache::s_instance.reset();
+ GeometryShaderCache::s_instance.reset();
+ g_texture_cache.reset();
+ g_perf_query.reset();
+ g_vertex_manager.reset();
+ g_framebuffer_manager.reset();
+ g_renderer.reset();
+}
+}
diff --git a/Source/Core/VideoBackends/Null/PerfQuery.h b/Source/Core/VideoBackends/Null/PerfQuery.h
new file mode 100644
index 0000000000..54a2d03cdb
--- /dev/null
+++ b/Source/Core/VideoBackends/Null/PerfQuery.h
@@ -0,0 +1,24 @@
+// Copyright 2015 Dolphin Emulator Project
+// Licensed under GPLv2+
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include "VideoCommon/PerfQueryBase.h"
+
+namespace Null
+{
+class PerfQuery : public PerfQueryBase
+{
+public:
+ PerfQuery() {}
+ ~PerfQuery() override {}
+ void EnableQuery(PerfQueryGroup type) override {}
+ void DisableQuery(PerfQueryGroup type) override {}
+ void ResetQuery() override {}
+ u32 GetQueryResult(PerfQueryType type) override { return 0; }
+ void FlushResults() override {}
+ bool IsFlushed() const { return true; }
+};
+
+} // namespace
diff --git a/Source/Core/VideoBackends/Null/Render.cpp b/Source/Core/VideoBackends/Null/Render.cpp
new file mode 100644
index 0000000000..fa26955ced
--- /dev/null
+++ b/Source/Core/VideoBackends/Null/Render.cpp
@@ -0,0 +1,46 @@
+// Copyright 2015 Dolphin Emulator Project
+// Licensed under GPLv2+
+// Refer to the license.txt file included.
+
+#include "Common/Logging/Log.h"
+
+#include "VideoBackends/Null/Render.h"
+
+#include "VideoCommon/VideoConfig.h"
+
+namespace Null
+{
+// Init functions
+Renderer::Renderer()
+{
+ g_Config.bRunning = true;
+ UpdateActiveConfig();
+}
+
+Renderer::~Renderer()
+{
+ g_Config.bRunning = false;
+ UpdateActiveConfig();
+}
+
+void Renderer::RenderText(const std::string& text, int left, int top, u32 color)
+{
+ NOTICE_LOG(VIDEO, "RenderText: %s\n", text.c_str());
+}
+
+TargetRectangle Renderer::ConvertEFBRectangle(const EFBRectangle& rc)
+{
+ TargetRectangle result;
+ result.left = rc.left;
+ result.top = rc.top;
+ result.right = rc.right;
+ result.bottom = rc.bottom;
+ return result;
+}
+
+void Renderer::SwapImpl(u32, u32, u32, u32, const EFBRectangle&, float)
+{
+ UpdateActiveConfig();
+}
+
+} // namespace Null
diff --git a/Source/Core/VideoBackends/Null/Render.h b/Source/Core/VideoBackends/Null/Render.h
new file mode 100644
index 0000000000..e436ce8123
--- /dev/null
+++ b/Source/Core/VideoBackends/Null/Render.h
@@ -0,0 +1,39 @@
+// Copyright 2015 Dolphin Emulator Project
+// Licensed under GPLv2+
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include "VideoCommon/RenderBase.h"
+
+namespace Null
+{
+class Renderer : public ::Renderer
+{
+public:
+ Renderer();
+ ~Renderer();
+
+ void RenderText(const std::string& pstr, int left, int top, u32 color) override;
+ u32 AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data) override { return 0; }
+ void PokeEFB(EFBAccessType type, const EfbPokeData* points, size_t num_points) override {}
+ u16 BBoxRead(int index) override { return 0; }
+ void BBoxWrite(int index, u16 value) override {}
+ int GetMaxTextureSize() override { return 16 * 1024; }
+ TargetRectangle ConvertEFBRectangle(const EFBRectangle& rc) override;
+
+ void SwapImpl(u32 xfb_addr, u32 fb_width, u32 fb_stride, u32 fb_height, const EFBRectangle& rc,
+ float gamma) override;
+
+ void ClearScreen(const EFBRectangle& rc, bool colorEnable, bool alphaEnable, bool zEnable,
+ u32 color, u32 z) override
+ {
+ }
+
+ void ReinterpretPixelData(unsigned int convtype) override {}
+ bool SaveScreenshot(const std::string& filename, const TargetRectangle& rc) override
+ {
+ return false;
+ }
+};
+}
diff --git a/Source/Core/VideoBackends/Null/ShaderCache.cpp b/Source/Core/VideoBackends/Null/ShaderCache.cpp
new file mode 100644
index 0000000000..e0fa000765
--- /dev/null
+++ b/Source/Core/VideoBackends/Null/ShaderCache.cpp
@@ -0,0 +1,76 @@
+// Copyright 2015 Dolphin Emulator Project
+// Licensed under GPLv2+
+// Refer to the license.txt file included.
+
+#include "VideoBackends/Null/ShaderCache.h"
+
+#include "VideoCommon/Debugger.h"
+#include "VideoCommon/Statistics.h"
+
+namespace Null
+{
+template
+ShaderCache::ShaderCache()
+{
+ Clear();
+
+ SETSTAT(stats.numPixelShadersCreated, 0);
+ SETSTAT(stats.numPixelShadersAlive, 0);
+}
+
+template
+ShaderCache::~ShaderCache()
+{
+ Clear();
+}
+
+template
+void ShaderCache::Clear()
+{
+ m_shaders.clear();
+ m_last_entry = nullptr;
+}
+
+template
+bool ShaderCache::SetShader(DSTALPHA_MODE dst_alpha_mode, u32 primitive_type)
+{
+ Uid uid = GetUid(dst_alpha_mode, primitive_type, API_OPENGL);
+
+ // Check if the shader is already set
+ if (m_last_entry)
+ {
+ if (uid == m_last_uid)
+ {
+ return true;
+ }
+ }
+
+ m_last_uid = uid;
+
+ // Check if the shader is already in the cache
+ auto iter = m_shaders.find(uid);
+ if (iter != m_shaders.end())
+ {
+ const std::string& entry = iter->second;
+ m_last_entry = &entry;
+
+ GFX_DEBUGGER_PAUSE_AT(NEXT_PIXEL_SHADER_CHANGE, true);
+ return true;
+ }
+
+ // Need to compile a new shader
+ ShaderCode code = GenerateCode(dst_alpha_mode, primitive_type, API_OPENGL);
+ m_shaders.emplace(uid, code.GetBuffer());
+
+ GFX_DEBUGGER_PAUSE_AT(NEXT_PIXEL_SHADER_CHANGE, true);
+ return true;
+}
+
+template class ShaderCache;
+template class ShaderCache;
+template class ShaderCache;
+
+std::unique_ptr VertexShaderCache::s_instance;
+std::unique_ptr GeometryShaderCache::s_instance;
+std::unique_ptr PixelShaderCache::s_instance;
+}
diff --git a/Source/Core/VideoBackends/Null/ShaderCache.h b/Source/Core/VideoBackends/Null/ShaderCache.h
new file mode 100644
index 0000000000..833c8acf36
--- /dev/null
+++ b/Source/Core/VideoBackends/Null/ShaderCache.h
@@ -0,0 +1,93 @@
+// Copyright 2015 Dolphin Emulator Project
+// Licensed under GPLv2+
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include