diff options
Diffstat (limited to 'Source/Core/VideoBackends/Software/SWmain.cpp')
| -rw-r--r-- | Source/Core/VideoBackends/Software/SWmain.cpp | 395 |
1 files changed, 156 insertions, 239 deletions
diff --git a/Source/Core/VideoBackends/Software/SWmain.cpp b/Source/Core/VideoBackends/Software/SWmain.cpp index b0f0af66f8..59162c2f06 100644 --- a/Source/Core/VideoBackends/Software/SWmain.cpp +++ b/Source/Core/VideoBackends/Software/SWmain.cpp @@ -3,6 +3,7 @@ // Refer to the license.txt file included. #include <atomic> +#include <memory> #include <string> #include "Common/CommonTypes.h" @@ -16,25 +17,29 @@ #include "Core/HW/Memmap.h" #include "Core/HW/VideoInterface.h" -#include "VideoBackends/Software/BPMemLoader.h" #include "VideoBackends/Software/Clipper.h" #include "VideoBackends/Software/DebugUtil.h" +#include "VideoBackends/Software/EfbCopy.h" #include "VideoBackends/Software/EfbInterface.h" -#include "VideoBackends/Software/OpcodeDecoder.h" #include "VideoBackends/Software/Rasterizer.h" -#include "VideoBackends/Software/SWCommandProcessor.h" #include "VideoBackends/Software/SWOGLWindow.h" #include "VideoBackends/Software/SWRenderer.h" -#include "VideoBackends/Software/SWStatistics.h" #include "VideoBackends/Software/SWVertexLoader.h" -#include "VideoBackends/Software/SWVideoConfig.h" #include "VideoBackends/Software/VideoBackend.h" -#include "VideoBackends/Software/XFMemLoader.h" -#include "VideoCommon/BoundingBox.h" +#include "VideoCommon/BPStructs.h" +#include "VideoCommon/CommandProcessor.h" #include "VideoCommon/Fifo.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/TextureCacheBase.h" +#include "VideoCommon/VertexLoaderManager.h" +#include "VideoCommon/VertexShaderManager.h" +#include "VideoCommon/VideoConfig.h" #include "VideoCommon/XFMemory.h" #define VSYNC_ENABLED 0 @@ -51,295 +56,207 @@ static volatile struct namespace SW { -static std::atomic<bool> fifoStateRun; -static std::atomic<bool> emuRunningState; -static std::mutex m_csSWVidOccupied; - -std::string VideoSoftware::GetName() const +class PerfQuery : public PerfQueryBase { - return "Software Renderer"; -} +public: + PerfQuery() {} + ~PerfQuery() {} -std::string VideoSoftware::GetDisplayName() const -{ - return "Software Renderer"; -} + void EnableQuery(PerfQueryGroup type) override {} + void DisableQuery(PerfQueryGroup type) override {} + void ResetQuery() override + { + memset(EfbInterface::perf_values, 0, sizeof(EfbInterface::perf_values)); + } + u32 GetQueryResult(PerfQueryType type) override + { + return EfbInterface::perf_values[type]; + }; + void FlushResults() override {} + bool IsFlushed() const {return true;}; +}; -void VideoSoftware::ShowConfig(void *hParent) +class TextureCache : public TextureCacheBase { - Host_ShowVideoConfig(hParent, GetDisplayName(), "gfx_software"); -} +public: + 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 srcFormat, const EFBRectangle& srcRect, + bool isIntensity, bool scaleByHalf) override + { + EfbCopy::CopyEfb(); + } -bool VideoSoftware::Initialize(void *window_handle) -{ - g_SWVideoConfig.Load((File::GetUserPath(D_CONFIG_IDX) + "gfx_software.ini").c_str()); +private: + struct TCacheEntry : TCacheEntryBase + { + TCacheEntry(const TCacheEntryConfig& _config) : TCacheEntryBase(_config) {} + ~TCacheEntry() {} - SWOGLWindow::Init(window_handle); + void Load(unsigned int width, unsigned int height, + unsigned int expanded_width, unsigned int level) override {} - InitBPMemory(); - InitXFMemory(); - SWCommandProcessor::Init(); - PixelEngine::Init(); - OpcodeDecoder::Init(); - Clipper::Init(); - Rasterizer::Init(); - SWRenderer::Init(); - DebugUtil::Init(); + void FromRenderTarget(u8* dst, PEControl::PixelFormat srcFormat, const EFBRectangle& srcRect, + bool scaleByHalf, unsigned int cbufid, const float *colmat) override + { + EfbCopy::CopyEfb(); + } - m_initialized = true; - return true; -} + void CopyRectangleFromTexture( + const TCacheEntryBase* source, + const MathUtil::Rectangle<int>& srcrect, + const MathUtil::Rectangle<int>& dstrect) override {} -void VideoSoftware::DoState(PointerWrap& p) -{ - bool software = true; - p.Do(software); - if (p.GetMode() == PointerWrap::MODE_READ && software == false) - // change mode to abort load of incompatible save state. - p.SetMode(PointerWrap::MODE_VERIFY); - - // TODO: incomplete? - SWCommandProcessor::DoState(p); - PixelEngine::DoState(p); - EfbInterface::DoState(p); - OpcodeDecoder::DoState(p); - Clipper::DoState(p); - p.Do(xfmem); - p.Do(bpmem); - p.DoPOD(swstats); - - // CP Memory - DoCPState(p); -} + void Bind(unsigned int stage) override {} -void VideoSoftware::CheckInvalidState() -{ - // there is no state to invalidate -} + bool Save(const std::string& filename, unsigned int level) override { return false; } + }; -void VideoSoftware::PauseAndLock(bool doLock, bool unpauseOnUnlock) -{ - if (doLock) + TCacheEntryBase* CreateTexture(const TCacheEntryConfig& config) override { - EmuStateChange(EMUSTATE_CHANGE_PAUSE); - if (!Core::IsGPUThread()) - m_csSWVidOccupied.lock(); + return new TCacheEntry(config); } - else - { - if (unpauseOnUnlock) - EmuStateChange(EMUSTATE_CHANGE_PLAY); - if (!Core::IsGPUThread()) - m_csSWVidOccupied.unlock(); - } -} +}; -void VideoSoftware::RunLoop(bool enable) +class XFBSource : public XFBSourceBase { - emuRunningState.store(enable); -} + void DecodeToTexture(u32 xfbAddr, u32 fbWidth, u32 fbHeight) override {} + void CopyEFB(float Gamma) override {} +}; -void VideoSoftware::EmuStateChange(EMUSTATE_CHANGE newState) +class FramebufferManager : public FramebufferManagerBase { - emuRunningState.store(newState == EMUSTATE_CHANGE_PLAY); -} - -void VideoSoftware::Shutdown() -{ - m_initialized = false; - - // TODO: should be in Video_Cleanup - SWRenderer::Shutdown(); - DebugUtil::Shutdown(); - - // Do our OSD callbacks - OSD::DoCallbacks(OSD::CallbackType::Shutdown); + 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 xfbAddr, u32 fbStride, u32 fbHeight, const EFBRectangle& sourceRc, float Gamma = 1.0f) override + { + EfbCopy::CopyEfb(); + } +}; - SWOGLWindow::Shutdown(); -} +static std::atomic<bool> fifoStateRun; +static std::atomic<bool> emuRunningState; +static std::mutex m_csSWVidOccupied; -void VideoSoftware::Video_Cleanup() +std::string VideoSoftware::GetName() const { + return "Software Renderer"; } -// This is called after Video_Initialize() from the Core -void VideoSoftware::Video_Prepare() +std::string VideoSoftware::GetDisplayName() const { - // Do our OSD callbacks - OSD::DoCallbacks(OSD::CallbackType::Initialization); - - SWRenderer::Prepare(); - - INFO_LOG(VIDEO, "Video backend initialized."); + return "Software Renderer"; } -// Run from the CPU thread (from VideoInterface.cpp) -void VideoSoftware::Video_BeginField(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight) +static void InitBackendInfo() { - // XXX: fbStride should be implemented properly here - // If stride isn't implemented then there are problems with XFB - // Animal Crossing is a good example for this. - s_beginFieldArgs.xfbAddr = xfbAddr; - s_beginFieldArgs.fbWidth = fbWidth; - s_beginFieldArgs.fbHeight = fbHeight; + g_Config.backend_info.APIType = API_NONE; + g_Config.backend_info.bSupports3DVision = false; + g_Config.backend_info.bSupportsDualSourceBlend = true; + g_Config.backend_info.bSupportsEarlyZ = true; + g_Config.backend_info.bSupportsOversizedViewports = true; + g_Config.backend_info.bSupportsPrimitiveRestart = false; + + // aamodes + g_Config.backend_info.AAModes = {1}; } -// Run from the CPU thread (from VideoInterface.cpp) -void VideoSoftware::Video_EndField() +void VideoSoftware::ShowConfig(void *hParent) { - // Techincally the XFB is continually rendered out scanline by scanline between - // BeginField and EndFeild, We could possibly get away with copying out the whole thing - // at BeginField for less lag, but for the safest emulation we run it here. - - if (g_bSkipCurrentFrame || s_beginFieldArgs.xfbAddr == 0) - { - swstats.frameCount++; - swstats.ResetFrame(); - Core::Callback_VideoCopiedToXFB(false); - return; - } - if (!g_SWVideoConfig.bBypassXFB) - { - EfbInterface::yuv422_packed *xfb = (EfbInterface::yuv422_packed *) Memory::GetPointer(s_beginFieldArgs.xfbAddr); - - SWRenderer::UpdateColorTexture(xfb, s_beginFieldArgs.fbWidth, s_beginFieldArgs.fbHeight); - } - - // Ideally we would just move all the OpenGL context stuff to the CPU thread, - // but this gets messy when the hardware rasterizer is enabled. - // And neobrain loves his hardware rasterizer. - - // If BypassXFB has already done a swap (cf. EfbCopy::CopyToXfb), skip this. - if (!g_SWVideoConfig.bBypassXFB) - { - // Dump frame if needed - DebugUtil::OnFrameEnd(s_beginFieldArgs.fbWidth, s_beginFieldArgs.fbHeight); - - // If we are in dual core mode, notify the GPU thread about the new color texture. - if (SConfig::GetInstance().bCPUThread) - s_swapRequested.store(true); - else - SWRenderer::Swap(s_beginFieldArgs.fbWidth, s_beginFieldArgs.fbHeight); - } + if (!m_initialized) + InitBackendInfo(); + Host_ShowVideoConfig(hParent, GetDisplayName(), "gfx_software"); } -u32 VideoSoftware::Video_AccessEFB(EFBAccessType type, u32 x, u32 y, u32 InputData) +bool VideoSoftware::Initialize(void *window_handle) { - u32 value = 0; + InitializeShared(); + InitBackendInfo(); - switch (type) - { - case PEEK_Z: - { - value = EfbInterface::GetDepth(x, y); - break; - } + g_Config.Load((File::GetUserPath(D_CONFIG_IDX) + "gfx_software.ini").c_str()); + g_Config.GameIniLoad(); + g_Config.UpdateProjectionHack(); + g_Config.VerifyValidity(); + UpdateActiveConfig(); - case POKE_Z: - break; - - case PEEK_COLOR: - { - u32 color = 0; - EfbInterface::GetColor(x, y, (u8*)&color); + SWOGLWindow::Init(window_handle); - // rgba to argb - value = (color >> 8) | (color & 0xff) << 24; - break; - } + PixelEngine::Init(); + Clipper::Init(); + Rasterizer::Init(); + SWRenderer::Init(); + DebugUtil::Init(); - case POKE_COLOR: - break; - } + // Do our OSD callbacks + OSD::DoCallbacks(OSD::CallbackType::Initialization); - return value; -} + m_initialized = true; -u32 VideoSoftware::Video_GetQueryResult(PerfQueryType type) -{ - return EfbInterface::perf_values[type]; + return true; } -u16 VideoSoftware::Video_GetBoundingBox(int index) +void VideoSoftware::Shutdown() { - return BoundingBox::coords[index]; -} + m_initialized = false; -bool VideoSoftware::Video_Screenshot(const std::string& filename) -{ - SWRenderer::SetScreenshot(filename.c_str()); - return true; -} + // Do our OSD callbacks + OSD::DoCallbacks(OSD::CallbackType::Shutdown); -// Run from the graphics thread -static void VideoFifo_CheckSwapRequest() -{ - if (s_swapRequested.load()) - { - SWRenderer::Swap(s_beginFieldArgs.fbWidth, s_beginFieldArgs.fbHeight); - s_swapRequested.store(false); - } + SWOGLWindow::Shutdown(); } -// ------------------------------- -// Enter and exit the video loop -// ------------------------------- -void VideoSoftware::Video_EnterLoop() +void VideoSoftware::Video_Cleanup() { - std::lock_guard<std::mutex> lk(m_csSWVidOccupied); - fifoStateRun.store(true); - - while (fifoStateRun.load()) + if (g_renderer) { - VideoFifo_CheckSwapRequest(); - g_video_backend->PeekMessages(); - - if (!SWCommandProcessor::RunBuffer()) - { - Common::YieldCPU(); - } - - while (!emuRunningState.load() && fifoStateRun.load()) - { - g_video_backend->PeekMessages(); - VideoFifo_CheckSwapRequest(); - m_csSWVidOccupied.unlock(); - Common::SleepCurrentThread(1); - m_csSWVidOccupied.lock(); - } + Fifo_Shutdown(); + + SWRenderer::Shutdown(); + DebugUtil::Shutdown(); + // The following calls are NOT Thread Safe + // And need to be called from the video thread + SWRenderer::Shutdown(); + VertexLoaderManager::Shutdown(); + g_framebuffer_manager.reset(); + g_texture_cache.reset(); + VertexShaderManager::Shutdown(); + PixelShaderManager::Shutdown(); + g_perf_query.reset(); + g_vertex_manager.reset(); + OpcodeDecoder_Shutdown(); + g_renderer.reset(); } } -void VideoSoftware::Video_ExitLoop() +// This is called after Video_Initialize() from the Core +void VideoSoftware::Video_Prepare() { - fifoStateRun.store(false); -} + g_renderer = std::make_unique<SWRenderer>(); -// TODO : could use the OSD class in video common, we would need to implement the Renderer class -// however most of it is useless for the SW backend so we could as well move it to its own class -void VideoSoftware::Video_AddMessage(const std::string& msg, u32 milliseconds) -{ -} -void VideoSoftware::Video_ClearMessages() -{ -} + CommandProcessor::Init(); + PixelEngine::Init(); -void VideoSoftware::Video_SetRendering(bool bEnabled) -{ - SWCommandProcessor::SetRendering(bEnabled); -} + BPInit(); + g_vertex_manager = std::make_unique<SWVertexLoader>(); + g_perf_query = std::make_unique<PerfQuery>(); + Fifo_Init(); // must be done before OpcodeDecoder_Init() + OpcodeDecoder_Init(); + IndexGenerator::Init(); + VertexShaderManager::Init(); + PixelShaderManager::Init(); + g_texture_cache = std::make_unique<TextureCache>(); + SWRenderer::Init(); + VertexLoaderManager::Init(); + g_framebuffer_manager = std::make_unique<FramebufferManager>(); -void VideoSoftware::Video_GatherPipeBursted() -{ - SWCommandProcessor::GatherPipeBursted(); -} + // Notify the core that the video backend is ready + Host_Message(WM_USER_CREATE); -void VideoSoftware::RegisterCPMMIO(MMIO::Mapping* mmio, u32 base) -{ - SWCommandProcessor::RegisterMMIO(mmio, base); + INFO_LOG(VIDEO, "Video backend initialized."); } -// Draw messages on top of the screen unsigned int VideoSoftware::PeekMessages() { return SWOGLWindow::s_instance->PeekMessages(); |
