diff --git a/Ryujinx/Ui/GLRenderer.cs b/Ryujinx/Ui/GLRenderer.cs index cc330336b2..25247b6c3e 100644 --- a/Ryujinx/Ui/GLRenderer.cs +++ b/Ryujinx/Ui/GLRenderer.cs @@ -3,6 +3,7 @@ using OpenTK; using OpenTK.Graphics; using OpenTK.Graphics.OpenGL; using OpenTK.Input; +using OpenTK.Platform; using Ryujinx.Configuration; using Ryujinx.Graphics.OpenGL; using Ryujinx.HLE; @@ -88,7 +89,9 @@ namespace Ryujinx.Ui private void GLRenderer_Initialized(object sender, EventArgs e) { + // Release the GL exclusivity that OpenTK gave us. GraphicsContext.MakeCurrent(null); + WaitEvent.Set(); } @@ -168,11 +171,19 @@ namespace Ryujinx.Ui public void Exit() { - _device.DisposeGpu(); + if (IsStopped) + { + return; + } IsStopped = true; IsActive = false; + using (ScopedGLContext scopedGLContext = new ScopedGLContext(WindowInfo, GraphicsContext)) + { + _device.DisposeGpu(); + } + WaitEvent.Set(); } @@ -188,8 +199,10 @@ namespace Ryujinx.Ui public void Render() { - GraphicsContext.MakeCurrent(WindowInfo); - _renderer.Initialize(); + using (ScopedGLContext scopedGLContext = new ScopedGLContext(WindowInfo, GraphicsContext)) + { + _renderer.Initialize(); + } while (IsActive) { @@ -198,44 +211,45 @@ namespace Ryujinx.Ui return; } - GraphicsContext.MakeCurrent(WindowInfo); - - GL.ClearColor(Color4.Black); - - _ticks += _chrono.ElapsedTicks; - - _chrono.Restart(); - - if (_device.WaitFifo()) + using (ScopedGLContext scopedGLContext = new ScopedGLContext(WindowInfo, GraphicsContext)) { - _device.ProcessFrame(); - } + GL.ClearColor(Color4.Black); - if (_ticks >= _ticksPerFrame) - { - _device.PresentFrame(SwapBuffers); + _ticks += _chrono.ElapsedTicks; - _device.Statistics.RecordSystemFrameTime(); + _chrono.Restart(); - double hostFps = _device.Statistics.GetSystemFrameRate(); - double gameFps = _device.Statistics.GetGameFrameRate(); + if (_device.WaitFifo()) + { + _device.ProcessFrame(); + } - string titleNameSection = string.IsNullOrWhiteSpace(_device.System.TitleName) ? string.Empty - : " | " + _device.System.TitleName; + if (_ticks >= _ticksPerFrame) + { + _device.PresentFrame(SwapBuffers); - string titleIdSection = string.IsNullOrWhiteSpace(_device.System.TitleIdText) ? string.Empty - : " | " + _device.System.TitleIdText.ToUpper(); + _device.Statistics.RecordSystemFrameTime(); - _newTitle = $"Ryujinx{titleNameSection}{titleIdSection} | Host FPS: {hostFps:0.0} | Game FPS: {gameFps:0.0} | " + - $"Game Vsync: {(_device.EnableDeviceVsync ? "On" : "Off")}"; + double hostFps = _device.Statistics.GetSystemFrameRate(); + double gameFps = _device.Statistics.GetGameFrameRate(); - _titleEvent = true; + string titleNameSection = string.IsNullOrWhiteSpace(_device.System.TitleName) ? string.Empty + : " | " + _device.System.TitleName; - _device.System.SignalVsync(); + string titleIdSection = string.IsNullOrWhiteSpace(_device.System.TitleIdText) ? string.Empty + : " | " + _device.System.TitleIdText.ToUpper(); - _device.VsyncEvent.Set(); + _newTitle = $"Ryujinx{titleNameSection}{titleIdSection} | Host FPS: {hostFps:0.0} | Game FPS: {gameFps:0.0} | " + + $"Game Vsync: {(_device.EnableDeviceVsync ? "On" : "Off")}"; - _ticks = Math.Min(_ticks - _ticksPerFrame, _ticksPerFrame); + _titleEvent = true; + + _device.System.SignalVsync(); + + _device.VsyncEvent.Set(); + + _ticks = Math.Min(_ticks - _ticksPerFrame, _ticksPerFrame); + } } } } @@ -245,7 +259,6 @@ namespace Ryujinx.Ui OpenTK.Graphics.GraphicsContext.CurrentContext.SwapBuffers(); } - public void MainLoop() { while (IsActive) diff --git a/Ryujinx/Ui/MainWindow.cs b/Ryujinx/Ui/MainWindow.cs index dcf7673f3d..2af7a56b09 100644 --- a/Ryujinx/Ui/MainWindow.cs +++ b/Ryujinx/Ui/MainWindow.cs @@ -433,14 +433,15 @@ namespace Ryujinx.Ui DiscordIntegrationModule.SwitchToMainMenu(); - _screenExitStatus.Set(); - Application.Invoke(delegate { _stopEmulation.Sensitive = false; _firmwareInstallFile.Sensitive = true; _firmwareInstallDirectory.Sensitive = true; + }); + + _screenExitStatus.Set(); } private static void UpdateGameMetadata(string titleId) @@ -475,7 +476,11 @@ namespace Ryujinx.Ui { UpdateGameMetadata(device.System.TitleIdText); - _gLWigdet?.Exit(); + if (_gLWigdet != null) + { + _gLWigdet.Exit(); + _screenExitStatus.WaitOne(); + } } Dispose(); @@ -627,15 +632,11 @@ namespace Ryujinx.Ui private void Exit_Pressed(object sender, EventArgs args) { - _gLWigdet?.Exit(); - End(_emulationContext); } private void Window_Close(object sender, DeleteEventArgs args) { - _gLWigdet?.Exit(); - End(_emulationContext); } diff --git a/Ryujinx/Ui/ScopedGLContext.cs b/Ryujinx/Ui/ScopedGLContext.cs new file mode 100644 index 0000000000..49d33a0961 --- /dev/null +++ b/Ryujinx/Ui/ScopedGLContext.cs @@ -0,0 +1,35 @@ +using OpenTK.Graphics; +using OpenTK.Platform; +using System; +using System.Threading; + +namespace Ryujinx.Ui +{ + class ScopedGLContext : IDisposable + { + private IGraphicsContext _graphicsContext; + + private static readonly object _lock = new object(); + + public ScopedGLContext(IWindowInfo windowInfo, IGraphicsContext graphicsContext) + { + _graphicsContext = graphicsContext; + + Monitor.Enter(_lock); + + MakeCurrent(windowInfo); + } + + private void MakeCurrent(IWindowInfo windowInfo) + { + _graphicsContext.MakeCurrent(windowInfo); + } + + public void Dispose() + { + MakeCurrent(null); + + Monitor.Exit(_lock); + } + } +}