mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-07-23 06:09:50 -06:00
Use events and memfences for EFB accesses. Also, Single-Core mode now works again.
git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@3750 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
@ -143,13 +143,8 @@ void Fifo_EnterLoop(const SVideoInitialize &video_initialize)
|
|||||||
video_initialize.pPeekMessages();
|
video_initialize.pPeekMessages();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Draw XFB if CP/GPfifo isn't used
|
|
||||||
VideoFifo_CheckSwapRequest();
|
VideoFifo_CheckSwapRequest();
|
||||||
|
VideoFifo_CheckEFBAccess();
|
||||||
if (g_EFBAccessRequested)
|
|
||||||
{
|
|
||||||
Video_OnThreadAccessEFB();
|
|
||||||
}
|
|
||||||
|
|
||||||
s_criticalFifo.Enter();
|
s_criticalFifo.Enter();
|
||||||
|
|
||||||
|
@ -40,5 +40,6 @@ void Fifo_DoState(PointerWrap &f);
|
|||||||
// Implemented by the Video Plugin
|
// Implemented by the Video Plugin
|
||||||
void VideoFifo_CheckSwapRequest();
|
void VideoFifo_CheckSwapRequest();
|
||||||
void VideoFifo_CheckSwapRequestAt(u32 xfbAddr, u32 fbWidth, u32 fbHeight);
|
void VideoFifo_CheckSwapRequestAt(u32 xfbAddr, u32 fbWidth, u32 fbHeight);
|
||||||
|
void VideoFifo_CheckEFBAccess();
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -262,6 +262,10 @@ void VideoFifo_CheckSwapRequestAt(u32 xfbAddr, u32 fbWidth, u32 fbHeight)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void VideoFifo_CheckEFBAccess()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
void Video_BeginField(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight)
|
void Video_BeginField(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
|
@ -99,13 +99,11 @@ int GLScissorX, GLScissorY, GLScissorW, GLScissorH;
|
|||||||
|
|
||||||
static bool s_PluginInitialized = false;
|
static bool s_PluginInitialized = false;
|
||||||
|
|
||||||
static bool s_swapRequested = false;
|
static volatile bool s_swapRequested = false;
|
||||||
static Common::Event s_swapResponseEvent;
|
static Common::Event s_swapResponseEvent;
|
||||||
|
|
||||||
static volatile u32 s_AccessEFBResult = 0, s_EFBx, s_EFBy;
|
static volatile bool s_efbAccessRequested = false;
|
||||||
static volatile EFBAccessType s_AccessEFBType;
|
static Common::Event s_efbResponseEvent;
|
||||||
static Common::Event s_AccessEFBDone;
|
|
||||||
static Common::CriticalSection s_criticalEFB;
|
|
||||||
|
|
||||||
|
|
||||||
void GetDllInfo (PLUGIN_INFO* _PluginInfo)
|
void GetDllInfo (PLUGIN_INFO* _PluginInfo)
|
||||||
@ -379,6 +377,9 @@ void Video_Prepare(void)
|
|||||||
s_swapResponseEvent.Init();
|
s_swapResponseEvent.Init();
|
||||||
s_swapResponseEvent.Set();
|
s_swapResponseEvent.Set();
|
||||||
|
|
||||||
|
s_efbAccessRequested = false;
|
||||||
|
s_efbResponseEvent.Init();
|
||||||
|
|
||||||
s_PluginInitialized = true;
|
s_PluginInitialized = true;
|
||||||
INFO_LOG(VIDEO, "Video plugin initialized.");
|
INFO_LOG(VIDEO, "Video plugin initialized.");
|
||||||
}
|
}
|
||||||
@ -387,6 +388,9 @@ void Shutdown(void)
|
|||||||
{
|
{
|
||||||
s_PluginInitialized = false;
|
s_PluginInitialized = false;
|
||||||
|
|
||||||
|
s_efbAccessRequested = false;
|
||||||
|
s_efbResponseEvent.Shutdown();
|
||||||
|
|
||||||
s_swapRequested = false;
|
s_swapRequested = false;
|
||||||
s_swapResponseEvent.Shutdown();
|
s_swapResponseEvent.Shutdown();
|
||||||
|
|
||||||
@ -439,7 +443,7 @@ static volatile struct
|
|||||||
FieldType field;
|
FieldType field;
|
||||||
u32 fbWidth;
|
u32 fbWidth;
|
||||||
u32 fbHeight;
|
u32 fbHeight;
|
||||||
} s_beginFieldArgs = { 0 };
|
} s_beginFieldArgs;
|
||||||
|
|
||||||
// Run from the graphics thread (from Fifo.cpp)
|
// Run from the graphics thread (from Fifo.cpp)
|
||||||
void VideoFifo_CheckSwapRequest()
|
void VideoFifo_CheckSwapRequest()
|
||||||
@ -492,7 +496,10 @@ void Video_BeginField(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight)
|
|||||||
{
|
{
|
||||||
if (s_PluginInitialized)
|
if (s_PluginInitialized)
|
||||||
{
|
{
|
||||||
s_swapResponseEvent.MsgWait();
|
if (g_VideoInitialize.bUseDualCore)
|
||||||
|
s_swapResponseEvent.MsgWait();
|
||||||
|
else
|
||||||
|
VideoFifo_CheckSwapRequest();
|
||||||
|
|
||||||
s_beginFieldArgs.xfbAddr = xfbAddr;
|
s_beginFieldArgs.xfbAddr = xfbAddr;
|
||||||
s_beginFieldArgs.field = field;
|
s_beginFieldArgs.field = field;
|
||||||
@ -505,12 +512,22 @@ void Video_BeginField(u32 xfbAddr, FieldType field, u32 fbWidth, u32 fbHeight)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Video_OnThreadAccessEFB()
|
static volatile struct
|
||||||
{
|
{
|
||||||
s_criticalEFB.Enter();
|
EFBAccessType type;
|
||||||
s_AccessEFBResult = 0;
|
u32 x;
|
||||||
|
u32 y;
|
||||||
|
} s_accessEFBArgs;
|
||||||
|
|
||||||
switch (s_AccessEFBType)
|
static volatile u32 s_AccessEFBResult = 0;
|
||||||
|
|
||||||
|
void VideoFifo_CheckEFBAccess()
|
||||||
|
{
|
||||||
|
s_efbAccessRequested = false;
|
||||||
|
|
||||||
|
Common::MemFence();
|
||||||
|
|
||||||
|
switch (s_accessEFBArgs.type)
|
||||||
{
|
{
|
||||||
case PEEK_Z:
|
case PEEK_Z:
|
||||||
{
|
{
|
||||||
@ -530,12 +547,14 @@ void Video_OnThreadAccessEFB()
|
|||||||
|
|
||||||
// Read the z value! Also adjust the pixel to read to the upscaled EFB resolution
|
// Read the z value! Also adjust the pixel to read to the upscaled EFB resolution
|
||||||
// Plus we need to flip the y value as the OGL image is upside down
|
// Plus we need to flip the y value as the OGL image is upside down
|
||||||
glReadPixels(s_EFBx*xScale, Renderer::GetTargetHeight() - s_EFBy*yScale, 1, 1, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, &z);
|
glReadPixels(s_accessEFBArgs.x*xScale, Renderer::GetTargetHeight() - s_accessEFBArgs.y*yScale, 1, 1, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, &z);
|
||||||
GL_REPORT_ERRORD();
|
GL_REPORT_ERRORD();
|
||||||
|
|
||||||
// Clamp the 32bits value returned by glReadPixels to a 24bits value (GC uses a 24bits Z-Buffer)
|
// Clamp the 32bits value returned by glReadPixels to a 24bits value (GC uses a 24bits Z-Buffer)
|
||||||
s_AccessEFBResult = z / 0x100;
|
s_AccessEFBResult = z / 0x100;
|
||||||
|
|
||||||
|
Common::MemFence();
|
||||||
|
|
||||||
// We should probably re-bind the old fbo here.
|
// We should probably re-bind the old fbo here.
|
||||||
if (g_Config.iMultisampleMode != MULTISAMPLE_OFF) {
|
if (g_Config.iMultisampleMode != MULTISAMPLE_OFF) {
|
||||||
Renderer::SetFramebuffer(0);
|
Renderer::SetFramebuffer(0);
|
||||||
@ -544,12 +563,19 @@ void Video_OnThreadAccessEFB()
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case POKE_Z:
|
case POKE_Z:
|
||||||
|
// TODO: Implement
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PEEK_COLOR:
|
case PEEK_COLOR:
|
||||||
|
// TODO: Implement
|
||||||
|
s_AccessEFBResult = 0;
|
||||||
|
Common::MemFence();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case POKE_COLOR:
|
case POKE_COLOR:
|
||||||
|
// TODO: Implement. One way is to draw a tiny pixel-sized rectangle at
|
||||||
|
// the exact location. Note: EFB pokes are susceptible to Z-buffering
|
||||||
|
// and perhaps blending.
|
||||||
//WARN_LOG(VIDEOINTERFACE, "This is probably some kind of software rendering");
|
//WARN_LOG(VIDEOINTERFACE, "This is probably some kind of software rendering");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -557,44 +583,26 @@ void Video_OnThreadAccessEFB()
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
g_EFBAccessRequested = false;
|
s_efbResponseEvent.Set();
|
||||||
s_AccessEFBDone.Set();
|
|
||||||
|
|
||||||
s_criticalEFB.Leave();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 Video_AccessEFB(EFBAccessType type, u32 x, u32 y)
|
u32 Video_AccessEFB(EFBAccessType type, u32 x, u32 y)
|
||||||
{
|
{
|
||||||
u32 result;
|
s_accessEFBArgs.type = type;
|
||||||
|
s_accessEFBArgs.x = x;
|
||||||
|
s_accessEFBArgs.y = y;
|
||||||
|
|
||||||
s_criticalEFB.Enter();
|
Common::MemFence();
|
||||||
|
|
||||||
s_AccessEFBType = type;
|
s_efbAccessRequested = true;
|
||||||
s_EFBx = x;
|
|
||||||
s_EFBy = y;
|
|
||||||
|
|
||||||
if (g_VideoInitialize.bUseDualCore)
|
if (g_VideoInitialize.bUseDualCore)
|
||||||
{
|
s_efbResponseEvent.MsgWait();
|
||||||
s_AccessEFBDone.Init();
|
|
||||||
g_EFBAccessRequested = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
s_criticalEFB.Leave();
|
|
||||||
|
|
||||||
if (g_VideoInitialize.bUseDualCore)
|
|
||||||
s_AccessEFBDone.Wait();
|
|
||||||
else
|
else
|
||||||
Video_OnThreadAccessEFB();
|
VideoFifo_CheckEFBAccess();
|
||||||
|
|
||||||
s_criticalEFB.Enter();
|
Common::MemFence();
|
||||||
|
|
||||||
if (g_VideoInitialize.bUseDualCore)
|
return s_AccessEFBResult;
|
||||||
s_AccessEFBDone.Shutdown();
|
|
||||||
|
|
||||||
result = s_AccessEFBResult;
|
|
||||||
|
|
||||||
s_criticalEFB.Leave();
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user