diff --git a/Ryujinx/Program.cs b/Ryujinx/Program.cs
index 24fbb9b8b5..4aaa5e9f2c 100644
--- a/Ryujinx/Program.cs
+++ b/Ryujinx/Program.cs
@@ -3,6 +3,7 @@ using Ryujinx.Common.Logging;
using Ryujinx.Configuration;
using Ryujinx.Debugger.Profiler;
using Ryujinx.Ui;
+using OpenTK;
using System;
using System.IO;
@@ -12,6 +13,12 @@ namespace Ryujinx
{
static void Main(string[] args)
{
+ Toolkit.Init(new ToolkitOptions
+ {
+ Backend = PlatformBackend.PreferNative,
+ EnableHighResolution = true
+ });
+
Console.Title = "Ryujinx Console";
string systemPath = Environment.GetEnvironmentVariable("Path", EnvironmentVariableTarget.Machine);
diff --git a/Ryujinx/Ui/GLRenderer.cs b/Ryujinx/Ui/GLRenderer.cs
new file mode 100644
index 0000000000..66f9ea25fc
--- /dev/null
+++ b/Ryujinx/Ui/GLRenderer.cs
@@ -0,0 +1,154 @@
+using System;
+using System.Collections.Generic;
+using System.Threading;
+using Ryujinx.HLE;
+using Ryujinx.Graphics.OpenGL;
+using System.Text;
+using OpenTK.Graphics;
+using Gdk;
+
+namespace Ryujinx.Ui
+{
+ public class GLRenderer : GLWidget
+ {
+ public ManualResetEvent waitEvent { get; set; }
+
+ public bool IsActive { get; set; }
+ public bool IsStopped { get; set; }
+
+ private const int TargetFps = 60;
+
+ private readonly long _ticksPerFrame;
+
+ private long _ticks = 0;
+
+ private System.Diagnostics.Stopwatch _chrono;
+
+ private Switch _device;
+
+ private Renderer _renderer;
+
+ public GLRenderer(Switch device) :base (new GraphicsMode(), 3, 3, GraphicsContextFlags.ForwardCompatible)
+ {
+ waitEvent = new ManualResetEvent(false);
+
+ _device = device;
+
+ this.Initialized += GLRenderer_Initialized;
+ this.Destroyed += GLRenderer_Destroyed;
+
+ Initialize();
+
+ _chrono = new System.Diagnostics.Stopwatch();
+
+ _ticksPerFrame = System.Diagnostics.Stopwatch.Frequency / TargetFps;
+ }
+
+ private void GLRenderer_Destroyed(object sender, EventArgs e)
+ {
+ Exit();
+
+ this.Dispose();
+ }
+
+ private void GLRenderer_Initialized(object sender, EventArgs e)
+ {
+ Start();
+ }
+
+ protected override bool OnConfigureEvent(EventConfigure evnt)
+ {
+ var result = base.OnConfigureEvent(evnt);
+
+ _renderer.Window.SetSize(AllocatedWidth, AllocatedHeight);
+
+ return result;
+ }
+
+ public void Start()
+ {
+ _renderer.Initialize();
+
+ _chrono.Restart();
+
+ IsActive = true;
+
+ GLib.Idle.Add(Render, GLib.Priority.HighIdle);
+ }
+
+ public void Exit()
+ {
+ _device.DisposeGpu();
+
+ IsStopped = true;
+
+ waitEvent.Set();
+ }
+
+ public void Initialize()
+ {
+ if (!(_device.Gpu.Renderer is Renderer))
+ {
+ throw new NotSupportedException($"GPU renderer must be an OpenGL renderer when using GLRenderer!");
+ }
+
+ _renderer = (Renderer)_device.Gpu.Renderer;
+ }
+
+ public bool Render()
+ {
+ if (!IsActive)
+ {
+ return true;
+ }
+
+ if (IsStopped)
+ {
+ return false;
+ }
+
+ _ticks += _chrono.ElapsedTicks;
+
+ _chrono.Restart();
+
+ if (_device.WaitFifo())
+ {
+ _device.ProcessFrame();
+ }
+
+ if (_ticks >= _ticksPerFrame)
+ {
+ _device.PresentFrame(SwapBuffers);
+
+ _device.Statistics.RecordSystemFrameTime();
+
+ double hostFps = _device.Statistics.GetSystemFrameRate();
+ double gameFps = _device.Statistics.GetGameFrameRate();
+
+ string titleNameSection = string.IsNullOrWhiteSpace(_device.System.TitleName) ? string.Empty
+ : " | " + _device.System.TitleName;
+
+ string titleIdSection = string.IsNullOrWhiteSpace(_device.System.TitleIdText) ? string.Empty
+ : " | " + _device.System.TitleIdText.ToUpper();
+
+ string newTitle = $"Ryujinx{titleNameSection}{titleIdSection} | Host FPS: {hostFps:0.0} | Game FPS: {gameFps:0.0} | " +
+ $"Game Vsync: {(_device.EnableDeviceVsync ? "On" : "Off")}";
+
+ this.ParentWindow.Title = newTitle;
+
+ _device.System.SignalVsync();
+
+ _device.VsyncEvent.Set();
+
+ _ticks = Math.Min(_ticks - _ticksPerFrame, _ticksPerFrame);
+ }
+
+ return true;
+ }
+
+ public void SwapBuffers()
+ {
+ OpenTK.Graphics.GraphicsContext.CurrentContext.SwapBuffers();
+ }
+ }
+}
diff --git a/Ryujinx/Ui/GLWidget.cs b/Ryujinx/Ui/GLWidget.cs
new file mode 100644
index 0000000000..3b93c946d4
--- /dev/null
+++ b/Ryujinx/Ui/GLWidget.cs
@@ -0,0 +1,556 @@
+//https://github.com/Nihlus/GLWidgetTest/blob/master/GLWidget/GLWidgetGTK3/GLWidget.cs
+#region License
+//
+// The Open Toolkit Library License
+//
+// Copyright (c) 2006 - 2009 the Open Toolkit library, except where noted.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights to
+// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+// the Software, and to permit persons to whom the Software is furnished to do
+// so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+//
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+using System.Security;
+using System.Threading;
+using System.ComponentModel;
+
+
+using OpenTK;
+using OpenTK.Graphics;
+using OpenTK.Platform;
+
+using Gtk;
+
+namespace Ryujinx.Ui
+{
+ [ToolboxItem(true)]
+ public class GLWidget : DrawingArea
+ {
+
+ #region Static attrs.
+
+ private static int _graphicsContextCount;
+ private static bool _sharedContextInitialized;
+
+ #endregion
+
+ #region Attributes
+
+ private IGraphicsContext _graphicsContext;
+ private IWindowInfo _windowInfo;
+ private bool _initialized;
+
+ #endregion
+
+ #region Properties
+
+ /// Use a single buffer versus a double buffer.
+ [Browsable(true)]
+ public bool SingleBuffer { get; set; }
+
+ /// Color Buffer Bits-Per-Pixel
+ public int ColorBPP { get; set; }
+
+ /// Accumulation Buffer Bits-Per-Pixel
+ public int AccumulatorBPP { get; set; }
+
+ /// Depth Buffer Bits-Per-Pixel
+ public int DepthBPP { get; set; }
+
+ /// Stencil Buffer Bits-Per-Pixel
+ public int StencilBPP { get; set; }
+
+ /// Number of samples
+ public int Samples { get; set; }
+
+ /// Indicates if steropic renderering is enabled
+ public bool Stereo { get; set; }
+
+ /// The major version of OpenGL to use.
+ public int GLVersionMajor { get; set; }
+
+ /// The minor version of OpenGL to use.
+ public int GLVersionMinor { get; set; }
+
+ public GraphicsContextFlags GraphicsContextFlags
+ {
+ get;
+ set;
+ }
+
+ #endregion
+
+ #region Construction/Destruction
+
+ /// Constructs a new GLWidget.
+ public GLWidget()
+ : this(GraphicsMode.Default)
+ {
+ }
+
+ /// Constructs a new GLWidget using a given GraphicsMode
+ public GLWidget(GraphicsMode graphicsMode)
+ : this(graphicsMode, 1, 0, GraphicsContextFlags.Default)
+ {
+ }
+
+ /// Constructs a new GLWidget
+ public GLWidget(GraphicsMode graphicsMode, int glVersionMajor, int glVersionMinor, GraphicsContextFlags graphicsContextFlags)
+ {
+ SingleBuffer = graphicsMode.Buffers == 1;
+ ColorBPP = graphicsMode.ColorFormat.BitsPerPixel;
+ AccumulatorBPP = graphicsMode.AccumulatorFormat.BitsPerPixel;
+ DepthBPP = graphicsMode.Depth;
+ StencilBPP = graphicsMode.Stencil;
+ Samples = graphicsMode.Samples;
+ Stereo = graphicsMode.Stereo;
+
+ GLVersionMajor = glVersionMajor;
+ GLVersionMinor = glVersionMinor;
+ GraphicsContextFlags = graphicsContextFlags;
+ }
+
+ ~GLWidget()
+ {
+ Dispose(false);
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing)
+ {
+ _graphicsContext.MakeCurrent(_windowInfo);
+
+ OnShuttingDown();
+
+ if (GraphicsContext.ShareContexts && (Interlocked.Decrement(ref _graphicsContextCount) == 0))
+ {
+ OnGraphicsContextShuttingDown();
+ _sharedContextInitialized = false;
+ }
+
+ _graphicsContext.Dispose();
+ }
+ }
+
+ #endregion
+
+ #region New Events
+
+ // Called when the first GraphicsContext is created in the case of GraphicsContext.ShareContexts == True;
+ public static event EventHandler GraphicsContextInitialized;
+
+ private static void OnGraphicsContextInitialized()
+ {
+ if (GraphicsContextInitialized != null)
+ {
+ GraphicsContextInitialized(null, EventArgs.Empty);
+ }
+ }
+
+ // Called when the first GraphicsContext is being destroyed in the case of GraphicsContext.ShareContexts == True;
+ public static event EventHandler GraphicsContextShuttingDown;
+
+ private static void OnGraphicsContextShuttingDown()
+ {
+ if (GraphicsContextShuttingDown != null)
+ {
+ GraphicsContextShuttingDown(null, EventArgs.Empty);
+ }
+ }
+
+ // Called when this GLWidget has a valid GraphicsContext
+ public event EventHandler Initialized;
+
+ protected virtual void OnInitialized()
+ {
+ if (Initialized != null)
+ {
+ Initialized(this, EventArgs.Empty);
+ }
+ }
+
+ // Called when this GLWidget needs to render a frame
+ public event EventHandler RenderFrame;
+
+ protected virtual void OnRenderFrame()
+ {
+ if (RenderFrame != null)
+ {
+ RenderFrame(this, EventArgs.Empty);
+ }
+ }
+
+ // Called when this GLWidget is being Disposed
+ public event EventHandler ShuttingDown;
+
+ protected virtual void OnShuttingDown()
+ {
+ if (ShuttingDown != null)
+ {
+ ShuttingDown(this, EventArgs.Empty);
+ }
+ }
+
+ #endregion
+
+ // Called when a widget is realized. (window handles and such are valid)
+ // protected override void OnRealized() { base.OnRealized(); }
+
+ // Called when the widget needs to be (fully or partially) redrawn.
+
+ protected override bool OnDrawn(Cairo.Context cr)
+ {
+ if (!_initialized)
+ Initialize();
+ else
+ _graphicsContext.MakeCurrent(_windowInfo);
+
+ return true;
+ }
+
+ // Called on Resize
+ protected override bool OnConfigureEvent(Gdk.EventConfigure evnt)
+ {
+ if (_graphicsContext != null)
+ {
+ _graphicsContext.Update(_windowInfo);
+ }
+
+ return true;
+ }
+
+ private void Initialize()
+ {
+ _initialized = true;
+
+ // If this looks uninitialized... initialize.
+ if (ColorBPP == 0)
+ {
+ ColorBPP = 32;
+
+ if (DepthBPP == 0)
+ {
+ DepthBPP = 16;
+ }
+ }
+
+ ColorFormat colorBufferColorFormat = new ColorFormat(ColorBPP);
+
+ ColorFormat accumulationColorFormat = new ColorFormat(AccumulatorBPP);
+
+ int buffers = 2;
+ if (SingleBuffer)
+ {
+ buffers--;
+ }
+
+ GraphicsMode graphicsMode = new GraphicsMode(colorBufferColorFormat, DepthBPP, StencilBPP, Samples, accumulationColorFormat, buffers, Stereo);
+
+ if (OpenTK.Configuration.RunningOnWindows)
+ {
+ Console.WriteLine("OpenTK running on windows");
+ }
+ else if (OpenTK.Configuration.RunningOnMacOS)
+ {
+ Console.WriteLine("OpenTK running on OSX");
+ }
+ else
+ {
+ Console.WriteLine("OpenTK running on X11");
+ }
+
+ this.Window.EnsureNative();
+
+ // IWindowInfo
+ if (OpenTK.Configuration.RunningOnWindows)
+ {
+ _windowInfo = InitializeWindows();
+ }
+ else if (OpenTK.Configuration.RunningOnMacOS)
+ {
+ _windowInfo = InitializeOSX();
+ }
+ else
+ {
+ _windowInfo = InitializeX(graphicsMode);
+ }
+
+ // GraphicsContext
+ _graphicsContext = new GraphicsContext(graphicsMode, _windowInfo, GLVersionMajor, GLVersionMinor, GraphicsContextFlags);
+ _graphicsContext.MakeCurrent(_windowInfo);
+
+ if (GraphicsContext.ShareContexts)
+ {
+ Interlocked.Increment(ref _graphicsContextCount);
+
+ if (!_sharedContextInitialized)
+ {
+ _sharedContextInitialized = true;
+ ((IGraphicsContextInternal)_graphicsContext).LoadAll();
+ OnGraphicsContextInitialized();
+ }
+ }
+ else
+ {
+ ((IGraphicsContextInternal)_graphicsContext).LoadAll();
+ OnGraphicsContextInitialized();
+ }
+
+ OnInitialized();
+ }
+
+ #region Windows Specific initalization
+
+ IWindowInfo InitializeWindows()
+ {
+ IntPtr windowHandle = gdk_win32_window_get_handle(this.Window.Handle);
+ return Utilities.CreateWindowsWindowInfo(windowHandle);
+ }
+
+ [SuppressUnmanagedCodeSecurity, DllImport("libgdk-3-0.dll")]
+ public static extern IntPtr gdk_win32_window_get_handle(IntPtr d);
+
+ #endregion
+
+ #region OSX Specific Initialization
+
+ IWindowInfo InitializeOSX()
+ {
+ IntPtr windowHandle = gdk_quartz_window_get_nswindow(this.Window.Handle);
+ //IntPtr viewHandle = gdk_quartz_window_get_nsview(this.GdkWindow.Handle);
+ return Utilities.CreateMacOSCarbonWindowInfo(windowHandle, true, true);
+ }
+
+ [SuppressUnmanagedCodeSecurity, DllImport("libgdk-quartz-2.0.0.dylib")]
+ static extern IntPtr gdk_quartz_window_get_nswindow(IntPtr handle);
+
+ [SuppressUnmanagedCodeSecurity, DllImport("libgdk-quartz-2.0.0.dylib")]
+ static extern IntPtr gdk_quartz_window_get_nsview(IntPtr handle);
+
+ #endregion
+
+ #region X Specific Initialization
+
+ const string UnixLibGdkName = "libgdk-3.so.0";
+
+ const string UnixLibX11Name = "libX11.so.6";
+ const string UnixLibGLName = "libGL.so.1";
+
+ const int GLX_NONE = 0;
+ const int GLX_USE_GL = 1;
+ const int GLX_BUFFER_SIZE = 2;
+ const int GLX_LEVEL = 3;
+ const int GLX_RGBA = 4;
+ const int GLX_DOUBLEBUFFER = 5;
+ const int GLX_STEREO = 6;
+ const int GLX_AUX_BUFFERS = 7;
+ const int GLX_RED_SIZE = 8;
+ const int GLX_GREEN_SIZE = 9;
+ const int GLX_BLUE_SIZE = 10;
+ const int GLX_ALPHA_SIZE = 11;
+ const int GLX_DEPTH_SIZE = 12;
+ const int GLX_STENCIL_SIZE = 13;
+ const int GLX_ACCUM_RED_SIZE = 14;
+ const int GLX_ACCUM_GREEN_SIZE = 15;
+ const int GLX_ACCUM_BLUE_SIZE = 16;
+ const int GLX_ACCUM_ALPHA_SIZE = 17;
+
+ public enum XVisualClass
+ {
+ StaticGray = 0,
+ GrayScale = 1,
+ StaticColor = 2,
+ PseudoColor = 3,
+ TrueColor = 4,
+ DirectColor = 5,
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ struct XVisualInfo
+ {
+ public IntPtr Visual;
+ public IntPtr VisualID;
+ public int Screen;
+ public int Depth;
+ public XVisualClass Class;
+ public long RedMask;
+ public long GreenMask;
+ public long blueMask;
+ public int ColormapSize;
+ public int BitsPerRgb;
+
+ public override string ToString()
+ {
+ return $"id ({VisualID}), screen ({Screen}), depth ({Depth}), class ({Class})";
+ }
+ }
+
+ [Flags]
+ internal enum XVisualInfoMask
+ {
+ No = 0x0,
+ ID = 0x1,
+ Screen = 0x2,
+ Depth = 0x4,
+ Class = 0x8,
+ Red = 0x10,
+ Green = 0x20,
+ Blue = 0x40,
+ ColormapSize = 0x80,
+ BitsPerRGB = 0x100,
+ All = 0x1FF,
+ }
+
+ private IWindowInfo InitializeX(GraphicsMode mode)
+ {
+ IntPtr display = gdk_x11_display_get_xdisplay(Display.Handle);
+ int screen = Screen.Number;
+
+ IntPtr windowHandle = gdk_x11_window_get_xid(Window.Handle);
+ IntPtr rootWindow = gdk_x11_window_get_xid(RootWindow.Handle);
+
+ IntPtr visualInfo;
+
+ if (mode.Index.HasValue)
+ {
+ XVisualInfo info = new XVisualInfo();
+ info.VisualID = mode.Index.Value;
+ int dummy;
+ visualInfo = XGetVisualInfo(display, XVisualInfoMask.ID, ref info, out dummy);
+ }
+ else
+ {
+ visualInfo = GetVisualInfo(display);
+ }
+
+ IWindowInfo retval = Utilities.CreateX11WindowInfo(display, screen, windowHandle, rootWindow, visualInfo);
+ XFree(visualInfo);
+
+ return retval;
+ }
+
+ private static IntPtr XGetVisualInfo(IntPtr display, XVisualInfoMask vinfo_mask, ref XVisualInfo template, out int nitems)
+ {
+ return XGetVisualInfoInternal(display, (IntPtr)(int)vinfo_mask, ref template, out nitems);
+ }
+
+ private IntPtr GetVisualInfo(IntPtr display)
+ {
+ try
+ {
+ int[] attributes = AttributeList.ToArray();
+ return glXChooseVisual(display, Screen.Number, attributes);
+ }
+ catch (DllNotFoundException e)
+ {
+ throw new DllNotFoundException("OpenGL dll not found!", e);
+ }
+ catch (EntryPointNotFoundException enf)
+ {
+ throw new EntryPointNotFoundException("Glx entry point not found!", enf);
+ }
+ }
+
+ private List AttributeList
+ {
+ get
+ {
+ List attributeList = new List(24);
+
+ attributeList.Add(GLX_RGBA);
+
+ if (!SingleBuffer)
+ attributeList.Add(GLX_DOUBLEBUFFER);
+
+ if (Stereo)
+ attributeList.Add(GLX_STEREO);
+
+ attributeList.Add(GLX_RED_SIZE);
+ attributeList.Add(ColorBPP / 4); // TODO support 16-bit
+
+ attributeList.Add(GLX_GREEN_SIZE);
+ attributeList.Add(ColorBPP / 4); // TODO support 16-bit
+
+ attributeList.Add(GLX_BLUE_SIZE);
+ attributeList.Add(ColorBPP / 4); // TODO support 16-bit
+
+ attributeList.Add(GLX_ALPHA_SIZE);
+ attributeList.Add(ColorBPP / 4); // TODO support 16-bit
+
+ attributeList.Add(GLX_DEPTH_SIZE);
+ attributeList.Add(DepthBPP);
+
+ attributeList.Add(GLX_STENCIL_SIZE);
+ attributeList.Add(StencilBPP);
+
+ attributeList.Add(GLX_ACCUM_RED_SIZE);
+ attributeList.Add(AccumulatorBPP / 4);// TODO support 16-bit
+
+ attributeList.Add(GLX_ACCUM_GREEN_SIZE);
+ attributeList.Add(AccumulatorBPP / 4);// TODO support 16-bit
+
+ attributeList.Add(GLX_ACCUM_BLUE_SIZE);
+ attributeList.Add(AccumulatorBPP / 4);// TODO support 16-bit
+
+ attributeList.Add(GLX_ACCUM_ALPHA_SIZE);
+ attributeList.Add(AccumulatorBPP / 4);// TODO support 16-bit
+
+ attributeList.Add(GLX_NONE);
+
+ return attributeList;
+ }
+ }
+
+ [DllImport(UnixLibX11Name, EntryPoint = "XGetVisualInfo")]
+ private static extern IntPtr XGetVisualInfoInternal(IntPtr display, IntPtr vinfo_mask, ref XVisualInfo template, out int nitems);
+
+ [SuppressUnmanagedCodeSecurity, DllImport(UnixLibX11Name)]
+ private static extern void XFree(IntPtr handle);
+
+ /// Returns the X resource (window or pixmap) belonging to a GdkDrawable.
+ /// XID gdk_x11_drawable_get_xid(GdkDrawable *drawable);
+ /// The GdkDrawable.
+ /// The ID of drawable's X resource.
+ [SuppressUnmanagedCodeSecurity, DllImport(UnixLibGdkName)]
+ private static extern IntPtr gdk_x11_drawable_get_xid(IntPtr gdkDisplay);
+
+ /// Returns the X resource (window or pixmap) belonging to a GdkDrawable.
+ /// XID gdk_x11_drawable_get_xid(GdkDrawable *drawable);
+ /// The GdkDrawable.
+ /// The ID of drawable's X resource.
+ [SuppressUnmanagedCodeSecurity, DllImport(UnixLibGdkName)]
+ private static extern IntPtr gdk_x11_window_get_xid(IntPtr gdkDisplay);
+
+ /// Returns the X display of a GdkDisplay.
+ /// Display* gdk_x11_display_get_xdisplay(GdkDisplay *display);
+ /// The GdkDrawable.
+ /// The X Display of the GdkDisplay.
+ [SuppressUnmanagedCodeSecurity, DllImport(UnixLibGdkName)]
+ private static extern IntPtr gdk_x11_display_get_xdisplay(IntPtr gdkDisplay);
+
+ [SuppressUnmanagedCodeSecurity, DllImport(UnixLibGLName)]
+ private static extern IntPtr glXChooseVisual(IntPtr display, int screen, int[] attr);
+
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/Ryujinx/Ui/MainWindow.cs b/Ryujinx/Ui/MainWindow.cs
index 734103fed2..57cb5a8530 100644
--- a/Ryujinx/Ui/MainWindow.cs
+++ b/Ryujinx/Ui/MainWindow.cs
@@ -30,7 +30,8 @@ namespace Ryujinx.Ui
private static HLE.Switch _emulationContext;
- private static GlScreen _screen;
+ // private static GlScreen _screen;
+ private static GLRenderer _gLWigdet;
private static AutoResetEvent _screenExitStatus = new AutoResetEvent(false);
@@ -384,15 +385,37 @@ namespace Ryujinx.Ui
{
device.Hid.InitializePrimaryController(ConfigurationState.Instance.Hid.ControllerType);
- using (_screen = new GlScreen(device))
+ _gLWigdet?.Exit();
+ _gLWigdet?.Dispose();
+ _gLWigdet = new GLRenderer(_emulationContext);
+
+ Application.Invoke(delegate
{
- _screen.MainLoop();
- }
+ Window window = new Window("Test");
+
+ window.HeightRequest = 720;
+ window.WidthRequest = 1280;
+ _gLWigdet.Expand = true;
+ window.Child = _gLWigdet;
+
+ window.ShowAll();
+ });
+
+ _gLWigdet.waitEvent.WaitOne();
+
+ Application.Invoke(delegate
+ {
+ _gLWigdet.Dispose();
+
+ if(_gLWigdet.Window != this.Window && _gLWigdet.Window != null)
+ {
+ _gLWigdet.Window.Dispose();
+ }
+ });
device.Dispose();
_emulationContext = null;
- _screen = null;
_gameLoaded = false;
DiscordIntegrationModule.SwitchToMainMenu();
@@ -595,17 +618,21 @@ 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);
}
private void StopEmulation_Pressed(object sender, EventArgs args)
{
- _screen?.Exit();
+ _gLWigdet?.Exit();
}
private void Installer_File_Pressed(object o, EventArgs args)