nullvideo: initial release of null video backend

This commit is contained in:
degasus 2014-02-03 14:02:17 +01:00
parent 10682dbf58
commit 59e4882af3
16 changed files with 625 additions and 8 deletions

View File

@ -233,6 +233,7 @@ set(LIBS
${LZO}
sfml-network
sfml-system
videonull
videoogl
videosoftware
z

View File

@ -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();
}
}

View File

@ -1,3 +1,4 @@
add_subdirectory(OGL)
add_subdirectory(Null)
add_subdirectory(Software)
# TODO: Add other backends here!

View File

@ -0,0 +1,14 @@
set(SRCS
NullBackend.cpp
Render.cpp
VertexManager.cpp
ShaderCache.cpp
)
set(LIBS
videocommon
common
)
add_dolphin_library(videonull "${SRCS}" "${LIBS}")

View File

@ -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<XFBSourceBase> CreateXFBSource(unsigned int target_width,
unsigned int target_height,
unsigned int layers) override
{
return std::make_unique<XFBSource>();
}
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
{
}
};

View File

@ -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<Renderer>();
g_vertex_manager = std::make_unique<VertexManager>();
g_perf_query = std::make_unique<PerfQuery>();
g_framebuffer_manager = std::make_unique<FramebufferManager>();
g_texture_cache = std::make_unique<TextureCache>();
VertexShaderCache::s_instance = std::make_unique<VertexShaderCache>();
GeometryShaderCache::s_instance = std::make_unique<GeometryShaderCache>();
PixelShaderCache::s_instance = std::make_unique<PixelShaderCache>();
}
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();
}
}

View File

@ -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

View File

@ -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

View File

@ -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;
}
};
}

View File

@ -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 <typename Uid>
ShaderCache<Uid>::ShaderCache()
{
Clear();
SETSTAT(stats.numPixelShadersCreated, 0);
SETSTAT(stats.numPixelShadersAlive, 0);
}
template <typename Uid>
ShaderCache<Uid>::~ShaderCache()
{
Clear();
}
template <typename Uid>
void ShaderCache<Uid>::Clear()
{
m_shaders.clear();
m_last_entry = nullptr;
}
template <typename Uid>
bool ShaderCache<Uid>::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<VertexShaderUid>;
template class ShaderCache<GeometryShaderUid>;
template class ShaderCache<PixelShaderUid>;
std::unique_ptr<VertexShaderCache> VertexShaderCache::s_instance;
std::unique_ptr<GeometryShaderCache> GeometryShaderCache::s_instance;
std::unique_ptr<PixelShaderCache> PixelShaderCache::s_instance;
}

View File

@ -0,0 +1,93 @@
// Copyright 2015 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#pragma once
#include <map>
#include <memory>
#include "VideoCommon/GeometryShaderGen.h"
#include "VideoCommon/PixelShaderGen.h"
#include "VideoCommon/VertexShaderGen.h"
#include "VideoCommon/VideoCommon.h"
namespace Null
{
template <typename Uid>
class ShaderCache
{
public:
ShaderCache();
virtual ~ShaderCache();
void Clear();
bool SetShader(DSTALPHA_MODE dst_alpha_mode, u32 primitive_type);
protected:
virtual Uid GetUid(DSTALPHA_MODE dst_alpha_mode, u32 primitive_type, API_TYPE api_type) = 0;
virtual ShaderCode GenerateCode(DSTALPHA_MODE dst_alpha_mode, u32 primitive_type,
API_TYPE api_type) = 0;
private:
std::map<Uid, std::string> m_shaders;
const std::string* m_last_entry = nullptr;
Uid m_last_uid;
UidChecker<Uid, ShaderCode> m_uid_checker;
};
class VertexShaderCache : public ShaderCache<VertexShaderUid>
{
public:
static std::unique_ptr<VertexShaderCache> s_instance;
protected:
VertexShaderUid GetUid(DSTALPHA_MODE dst_alpha_mode, u32 primitive_type,
API_TYPE api_type) override
{
return GetVertexShaderUid(api_type);
}
ShaderCode GenerateCode(DSTALPHA_MODE dst_alpha_mode, u32 primitive_type,
API_TYPE api_type) override
{
return GenerateVertexShaderCode(api_type);
}
};
class GeometryShaderCache : public ShaderCache<GeometryShaderUid>
{
public:
static std::unique_ptr<GeometryShaderCache> s_instance;
protected:
GeometryShaderUid GetUid(DSTALPHA_MODE dst_alpha_mode, u32 primitive_type,
API_TYPE api_type) override
{
return GetGeometryShaderUid(primitive_type, api_type);
}
ShaderCode GenerateCode(DSTALPHA_MODE dst_alpha_mode, u32 primitive_type,
API_TYPE api_type) override
{
return GenerateGeometryShaderCode(primitive_type, api_type);
}
};
class PixelShaderCache : public ShaderCache<PixelShaderUid>
{
public:
static std::unique_ptr<PixelShaderCache> s_instance;
protected:
PixelShaderUid GetUid(DSTALPHA_MODE dst_alpha_mode, u32 primitive_type,
API_TYPE api_type) override
{
return GetPixelShaderUid(dst_alpha_mode, api_type);
}
ShaderCode GenerateCode(DSTALPHA_MODE dst_alpha_mode, u32 primitive_type,
API_TYPE api_type) override
{
return GeneratePixelShaderCode(dst_alpha_mode, api_type);
}
};
} // namespace NULL

View File

@ -0,0 +1,60 @@
// Copyright 2015 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#pragma once
#include "VideoCommon/TextureCacheBase.h"
namespace Null
{
class TextureCache : public TextureCacheBase
{
public:
TextureCache() {}
~TextureCache() {}
void CompileShaders() override {}
void DeleteShaders() override {}
void ConvertTexture(TCacheEntryBase* entry, TCacheEntryBase* unconverted, void* palette,
TlutFormat format) override
{
}
void CopyEFB(u8* dst, u32 format, u32 native_width, u32 bytes_per_row, u32 num_blocks_y,
u32 memory_stride, PEControl::PixelFormat src_format, const EFBRectangle& src_rect,
bool is_intensity, bool scale_by_half) override
{
}
private:
struct TCacheEntry : TCacheEntryBase
{
TCacheEntry(const TCacheEntryConfig& _config) : TCacheEntryBase(_config) {}
~TCacheEntry() {}
void Load(unsigned int width, unsigned int height, unsigned int expanded_width,
unsigned int level) override
{
}
void FromRenderTarget(u8* dst, PEControl::PixelFormat src_format, const EFBRectangle& src_rect,
bool scale_by_half, unsigned int cbufid, const float* colmat) override
{
}
void CopyRectangleFromTexture(const TCacheEntryBase* source,
const MathUtil::Rectangle<int>& srcrect,
const MathUtil::Rectangle<int>& dstrect) override
{
}
void Bind(unsigned int stage) override {}
bool Save(const std::string& filename, unsigned int level) override { return false; }
};
TCacheEntryBase* CreateTexture(const TCacheEntryConfig& config) override
{
return new TCacheEntry(config);
}
};
} // Null name space

View File

@ -0,0 +1,53 @@
// Copyright 2015 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#include "VideoBackends/Null/VertexManager.h"
#include "VideoBackends/Null/ShaderCache.h"
#include "VideoCommon/IndexGenerator.h"
#include "VideoCommon/Statistics.h"
#include "VideoCommon/VertexLoaderManager.h"
#include "VideoCommon/VideoConfig.h"
namespace Null
{
class NullNativeVertexFormat : public NativeVertexFormat
{
public:
NullNativeVertexFormat() {}
void SetupVertexPointers() override {}
};
NativeVertexFormat*
VertexManager::CreateNativeVertexFormat(const PortableVertexDeclaration& vtx_decl)
{
return new NullNativeVertexFormat;
}
VertexManager::VertexManager() : m_local_v_buffer(MAXVBUFFERSIZE), m_local_i_buffer(MAXIBUFFERSIZE)
{
}
VertexManager::~VertexManager()
{
}
void VertexManager::ResetBuffer(u32 stride)
{
s_pCurBufferPointer = s_pBaseBufferPointer = m_local_v_buffer.data();
s_pEndBufferPointer = s_pCurBufferPointer + m_local_v_buffer.size();
IndexGenerator::Start(&m_local_i_buffer[0]);
}
void VertexManager::vFlush(bool use_dst_alpha)
{
VertexShaderCache::s_instance->SetShader(
use_dst_alpha ? DSTALPHA_DUAL_SOURCE_BLEND : DSTALPHA_NONE, current_primitive_type);
GeometryShaderCache::s_instance->SetShader(
use_dst_alpha ? DSTALPHA_DUAL_SOURCE_BLEND : DSTALPHA_NONE, current_primitive_type);
PixelShaderCache::s_instance->SetShader(
use_dst_alpha ? DSTALPHA_DUAL_SOURCE_BLEND : DSTALPHA_NONE, current_primitive_type);
}
} // namespace

View File

@ -0,0 +1,28 @@
// Copyright 2015 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#pragma once
#include <vector>
#include "VideoCommon/VertexManagerBase.h"
namespace Null
{
class VertexManager : public VertexManagerBase
{
public:
VertexManager();
~VertexManager();
NativeVertexFormat* CreateNativeVertexFormat(const PortableVertexDeclaration& vtx_decl) override;
protected:
void ResetBuffer(u32 stride) override;
private:
void vFlush(bool use_dst_alpha) override;
std::vector<u8> m_local_v_buffer;
std::vector<u16> m_local_i_buffer;
};
}

View File

@ -0,0 +1,25 @@
// Copyright 2015 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#pragma once
#include "VideoCommon/VideoBackendBase.h"
namespace Null
{
class VideoBackend : public VideoBackendBase
{
bool Initialize(void* window_handle) override;
void Shutdown() override;
std::string GetName() const override { return "Null"; }
std::string GetDisplayName() const override { return "Null"; }
void Video_Prepare() override;
void Video_Cleanup() override;
void ShowConfig(void* parent) override;
unsigned int PeekMessages() override { return 0; }
};
}

View File

@ -12,6 +12,7 @@
#include "VideoBackends/D3D/VideoBackend.h"
#include "VideoBackends/D3D12/VideoBackend.h"
#endif
#include "VideoBackends/Null/VideoBackend.h"
#include "VideoBackends/OGL/VideoBackend.h"
#include "VideoBackends/Software/VideoBackend.h"
@ -34,7 +35,7 @@ __declspec(dllexport) DWORD NvOptimusEnablement = 1;
void VideoBackendBase::PopulateList()
{
// OGL > D3D11 > D3D12 > SW
// OGL > D3D11 > D3D12 > SW > Null
g_available_video_backends.push_back(std::make_unique<OGL::VideoBackend>());
#ifdef _WIN32
g_available_video_backends.push_back(std::make_unique<DX11::VideoBackend>());
@ -48,6 +49,7 @@ void VideoBackendBase::PopulateList()
}
#endif
g_available_video_backends.push_back(std::make_unique<SW::VideoSoftware>());
g_available_video_backends.push_back(std::make_unique<Null::VideoBackend>());
const auto iter =
std::find_if(g_available_video_backends.begin(), g_available_video_backends.end(),