Core Stop and Start: Added alternative separate thread timer/loop based waiting, instead of same thread loop waiting. You can try it with the SETUP_TIMER_WAITING option in Setup.h.
git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@2375 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
parent
769160dfbd
commit
927815bc9b
|
@ -49,6 +49,15 @@
|
|||
// Build with playback rerecording options
|
||||
//#define SETUP_AVOID_OPENGL_SCREEN_MESSAGE_HANG
|
||||
|
||||
// Use a timer to wait for threads for stop instead of WaitForEternity()
|
||||
/* I tried that this worked with these options
|
||||
SETUP_FREE_VIDEO_PLUGIN_ON_BOOT
|
||||
SETUP_DONT_FREE_PLUGIN_ON_STOP
|
||||
then the Confirm on Close message box doesn't hang, and we have a controlled Shutdown process
|
||||
without any hanged threads. The downside is a few error messages in the ShutDown() of the
|
||||
OpenGL plugin, so I still need FreeLibrary() to clean it, even with this option. */
|
||||
//#define SETUP_TIMER_WAITING
|
||||
|
||||
// Build with playback rerecording options
|
||||
//#define RERECORDING
|
||||
|
||||
|
|
|
@ -15,7 +15,16 @@
|
|||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "Setup.h"
|
||||
#include "Thread.h"
|
||||
// -----------------------------------------
|
||||
#ifdef SETUP_TIMER_WAITING
|
||||
// -----------------
|
||||
#include <windows.h>
|
||||
#include "ConsoleWindow.h"
|
||||
EventCallBack FunctionPointer[10];
|
||||
#endif
|
||||
// ------------------------
|
||||
|
||||
#define THREAD_DEBUG 1
|
||||
|
||||
|
@ -99,9 +108,18 @@ void Thread::SetCurrentThreadAffinity(int mask)
|
|||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Regular same thread loop based waiting
|
||||
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
|
||||
Event::Event()
|
||||
{
|
||||
m_hEvent = 0;
|
||||
#ifdef SETUP_TIMER_WAITING
|
||||
DoneWaiting = false;
|
||||
StartWait = false;
|
||||
hTimer = NULL;
|
||||
hTimerQueue = NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
void Event::Init()
|
||||
|
@ -115,22 +133,125 @@ void Event::Shutdown()
|
|||
m_hEvent = 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Event::Set()
|
||||
{
|
||||
SetEvent(m_hEvent);
|
||||
}
|
||||
|
||||
|
||||
void Event::Wait()
|
||||
{
|
||||
WaitForSingleObject(m_hEvent, INFINITE);
|
||||
}
|
||||
/////////////////////////////////////
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
/* Separate thread timer based waiting, instead of same thread loop waiting. The downside with this
|
||||
is that it's less convenient to use because we can't stall any threads with a loop. The positive
|
||||
is that we don't cause these incredibly annoying WaitForEternity() hangings. */
|
||||
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
|
||||
#ifdef SETUP_TIMER_WAITING
|
||||
/* I could not figure out how to place this in the class to, CreateTimerQueueTimer() would complain
|
||||
about some kind of type casting, anyone have any ideas about how to do it? */
|
||||
VOID CALLBACK TimerRoutine(PVOID lpParam, BOOLEAN TimerOrWaitFired)
|
||||
{
|
||||
if (lpParam == NULL)
|
||||
{
|
||||
Console::Print("TimerRoutine lpParam is NULL\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
// lpParam points to the argument; in this case it is an int
|
||||
|
||||
//Console::Print("Timer[%i] will call back\n", *(int*)lpParam);
|
||||
}
|
||||
|
||||
// Call back
|
||||
int Id = *(int*)lpParam;
|
||||
if (FunctionPointer[Id]) FunctionPointer[Id]();
|
||||
}
|
||||
|
||||
// Create a timer that will call back to the calling function
|
||||
bool Event::TimerWait(EventCallBack WaitCB, int _Id, bool OptCondition)
|
||||
{
|
||||
Id = _Id;
|
||||
|
||||
//Console::Print("TimerWait[%i]: %i %i %i\n", Id, StartWait, DoneWaiting, OptCondition);
|
||||
|
||||
FunctionPointer[Id] = WaitCB;
|
||||
|
||||
// This means we are done waiting, so we wont call back again, and we also reset the variables for this Event
|
||||
if (DoneWaiting && OptCondition)
|
||||
{
|
||||
StartWait = false;
|
||||
DoneWaiting = false;
|
||||
FunctionPointer[Id] = NULL;
|
||||
|
||||
// Delete all timers in the timer queue.
|
||||
if (!DeleteTimerQueue(hTimerQueue))
|
||||
Console::Print("DeleteTimerQueue failed (%d)\n", GetLastError());
|
||||
|
||||
hTimer = NULL;
|
||||
hTimerQueue = NULL;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Else start a new callback timer
|
||||
StartWait = true;
|
||||
|
||||
// Create the timer queue if needed
|
||||
if (!hTimerQueue)
|
||||
{
|
||||
hTimerQueue = CreateTimerQueue();
|
||||
if (NULL == hTimerQueue)
|
||||
{
|
||||
Console::Print("CreateTimerQueue failed (%d)\n", GetLastError());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Set a timer to call the timer routine in 10 seconds.
|
||||
if (!CreateTimerQueueTimer( &hTimer, hTimerQueue,
|
||||
(WAITORTIMERCALLBACK)TimerRoutine, &Id , 10, 0, 0))
|
||||
{
|
||||
Console::Print("CreateTimerQueueTimer failed (%d)\n", GetLastError());
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
// Check if we are done or not
|
||||
bool Event::DoneWait()
|
||||
{
|
||||
if (StartWait && DoneWaiting)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
// Tells the timer that we are done waiting
|
||||
void Event::SetTimer()
|
||||
{
|
||||
// We can not be done before we have started waiting
|
||||
if (StartWait) DoneWaiting = true;
|
||||
}
|
||||
#endif
|
||||
////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Supporting functions
|
||||
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
|
||||
|
||||
void SleepCurrentThread(int ms)
|
||||
{
|
||||
Sleep(ms);
|
||||
}
|
||||
|
||||
|
||||
typedef struct tagTHREADNAME_INFO
|
||||
{
|
||||
DWORD dwType; // must be 0x1000
|
||||
|
@ -188,6 +309,8 @@ LONG SyncInterlockedExchange(LONG *Dest, LONG Val)
|
|||
{
|
||||
return InterlockedExchange(Dest, Val);
|
||||
}
|
||||
////////////////////////////////////////
|
||||
|
||||
|
||||
#else // !WIN32, so must be POSIX threads
|
||||
|
||||
|
|
|
@ -33,6 +33,15 @@
|
|||
|
||||
#include "Common.h"
|
||||
|
||||
|
||||
// -----------------------------------------
|
||||
#ifdef SETUP_TIMER_WAITING
|
||||
// -----------------
|
||||
typedef void (*EventCallBack)(void);
|
||||
#endif
|
||||
// ----------------------
|
||||
|
||||
|
||||
namespace Common
|
||||
{
|
||||
class CriticalSection
|
||||
|
@ -78,6 +87,7 @@ private:
|
|||
};
|
||||
|
||||
|
||||
|
||||
class Event
|
||||
{
|
||||
public:
|
||||
|
@ -89,6 +99,20 @@ public:
|
|||
void Set();
|
||||
void Wait();
|
||||
|
||||
// -----------------------------------------
|
||||
#ifdef SETUP_TIMER_WAITING
|
||||
// -----------------
|
||||
bool TimerWait(EventCallBack WaitCB, int Id = 0, bool OptCondition = true);
|
||||
bool DoneWait();
|
||||
void SetTimer();
|
||||
bool DoneWaiting;
|
||||
bool StartWait;
|
||||
int Id;
|
||||
HANDLE hTimer;
|
||||
HANDLE hTimerQueue;
|
||||
#endif
|
||||
// ---------------------------
|
||||
|
||||
private:
|
||||
#ifdef _WIN32
|
||||
HANDLE m_hEvent;
|
||||
|
|
|
@ -24,8 +24,8 @@
|
|||
#else
|
||||
#endif
|
||||
|
||||
#include "Thread.h" // Common
|
||||
#include "Setup.h"
|
||||
#include "Setup.h" // Common
|
||||
#include "Thread.h"
|
||||
#include "Timer.h"
|
||||
#include "Common.h"
|
||||
#include "ConsoleWindow.h"
|
||||
|
@ -110,6 +110,19 @@ SCoreStartupParameter g_CoreStartupParameter;
|
|||
// This event is set when the emuthread starts.
|
||||
Common::Event emuThreadGoing;
|
||||
Common::Event cpuRunloopQuit;
|
||||
|
||||
// -----------------------------------------
|
||||
#ifdef SETUP_TIMER_WAITING
|
||||
// -----------------
|
||||
bool VideoThreadRunning = false;
|
||||
bool StopUpToVideoDone = false;
|
||||
bool EmuThreadReachedEnd = false;
|
||||
bool StopReachedEnd = false;
|
||||
static Common::Event VideoThreadEvent;
|
||||
static Common::Event VideoThreadEvent2;
|
||||
void EmuThreadEnd();
|
||||
#endif
|
||||
// ---------------------------
|
||||
//////////////////////////////////////
|
||||
|
||||
|
||||
|
@ -162,9 +175,24 @@ void ReconnectPad()
|
|||
void ReconnectWiimote()
|
||||
{
|
||||
// This seems to be a hack that just sets some IPC registers to zero. Dubious.
|
||||
/* JP: Yes, it's basically nothing right now, I could not figure out how to reset the Wiimote
|
||||
for reconnection */
|
||||
HW::InitWiimote();
|
||||
Console::Print("ReconnectWiimote()\n");
|
||||
}
|
||||
|
||||
// -----------------------------------------
|
||||
#ifdef SETUP_TIMER_WAITING
|
||||
// -----------------
|
||||
void VideoThreadEnd()
|
||||
{
|
||||
VideoThreadRunning = false;
|
||||
VideoThreadEvent.SetTimer();
|
||||
VideoThreadEvent2.SetTimer();
|
||||
//Console::Print("VideoThreadEnd\n");
|
||||
}
|
||||
#endif
|
||||
// ---------------------------
|
||||
/////////////////////////////////////
|
||||
|
||||
|
||||
|
@ -201,6 +229,9 @@ bool Init()
|
|||
g_EmuThread = new Common::Thread(EmuThread, NULL);
|
||||
emuThreadGoing.Wait();
|
||||
emuThreadGoing.Shutdown();
|
||||
#ifdef SETUP_TIMER_WAITING
|
||||
VideoThreadRunning = true;
|
||||
#endif
|
||||
|
||||
// All right, the event is set and killed. We are now running.
|
||||
Host_SetWaitCursor(false);
|
||||
|
@ -208,17 +239,29 @@ bool Init()
|
|||
}
|
||||
|
||||
// Called from GUI thread or VI thread (why VI??? That must be bad. Window close? TODO: Investigate.)
|
||||
void Stop() // - Hammertime!
|
||||
// JP: No, when you press Stop this is run from the Main Thread it seems
|
||||
// - Hammertime!
|
||||
void Stop()
|
||||
{
|
||||
const SCoreStartupParameter& _CoreParameter = SConfig::GetInstance().m_LocalCoreStartupParameter;
|
||||
|
||||
#ifdef SETUP_TIMER_WAITING
|
||||
if (!StopUpToVideoDone)
|
||||
{
|
||||
Console::Print("--------------------------------------------------------------\n");
|
||||
Console::Print("Stop [Main Thread]: Shutting down...\n");
|
||||
// Reset variables
|
||||
StopReachedEnd = false;
|
||||
EmuThreadReachedEnd = false;
|
||||
#endif
|
||||
|
||||
Host_SetWaitCursor(true);
|
||||
if (PowerPC::GetState() == PowerPC::CPU_POWERDOWN)
|
||||
return;
|
||||
|
||||
// stop the CPU
|
||||
// Stop the CPU
|
||||
PowerPC::Stop();
|
||||
CCPU::StepOpcode(); //kick it if it's waiting
|
||||
CCPU::StepOpcode(); // Kick it if it's waiting
|
||||
|
||||
cpuRunloopQuit.Wait();
|
||||
cpuRunloopQuit.Shutdown();
|
||||
|
@ -229,10 +272,22 @@ void Stop() // - Hammertime!
|
|||
|
||||
// If dual core mode, the CPU thread should immediately exit here.
|
||||
|
||||
Console::Print("Stop [Main Thread]: Wait for Video Loop...\n");
|
||||
|
||||
// Should be moved inside the plugin.
|
||||
if (_CoreParameter.bUseDualCore)
|
||||
CPluginManager::GetInstance().GetVideo()->Video_ExitLoop();
|
||||
|
||||
#ifdef SETUP_TIMER_WAITING
|
||||
StopUpToVideoDone = true;
|
||||
}
|
||||
// Call this back
|
||||
//if (!VideoThreadEvent.TimerWait(Stop, 1, EmuThreadReachedEnd) || !EmuThreadReachedEnd) return;
|
||||
if (!VideoThreadEvent.TimerWait(Stop, 1)) return;
|
||||
|
||||
//Console::Print("Stop() will continue\n");
|
||||
#endif
|
||||
|
||||
/* Video_EnterLoop() should now exit so that EmuThread() will continue concurrently with the rest
|
||||
of the commands in this function */
|
||||
|
||||
|
@ -240,24 +295,37 @@ void Stop() // - Hammertime!
|
|||
And since we have no while(GetMessage()) loop we can't wait for this to happen, or say exactly when
|
||||
the loop has ended */
|
||||
#ifdef _WIN32
|
||||
PostMessage((HWND)g_pWindowHandle, WM_QUIT, 0, 0);
|
||||
//PostMessage((HWND)g_pWindowHandle, WM_QUIT, 0, 0);
|
||||
#endif
|
||||
|
||||
// Close the trace file
|
||||
Core::StopTrace();
|
||||
#ifndef SETUP_TIMER_WAITING // This hangs
|
||||
LogManager::Shutdown();
|
||||
#endif
|
||||
// Update mouse pointer
|
||||
Host_SetWaitCursor(false);
|
||||
#ifdef SETUP_AVOID_CHILD_WINDOW_RENDERING_HANG
|
||||
/* This may hang when we are rendering to a child window, but currently it doesn't, at least
|
||||
not on my system, but I'll leave this option for a while anyway */
|
||||
if (GetParent((HWND)g_pWindowHandle) == NULL)
|
||||
#endif
|
||||
#ifndef SETUP_TIMER_WAITING // This is moved
|
||||
delete g_EmuThread; // Wait for emuthread to close.
|
||||
g_EmuThread = 0;
|
||||
#endif
|
||||
#ifdef SETUP_TIMER_WAITING
|
||||
Host_UpdateGUI();
|
||||
StopUpToVideoDone = false;
|
||||
StopReachedEnd = true;
|
||||
//Console::Print("Stop() reached the end\n");
|
||||
if (EmuThreadReachedEnd) Console::Print("--------------------------------------------------------------\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Create the CPU thread
|
||||
// Create the CPU thread. For use with Single Core mode only.
|
||||
// ---------------
|
||||
THREAD_RETURN CpuThread(void *pArg)
|
||||
{
|
||||
|
@ -465,6 +533,34 @@ THREAD_RETURN EmuThread(void *pArg)
|
|||
// I bet that many of our stopping problems come from this loop not properly exiting.
|
||||
Plugins.GetVideo()->Video_EnterLoop();
|
||||
}
|
||||
#ifdef SETUP_TIMER_WAITING
|
||||
|
||||
VideoThreadEvent2.TimerWait(EmuThreadEnd, 2);
|
||||
//Console::Print("Video loop [Video Thread]: Stopped\n");
|
||||
return 0;
|
||||
}
|
||||
void EmuThreadEnd()
|
||||
{
|
||||
CPluginManager &Plugins = CPluginManager::GetInstance();
|
||||
const SCoreStartupParameter& _CoreParameter = SConfig::GetInstance().m_LocalCoreStartupParameter;
|
||||
|
||||
//Console::Print("Video loop [Video Thread]: EmuThreadEnd [StopEnd:%i]\n", StopReachedEnd);
|
||||
|
||||
//if (!VideoThreadEvent2.TimerWait(EmuThreadEnd, 2)) return;
|
||||
if (!VideoThreadEvent2.TimerWait(EmuThreadEnd, 2, StopReachedEnd) || !StopReachedEnd)
|
||||
{
|
||||
Console::Print("Stop [Video Thread]: Waiting for Stop() and Video Loop to end...\n");
|
||||
return;
|
||||
}
|
||||
|
||||
//Console::Print("EmuThreadEnd() will continue\n");
|
||||
|
||||
/* There will be a few problems with the OpenGL ShutDown() after this, for example the "Release
|
||||
Device Context Failed" error message */
|
||||
#endif
|
||||
|
||||
Console::Print("Stop [Video Thread]: Stop() and Video Loop Ended\n");
|
||||
Console::Print("Stop [Video Thread]: Shutting down HW and Plugins\n");
|
||||
|
||||
// We have now exited the Video Loop and will shut down
|
||||
|
||||
|
@ -484,6 +580,7 @@ THREAD_RETURN EmuThread(void *pArg)
|
|||
if (g_pUpdateFPSDisplay != NULL)
|
||||
g_pUpdateFPSDisplay("Stopping...");
|
||||
|
||||
#ifndef SETUP_TIMER_WAITING
|
||||
if (cpuThread)
|
||||
{
|
||||
// There is a CPU thread - join it.
|
||||
|
@ -491,6 +588,7 @@ THREAD_RETURN EmuThread(void *pArg)
|
|||
// Returns after game exited
|
||||
cpuThread = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
// The hardware is uninitialized
|
||||
g_bHwInit = false;
|
||||
|
@ -503,8 +601,18 @@ THREAD_RETURN EmuThread(void *pArg)
|
|||
// so we can restart the plugins (or load new ones) for the next game.
|
||||
if (_CoreParameter.hMainWindow == g_pWindowHandle)
|
||||
Host_UpdateMainFrame();
|
||||
|
||||
#ifdef SETUP_TIMER_WAITING
|
||||
EmuThreadReachedEnd = true;
|
||||
//Console::Print("EmuThread() reached the end\n");
|
||||
Host_UpdateGUI();
|
||||
Console::Print("Stop [Video Thread]: Done\n");
|
||||
if (StopReachedEnd) Console::Print("--------------------------------------------------------------\n");
|
||||
delete g_EmuThread; // Wait for emuthread to close.
|
||||
g_EmuThread = 0;
|
||||
#endif
|
||||
#ifndef SETUP_TIMER_WAITING
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -73,7 +73,17 @@ namespace Core
|
|||
void SetBlockStart(u32 addr);
|
||||
void StopTrace();
|
||||
|
||||
// -----------------------------------------
|
||||
#ifdef SETUP_TIMER_WAITING
|
||||
// -----------------
|
||||
// Thread shutdown
|
||||
void VideoThreadEnd();
|
||||
#endif
|
||||
// ---------------------------
|
||||
|
||||
// -----------------------------------------
|
||||
#ifdef RERECORDING
|
||||
// -----------------
|
||||
void FrameUpdate();
|
||||
void FrameAdvance();
|
||||
void FrameStepOnOff();
|
||||
|
@ -84,6 +94,7 @@ namespace Core
|
|||
extern int g_FrameCounter;
|
||||
extern bool g_FrameStep;
|
||||
#endif
|
||||
// ---------------------------
|
||||
|
||||
} // namespace
|
||||
|
||||
|
|
|
@ -47,6 +47,9 @@ void Host_SetDebugMode(bool enable);
|
|||
void Host_SetWaitCursor(bool enable);
|
||||
|
||||
void Host_UpdateStatusBar(const char* _pText, int Filed = 0);
|
||||
#ifdef SETUP_TIMER_WAITING
|
||||
void Host_UpdateGUI();
|
||||
#endif
|
||||
|
||||
void Host_SysMessage(const char *fmt, ...);
|
||||
void Host_SetWiiMoteConnectionState(int _State);
|
||||
|
|
|
@ -194,15 +194,29 @@ int abc = 0;
|
|||
Core::ReconnectWiimote();
|
||||
return 0;
|
||||
|
||||
// -----------------------------------------
|
||||
#ifdef RERECORDING
|
||||
// -----------------
|
||||
case INPUT_FRAME_COUNTER:
|
||||
// Wind back the frame counter after a save state has been loaded
|
||||
Core::WindBack((int)lParam);
|
||||
return 0;
|
||||
#endif
|
||||
// -----------------------------
|
||||
|
||||
// -----------------------------------------
|
||||
#ifdef SETUP_TIMER_WAITING
|
||||
// -----------------
|
||||
case OPENGL_VIDEO_STOP:
|
||||
// The Video thread has been shut down
|
||||
Core::VideoThreadEnd();
|
||||
//Console::Print("OPENGL_VIDEO_STOP\n");
|
||||
return 0;
|
||||
#endif
|
||||
// -----------------------------
|
||||
}
|
||||
break;
|
||||
|
||||
//default:
|
||||
// return wxPanel::MSWWindowProc(nMsg, wParam, lParam);
|
||||
}
|
||||
|
|
|
@ -71,6 +71,7 @@ class CFrame : public wxFrame
|
|||
void InitBitmaps();
|
||||
void DoStop();
|
||||
bool bRenderToMain;
|
||||
void UpdateGUI();
|
||||
|
||||
// ---------------------------------------
|
||||
// Wiimote leds
|
||||
|
@ -220,7 +221,6 @@ class CFrame : public wxFrame
|
|||
wxMenuItem* m_pMenuItemSave;
|
||||
wxToolBarToolBase* m_pToolPlay;
|
||||
|
||||
void UpdateGUI();
|
||||
void BootGame();
|
||||
|
||||
// Double click and mouse move options
|
||||
|
|
|
@ -31,16 +31,17 @@
|
|||
#include <sys/param.h>
|
||||
#endif
|
||||
|
||||
#include "Globals.h" // Core
|
||||
#include "Host.h"
|
||||
|
||||
#include "Common.h" // Common
|
||||
#include "CPUDetect.h"
|
||||
#include "IniFile.h"
|
||||
#include "FileUtil.h"
|
||||
#include "ConsoleWindow.h"
|
||||
#include "Setup.h"
|
||||
|
||||
#include "Main.h" // Local
|
||||
#include "Host.h" // Core
|
||||
|
||||
#include "Globals.h" // Local
|
||||
#include "Main.h"
|
||||
#include "Frame.h"
|
||||
#include "ConfigManager.h"
|
||||
#include "CodeWindow.h"
|
||||
|
@ -458,6 +459,13 @@ void Host_UpdateStatusBar(const char* _pText, int Field)
|
|||
wxPostEvent(main_frame, event);
|
||||
}
|
||||
|
||||
#ifdef SETUP_TIMER_WAITING
|
||||
void Host_UpdateGUI()
|
||||
{
|
||||
main_frame->UpdateGUI();
|
||||
}
|
||||
#endif
|
||||
|
||||
void Host_SysMessage(const char *fmt, ...)
|
||||
{
|
||||
va_list list;
|
||||
|
|
|
@ -17,10 +17,14 @@
|
|||
|
||||
#include <string.h>
|
||||
|
||||
#include "Setup.h"
|
||||
#ifdef SETUP_TIMER_WAITING
|
||||
#include "../../../Plugins/Plugin_VideoOGL/Src/OS/Win32.h"
|
||||
#endif
|
||||
#include "MemoryUtil.h"
|
||||
#include "Thread.h"
|
||||
#include "OpcodeDecoding.h"
|
||||
#include "Setup.h"
|
||||
#include "ConsoleWindow.h"
|
||||
|
||||
#include "Fifo.h"
|
||||
|
||||
|
@ -96,8 +100,18 @@ void Video_SendFifoData(u8* _uData, u32 len)
|
|||
void Fifo_ExitLoop()
|
||||
{
|
||||
fifoStateRun = false;
|
||||
#ifndef SETUP_TIMER_WAITING
|
||||
fifo_exit_event.Wait();
|
||||
fifo_exit_event.Shutdown();
|
||||
#else
|
||||
//Console::Print("Video: Fifo_ExitLoop: Done:%i\n", fifo_exit_event.DoneWait());
|
||||
if (fifo_exit_event.TimerWait(Fifo_ExitLoop))
|
||||
{
|
||||
//Console::Print("Video: Fifo_Shutdown: Done:%i\n\n", fifo_exit_event.DoneWait());
|
||||
fifo_exit_event.Shutdown();
|
||||
PostMessage(EmuWindow::GetParentWnd(), WM_USER, OPENGL_VIDEO_STOP, 0);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void Fifo_EnterLoop(const SVideoInitialize &video_initialize)
|
||||
|
@ -111,6 +125,7 @@ void Fifo_EnterLoop(const SVideoInitialize &video_initialize)
|
|||
#if defined(_WIN32) && !defined(SETUP_AVOID_OPENGL_SCREEN_MESSAGE_HANG)
|
||||
video_initialize.pPeekMessages();
|
||||
#endif
|
||||
|
||||
if (_fifo.CPReadWriteDistance == 0)
|
||||
Common::SleepCurrentThread(1);
|
||||
|
||||
|
@ -187,4 +202,7 @@ void Fifo_EnterLoop(const SVideoInitialize &video_initialize)
|
|||
}
|
||||
}
|
||||
fifo_exit_event.Set();
|
||||
#ifdef SETUP_TIMER_WAITING
|
||||
fifo_exit_event.SetTimer();
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -28,7 +28,8 @@ enum PLUGIN_COMM
|
|||
OPENGL_WM_USER_CREATE,
|
||||
NJOY_RELOAD, // Reload nJoy if DirectInput has failed
|
||||
WIIMOTE_RECONNECT, // Reconnect the Wiimote if it has disconnected
|
||||
INPUT_FRAME_COUNTER // Wind back the frame counter for rerecording
|
||||
INPUT_FRAME_COUNTER, // Wind back the frame counter for rerecording
|
||||
OPENGL_VIDEO_STOP
|
||||
};
|
||||
///////////////////////////////
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "Config.h"
|
||||
#include "IniFile.h"
|
||||
#include "svnrev.h"
|
||||
#include "Setup.h"
|
||||
|
||||
#include "Render.h"
|
||||
|
||||
|
@ -770,7 +771,9 @@ void OpenGL_Shutdown()
|
|||
|
||||
if (hDC && !ReleaseDC(EmuWindow::GetWnd(), hDC)) // Are We Able To Release The DC
|
||||
{
|
||||
#ifndef SETUP_TIMER_WAITING // This fails
|
||||
MessageBox(NULL,"Release Device Context Failed.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION);
|
||||
#endif
|
||||
hDC = NULL; // Set DC To NULL
|
||||
}
|
||||
#elif defined(HAVE_X11) && HAVE_X11
|
||||
|
|
|
@ -148,6 +148,11 @@ HWND GetParentWnd()
|
|||
return m_hParent;
|
||||
}
|
||||
|
||||
HWND GetChildParentWnd()
|
||||
{
|
||||
return m_hMain;
|
||||
}
|
||||
|
||||
LRESULT CALLBACK WndProc( HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam )
|
||||
{
|
||||
HDC hdc;
|
||||
|
|
|
@ -25,6 +25,7 @@ namespace EmuWindow
|
|||
|
||||
HWND GetWnd();
|
||||
HWND GetParentWnd();
|
||||
HWND GetChildParentWnd();
|
||||
HWND Create(HWND hParent, HINSTANCE hInstance, const TCHAR *title);
|
||||
void Show();
|
||||
void Close();
|
||||
|
|
|
@ -299,7 +299,9 @@ void Video_Prepare(void)
|
|||
void Shutdown(void)
|
||||
{
|
||||
Fifo_Shutdown();
|
||||
#ifndef SETUP_TIMER_WAITING // This is not compatible, it crashes after the second Stop
|
||||
TextureConverter::Shutdown();
|
||||
#endif
|
||||
VertexLoaderManager::Shutdown();
|
||||
VertexShaderCache::Shutdown();
|
||||
VertexShaderManager::Shutdown();
|
||||
|
@ -308,8 +310,14 @@ void Shutdown(void)
|
|||
VertexManager::Shutdown();
|
||||
TextureMngr::Shutdown();
|
||||
OpcodeDecoder_Shutdown();
|
||||
#ifndef SETUP_TIMER_WAITING // This is not compatible, it may crashes after a Stop
|
||||
Renderer::Shutdown();
|
||||
#endif
|
||||
OpenGL_Shutdown();
|
||||
#ifdef SETUP_TIMER_WAITING
|
||||
// Do we ever destroy the window?
|
||||
EmuWindow::Close();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue