VideoSoftware: Added Real XFB support.

Massivly increases the accuracy of VideoSoftware, if it's going to be slow, it
might as well be accurate.

 * Fixes flickering issues in games which double render to get Hardware AA, like the Peach's Castle tech demo.
 * Rouge Squadren 2's Cantina Intro doesn't flicker anymore, but it duplicates the top half of the screen onto the bottom.
 * Any games which need RealXFB support should now work in Video Software
This commit is contained in:
Scott Mansell
2013-08-20 23:51:39 +12:00
parent fa8a4cdbb5
commit d52e241cdf
6 changed files with 250 additions and 47 deletions

View File

@ -15,20 +15,26 @@
#include "HW/Memmap.h"
#include "Core.h"
static const float s_gammaLUT[] =
{
1.0f,
1.7f,
2.2f,
1.0f
};
namespace EfbCopy
{
void CopyToXfb()
void CopyToXfb(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc, float Gamma)
{
GLInterface->Update(); // just updates the render window position and the backbuffer size
if (!g_SWVideoConfig.bHwRasterizer)
{
// copy to open gl for rendering
EfbInterface::UpdateColorTexture();
SWRenderer::DrawTexture(EfbInterface::efbColorTexture, EFB_WIDTH, EFB_HEIGHT);
}
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);
SWRenderer::SwapBuffer();
EfbInterface::CopyToXFB(xfb_in_ram, fbWidth, fbHeight, sourceRc, Gamma);
}
}
void CopyToRam()
@ -47,8 +53,8 @@ namespace EfbCopy
int left = bpmem.copyTexSrcXY.x;
int top = bpmem.copyTexSrcXY.y;
int right = left + bpmem.copyTexSrcWH.x;
int bottom = top + bpmem.copyTexSrcWH.y;
int right = left + bpmem.copyTexSrcWH.x + 1;
int bottom = top + bpmem.copyTexSrcWH.y + 1;
for (u16 y = top; y <= bottom; y++)
{
@ -62,21 +68,47 @@ namespace EfbCopy
void CopyEfb()
{
if (bpmem.triggerEFBCopy.copy_to_xfb)
DebugUtil::OnFrameEnd();
EFBRectangle rc;
rc.left = (int)bpmem.copyTexSrcXY.x;
rc.top = (int)bpmem.copyTexSrcXY.y;
// Here Width+1 like Height, otherwise some textures are corrupted already since the native resolution.
rc.right = (int)(bpmem.copyTexSrcXY.x + bpmem.copyTexSrcWH.x + 1);
rc.bottom = (int)(bpmem.copyTexSrcXY.y + bpmem.copyTexSrcWH.y + 1);
//if (bpmem.triggerEFBCopy.copy_to_xfb)
// DebugUtil::OnFrameEnd(); // FIXME: not actually frame end
if (!g_bSkipCurrentFrame)
{
if (bpmem.triggerEFBCopy.copy_to_xfb)
{
CopyToXfb();
Core::Callback_VideoCopiedToXFB(true);
float yScale;
if (bpmem.triggerEFBCopy.scale_invert)
yScale = 256.0f / (float)bpmem.dispcopyyscale;
else
yScale = (float)bpmem.dispcopyyscale / 256.0f;
swstats.frameCount++;
float xfbLines = ((bpmem.copyTexSrcWH.y + 1.0f) * yScale);
if (yScale != 1.0)
WARN_LOG(VIDEO, "yScale of %f is currently unsupported", yScale);
if ((u32)xfbLines > MAX_XFB_HEIGHT)
{
INFO_LOG(VIDEO, "Tried to scale EFB to too many XFB lines (%f)", xfbLines);
xfbLines = MAX_XFB_HEIGHT;
}
CopyToXfb(bpmem.copyTexDest << 5,
bpmem.copyMipMapStrideChannels << 4,
(u32)xfbLines,
rc,
s_gammaLUT[bpmem.triggerEFBCopy.gamma]);
}
else
{
CopyToRam();
CopyToRam(); // FIXME: should use the rectangle we have already created above
}
if (bpmem.triggerEFBCopy.clear)
@ -87,13 +119,5 @@ namespace EfbCopy
ClearEfb();
}
}
else
{
if (bpmem.triggerEFBCopy.copy_to_xfb)
{
// no frame rendered but tell that a frame has finished for frame skip counter
Core::Callback_VideoCopiedToXFB(false);
}
}
}
}