diff options
Diffstat (limited to 'Source/Core/VideoCommon/FramebufferManagerBase.cpp')
| -rw-r--r-- | Source/Core/VideoCommon/FramebufferManagerBase.cpp | 364 |
1 files changed, 189 insertions, 175 deletions
diff --git a/Source/Core/VideoCommon/FramebufferManagerBase.cpp b/Source/Core/VideoCommon/FramebufferManagerBase.cpp index ab095f1020..b9cf3eb4d6 100644 --- a/Source/Core/VideoCommon/FramebufferManagerBase.cpp +++ b/Source/Core/VideoCommon/FramebufferManagerBase.cpp @@ -2,18 +2,21 @@ // Licensed under GPLv2+ // Refer to the license.txt file included. +#include "VideoCommon/FramebufferManagerBase.h" #include <algorithm> #include <array> #include <memory> -#include "VideoCommon/FramebufferManagerBase.h" #include "VideoCommon/RenderBase.h" #include "VideoCommon/VideoConfig.h" std::unique_ptr<FramebufferManagerBase> g_framebuffer_manager; -std::unique_ptr<XFBSourceBase> FramebufferManagerBase::m_realXFBSource; // Only used in Real XFB mode -FramebufferManagerBase::VirtualXFBListType FramebufferManagerBase::m_virtualXFBList; // Only used in Virtual XFB mode -std::array<const XFBSourceBase*, FramebufferManagerBase::MAX_VIRTUAL_XFB> FramebufferManagerBase::m_overlappingXFBArray; +std::unique_ptr<XFBSourceBase> + FramebufferManagerBase::m_realXFBSource; // Only used in Real XFB mode +FramebufferManagerBase::VirtualXFBListType + FramebufferManagerBase::m_virtualXFBList; // Only used in Virtual XFB mode +std::array<const XFBSourceBase*, FramebufferManagerBase::MAX_VIRTUAL_XFB> + FramebufferManagerBase::m_overlappingXFBArray; unsigned int FramebufferManagerBase::s_last_xfb_width = 1; unsigned int FramebufferManagerBase::s_last_xfb_height = 1; @@ -22,229 +25,240 @@ unsigned int FramebufferManagerBase::m_EFBLayers = 1; FramebufferManagerBase::FramebufferManagerBase() { - // Can't hurt - m_overlappingXFBArray.fill(nullptr); + // Can't hurt + m_overlappingXFBArray.fill(nullptr); } FramebufferManagerBase::~FramebufferManagerBase() { - // Necessary, as these are static members - // (they really shouldn't be and should be refactored at some point). - m_virtualXFBList.clear(); - m_realXFBSource.reset(); + // Necessary, as these are static members + // (they really shouldn't be and should be refactored at some point). + m_virtualXFBList.clear(); + m_realXFBSource.reset(); } -const XFBSourceBase* const* FramebufferManagerBase::GetXFBSource(u32 xfbAddr, u32 fbWidth, u32 fbHeight, u32* xfbCountP) +const XFBSourceBase* const* FramebufferManagerBase::GetXFBSource(u32 xfbAddr, u32 fbWidth, + u32 fbHeight, u32* xfbCountP) { - if (!g_ActiveConfig.bUseXFB) - return nullptr; + if (!g_ActiveConfig.bUseXFB) + return nullptr; - if (g_ActiveConfig.bUseRealXFB) - return GetRealXFBSource(xfbAddr, fbWidth, fbHeight, xfbCountP); - else - return GetVirtualXFBSource(xfbAddr, fbWidth, fbHeight, xfbCountP); + if (g_ActiveConfig.bUseRealXFB) + return GetRealXFBSource(xfbAddr, fbWidth, fbHeight, xfbCountP); + else + return GetVirtualXFBSource(xfbAddr, fbWidth, fbHeight, xfbCountP); } -const XFBSourceBase* const* FramebufferManagerBase::GetRealXFBSource(u32 xfbAddr, u32 fbWidth, u32 fbHeight, u32* xfbCountP) +const XFBSourceBase* const* FramebufferManagerBase::GetRealXFBSource(u32 xfbAddr, u32 fbWidth, + u32 fbHeight, u32* xfbCountP) { - *xfbCountP = 1; + *xfbCountP = 1; - // recreate if needed - if (m_realXFBSource && (m_realXFBSource->texWidth != fbWidth || m_realXFBSource->texHeight != fbHeight)) - m_realXFBSource.reset(); + // recreate if needed + if (m_realXFBSource && + (m_realXFBSource->texWidth != fbWidth || m_realXFBSource->texHeight != fbHeight)) + m_realXFBSource.reset(); - if (!m_realXFBSource && g_framebuffer_manager) - m_realXFBSource = g_framebuffer_manager->CreateXFBSource(fbWidth, fbHeight, 1); + if (!m_realXFBSource && g_framebuffer_manager) + m_realXFBSource = g_framebuffer_manager->CreateXFBSource(fbWidth, fbHeight, 1); - if (!m_realXFBSource) - return nullptr; + if (!m_realXFBSource) + return nullptr; - m_realXFBSource->srcAddr = xfbAddr; + m_realXFBSource->srcAddr = xfbAddr; - m_realXFBSource->srcWidth = MAX_XFB_WIDTH; - m_realXFBSource->srcHeight = MAX_XFB_HEIGHT; + m_realXFBSource->srcWidth = MAX_XFB_WIDTH; + m_realXFBSource->srcHeight = MAX_XFB_HEIGHT; - m_realXFBSource->texWidth = fbWidth; - m_realXFBSource->texHeight = fbHeight; + m_realXFBSource->texWidth = fbWidth; + m_realXFBSource->texHeight = fbHeight; - m_realXFBSource->sourceRc.left = 0; - m_realXFBSource->sourceRc.top = 0; - m_realXFBSource->sourceRc.right = fbWidth; - m_realXFBSource->sourceRc.bottom = fbHeight; + m_realXFBSource->sourceRc.left = 0; + m_realXFBSource->sourceRc.top = 0; + m_realXFBSource->sourceRc.right = fbWidth; + m_realXFBSource->sourceRc.bottom = fbHeight; - // Decode YUYV data from GameCube RAM - m_realXFBSource->DecodeToTexture(xfbAddr, fbWidth, fbHeight); + // Decode YUYV data from GameCube RAM + m_realXFBSource->DecodeToTexture(xfbAddr, fbWidth, fbHeight); - m_overlappingXFBArray[0] = m_realXFBSource.get(); - return &m_overlappingXFBArray[0]; + m_overlappingXFBArray[0] = m_realXFBSource.get(); + return &m_overlappingXFBArray[0]; } -const XFBSourceBase* const* FramebufferManagerBase::GetVirtualXFBSource(u32 xfbAddr, u32 fbWidth, u32 fbHeight, u32* xfbCountP) +const XFBSourceBase* const* +FramebufferManagerBase::GetVirtualXFBSource(u32 xfbAddr, u32 fbWidth, u32 fbHeight, u32* xfbCountP) { - u32 xfbCount = 0; + u32 xfbCount = 0; - if (m_virtualXFBList.empty()) // no Virtual XFBs available - return nullptr; + if (m_virtualXFBList.empty()) // no Virtual XFBs available + return nullptr; - u32 srcLower = xfbAddr; - u32 srcUpper = xfbAddr + 2 * fbWidth * fbHeight; + u32 srcLower = xfbAddr; + u32 srcUpper = xfbAddr + 2 * fbWidth * fbHeight; - VirtualXFBListType::reverse_iterator - it = m_virtualXFBList.rbegin(), - vlend = m_virtualXFBList.rend(); - for (; it != vlend; ++it) - { - VirtualXFB* vxfb = &*it; + VirtualXFBListType::reverse_iterator it = m_virtualXFBList.rbegin(), + vlend = m_virtualXFBList.rend(); + for (; it != vlend; ++it) + { + VirtualXFB* vxfb = &*it; - u32 dstLower = vxfb->xfbAddr; - u32 dstUpper = vxfb->xfbAddr + 2 * vxfb->xfbWidth * vxfb->xfbHeight; + u32 dstLower = vxfb->xfbAddr; + u32 dstUpper = vxfb->xfbAddr + 2 * vxfb->xfbWidth * vxfb->xfbHeight; - if (AddressRangesOverlap(srcLower, srcUpper, dstLower, dstUpper)) - { - m_overlappingXFBArray[xfbCount] = vxfb->xfbSource.get(); - ++xfbCount; - } - } + if (AddressRangesOverlap(srcLower, srcUpper, dstLower, dstUpper)) + { + m_overlappingXFBArray[xfbCount] = vxfb->xfbSource.get(); + ++xfbCount; + } + } - *xfbCountP = xfbCount; - return &m_overlappingXFBArray[0]; + *xfbCountP = xfbCount; + return &m_overlappingXFBArray[0]; } -void FramebufferManagerBase::CopyToXFB(u32 xfbAddr, u32 fbStride, u32 fbHeight, const EFBRectangle& sourceRc, float Gamma) +void FramebufferManagerBase::CopyToXFB(u32 xfbAddr, u32 fbStride, u32 fbHeight, + const EFBRectangle& sourceRc, float Gamma) { - if (g_ActiveConfig.bUseRealXFB) - { - if (g_framebuffer_manager) - g_framebuffer_manager->CopyToRealXFB(xfbAddr, fbStride, fbHeight, sourceRc, Gamma); - } - else - { - CopyToVirtualXFB(xfbAddr, fbStride, fbHeight, sourceRc, Gamma); - } + if (g_ActiveConfig.bUseRealXFB) + { + if (g_framebuffer_manager) + g_framebuffer_manager->CopyToRealXFB(xfbAddr, fbStride, fbHeight, sourceRc, Gamma); + } + else + { + CopyToVirtualXFB(xfbAddr, fbStride, fbHeight, sourceRc, Gamma); + } } -void FramebufferManagerBase::CopyToVirtualXFB(u32 xfbAddr, u32 fbStride, u32 fbHeight, const EFBRectangle& sourceRc, float Gamma) +void FramebufferManagerBase::CopyToVirtualXFB(u32 xfbAddr, u32 fbStride, u32 fbHeight, + const EFBRectangle& sourceRc, float Gamma) { - if (!g_framebuffer_manager) - return; - - VirtualXFBListType::iterator vxfb = FindVirtualXFB(xfbAddr, sourceRc.GetWidth(), fbHeight); - - if (m_virtualXFBList.end() == vxfb) - { - if (m_virtualXFBList.size() < MAX_VIRTUAL_XFB) - { - // create a new Virtual XFB and place it at the front of the list - m_virtualXFBList.emplace_front(); - vxfb = m_virtualXFBList.begin(); - } - else - { - // Replace the last virtual XFB - --vxfb; - } - } - //else // replace existing virtual XFB - - // move this Virtual XFB to the front of the list. - if (m_virtualXFBList.begin() != vxfb) - m_virtualXFBList.splice(m_virtualXFBList.begin(), m_virtualXFBList, vxfb); - - unsigned int target_width, target_height; - g_framebuffer_manager->GetTargetSize(&target_width, &target_height); - - // recreate if needed - if (vxfb->xfbSource && (vxfb->xfbSource->texWidth != target_width || vxfb->xfbSource->texHeight != target_height)) - vxfb->xfbSource.reset(); - - if (!vxfb->xfbSource) - { - vxfb->xfbSource = g_framebuffer_manager->CreateXFBSource(target_width, target_height, m_EFBLayers); - if (!vxfb->xfbSource) - return; - - vxfb->xfbSource->texWidth = target_width; - vxfb->xfbSource->texHeight = target_height; - } - - vxfb->xfbSource->srcAddr = vxfb->xfbAddr = xfbAddr; - vxfb->xfbSource->srcWidth = vxfb->xfbWidth = sourceRc.GetWidth(); - vxfb->xfbSource->srcHeight = vxfb->xfbHeight = fbHeight; - - vxfb->xfbSource->sourceRc = g_renderer->ConvertEFBRectangle(sourceRc); - - // keep stale XFB data from being used - ReplaceVirtualXFB(); - - // Copy EFB data to XFB and restore render target again - vxfb->xfbSource->CopyEFB(Gamma); + if (!g_framebuffer_manager) + return; + + VirtualXFBListType::iterator vxfb = FindVirtualXFB(xfbAddr, sourceRc.GetWidth(), fbHeight); + + if (m_virtualXFBList.end() == vxfb) + { + if (m_virtualXFBList.size() < MAX_VIRTUAL_XFB) + { + // create a new Virtual XFB and place it at the front of the list + m_virtualXFBList.emplace_front(); + vxfb = m_virtualXFBList.begin(); + } + else + { + // Replace the last virtual XFB + --vxfb; + } + } + // else // replace existing virtual XFB + + // move this Virtual XFB to the front of the list. + if (m_virtualXFBList.begin() != vxfb) + m_virtualXFBList.splice(m_virtualXFBList.begin(), m_virtualXFBList, vxfb); + + unsigned int target_width, target_height; + g_framebuffer_manager->GetTargetSize(&target_width, &target_height); + + // recreate if needed + if (vxfb->xfbSource && + (vxfb->xfbSource->texWidth != target_width || vxfb->xfbSource->texHeight != target_height)) + vxfb->xfbSource.reset(); + + if (!vxfb->xfbSource) + { + vxfb->xfbSource = + g_framebuffer_manager->CreateXFBSource(target_width, target_height, m_EFBLayers); + if (!vxfb->xfbSource) + return; + + vxfb->xfbSource->texWidth = target_width; + vxfb->xfbSource->texHeight = target_height; + } + + vxfb->xfbSource->srcAddr = vxfb->xfbAddr = xfbAddr; + vxfb->xfbSource->srcWidth = vxfb->xfbWidth = sourceRc.GetWidth(); + vxfb->xfbSource->srcHeight = vxfb->xfbHeight = fbHeight; + + vxfb->xfbSource->sourceRc = g_renderer->ConvertEFBRectangle(sourceRc); + + // keep stale XFB data from being used + ReplaceVirtualXFB(); + + // Copy EFB data to XFB and restore render target again + vxfb->xfbSource->CopyEFB(Gamma); } -FramebufferManagerBase::VirtualXFBListType::iterator FramebufferManagerBase::FindVirtualXFB(u32 xfbAddr, u32 width, u32 height) +FramebufferManagerBase::VirtualXFBListType::iterator +FramebufferManagerBase::FindVirtualXFB(u32 xfbAddr, u32 width, u32 height) { - const u32 srcLower = xfbAddr; - const u32 srcUpper = xfbAddr + 2 * width * height; + const u32 srcLower = xfbAddr; + const u32 srcUpper = xfbAddr + 2 * width * height; - return std::find_if(m_virtualXFBList.begin(), m_virtualXFBList.end(), [srcLower, srcUpper](const VirtualXFB& xfb) { - const u32 dstLower = xfb.xfbAddr; - const u32 dstUpper = xfb.xfbAddr + 2 * xfb.xfbWidth * xfb.xfbHeight; + return std::find_if(m_virtualXFBList.begin(), m_virtualXFBList.end(), + [srcLower, srcUpper](const VirtualXFB& xfb) { + const u32 dstLower = xfb.xfbAddr; + const u32 dstUpper = xfb.xfbAddr + 2 * xfb.xfbWidth * xfb.xfbHeight; - return dstLower >= srcLower && dstUpper <= srcUpper; - }); + return dstLower >= srcLower && dstUpper <= srcUpper; + }); } void FramebufferManagerBase::ReplaceVirtualXFB() { - VirtualXFBListType::iterator it = m_virtualXFBList.begin(); - - const s32 srcLower = it->xfbAddr; - const s32 srcUpper = it->xfbAddr + 2 * it->xfbWidth * it->xfbHeight; - const s32 lineSize = 2 * it->xfbWidth; - - ++it; - - for (; it != m_virtualXFBList.end(); ++it) - { - s32 dstLower = it->xfbAddr; - s32 dstUpper = it->xfbAddr + 2 * it->xfbWidth * it->xfbHeight; - - if (dstLower >= srcLower && dstUpper <= srcUpper) - { - // Invalidate the data - it->xfbAddr = 0; - it->xfbHeight = 0; - it->xfbWidth = 0; - } - else if (AddressRangesOverlap(srcLower, srcUpper, dstLower, dstUpper)) - { - s32 upperOverlap = (srcUpper - dstLower) / lineSize; - s32 lowerOverlap = (dstUpper - srcLower) / lineSize; - - if (upperOverlap > 0 && lowerOverlap < 0) - { - it->xfbAddr += lineSize * upperOverlap; - it->xfbHeight -= upperOverlap; - } - else if (lowerOverlap > 0) - { - it->xfbHeight -= lowerOverlap; - } - } - } + VirtualXFBListType::iterator it = m_virtualXFBList.begin(); + + const s32 srcLower = it->xfbAddr; + const s32 srcUpper = it->xfbAddr + 2 * it->xfbWidth * it->xfbHeight; + const s32 lineSize = 2 * it->xfbWidth; + + ++it; + + for (; it != m_virtualXFBList.end(); ++it) + { + s32 dstLower = it->xfbAddr; + s32 dstUpper = it->xfbAddr + 2 * it->xfbWidth * it->xfbHeight; + + if (dstLower >= srcLower && dstUpper <= srcUpper) + { + // Invalidate the data + it->xfbAddr = 0; + it->xfbHeight = 0; + it->xfbWidth = 0; + } + else if (AddressRangesOverlap(srcLower, srcUpper, dstLower, dstUpper)) + { + s32 upperOverlap = (srcUpper - dstLower) / lineSize; + s32 lowerOverlap = (dstUpper - srcLower) / lineSize; + + if (upperOverlap > 0 && lowerOverlap < 0) + { + it->xfbAddr += lineSize * upperOverlap; + it->xfbHeight -= upperOverlap; + } + else if (lowerOverlap > 0) + { + it->xfbHeight -= lowerOverlap; + } + } + } } int FramebufferManagerBase::ScaleToVirtualXfbWidth(int x) { - if (g_ActiveConfig.RealXFBEnabled()) - return x; + if (g_ActiveConfig.RealXFBEnabled()) + return x; - return x * (int)Renderer::GetTargetRectangle().GetWidth() / (int)FramebufferManagerBase::LastXfbWidth(); + return x * (int)Renderer::GetTargetRectangle().GetWidth() / + (int)FramebufferManagerBase::LastXfbWidth(); } int FramebufferManagerBase::ScaleToVirtualXfbHeight(int y) { - if (g_ActiveConfig.RealXFBEnabled()) - return y; + if (g_ActiveConfig.RealXFBEnabled()) + return y; - return y * (int)Renderer::GetTargetRectangle().GetHeight() / (int)FramebufferManagerBase::LastXfbHeight(); + return y * (int)Renderer::GetTargetRectangle().GetHeight() / + (int)FramebufferManagerBase::LastXfbHeight(); } |
