diff --git a/Ryujinx/Ryujinx.csproj b/Ryujinx/Ryujinx.csproj index d4850a7c0c..bde01b243e 100644 --- a/Ryujinx/Ryujinx.csproj +++ b/Ryujinx/Ryujinx.csproj @@ -72,6 +72,7 @@ + diff --git a/Ryujinx/Ui/GLRenderer.cs b/Ryujinx/Ui/GLRenderer.cs index 613dc801ea..55247ff28f 100644 --- a/Ryujinx/Ui/GLRenderer.cs +++ b/Ryujinx/Ui/GLRenderer.cs @@ -1,14 +1,7 @@ -using System; -using System.Collections.Generic; -using System.Threading; -using Ryujinx.HLE; -using Ryujinx.Graphics.OpenGL; -using System.Text; -using OpenTK.Input; -using OpenTK.Graphics; -using OpenTK.Graphics.OpenGL; +using Gdk; using OpenTK; using OpenTK.Graphics; +using OpenTK.Graphics.OpenGL; using OpenTK.Input; using Ryujinx.Configuration; using Ryujinx.Graphics.OpenGL; @@ -17,8 +10,9 @@ using Ryujinx.HLE.Input; using Ryujinx.Profiler.UI; using Ryujinx.Ui; using System; +using System.Collections.Generic; +using System.Text; using System.Threading; -using Gdk; namespace Ryujinx.Ui { @@ -27,14 +21,16 @@ namespace Ryujinx.Ui private const int TouchScreenWidth = 1280; private const int TouchScreenHeight = 720; private const int TargetFps = 60; - public ManualResetEvent waitEvent { get; set; } - public bool IsActive { get; set; } - public bool IsStopped { get; set; } - public bool IsFocussed { get; set; } = true; + public ManualResetEvent WaitEvent { get; set; } + + public bool IsActive { get; set; } + public bool IsStopped { get; set; } + public bool IsFocussed { get; set; } = false; private double _mouseX; private double _mouseY; + private bool _mousePressed; private bool _titleEvent; @@ -56,7 +52,7 @@ namespace Ryujinx.Ui public GLRenderer(Switch device) :base (new GraphicsMode(), 3, 3, GraphicsContextFlags.ForwardCompatible) { - waitEvent = new ManualResetEvent(false); + WaitEvent = new ManualResetEvent(false); _device = device; @@ -71,7 +67,7 @@ namespace Ryujinx.Ui _primaryController = new Input.NpadController(ConfigurationState.Instance.Hid.JoystickControls); - AddEvents((int)(Gdk.EventMask.ButtonPressMask | Gdk.EventMask.ButtonReleaseMask)); + AddEvents((int)(Gdk.EventMask.ButtonPressMask | Gdk.EventMask.ButtonReleaseMask | Gdk.EventMask.PointerMotionMask)); } private void Parent_FocusOutEvent(object o, Gtk.FocusOutEventArgs args) @@ -94,7 +90,7 @@ namespace Ryujinx.Ui private void GLRenderer_Initialized(object sender, EventArgs e) { GraphicsContext.MakeCurrent(null); - waitEvent.Set(); + WaitEvent.Set(); } protected override bool OnConfigureEvent(EventConfigure evnt) @@ -119,10 +115,15 @@ namespace Ryujinx.Ui parent.FocusInEvent += Parent_FocusInEvent; parent.FocusOutEvent += Parent_FocusOutEvent; - parent.Present(); + Gtk.Application.Invoke(delegate + { + parent.Present(); + }); - Thread renderLoopThread = new Thread(Render); - renderLoopThread.Name = "GUI.RenderLoop"; + Thread renderLoopThread = new Thread(Render) + { + Name = "GUI.RenderLoop" + }; renderLoopThread.Start(); MainLoop(); @@ -137,22 +138,43 @@ namespace Ryujinx.Ui _mouseX = evnt.X; _mouseY = evnt.Y; + if (evnt.Button == 1) + { + _mousePressed = true; + } + + return false; + } + + protected override bool OnButtonReleaseEvent(EventButton evnt) + { + if (evnt.Button == 1) + { + _mousePressed = false; + } + + return false; + } + + protected override bool OnMotionNotifyEvent(EventMotion evnt) + { + if (evnt.Device.InputSource == InputSource.Mouse) + { + _mouseX = evnt.X; + _mouseY = evnt.Y; + } + return false; } public void Exit() { - Gtk.Window parent = this.Toplevel as Gtk.Window; - - parent.FocusInEvent -= Parent_FocusInEvent; - parent.FocusOutEvent -= Parent_FocusOutEvent; - _device.DisposeGpu(); IsStopped = true; IsActive = false; - waitEvent.Set(); + WaitEvent.Set(); } public void Initialize() @@ -241,7 +263,7 @@ namespace Ryujinx.Ui UpdateFrame(); // Polling becomes expensive if it's not slept - Thread.Sleep(5); + Thread.Sleep(1); } } @@ -264,7 +286,6 @@ namespace Ryujinx.Ui HLE.Input.Keyboard? hidKeyboard = null; KeyboardState keyboard = OpenTK.Input.Keyboard.GetState(); - MouseState mouse = OpenTK.Input.Mouse.GetCursorState(); int leftJoystickDx = 0; int leftJoystickDy = 0; @@ -272,10 +293,9 @@ namespace Ryujinx.Ui int rightJoystickDy = 0; // Keyboard Input - #if USE_PROFILING // Profiler input, lets the profiler get access to the main windows keyboard state - _profileWindow.UpdateKeyInput(keyboard); + _profileWindow.UpdateKeyInput(keyboard); #endif // Normal Input @@ -330,7 +350,7 @@ namespace Ryujinx.Ui // Get screen touch position from left mouse click // OpenTK always captures mouse events, even if out of focus, so check if window is focused. - if (IsFocussed && mouse.LeftButton == ButtonState.Pressed) + if (IsFocussed && _mousePressed) { int scrnWidth = AllocatedWidth; int scrnHeight = AllocatedHeight; @@ -344,14 +364,24 @@ namespace Ryujinx.Ui scrnHeight = (AllocatedWidth * TouchScreenHeight) / TouchScreenWidth; } - if (mouse.X >= 0 && - mouse.Y >= 0 && - mouse.X < scrnWidth && - mouse.Y < scrnHeight) - { - int mX = ((int)_mouseX * TouchScreenWidth) / scrnWidth; - int mY = ((int)_mouseY * TouchScreenHeight) / scrnHeight; + int startX = (AllocatedWidth - scrnWidth) >> 1; + int startY = (AllocatedHeight - scrnHeight) >> 1; + + int endX = startX + scrnWidth; + int endY = startY + scrnHeight; + + + if (_mouseX >= startX && + _mouseY >= startY && + _mouseX < endX && + _mouseY < endY) + { + int scrnMouseX = (int)_mouseX - startX; + int scrnMouseY = (int)_mouseY - startY; + + int mX = (scrnMouseX * TouchScreenWidth) / scrnWidth; + int mY = (scrnMouseY * TouchScreenHeight) / scrnHeight; TouchPoint currentPoint = new TouchPoint { diff --git a/Ryujinx/Ui/GLWidget.cs b/Ryujinx/Ui/GLWidget.cs deleted file mode 100644 index 57f15d5d4e..0000000000 --- a/Ryujinx/Ui/GLWidget.cs +++ /dev/null @@ -1,567 +0,0 @@ -//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; - - public bool IsRenderHandler { get; set; } = false; - - #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) - { - try - { - GraphicsContext.MakeCurrent(WindowInfo); - }catch(Exception ex) - { - - } - - OnShuttingDown(); - - if (OpenTK.Graphics.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 if(!IsRenderHandler) - 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 (OpenTK.Graphics.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; - } - } - - public IGraphicsContext GraphicsContext { get => _graphicsContext; set => _graphicsContext = value; } - public IWindowInfo WindowInfo { get => _windowInfo; set => _windowInfo = value; } - - [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 c1345ff977..b3312576f8 100644 --- a/Ryujinx/Ui/MainWindow.cs +++ b/Ryujinx/Ui/MainWindow.cs @@ -399,7 +399,7 @@ namespace Ryujinx.Ui _gLWigdet.ShowAll(); }); - _gLWigdet.waitEvent.WaitOne(); + _gLWigdet.WaitEvent.WaitOne(); _gLWigdet.Start();