mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-07-23 14:19:46 -06:00
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:
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user