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

@ -183,20 +183,20 @@ void FramebufferManager::Shutdown()
m_virtualXFBList.clear();
}
void FramebufferManager::CopyToXFB(u32 xfbAddr, u32 dstWidth, u32 dstHeight, const TRectangle& sourceRc)
void FramebufferManager::CopyToXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const TRectangle& sourceRc)
{
if (g_Config.bUseXFB)
copyToRealXFB(xfbAddr, dstWidth, dstHeight, sourceRc);
copyToRealXFB(xfbAddr, fbWidth, fbHeight, sourceRc);
else
copyToVirtualXFB(xfbAddr, dstWidth, dstHeight, sourceRc);
copyToVirtualXFB(xfbAddr, fbWidth, fbHeight, sourceRc);
}
const XFBSource* FramebufferManager::GetXFBSource(u32 xfbAddr, u32 srcWidth, u32 srcHeight)
const XFBSource* FramebufferManager::GetXFBSource(u32 xfbAddr, u32 fbWidth, u32 fbHeight)
{
if (g_Config.bUseXFB)
return getRealXFBSource(xfbAddr, srcWidth, srcHeight);
return getRealXFBSource(xfbAddr, fbWidth, fbHeight);
else
return getVirtualXFBSource(xfbAddr, srcWidth, srcHeight);
return getVirtualXFBSource(xfbAddr, fbWidth, fbHeight);
}
GLuint FramebufferManager::GetEFBColorTexture(const TRectangle& sourceRc) const
@ -283,7 +283,7 @@ FramebufferManager::findVirtualXFB(u32 xfbAddr, u32 width, u32 height)
return m_virtualXFBList.end();
}
void FramebufferManager::copyToRealXFB(u32 xfbAddr, u32 dstWidth, u32 dstHeight, const TRectangle& sourceRc)
void FramebufferManager::copyToRealXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const TRectangle& sourceRc)
{
u8* pXFB = Memory_GetPtr(xfbAddr);
if (!pXFB)
@ -292,22 +292,22 @@ void FramebufferManager::copyToRealXFB(u32 xfbAddr, u32 dstWidth, u32 dstHeight,
return;
}
XFB_Write(pXFB, sourceRc, dstWidth, dstHeight);
XFB_Write(pXFB, sourceRc, fbWidth, fbHeight);
}
void FramebufferManager::copyToVirtualXFB(u32 xfbAddr, u32 dstWidth, u32 dstHeight, const TRectangle& sourceRc)
void FramebufferManager::copyToVirtualXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const TRectangle& sourceRc)
{
GLuint xfbTexture;
VirtualXFBListType::iterator it = findVirtualXFB(xfbAddr, dstWidth, dstHeight);
VirtualXFBListType::iterator it = findVirtualXFB(xfbAddr, fbWidth, fbHeight);
if (it != m_virtualXFBList.end())
{
// Overwrite an existing Virtual XFB.
it->xfbAddr = xfbAddr;
it->xfbWidth = dstWidth;
it->xfbHeight = dstHeight;
it->xfbWidth = fbWidth;
it->xfbHeight = fbHeight;
it->xfbSource.texWidth = m_targetWidth;
it->xfbSource.texHeight = m_targetHeight;
@ -342,8 +342,8 @@ void FramebufferManager::copyToVirtualXFB(u32 xfbAddr, u32 dstWidth, u32 dstHeig
VirtualXFB newVirt;
newVirt.xfbAddr = xfbAddr;
newVirt.xfbWidth = dstWidth;
newVirt.xfbHeight = dstHeight;
newVirt.xfbWidth = fbWidth;
newVirt.xfbHeight = fbHeight;
newVirt.xfbSource.texture = xfbTexture;
newVirt.xfbSource.texWidth = m_targetWidth;
@ -405,15 +405,15 @@ void FramebufferManager::copyToVirtualXFB(u32 xfbAddr, u32 dstWidth, u32 dstHeig
}
}
const XFBSource* FramebufferManager::getRealXFBSource(u32 xfbAddr, u32 srcWidth, u32 srcHeight)
const XFBSource* FramebufferManager::getRealXFBSource(u32 xfbAddr, u32 fbWidth, u32 fbHeight)
{
m_realXFBSource.texWidth = XFB_WIDTH;
m_realXFBSource.texHeight = XFB_HEIGHT;
m_realXFBSource.sourceRc.left = 0;
m_realXFBSource.sourceRc.top = 0;
m_realXFBSource.sourceRc.right = srcWidth;
m_realXFBSource.sourceRc.bottom = srcHeight;
m_realXFBSource.sourceRc.right = fbWidth;
m_realXFBSource.sourceRc.bottom = fbHeight;
if (!m_realXFBSource.texture)
{
@ -426,12 +426,12 @@ const XFBSource* FramebufferManager::getRealXFBSource(u32 xfbAddr, u32 srcWidth,
}
// Decode YUYV data from GameCube RAM
TextureConverter::DecodeToTexture(xfbAddr, srcWidth, srcHeight, m_realXFBSource.texture);
TextureConverter::DecodeToTexture(xfbAddr, fbWidth, fbHeight, m_realXFBSource.texture);
return &m_realXFBSource;
}
const XFBSource* FramebufferManager::getVirtualXFBSource(u32 xfbAddr, u32 srcWidth, u32 srcHeight)
const XFBSource* FramebufferManager::getVirtualXFBSource(u32 xfbAddr, u32 fbWidth, u32 fbHeight)
{
if (m_virtualXFBList.size() == 0)
{
@ -439,7 +439,7 @@ const XFBSource* FramebufferManager::getVirtualXFBSource(u32 xfbAddr, u32 srcWid
return NULL;
}
VirtualXFBListType::iterator it = findVirtualXFB(xfbAddr, srcWidth, srcHeight);
VirtualXFBListType::iterator it = findVirtualXFB(xfbAddr, fbWidth, fbHeight);
if (it == m_virtualXFBList.end())
{
// Virtual XFB is not in the list, so return the most recently rendered

View File

@ -97,9 +97,9 @@ public:
// sourceRc is in GL target coordinates, not GameCube EFB coordinates!
// TODO: Clean that up.
void CopyToXFB(u32 xfbAddr, u32 dstWidth, u32 dstHeight, const TRectangle& sourceRc);
void CopyToXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const TRectangle& sourceRc);
const XFBSource* GetXFBSource(u32 xfbAddr, u32 srcWidth, u32 srcHeight);
const XFBSource* GetXFBSource(u32 xfbAddr, u32 fbWidth, u32 fbHeight);
// To get the EFB in texture form, these functions may have to transfer
// the EFB to a resolved texture first.
@ -124,10 +124,10 @@ private:
VirtualXFBListType::iterator findVirtualXFB(u32 xfbAddr, u32 width, u32 height);
void copyToRealXFB(u32 xfbAddr, u32 dstWidth, u32 dstHeight, const TRectangle& sourceRc);
void copyToVirtualXFB(u32 xfbAddr, u32 dstWidth, u32 dstHeight, const TRectangle& sourceRc);
const XFBSource* getRealXFBSource(u32 xfbAddr, u32 srcWidth, u32 srcHeight);
const XFBSource* getVirtualXFBSource(u32 xfbAddr, u32 srcWidth, u32 srcHeight);
void copyToRealXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const TRectangle& sourceRc);
void copyToVirtualXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const TRectangle& sourceRc);
const XFBSource* getRealXFBSource(u32 xfbAddr, u32 fbWidth, u32 fbHeight);
const XFBSource* getVirtualXFBSource(u32 xfbAddr, u32 fbWidth, u32 fbHeight);
int m_targetWidth;
int m_targetHeight;

View File

@ -55,6 +55,7 @@
#include "Timer.h"
#include "StringUtil.h"
#include "FramebufferManager.h"
#include "Fifo.h"
#include "main.h" // Local
#ifdef _WIN32
@ -660,39 +661,19 @@ void ComputeBackbufferRectangle(TRectangle *rc)
rc->bottom = YOffset + ceil(FloatGLHeight);
}
// TODO: Use something less ugly than an Evil Global Variable.
// Also, protect this structure with a mutex.
extern volatile struct // Comes from main.cpp
{
u32 xfbAddr;
u32 width;
u32 height;
s32 yOffset;
} tUpdateXFBArgs;
void Renderer::RenderToXFB(u32 xfbAddr, u32 dstWidth, u32 dstHeight, const TRectangle& sourceRc)
void Renderer::RenderToXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const TRectangle& sourceRc)
{
u32 aLower = xfbAddr;
u32 aUpper = xfbAddr + 2 * dstWidth * dstHeight;
u32 bLower = tUpdateXFBArgs.xfbAddr;
u32 bUpper = tUpdateXFBArgs.xfbAddr + 2 * tUpdateXFBArgs.width * tUpdateXFBArgs.height;
// If we're about to write into a requested XFB, make sure the previous
// If we're about to write to a requested XFB, make sure the previous
// contents make it to the screen first.
if (g_XFBUpdateRequested && addrRangesOverlap(aLower, aUpper, bLower, bUpper))
{
Video_UpdateXFB(NULL, 0, 0, 0, FALSE);
}
VideoFifo_CheckSwapRequestAt(xfbAddr, fbWidth, fbHeight);
s_framebufferManager.CopyToXFB(xfbAddr, dstWidth, dstHeight, sourceRc);
s_framebufferManager.CopyToXFB(xfbAddr, fbWidth, fbHeight, sourceRc);
}
// This function has the final picture. We adjust the aspect ratio here.
// yOffset is used to eliminate interlacing jitter in Real XFB mode.
void Renderer::Swap(u32 xfbAddr, u32 srcWidth, u32 srcHeight, s32 yOffset)
void Renderer::Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight)
{
const XFBSource* xfbSource = s_framebufferManager.GetXFBSource(xfbAddr, srcWidth, srcHeight);
const XFBSource* xfbSource = s_framebufferManager.GetXFBSource(xfbAddr, fbWidth, fbHeight);
if (!xfbSource)
{
WARN_LOG(VIDEO, "Failed to get video for this frame");
@ -724,6 +705,7 @@ void Renderer::Swap(u32 xfbAddr, u32 srcWidth, u32 srcHeight, s32 yOffset)
v_max = (float)xfbSource->texHeight;
}
int yOffset = (g_Config.bUseXFB && field == FIELD_LOWER) ? -1 : 0;
v_min -= yOffset;
v_max -= yOffset;

View File

@ -87,10 +87,10 @@ public:
static void FlipImageData(u8 *data, int w, int h);
static bool SaveRenderTarget(const char *filename, int w, int h, int YOffset = 0);
static void RenderToXFB(u32 xfbAddr, u32 dstWidth, u32 dstHeight, const TRectangle& sourceRc);
static void RenderToXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const TRectangle& sourceRc);
// Finish up the current frame, print some stats
static void Swap(u32 xfbAddr, u32 srcWidth, u32 srcHeight, s32 yOffset);
static void Swap(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight);
};
void ComputeBackbufferRectangle(TRectangle *rc);

View File

@ -99,6 +99,9 @@ int GLScissorX, GLScissorY, GLScissorW, GLScissorH;
static bool s_PluginInitialized = false;
static bool s_swapRequested = false;
static Common::Event s_swapResponseEvent;
static volatile u32 s_AccessEFBResult = 0, s_EFBx, s_EFBy;
static volatile EFBAccessType s_AccessEFBType;
static Common::Event s_AccessEFBDone;
@ -372,6 +375,10 @@ void Video_Prepare(void)
VertexLoaderManager::Init();
TextureConverter::Init();
s_swapRequested = false;
s_swapResponseEvent.Init();
s_swapResponseEvent.Set();
s_PluginInitialized = true;
INFO_LOG(VIDEO, "Video plugin initialized.");
}
@ -380,6 +387,9 @@ void Shutdown(void)
{
s_PluginInitialized = false;
s_swapRequested = false;
s_swapResponseEvent.Shutdown();
Fifo_Shutdown();
PostProcessing::Shutdown();
TextureConverter::Shutdown();
@ -423,48 +433,75 @@ void Video_AddMessage(const char* pstr, u32 milliseconds)
OSD::AddMessage(pstr, milliseconds);
}
// TODO: Protect this structure with a mutex.
volatile struct
{
static volatile struct
{
u32 xfbAddr;
u32 width;
u32 height;
s32 yOffset;
} tUpdateXFBArgs;
FieldType field;
u32 fbWidth;
u32 fbHeight;
} s_beginFieldArgs = { 0 };
// Run from the CPU thread (from VideoInterface.cpp) for certain homebrew games only
void Video_UpdateXFB(u32 _dwXFBAddr, u32 _dwWidth, u32 _dwHeight, s32 _dwYOffset, bool scheduling)
// Run from the graphics thread (from Fifo.cpp)
void VideoFifo_CheckSwapRequest()
{
if (s_swapRequested)
{
s_swapRequested = false;
Common::MemFence();
Renderer::Swap(s_beginFieldArgs.xfbAddr, s_beginFieldArgs.field, s_beginFieldArgs.fbWidth, s_beginFieldArgs.fbHeight);
// TODO: Find better name for this because I don't know if it means what it says.
g_VideoInitialize.pCopiedToXFB();
s_swapResponseEvent.Set();
}
}
inline bool addrRangesOverlap(u32 aLower, u32 aUpper, u32 bLower, u32 bUpper)
{
return (
(aLower >= bLower && aLower < bUpper) ||
(aUpper >= bLower && aUpper < bUpper) ||
(bLower >= aLower && bLower < aUpper) ||
(bUpper >= aLower && bUpper < aUpper)
);
}
// Run from the graphics thread (from Fifo.cpp)
void VideoFifo_CheckSwapRequestAt(u32 xfbAddr, u32 fbWidth, u32 fbHeight)
{
if (s_swapRequested)
{
u32 aLower = xfbAddr;
u32 aUpper = xfbAddr + 2 * fbWidth * fbHeight;
Common::MemFence();
u32 bLower = s_beginFieldArgs.xfbAddr;
u32 bUpper = s_beginFieldArgs.xfbAddr + 2 * s_beginFieldArgs.fbWidth * s_beginFieldArgs.fbHeight;
if (addrRangesOverlap(aLower, aUpper, bLower, bUpper))
VideoFifo_CheckSwapRequest();
}
}
// Run from the CPU thread (from VideoInterface.cpp)
void Video_BeginField(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight)
{
if (s_PluginInitialized)
{
if (scheduling) // From CPU in DC mode
{
tUpdateXFBArgs.xfbAddr = _dwXFBAddr;
tUpdateXFBArgs.width = _dwWidth;
tUpdateXFBArgs.height = _dwHeight;
tUpdateXFBArgs.yOffset = _dwYOffset;
s_swapResponseEvent.MsgWait();
g_XFBUpdateRequested = TRUE;
}
else // From CPU in SC mode or graphics thread in DC mode
{
g_XFBUpdateRequested = FALSE;
s_beginFieldArgs.xfbAddr = xfbAddr;
s_beginFieldArgs.field = field;
s_beginFieldArgs.fbWidth = fbWidth;
s_beginFieldArgs.fbHeight = fbHeight;
if (!_dwXFBAddr)
{
// From graphics thread in DC mode
_dwXFBAddr = tUpdateXFBArgs.xfbAddr;
_dwWidth = tUpdateXFBArgs.width;
_dwHeight = tUpdateXFBArgs.height;
_dwYOffset = tUpdateXFBArgs.yOffset;
}
Common::MemFence();
// TODO: Use real XFB source parameters based on VI settings
Renderer::Swap(_dwXFBAddr, _dwWidth, _dwHeight, g_Config.bUseXFB ? _dwYOffset : 0);
g_VideoInitialize.pCopiedToXFB();
}
s_swapRequested = true;
}
}