From 927815bc9b8ed86f3e8d56c8ae8707f21684fc5e Mon Sep 17 00:00:00 2001 From: John Peterson Date: Sun, 22 Feb 2009 21:16:12 +0000 Subject: [PATCH] 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 --- Source/Core/Common/Src/Setup.h | 9 ++ Source/Core/Common/Src/Thread.cpp | 125 ++++++++++++++++- Source/Core/Common/Src/Thread.h | 24 ++++ Source/Core/Core/Src/Core.cpp | 130 ++++++++++++++++-- Source/Core/Core/Src/Core.h | 13 +- Source/Core/Core/Src/Host.h | 3 + Source/Core/DolphinWX/Src/Frame.cpp | 22 ++- Source/Core/DolphinWX/Src/Frame.h | 2 +- Source/Core/DolphinWX/Src/Main.cpp | 16 ++- Source/Core/VideoCommon/Src/Fifo.cpp | 24 +++- Source/PluginSpecs/PluginSpecs.h | 3 +- Source/Plugins/Plugin_VideoOGL/Src/GLUtil.cpp | 5 +- .../Plugins/Plugin_VideoOGL/Src/Globals.cpp | 4 +- .../Plugins/Plugin_VideoOGL/Src/OS/Win32.cpp | 5 + Source/Plugins/Plugin_VideoOGL/Src/OS/Win32.h | 1 + Source/Plugins/Plugin_VideoOGL/Src/main.cpp | 12 +- 16 files changed, 367 insertions(+), 31 deletions(-) diff --git a/Source/Core/Common/Src/Setup.h b/Source/Core/Common/Src/Setup.h index 865ef746a9..d13d0e2dbf 100644 --- a/Source/Core/Common/Src/Setup.h +++ b/Source/Core/Common/Src/Setup.h @@ -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 diff --git a/Source/Core/Common/Src/Thread.cpp b/Source/Core/Common/Src/Thread.cpp index efc4815cb2..a5c4e53cc6 100644 --- a/Source/Core/Common/Src/Thread.cpp +++ b/Source/Core/Common/Src/Thread.cpp @@ -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 + #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 diff --git a/Source/Core/Common/Src/Thread.h b/Source/Core/Common/Src/Thread.h index 0aaf5023ae..1787b9cc53 100644 --- a/Source/Core/Common/Src/Thread.h +++ b/Source/Core/Common/Src/Thread.h @@ -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; diff --git a/Source/Core/Core/Src/Core.cpp b/Source/Core/Core/Src/Core.cpp index 694d30951c..7727852af9 100644 --- a/Source/Core/Core/Src/Core.cpp +++ b/Source/Core/Core/Src/Core.cpp @@ -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,7 +533,35 @@ 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 // does this comment still apply? @@ -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,10 +588,11 @@ THREAD_RETURN EmuThread(void *pArg) // Returns after game exited cpuThread = NULL; } +#endif // The hardware is uninitialized g_bHwInit = false; - + HW::Shutdown(); Plugins.ShutdownPlugins(); @@ -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 } diff --git a/Source/Core/Core/Src/Core.h b/Source/Core/Core/Src/Core.h index 2403b3c6f4..4d77746815 100644 --- a/Source/Core/Core/Src/Core.h +++ b/Source/Core/Core/Src/Core.h @@ -61,7 +61,7 @@ namespace Core bool GetRealWiimote(); void ReconnectWiimote(); void ReconnectPad(); - + extern bool bReadTrace; extern bool bWriteTrace; @@ -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 diff --git a/Source/Core/Core/Src/Host.h b/Source/Core/Core/Src/Host.h index 2fc9933236..677f85c31b 100644 --- a/Source/Core/Core/Src/Host.h +++ b/Source/Core/Core/Src/Host.h @@ -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); diff --git a/Source/Core/DolphinWX/Src/Frame.cpp b/Source/Core/DolphinWX/Src/Frame.cpp index 2b91717759..f171d0d0f3 100644 --- a/Source/Core/DolphinWX/Src/Frame.cpp +++ b/Source/Core/DolphinWX/Src/Frame.cpp @@ -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; + // ----------------- + 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); } diff --git a/Source/Core/DolphinWX/Src/Frame.h b/Source/Core/DolphinWX/Src/Frame.h index 8cbec8e048..588ea699be 100644 --- a/Source/Core/DolphinWX/Src/Frame.h +++ b/Source/Core/DolphinWX/Src/Frame.h @@ -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 diff --git a/Source/Core/DolphinWX/Src/Main.cpp b/Source/Core/DolphinWX/Src/Main.cpp index 18eecec035..73c487a55e 100644 --- a/Source/Core/DolphinWX/Src/Main.cpp +++ b/Source/Core/DolphinWX/Src/Main.cpp @@ -31,16 +31,17 @@ #include #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; diff --git a/Source/Core/VideoCommon/Src/Fifo.cpp b/Source/Core/VideoCommon/Src/Fifo.cpp index 8c2940f9af..168d893cdd 100644 --- a/Source/Core/VideoCommon/Src/Fifo.cpp +++ b/Source/Core/VideoCommon/Src/Fifo.cpp @@ -17,10 +17,14 @@ #include +#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; - fifo_exit_event.Wait(); - fifo_exit_event.Shutdown(); + #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 } diff --git a/Source/PluginSpecs/PluginSpecs.h b/Source/PluginSpecs/PluginSpecs.h index 40e1ba8218..d5743d4895 100644 --- a/Source/PluginSpecs/PluginSpecs.h +++ b/Source/PluginSpecs/PluginSpecs.h @@ -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 }; /////////////////////////////// diff --git a/Source/Plugins/Plugin_VideoOGL/Src/GLUtil.cpp b/Source/Plugins/Plugin_VideoOGL/Src/GLUtil.cpp index 9c36207bf2..da11accbe1 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/GLUtil.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/GLUtil.cpp @@ -19,6 +19,7 @@ #include "Config.h" #include "IniFile.h" #include "svnrev.h" +#include "Setup.h" #include "Render.h" @@ -768,9 +769,11 @@ void OpenGL_Shutdown() hRC = NULL; // Set RC To NULL } - if (hDC && !ReleaseDC(EmuWindow::GetWnd(),hDC)) // Are We Able To Release The DC + 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 diff --git a/Source/Plugins/Plugin_VideoOGL/Src/Globals.cpp b/Source/Plugins/Plugin_VideoOGL/Src/Globals.cpp index ac4387c3ae..b2546885a4 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/Globals.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/Globals.cpp @@ -83,7 +83,7 @@ void __Log(const char *fmt, ...) if (pfLog != NULL && LocalLogFile) fwrite(Msg, strlen(Msg), 1, pfLog); - Console::Print(Msg); + Console::Print(Msg); } @@ -100,7 +100,7 @@ void __Log(int type, const char *fmt, ...) va_end(ap); g_VideoInitialize.pLog(Msg, FALSE); - Console::Print(Msg); + Console::Print(Msg); } #endif diff --git a/Source/Plugins/Plugin_VideoOGL/Src/OS/Win32.cpp b/Source/Plugins/Plugin_VideoOGL/Src/OS/Win32.cpp index f603f2b935..82dfc241b1 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/OS/Win32.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/OS/Win32.cpp @@ -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; diff --git a/Source/Plugins/Plugin_VideoOGL/Src/OS/Win32.h b/Source/Plugins/Plugin_VideoOGL/Src/OS/Win32.h index 727be1893c..f31a02b00a 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/OS/Win32.h +++ b/Source/Plugins/Plugin_VideoOGL/Src/OS/Win32.h @@ -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(); diff --git a/Source/Plugins/Plugin_VideoOGL/Src/main.cpp b/Source/Plugins/Plugin_VideoOGL/Src/main.cpp index c253c60bcc..b2adb237a9 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/main.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/main.cpp @@ -299,7 +299,9 @@ void Video_Prepare(void) void Shutdown(void) { Fifo_Shutdown(); - TextureConverter::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(); - Renderer::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 }