diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/EfbCopy.cpp b/Source/Plugins/Plugin_VideoSoftware/Src/EfbCopy.cpp index 5b858e61a8..4ca84cd716 100644 --- a/Source/Plugins/Plugin_VideoSoftware/Src/EfbCopy.cpp +++ b/Source/Plugins/Plugin_VideoSoftware/Src/EfbCopy.cpp @@ -28,12 +28,23 @@ namespace EfbCopy void CopyToXfb(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc, float Gamma) { if (!g_SWVideoConfig.bHwRasterizer) + { INFO_LOG(VIDEO, "xfbaddr: %x, fbwidth: %i, fbheight: %i, source: (%i, %i, %i, %i), Gamma %f", xfbAddr, fbWidth, fbHeight, sourceRc.top, sourceRc.left, sourceRc.bottom, sourceRc.right, Gamma); - EfbInterface::yuv422_packed* xfb_in_ram = (EfbInterface::yuv422_packed *) Memory::GetPointer(xfbAddr); - EfbInterface::CopyToXFB(xfb_in_ram, fbWidth, fbHeight, sourceRc, Gamma); + if(!g_SWVideoConfig.bBypassXFB) { + EfbInterface::yuv422_packed* xfb_in_ram = (EfbInterface::yuv422_packed *) Memory::GetPointer(xfbAddr); + + EfbInterface::CopyToXFB(xfb_in_ram, fbWidth, fbHeight, sourceRc, Gamma); + + } else { + s8 *colorTexture = SWRenderer::getColorTexture(); // Ask SWRenderer for the next colour texture + + EfbInterface::BypassXFB(colourTexture, fbWidth, fbHeight, sourceRc, Gamma); + + SWRenderer::swapColorTexture(); // Tell SWRenderer we are now finished with it. + } } } diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/EfbInterface.cpp b/Source/Plugins/Plugin_VideoSoftware/Src/EfbInterface.cpp index d20ea39b96..7ab5b2f942 100644 --- a/Source/Plugins/Plugin_VideoSoftware/Src/EfbInterface.cpp +++ b/Source/Plugins/Plugin_VideoSoftware/Src/EfbInterface.cpp @@ -549,6 +549,26 @@ namespace EfbInterface } } + // Like CopyToXFB, but we copy directly into the opengl colour texture without going via Gamecube main memory or doing a yuyv conversion + void BypassXFB(u8* texture, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc, float Gamma) { + u32 color; + u8* colorPtr = (u8*)&color; + u32* texturePtr = (u32*)texture; + u32 textureAddress = 0; + + int left = sourceRc.left; + int right = sourceRc.right; + + for (u16 y = sourceRc.top; y < sourceRc.bottom; y++) + { + for (u16 x = left; x < right; x++) + { + GetColor(x, y, colorPtr); + texturePtr[textureAddress++] = Common::swap32(color); + } + } + } + bool ZCompare(u16 x, u16 y, u32 z) { u32 offset = GetDepthOffset(x, y); diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/EfbInterface.h b/Source/Plugins/Plugin_VideoSoftware/Src/EfbInterface.h index 18807916d3..b00a06239e 100644 --- a/Source/Plugins/Plugin_VideoSoftware/Src/EfbInterface.h +++ b/Source/Plugins/Plugin_VideoSoftware/Src/EfbInterface.h @@ -49,6 +49,7 @@ namespace EfbInterface u8* GetPixelPointer(u16 x, u16 y, bool depth); void CopyToXFB(yuv422_packed* xfb_in_ram, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc, float Gamma); + void BypassXFB(u8* texture, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc, float Gamma); void DoState(PointerWrap &p); } diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/SWRenderer.cpp b/Source/Plugins/Plugin_VideoSoftware/Src/SWRenderer.cpp index 23ff15d883..426ab3194e 100644 --- a/Source/Plugins/Plugin_VideoSoftware/Src/SWRenderer.cpp +++ b/Source/Plugins/Plugin_VideoSoftware/Src/SWRenderer.cpp @@ -172,10 +172,18 @@ void DrawButton(GLuint tex, float *coords) } #endif +u8* SWRenderer::getColorTexture() { + return s_xfbColorTexture[!s_currentColorTexture]; +} + +void SWRenderer::swapColorTexture() { + s_currentColorTexture = !s_currentColorTexture; +} + void SWRenderer::UpdateColorTexture(EfbInterface::yuv422_packed *xfb, u32 fbWidth, u32 fbHeight) { u32 offset = 0; - u8 *TexturePointer = s_xfbColorTexture[!s_currentColorTexture]; + u8 *TexturePointer = getColorTexture(); for (u16 y = 0; y < fbHeight; y++) { @@ -201,7 +209,7 @@ void SWRenderer::UpdateColorTexture(EfbInterface::yuv422_packed *xfb, u32 fbWidt } xfb += fbWidth; } - s_currentColorTexture = !s_currentColorTexture; + swapColorTexture(); } // Called on the GPU thread diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/SWRenderer.h b/Source/Plugins/Plugin_VideoSoftware/Src/SWRenderer.h index 6b75dbd1b9..a2f737f2a8 100644 --- a/Source/Plugins/Plugin_VideoSoftware/Src/SWRenderer.h +++ b/Source/Plugins/Plugin_VideoSoftware/Src/SWRenderer.h @@ -17,6 +17,8 @@ namespace SWRenderer void RenderText(const char* pstr, int left, int top, u32 color); void DrawDebugText(); + u8* getColorTexture(); + void swapColorTexture(); void UpdateColorTexture(EfbInterface::yuv422_packed *xfb, u32 fbWidth, u32 fbHeight); void DrawTexture(u8 *texture, int width, int height); diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/SWVideoConfig.cpp b/Source/Plugins/Plugin_VideoSoftware/Src/SWVideoConfig.cpp index a6ebb97eb9..fbd8b95108 100644 --- a/Source/Plugins/Plugin_VideoSoftware/Src/SWVideoConfig.cpp +++ b/Source/Plugins/Plugin_VideoSoftware/Src/SWVideoConfig.cpp @@ -15,6 +15,7 @@ SWVideoConfig::SWVideoConfig() renderToMainframe = false; bHwRasterizer = false; + bBypassXFB = false; bShowStats = false; @@ -41,6 +42,7 @@ void SWVideoConfig::Load(const char* ini_file) iniFile.Get("Hardware", "RenderToMainframe", &renderToMainframe, false); iniFile.Get("Rendering", "HwRasterizer", &bHwRasterizer, false); + iniFile.Get("Rendering", "BypassXFB", &bBypassXFB, false); iniFile.Get("Rendering", "ZComploc", &bZComploc, true); iniFile.Get("Rendering", "ZFreeze", &bZFreeze, true); @@ -65,6 +67,7 @@ void SWVideoConfig::Save(const char* ini_file) iniFile.Set("Hardware", "RenderToMainframe", renderToMainframe); iniFile.Set("Rendering", "HwRasterizer", bHwRasterizer); + iniFile.Set("Rendering", "BypassXFB", bBypassXFB); iniFile.Set("Rendering", "ZComploc", &bZComploc); iniFile.Set("Rendering", "ZFreeze", &bZFreeze); diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/SWVideoConfig.h b/Source/Plugins/Plugin_VideoSoftware/Src/SWVideoConfig.h index 94e3a6b2a8..5e88da174e 100644 --- a/Source/Plugins/Plugin_VideoSoftware/Src/SWVideoConfig.h +++ b/Source/Plugins/Plugin_VideoSoftware/Src/SWVideoConfig.h @@ -22,6 +22,7 @@ struct SWVideoConfig : NonCopyable bool renderToMainframe; bool bHwRasterizer; + bool bBypassXFB; // Emulation features bool bZComploc; diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/SWmain.cpp b/Source/Plugins/Plugin_VideoSoftware/Src/SWmain.cpp index 6773fd9e0e..a68489eaaf 100644 --- a/Source/Plugins/Plugin_VideoSoftware/Src/SWmain.cpp +++ b/Source/Plugins/Plugin_VideoSoftware/Src/SWmain.cpp @@ -237,9 +237,11 @@ void VideoSoftware::Video_EndField() } } - EfbInterface::yuv422_packed *xfb = (EfbInterface::yuv422_packed *) Memory::GetPointer(xfbAddr); + if(!g_SWVideoConfig.bBypassXFB) { + EfbInterface::yuv422_packed *xfb = (EfbInterface::yuv422_packed *) Memory::GetPointer(xfbAddr); - SWRenderer::UpdateColorTexture(xfb, s_beginFieldArgs.fbWidth, s_beginFieldArgs.fbHeight); + SWRenderer::UpdateColorTexture(xfb, s_beginFieldArgs.fbWidth, s_beginFieldArgs.fbHeight); + } } // Idealy we would just move all the opengl contex stuff to the CPU thread, but this gets diff --git a/Source/Plugins/Plugin_VideoSoftware/Src/VideoConfigDialog.cpp b/Source/Plugins/Plugin_VideoSoftware/Src/VideoConfigDialog.cpp index eea908edfc..18eaf08812 100644 --- a/Source/Plugins/Plugin_VideoSoftware/Src/VideoConfigDialog.cpp +++ b/Source/Plugins/Plugin_VideoSoftware/Src/VideoConfigDialog.cpp @@ -68,6 +68,9 @@ VideoConfigDialog::VideoConfigDialog(wxWindow* parent, const std::string& title, // rasterizer szr_rendering->Add(new SettingCheckBox(page_general, wxT("Hardware rasterization"), wxT(""), vconfig.bHwRasterizer)); + + // xfb + szr_rendering->Add(new SettingCheckBox(page_general, wxT("Bypass XFB"), wxT(""), vconfig.bBypassXFB)); } // - info