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:
Nolan Check
2009-07-11 16:52:34 +00:00
parent 442fbf6476
commit ffb1f411d8
4 changed files with 54 additions and 46 deletions

View File

@ -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();

View File

@ -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

View File

@ -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)
{ {
/* /*

View File

@ -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;
} }