mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-07-28 16:49:58 -06:00
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:
@ -9,7 +9,7 @@
|
||||
#include "VideoConfigDialog.h"
|
||||
#endif // HAVE_WX
|
||||
|
||||
|
||||
#include "Atomic.h"
|
||||
#include "SWCommandProcessor.h"
|
||||
#include "OpcodeDecoder.h"
|
||||
#include "SWVideoConfig.h"
|
||||
@ -29,10 +29,22 @@
|
||||
#include "OpcodeDecoder.h"
|
||||
#include "SWVertexLoader.h"
|
||||
#include "SWStatistics.h"
|
||||
#include "HW/VideoInterface.h"
|
||||
#include "HW/Memmap.h"
|
||||
|
||||
#include "OnScreenDisplay.h"
|
||||
#define VSYNC_ENABLED 0
|
||||
|
||||
static volatile u32 s_swapRequested = false;
|
||||
|
||||
static volatile struct
|
||||
{
|
||||
u32 xfbAddr;
|
||||
FieldType field;
|
||||
u32 fbWidth;
|
||||
u32 fbHeight;
|
||||
} s_beginFieldArgs;
|
||||
|
||||
namespace SW
|
||||
{
|
||||
|
||||
@ -191,12 +203,51 @@ void VideoSoftware::Video_Prepare()
|
||||
|
||||
// Run from the CPU thread (from VideoInterface.cpp)
|
||||
void VideoSoftware::Video_BeginField(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight)
|
||||
{
|
||||
{
|
||||
s_beginFieldArgs.xfbAddr = xfbAddr;
|
||||
s_beginFieldArgs.field = field;
|
||||
s_beginFieldArgs.fbWidth = fbWidth;
|
||||
s_beginFieldArgs.fbHeight = fbHeight;
|
||||
}
|
||||
|
||||
// Run from the CPU thread (from VideoInterface.cpp)
|
||||
void VideoSoftware::Video_EndField()
|
||||
{
|
||||
// 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.bHwRasterizer) {
|
||||
|
||||
// Force Progressive
|
||||
u32 xfbAddr = VideoInterface::GetXFBAddressTop();
|
||||
|
||||
// All drivers make an assumption that the two fields are interleaved in the framebuffer
|
||||
// Give a warning if this isn't true.
|
||||
if (xfbAddr + 1280 != VideoInterface::GetXFBAddressBottom()) {
|
||||
WARN_LOG(VIDEO, "Feilds are not interleaved in XFB as expected.");
|
||||
}
|
||||
|
||||
EfbInterface::yuv422_packed *xfb = (EfbInterface::yuv422_packed *) Memory::GetPointer(xfbAddr);
|
||||
|
||||
SWRenderer::UpdateColorTexture(xfb);
|
||||
}
|
||||
|
||||
// Idealy we would just move all the opengl contex stuff to the CPU thread, but this gets
|
||||
// messy when the Hardware Rasterizer is enabled.
|
||||
// And Neobrain loves his Hardware Rasterizer
|
||||
|
||||
// If we are runing dual core, Signal the GPU thread about the new colour texture.
|
||||
if (SConfig::GetInstance().m_LocalCoreStartupParameter.bCPUThread)
|
||||
Common::AtomicStoreRelease(s_swapRequested, true);
|
||||
else
|
||||
SWRenderer::Swap(s_beginFieldArgs.fbWidth, s_beginFieldArgs.fbHeight);
|
||||
}
|
||||
|
||||
u32 VideoSoftware::Video_AccessEFB(EFBAccessType type, u32 x, u32 y, u32 InputData)
|
||||
@ -242,6 +293,16 @@ bool VideoSoftware::Video_Screenshot(const char *_szFilename)
|
||||
return false;
|
||||
}
|
||||
|
||||
// Run from the graphics thread
|
||||
static void VideoFifo_CheckSwapRequest()
|
||||
{
|
||||
if (Common::AtomicLoadAcquire(s_swapRequested))
|
||||
{
|
||||
SWRenderer::Swap(s_beginFieldArgs.fbWidth, s_beginFieldArgs.fbHeight);
|
||||
Common::AtomicStoreRelease(s_swapRequested, false);
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------------------
|
||||
// Enter and exit the video loop
|
||||
// -------------------------------
|
||||
@ -252,6 +313,7 @@ void VideoSoftware::Video_EnterLoop()
|
||||
|
||||
while (fifoStateRun)
|
||||
{
|
||||
VideoFifo_CheckSwapRequest();
|
||||
g_video_backend->PeekMessages();
|
||||
|
||||
if (!SWCommandProcessor::RunBuffer())
|
||||
@ -262,11 +324,12 @@ void VideoSoftware::Video_EnterLoop()
|
||||
while (!emuRunningState && fifoStateRun)
|
||||
{
|
||||
g_video_backend->PeekMessages();
|
||||
VideoFifo_CheckSwapRequest();
|
||||
m_csSWVidOccupied.unlock();
|
||||
Common::SleepCurrentThread(1);
|
||||
m_csSWVidOccupied.lock();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void VideoSoftware::Video_ExitLoop()
|
||||
|
Reference in New Issue
Block a user