diff --git a/Source/Core/Common/Src/Thread.cpp b/Source/Core/Common/Src/Thread.cpp index 18f0763b51..716f79ff55 100644 --- a/Source/Core/Common/Src/Thread.cpp +++ b/Source/Core/Common/Src/Thread.cpp @@ -28,6 +28,10 @@ #include "Thread.h" +#if defined(THREAD_VIDEO_WAKEUP_ONIDLE) && defined(_WIN32) +HANDLE g_hEventOnIdle=NULL; +#endif + namespace Common { #ifdef _WIN32 diff --git a/Source/Core/Common/Src/Thread.h b/Source/Core/Common/Src/Thread.h index af084c6b4b..6043215eef 100644 --- a/Source/Core/Common/Src/Thread.h +++ b/Source/Core/Common/Src/Thread.h @@ -32,6 +32,14 @@ #include "Common.h" + +// for testing purpose +//#define THREAD_VIDEO_WAKEUP_ONIDLE + +#if defined(THREAD_VIDEO_WAKEUP_ONIDLE) && defined(_WIN32) +extern HANDLE g_hEventOnIdle; +#endif + namespace Common { class CriticalSection diff --git a/Source/Core/Core/Src/Core.cpp b/Source/Core/Core/Src/Core.cpp index 10c65eafe9..5e6c003619 100644 --- a/Source/Core/Core/Src/Core.cpp +++ b/Source/Core/Core/Src/Core.cpp @@ -367,10 +367,17 @@ THREAD_RETURN EmuThread(void *pArg) } else { +#if defined(THREAD_VIDEO_WAKEUP_ONIDLE) && defined(_WIN32) + g_hEventOnIdle = CreateEvent( NULL, FALSE, FALSE, "EventOnIdle"); + if (g_hEventOnIdle == NULL) PanicAlert("EmuThread() -> Create EventOnIdle error"); +#endif cpuThread = new Common::Thread(CpuThread, pArg); PluginVideo::Video_Prepare(); //wglMakeCurrent Common::SetCurrentThreadName("Video thread"); PluginVideo::Video_EnterLoop(); +#if defined(THREAD_VIDEO_WAKEUP_ONIDLE) && defined(_WIN32) + CloseHandle(g_hEventOnIdle); +#endif } // Wait for CPU thread to exit - it should have been signaled to do so by now diff --git a/Source/Core/Core/Src/HW/CommandProcessor.cpp b/Source/Core/Core/Src/HW/CommandProcessor.cpp index 9fa506b16c..b9bcc3978d 100644 --- a/Source/Core/Core/Src/HW/CommandProcessor.cpp +++ b/Source/Core/Core/Src/HW/CommandProcessor.cpp @@ -459,9 +459,10 @@ void CatchUpGPU() void UpdateFifoRegister() { // update the distance -#ifdef _WIN32 - if (Core::g_CoreStartupParameter.bUseDualCore) EnterCriticalSection(&fifo.sync); -#endif +//#ifdef _WIN32 +// not needed since we are already in the critical section in DC mode -> see write16(...) (unique reference) +// if (Core::g_CoreStartupParameter.bUseDualCore) EnterCriticalSection(&fifo.sync); +//#endif int wp = fifo.CPWritePointer; int rp = fifo.CPReadPointer; if (wp >= rp) @@ -469,9 +470,10 @@ void UpdateFifoRegister() else fifo.CPReadWriteDistance = (wp - fifo.CPBase) + (fifo.CPEnd - rp); -#ifdef _WIN32 - if (Core::g_CoreStartupParameter.bUseDualCore) LeaveCriticalSection(&fifo.sync); -#endif +//#ifdef _WIN32 +// not needed since we are already in the critical section in DC mode (see write16) +// if (Core::g_CoreStartupParameter.bUseDualCore) LeaveCriticalSection(&fifo.sync); +//#endif if (!Core::g_CoreStartupParameter.bUseDualCore) CatchUpGPU(); } diff --git a/Source/Core/Core/Src/PowerPC/PowerPC.cpp b/Source/Core/Core/Src/PowerPC/PowerPC.cpp index 7058f4ec17..35ce178b7b 100644 --- a/Source/Core/Core/Src/PowerPC/PowerPC.cpp +++ b/Source/Core/Core/Src/PowerPC/PowerPC.cpp @@ -33,6 +33,8 @@ #include "../Host.h" +#include "thread.h" // for g_hEventOnIdle + namespace PowerPC { // STATE_TO_SAVE @@ -293,6 +295,10 @@ namespace PowerPC //DualCore OnIdle void OnIdleDC(void) { +#if defined(THREAD_VIDEO_WAKEUP_ONIDLE) && defined(_WIN32) + if (g_hEventOnIdle==NULL) PanicAlert("Idle() -> EventOnIdle NULL"); + if (! SetEvent(g_hEventOnIdle) ) { PanicAlert("Idle() -> SetEvent EventOnIdle failed");} +#endif CoreTiming::Idle(); } } diff --git a/Source/Core/VideoCommon/Src/Fifo.cpp b/Source/Core/VideoCommon/Src/Fifo.cpp index 4781a351c1..d6e6cef4b0 100644 --- a/Source/Core/VideoCommon/Src/Fifo.cpp +++ b/Source/Core/VideoCommon/Src/Fifo.cpp @@ -127,20 +127,36 @@ void Video_SendFifoData(u8* _uData) void Fifo_EnterLoop(const SVideoInitialize &video_initialize) { SCPFifoStruct &_fifo = *video_initialize.pCPFifo; +#if defined(THREAD_VIDEO_WAKEUP_ONIDLE) && defined(_WIN32) + HANDLE hEventOnIdle= OpenEventA(EVENT_ALL_ACCESS,FALSE,(LPCSTR)"EventOnIdle"); + if (hEventOnIdle==NULL) PanicAlert("Fifo_EnterLoop() -> EventOnIdle NULL"); +#endif // TODO(ector): Don't peek so often! while (video_initialize.pPeekMessages()) { +#if defined(THREAD_VIDEO_WAKEUP_ONIDLE) && defined(_WIN32) + if (MsgWaitForMultipleObjects(1, &hEventOnIdle, FALSE, 1L, QS_ALLEVENTS) == WAIT_ABANDONED) + break; +#endif if (_fifo.CPReadWriteDistance < 1) //fifo.CPLoWatermark) +#if defined(THREAD_VIDEO_WAKEUP_ONIDLE) && defined(_WIN32) + continue; +#else Common::SleepCurrentThread(1); +#endif //etc... // check if we are able to run this buffer if ((_fifo.bFF_GPReadEnable) && !(_fifo.bFF_BPEnable && _fifo.bFF_Breakpoint)) { - int count = 200; +#if defined(THREAD_VIDEO_WAKEUP_ONIDLE) && defined(_WIN32) + while(_fifo.CPReadWriteDistance > 0) +#else + int count = 200; while(_fifo.CPReadWriteDistance > 0 && count) - { +#endif + { // check if we are on a breakpoint if (_fifo.bFF_BPEnable) { @@ -169,10 +185,15 @@ void Fifo_EnterLoop(const SVideoInitialize &video_initialize) _fifo.CPReadPointer = _fifo.CPBase; //LOG(COMMANDPROCESSOR, "BUFFER LOOP"); } +#ifndef THREAD_VIDEO_WAKEUP_ONIDLE count--; +#endif } } } +#if defined(THREAD_VIDEO_WAKEUP_ONIDLE) && defined(_WIN32) + CloseHandle(hEventOnIdle); +#endif }