From a528199cd4daa412e66f3230d4322ee2904e4fd7 Mon Sep 17 00:00:00 2001 From: Thog Date: Wed, 12 Feb 2020 15:55:45 +0100 Subject: [PATCH] Some fixes for the new GLRenderer Changelog: - Fix transparency of the window on some games on Windows. - Fix escape key not being able to exit emulation. - Fix inverted logic in fullscreen event handling. - Fix a race condition when stoping emulation causing a hang. - Fix a memory leak of the OpenGL context when stoping emulation (saving ~200MB of RAM when stoping emulation). - Simplify and document behaviours when exiting the emulator while the emulation is running. --- Ryujinx/Ui/GLRenderer.cs | 72 ++++++++++++++++++++++------------------ Ryujinx/Ui/MainWindow.cs | 46 ++++++++++++------------- 2 files changed, 60 insertions(+), 58 deletions(-) diff --git a/Ryujinx/Ui/GLRenderer.cs b/Ryujinx/Ui/GLRenderer.cs index 7506821737..0e5c7bb11f 100644 --- a/Ryujinx/Ui/GLRenderer.cs +++ b/Ryujinx/Ui/GLRenderer.cs @@ -63,6 +63,7 @@ namespace Ryujinx.Ui this.Initialized += GLRenderer_Initialized; this.Destroyed += GLRenderer_Destroyed; + this.ShuttingDown += GLRenderer_ShuttingDown; Initialize(); @@ -81,6 +82,11 @@ namespace Ryujinx.Ui this.Shown += Renderer_Shown; } + private void GLRenderer_ShuttingDown(object sender, EventArgs args) + { + Exit(); + } + private void Parent_FocusOutEvent(object o, Gtk.FocusOutEventArgs args) { IsFocused = false; @@ -93,9 +99,7 @@ namespace Ryujinx.Ui private void GLRenderer_Destroyed(object sender, EventArgs e) { - Exit(); - - this.Dispose(); + Dispose(); } protected void Renderer_Shown(object sender, EventArgs e) @@ -106,41 +110,38 @@ namespace Ryujinx.Ui public void HandleScreenState(KeyboardState keyboard) { bool toggleFullscreen = keyboard.IsKeyDown(OpenTK.Input.Key.F11) - || ((keyboard.IsKeyDown(OpenTK.Input.Key.AltLeft) - || keyboard.IsKeyDown(OpenTK.Input.Key.AltRight)) - && keyboard.IsKeyDown(OpenTK.Input.Key.Enter)); + || ((keyboard.IsKeyDown(OpenTK.Input.Key.AltLeft) + || keyboard.IsKeyDown(OpenTK.Input.Key.AltRight)) + && keyboard.IsKeyDown(OpenTK.Input.Key.Enter)) + || keyboard.IsKeyDown(OpenTK.Input.Key.Escape); - if (toggleFullscreen == _toggleFullscreen) + bool fullScreenToggled = ParentWindow.State.HasFlag(Gdk.WindowState.Fullscreen); + + if (toggleFullscreen != _toggleFullscreen) { - return; + if (toggleFullscreen) + { + if (fullScreenToggled) + { + ParentWindow.Unfullscreen(); + (Toplevel as MainWindow)?.ToggleExtraWidgets(true); + } + else + { + if (keyboard.IsKeyDown(OpenTK.Input.Key.Escape)) + { + Exit(); + } + else + { + ParentWindow.Fullscreen(); + (Toplevel as MainWindow)?.ToggleExtraWidgets(false); + } + } + } } _toggleFullscreen = toggleFullscreen; - - Gtk.Application.Invoke(delegate - { - if (this.ParentWindow.State.HasFlag(Gdk.WindowState.Fullscreen)) - { - if (keyboard.IsKeyDown(OpenTK.Input.Key.Escape) || _toggleFullscreen) - { - this.ParentWindow.Unfullscreen(); - (this.Toplevel as MainWindow)?.ToggleExtraWidgets(true); - } - } - else - { - if (keyboard.IsKeyDown(OpenTK.Input.Key.Escape)) - { - Exit(); - } - - if (_toggleFullscreen) - { - this.ParentWindow.Fullscreen(); - (this.Toplevel as MainWindow)?.ToggleExtraWidgets(false); - } - } - }); } private void GLRenderer_Initialized(object sender, EventArgs e) @@ -282,6 +283,11 @@ namespace Ryujinx.Ui if (_ticks >= _ticksPerFrame) { + // Ensure that the content is Opaque. + GL.ColorMask(false, false, false, true); + GL.ClearColor(0.0f, 0.0f, 0.0f, 1.0f); + GL.ColorMask(true, true, true, true); + _device.PresentFrame(SwapBuffers); _device.Statistics.RecordSystemFrameTime(); diff --git a/Ryujinx/Ui/MainWindow.cs b/Ryujinx/Ui/MainWindow.cs index 6c771bb96f..9f6dc4941c 100644 --- a/Ryujinx/Ui/MainWindow.cs +++ b/Ryujinx/Ui/MainWindow.cs @@ -31,7 +31,7 @@ namespace Ryujinx.Ui private static GLRenderer _gLWidget; - private static AutoResetEvent _screenExitStatus = new AutoResetEvent(false); + private static AutoResetEvent _deviceExitStatus = new AutoResetEvent(false); private static ListStore _tableStore; @@ -356,7 +356,7 @@ namespace Ryujinx.Ui _emulationContext = device; - _screenExitStatus.Reset(); + _deviceExitStatus.Reset(); #if MACOS_BUILD CreateGameWindow(device); @@ -391,8 +391,6 @@ namespace Ryujinx.Ui { device.Hid.InitializePrimaryController(ConfigurationState.Instance.Hid.ControllerType); - _gLWidget?.Exit(); - _gLWidget?.Dispose(); _gLWidget = new GLRenderer(_emulationContext); Application.Invoke(delegate @@ -409,6 +407,10 @@ namespace Ryujinx.Ui _gLWidget.Start(); + device.Dispose(); + _deviceExitStatus.Set(); + + // NOTE: Everything that is here will not be executed when you close the UI. Application.Invoke(delegate { _viewBox.Remove(_gLWidget); @@ -419,36 +421,31 @@ namespace Ryujinx.Ui _gLWidget.Window.Dispose(); } + _gLWidget.Dispose(); + _viewBox.Add(_gameTableWindow); _gameTableWindow.Expand = true; this.Window.Title = "Ryujinx"; + _emulationContext = null; + _gameLoaded = false; + _gLWidget = null; + + DiscordIntegrationModule.SwitchToMainMenu(); + _listStatusBox.ShowAll(); UpdateColumns(); UpdateGameTable(); Task.Run(RefreshFirmwareLabel); - }); - device.Dispose(); - - _emulationContext = null; - _gameLoaded = false; - _gLWidget = null; - - DiscordIntegrationModule.SwitchToMainMenu(); - - Application.Invoke(delegate - { _stopEmulation.Sensitive = false; _firmwareInstallFile.Sensitive = true; _firmwareInstallDirectory.Sensitive = true; }); - - _screenExitStatus.Set(); } public void ToggleExtraWidgets(bool show) @@ -469,7 +466,7 @@ namespace Ryujinx.Ui bool fullScreenToggled = this.Window.State.HasFlag(Gdk.WindowState.Fullscreen); - _fullScreen.Label = !fullScreenToggled ? "Exit Fullscreen" : "Enter Fullscreen"; + _fullScreen.Label = fullScreenToggled ? "Exit Fullscreen" : "Enter Fullscreen"; } private static void UpdateGameMetadata(string titleId) @@ -506,8 +503,11 @@ namespace Ryujinx.Ui if (_gLWidget != null) { + // We tell the widget that we are exiting _gLWidget.Exit(); - _screenExitStatus.WaitOne(); + + // Wait for the other thread to dispose the HLE context before exiting. + _deviceExitStatus.WaitOne(); } } @@ -874,17 +874,13 @@ namespace Ryujinx.Ui { Fullscreen(); - _fullScreen.Label = "Exit Fullscreen"; - - ToggleExtraWidgets(false); + ToggleExtraWidgets(true); } else { Unfullscreen(); - _fullScreen.Label = "Enter Fullscreen"; - - ToggleExtraWidgets(true); + ToggleExtraWidgets(false); } }