Switch to Video_BeginField; hopefully fix or reduce some video stability problems by using Events.

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@3740 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
Nolan Check
2009-07-11 02:34:16 +00:00
parent 2a236a4631
commit dc7d9ab998
13 changed files with 185 additions and 166 deletions

View File

@ -24,7 +24,7 @@ PluginVideo::PluginVideo(const char *_Filename) : CPlugin(_Filename), validVideo
{
Video_Prepare = 0;
Video_SendFifoData = 0;
Video_UpdateXFB = 0;
Video_BeginField = 0;
Video_EnterLoop = 0;
Video_ExitLoop = 0;
Video_Screenshot = 0;
@ -35,8 +35,8 @@ PluginVideo::PluginVideo(const char *_Filename) : CPlugin(_Filename), validVideo
(LoadSymbol("Video_Prepare"));
Video_SendFifoData = reinterpret_cast<TVideo_SendFifoData>
(LoadSymbol("Video_SendFifoData"));
Video_UpdateXFB = reinterpret_cast<TVideo_UpdateXFB>
(LoadSymbol("Video_UpdateXFB"));
Video_BeginField = reinterpret_cast<TVideo_BeginField>
(LoadSymbol("Video_BeginField"));
Video_Screenshot = reinterpret_cast<TVideo_Screenshot>
(LoadSymbol("Video_Screenshot"));
Video_EnterLoop = reinterpret_cast<TVideo_EnterLoop>
@ -50,7 +50,7 @@ PluginVideo::PluginVideo(const char *_Filename) : CPlugin(_Filename), validVideo
if ((Video_Prepare != 0) &&
(Video_SendFifoData != 0) &&
(Video_UpdateXFB != 0) &&
(Video_BeginField != 0) &&
(Video_EnterLoop != 0) &&
(Video_ExitLoop != 0) &&
(Video_Screenshot != 0) &&

View File

@ -25,7 +25,7 @@ namespace Common {
typedef void (__cdecl* TVideo_Prepare)();
typedef void (__cdecl* TVideo_SendFifoData)(u8*,u32);
typedef void (__cdecl* TVideo_UpdateXFB)(u32, u32, u32, s32, bool);
typedef void (__cdecl* TVideo_BeginField)(u32, FieldType, u32, u32);
typedef bool (__cdecl* TVideo_Screenshot)(const char* filename);
typedef void (__cdecl* TVideo_EnterLoop)();
typedef void (__cdecl* TVideo_ExitLoop)();
@ -43,7 +43,7 @@ public:
TVideo_SendFifoData Video_SendFifoData;
TVideo_EnterLoop Video_EnterLoop;
TVideo_ExitLoop Video_ExitLoop;
TVideo_UpdateXFB Video_UpdateXFB;
TVideo_BeginField Video_BeginField;
TVideo_AccessEFB Video_AccessEFB;
TVideo_AddMessage Video_AddMessage;

View File

@ -71,6 +71,18 @@
namespace Common
{
// MemFence: Neither the compiler nor the CPU can reorder memory accesses
// beyond this barrier.
__forceinline void MemFence()
{
#ifdef _WIN32
MemoryBarrier();
#else
// TODO: UNIX experts, please implement the memory fence.
#endif
}
class CriticalSection
{
#ifdef _WIN32

View File

@ -987,15 +987,7 @@ void GenerateVIInterrupt(VIInterruptType _VIInterrupt)
}
}
u8* GetXFBPointerTop()
{
if (m_XFBInfoTop.POFF)
return Memory::GetPointer(m_XFBInfoTop.FBB << 5);
else
return Memory::GetPointer(m_XFBInfoTop.FBB);
}
u32 GetXFBPointerTop_GC()
u32 GetXFBAddressTop()
{
if (m_XFBInfoTop.POFF)
return m_XFBInfoTop.FBB << 5;
@ -1003,16 +995,7 @@ u32 GetXFBPointerTop_GC()
return m_XFBInfoTop.FBB;
}
u8* GetXFBPointerBottom()
{
// POFF for XFB bottom is connected to POFF for XFB top
if (m_XFBInfoTop.POFF)
return Memory::GetPointer(m_XFBInfoBottom.FBB << 5);
else
return Memory::GetPointer(m_XFBInfoBottom.FBB);
}
u32 GetXFBPointerBottom_GC()
u32 GetXFBAddressBottom()
{
// POFF for XFB bottom is connected to POFF for XFB top
if (m_XFBInfoTop.POFF)
@ -1058,6 +1041,25 @@ int getTicksPerLine() {
}
static void BeginField(u32 xfbAddr, FieldType field)
{
static const char* const fieldTypeNames[] = { "Progressive", "Upper", "Lower" };
DEBUG_LOG(VIDEOINTERFACE, "(VI->BeginField): addr: %.08X | FieldSteps %u | FbSteps %u | ACV %u | Field %s",
xfbAddr, m_HorizontalStepping.FieldSteps, m_HorizontalStepping.FbSteps, m_VerticalTimingRegister.ACV,
fieldTypeNames[field]
);
u32 fbWidth = m_HorizontalStepping.FieldSteps * 16;
u32 fbHeight = (m_HorizontalStepping.FbSteps / m_HorizontalStepping.FieldSteps) * m_VerticalTimingRegister.ACV;
Common::PluginVideo* video = CPluginManager::GetInstance().GetVideo();
if (xfbAddr && video->IsValid())
{
video->Video_BeginField(xfbAddr, field, fbWidth, fbHeight);
}
}
// Purpose 1: Send VI interrupt for every screen refresh
// Purpose 2: Execute XFB copy in homebrew games
// Run when: This is run 7200 times per second on full speed
@ -1094,57 +1096,32 @@ void Update()
if (m_VBeamPos == NextXFBRender)
{
u32 xfbAddr = 0;
int yOffset = 0;
if (NextXFBRender == 1)
{
NextXFBRender = LinesPerField;
// TODO: proper VI regs typedef and logic for XFB to work.
// eg. Animal Crossing gc have smth in TFBL.XOF bitfield.
// "XOF - Horizontal Offset of the left-most pixel within the first word of the fetched picture."
xfbAddr = GetXFBPointerTop_GC();
u32 xfbAddr = GetXFBAddressTop();
BeginField(xfbAddr, m_DisplayControlRegister.NIN ? FIELD_PROGRESSIVE : FIELD_UPPER);
}
else
{
NextXFBRender = 1;
// Previously checked m_XFBInfoTop.POFF then used m_XFBInfoBottom.FBB, try reverting if there are problems
xfbAddr = GetXFBPointerBottom_GC();
yOffset = -1;
}
Common::PluginVideo* video = CPluginManager::GetInstance().GetVideo();
if (xfbAddr && video->IsValid())
{
int fbWidth = m_HorizontalStepping.FieldSteps * 16;
int fbHeight = (m_HorizontalStepping.FbSteps / m_HorizontalStepping.FieldSteps) * m_VerticalTimingRegister.ACV;
DEBUG_LOG(VIDEOINTERFACE, "(VI->XFBUpdate): ptr: %.08X | %ix%i | xoff: %i",
xfbAddr, fbWidth, fbHeight, m_XFBInfoTop.XOFF);
if (Core::GetStartupParameter().bUseDualCore)
// scheduled on EmuThread in DC mode
video->Video_UpdateXFB(xfbAddr, fbWidth, fbHeight, yOffset, TRUE);
else
// otherwise do it now from here (CPUthread)
video->Video_UpdateXFB(xfbAddr, fbWidth, fbHeight, yOffset, FALSE);
u32 xfbAddr = GetXFBAddressBottom();
BeginField(xfbAddr, m_DisplayControlRegister.NIN ? FIELD_PROGRESSIVE : FIELD_LOWER);
}
}
// check INT_PRERETRACE
if (m_InterruptRegister[0].VCT == m_VBeamPos)
{
m_InterruptRegister[0].IR_INT = 1;
UpdateInterrupts();
}
// INT_POSTRETRACE
if (m_InterruptRegister[1].VCT == m_VBeamPos)
{
m_InterruptRegister[1].IR_INT = 1;
UpdateInterrupts();
}
for (int i = 0; i < 4; ++i)
{
if (m_InterruptRegister[i].VCT == m_VBeamPos)
{
m_InterruptRegister[i].IR_INT = 1;
UpdateInterrupts();
}
}
}
} // namespace

View File

@ -28,8 +28,6 @@
#include "Fifo.h"
// TODO (mb2): move/rm this global
volatile u32 g_XFBUpdateRequested = FALSE;
extern u8* g_pVideoData;
volatile bool g_EFBAccessRequested = false;
@ -63,7 +61,6 @@ void Fifo_Init()
videoBuffer = (u8*)AllocateMemoryPages(FIFO_SIZE);
fifo_exit_event.Init();
fifoStateRun = false;
g_XFBUpdateRequested = FALSE;
}
void Fifo_Shutdown()
@ -147,10 +144,7 @@ void Fifo_EnterLoop(const SVideoInitialize &video_initialize)
#endif
// Draw XFB if CP/GPfifo isn't used
if (g_XFBUpdateRequested)
{
Video_UpdateXFB(NULL, 0, 0, 0, FALSE);
}
VideoFifo_CheckSwapRequest();
if (g_EFBAccessRequested)
{

View File

@ -37,4 +37,8 @@ void Fifo_ExitLoopNonBlocking();
void Fifo_DoState(PointerWrap &f);
// Implemented by the Video Plugin
void VideoFifo_CheckSwapRequest();
void VideoFifo_CheckSwapRequestAt(u32 xfbAddr, u32 fbWidth, u32 fbHeight);
#endif