2018-02-04 23:08:20 +00:00
|
|
|
using OpenTK;
|
|
|
|
using OpenTK.Graphics;
|
2018-03-03 01:49:17 +00:00
|
|
|
using OpenTK.Input;
|
2018-02-20 20:09:23 +00:00
|
|
|
using Ryujinx.Graphics.Gal;
|
2018-06-11 00:46:42 +00:00
|
|
|
using Ryujinx.HLE;
|
|
|
|
using Ryujinx.HLE.Input;
|
2018-02-04 23:08:20 +00:00
|
|
|
using System;
|
2018-07-12 17:03:52 +00:00
|
|
|
using System.Threading;
|
|
|
|
|
|
|
|
using Stopwatch = System.Diagnostics.Stopwatch;
|
2018-02-04 23:08:20 +00:00
|
|
|
|
|
|
|
namespace Ryujinx
|
|
|
|
{
|
2018-10-31 01:43:02 +00:00
|
|
|
public class GlScreen : GameWindow
|
2018-02-04 23:08:20 +00:00
|
|
|
{
|
2018-03-03 01:49:17 +00:00
|
|
|
private const int TouchScreenWidth = 1280;
|
|
|
|
private const int TouchScreenHeight = 720;
|
|
|
|
|
2018-10-31 01:43:02 +00:00
|
|
|
private const int TargetFps = 60;
|
2018-07-12 17:03:52 +00:00
|
|
|
|
2018-10-31 01:43:02 +00:00
|
|
|
private Switch _device;
|
2018-02-04 23:08:20 +00:00
|
|
|
|
2018-10-31 01:43:02 +00:00
|
|
|
private IGalRenderer _renderer;
|
2018-02-04 23:08:20 +00:00
|
|
|
|
2019-04-22 06:54:31 +00:00
|
|
|
private HidHotkeyButtons _prevHotkeyButtons = 0;
|
|
|
|
|
2018-10-31 01:43:02 +00:00
|
|
|
private KeyboardState? _keyboard = null;
|
2018-06-21 21:10:19 +00:00
|
|
|
|
2018-10-31 01:43:02 +00:00
|
|
|
private MouseState? _mouse = null;
|
2018-06-24 00:39:25 +00:00
|
|
|
|
2018-10-31 01:43:02 +00:00
|
|
|
private Thread _renderThread;
|
2018-07-12 17:03:52 +00:00
|
|
|
|
2018-10-31 01:43:02 +00:00
|
|
|
private bool _resizeEvent;
|
2018-07-12 17:03:52 +00:00
|
|
|
|
2018-10-31 01:43:02 +00:00
|
|
|
private bool _titleEvent;
|
2018-07-12 17:03:52 +00:00
|
|
|
|
2018-10-31 01:43:02 +00:00
|
|
|
private string _newTitle;
|
2018-07-12 17:03:52 +00:00
|
|
|
|
2018-10-31 01:43:02 +00:00
|
|
|
public GlScreen(Switch device, IGalRenderer renderer)
|
2018-02-04 23:08:20 +00:00
|
|
|
: base(1280, 720,
|
|
|
|
new GraphicsMode(), "Ryujinx", 0,
|
|
|
|
DisplayDevice.Default, 3, 3,
|
|
|
|
GraphicsContextFlags.ForwardCompatible)
|
|
|
|
{
|
2018-10-31 01:43:02 +00:00
|
|
|
_device = device;
|
|
|
|
_renderer = renderer;
|
2018-03-04 23:32:18 +00:00
|
|
|
|
|
|
|
Location = new Point(
|
|
|
|
(DisplayDevice.Default.Width / 2) - (Width / 2),
|
|
|
|
(DisplayDevice.Default.Height / 2) - (Height / 2));
|
2018-07-12 17:03:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
private void RenderLoop()
|
|
|
|
{
|
|
|
|
MakeCurrent();
|
|
|
|
|
2018-10-31 01:43:02 +00:00
|
|
|
Stopwatch chrono = new Stopwatch();
|
2018-07-12 17:03:52 +00:00
|
|
|
|
2018-10-31 01:43:02 +00:00
|
|
|
chrono.Start();
|
2018-07-12 17:03:52 +00:00
|
|
|
|
2018-10-31 01:43:02 +00:00
|
|
|
long ticksPerFrame = Stopwatch.Frequency / TargetFps;
|
2018-07-12 17:03:52 +00:00
|
|
|
|
2018-10-31 01:43:02 +00:00
|
|
|
long ticks = 0;
|
2018-07-12 17:03:52 +00:00
|
|
|
|
|
|
|
while (Exists && !IsExiting)
|
|
|
|
{
|
2018-10-31 01:43:02 +00:00
|
|
|
if (_device.WaitFifo())
|
2018-07-12 17:03:52 +00:00
|
|
|
{
|
2018-10-31 01:43:02 +00:00
|
|
|
_device.ProcessFrame();
|
2018-07-12 17:03:52 +00:00
|
|
|
}
|
|
|
|
|
2018-10-31 01:43:02 +00:00
|
|
|
_renderer.RunActions();
|
2018-07-12 17:03:52 +00:00
|
|
|
|
2018-10-31 01:43:02 +00:00
|
|
|
if (_resizeEvent)
|
2018-07-12 17:03:52 +00:00
|
|
|
{
|
2018-10-31 01:43:02 +00:00
|
|
|
_resizeEvent = false;
|
2018-07-12 17:03:52 +00:00
|
|
|
|
2018-10-31 01:43:02 +00:00
|
|
|
_renderer.RenderTarget.SetWindowSize(Width, Height);
|
2018-07-12 17:03:52 +00:00
|
|
|
}
|
|
|
|
|
2018-10-31 01:43:02 +00:00
|
|
|
ticks += chrono.ElapsedTicks;
|
2018-07-12 17:03:52 +00:00
|
|
|
|
2018-10-31 01:43:02 +00:00
|
|
|
chrono.Restart();
|
2018-07-12 17:03:52 +00:00
|
|
|
|
2018-10-31 01:43:02 +00:00
|
|
|
if (ticks >= ticksPerFrame)
|
2018-07-12 17:03:52 +00:00
|
|
|
{
|
|
|
|
RenderFrame();
|
|
|
|
|
|
|
|
//Queue max. 1 vsync
|
2018-10-31 01:43:02 +00:00
|
|
|
ticks = Math.Min(ticks - ticksPerFrame, ticksPerFrame);
|
2018-07-12 17:03:52 +00:00
|
|
|
}
|
|
|
|
}
|
2018-02-04 23:08:20 +00:00
|
|
|
}
|
|
|
|
|
2018-07-12 17:03:52 +00:00
|
|
|
public void MainLoop()
|
2018-02-04 23:08:20 +00:00
|
|
|
{
|
2018-07-12 17:03:52 +00:00
|
|
|
VSync = VSyncMode.Off;
|
|
|
|
|
|
|
|
Visible = true;
|
2018-04-14 04:31:27 +00:00
|
|
|
|
2018-10-31 01:43:02 +00:00
|
|
|
_renderer.RenderTarget.SetWindowSize(Width, Height);
|
2018-07-12 17:03:52 +00:00
|
|
|
|
|
|
|
Context.MakeCurrent(null);
|
|
|
|
|
|
|
|
//OpenTK doesn't like sleeps in its thread, to avoid this a renderer thread is created
|
2018-10-31 01:43:02 +00:00
|
|
|
_renderThread = new Thread(RenderLoop);
|
2018-07-12 17:03:52 +00:00
|
|
|
|
2018-10-31 01:43:02 +00:00
|
|
|
_renderThread.Start();
|
2018-07-12 17:03:52 +00:00
|
|
|
|
|
|
|
while (Exists && !IsExiting)
|
|
|
|
{
|
|
|
|
ProcessEvents();
|
|
|
|
|
|
|
|
if (!IsExiting)
|
|
|
|
{
|
|
|
|
UpdateFrame();
|
|
|
|
|
2018-10-31 01:43:02 +00:00
|
|
|
if (_titleEvent)
|
2018-07-12 17:03:52 +00:00
|
|
|
{
|
2018-10-31 01:43:02 +00:00
|
|
|
_titleEvent = false;
|
2018-07-12 17:03:52 +00:00
|
|
|
|
2018-10-31 01:43:02 +00:00
|
|
|
Title = _newTitle;
|
2018-07-12 17:03:52 +00:00
|
|
|
}
|
|
|
|
}
|
2018-07-02 22:08:54 +00:00
|
|
|
|
2018-07-29 04:35:36 +00:00
|
|
|
//Polling becomes expensive if it's not slept
|
|
|
|
Thread.Sleep(1);
|
2018-07-02 22:08:54 +00:00
|
|
|
}
|
|
|
|
}
|
2018-02-04 23:08:20 +00:00
|
|
|
|
2018-07-12 17:03:52 +00:00
|
|
|
private new void UpdateFrame()
|
2018-02-04 23:08:20 +00:00
|
|
|
{
|
2019-04-22 06:54:31 +00:00
|
|
|
HidHotkeyButtons currentHotkeyButtons = 0;
|
2018-10-31 01:43:02 +00:00
|
|
|
HidControllerButtons currentButton = 0;
|
|
|
|
HidJoystickPosition leftJoystick;
|
|
|
|
HidJoystickPosition rightJoystick;
|
2018-02-22 13:28:27 +00:00
|
|
|
|
2018-10-31 01:43:02 +00:00
|
|
|
int leftJoystickDx = 0;
|
|
|
|
int leftJoystickDy = 0;
|
|
|
|
int rightJoystickDx = 0;
|
|
|
|
int rightJoystickDy = 0;
|
2018-06-24 00:39:25 +00:00
|
|
|
|
2018-07-02 22:08:54 +00:00
|
|
|
//Keyboard Input
|
2018-10-31 01:43:02 +00:00
|
|
|
if (_keyboard.HasValue)
|
2018-06-21 21:10:19 +00:00
|
|
|
{
|
2018-10-31 01:43:02 +00:00
|
|
|
KeyboardState keyboard = _keyboard.Value;
|
2018-06-21 21:10:19 +00:00
|
|
|
|
2019-04-22 06:54:31 +00:00
|
|
|
currentHotkeyButtons = Configuration.Instance.KeyboardControls.GetHotkeyButtons(keyboard);
|
|
|
|
currentButton = Configuration.Instance.KeyboardControls.GetButtons(keyboard);
|
2018-07-29 04:35:36 +00:00
|
|
|
|
2019-04-22 06:54:31 +00:00
|
|
|
(leftJoystickDx, leftJoystickDy) = Configuration.Instance.KeyboardControls.GetLeftStick(keyboard);
|
2019-02-11 12:00:32 +00:00
|
|
|
(rightJoystickDx, rightJoystickDy) = Configuration.Instance.KeyboardControls.GetRightStick(keyboard);
|
2018-07-02 22:08:54 +00:00
|
|
|
}
|
2018-11-20 00:01:36 +00:00
|
|
|
|
2019-02-11 12:00:32 +00:00
|
|
|
currentButton |= Configuration.Instance.GamepadControls.GetButtons();
|
2018-08-16 23:47:36 +00:00
|
|
|
|
2018-07-29 04:35:36 +00:00
|
|
|
//Keyboard has priority stick-wise
|
2018-10-31 01:43:02 +00:00
|
|
|
if (leftJoystickDx == 0 && leftJoystickDy == 0)
|
2018-07-02 22:08:54 +00:00
|
|
|
{
|
2019-02-11 12:00:32 +00:00
|
|
|
(leftJoystickDx, leftJoystickDy) = Configuration.Instance.GamepadControls.GetLeftStick();
|
2018-06-21 21:10:19 +00:00
|
|
|
}
|
2018-03-03 01:49:17 +00:00
|
|
|
|
2018-10-31 01:43:02 +00:00
|
|
|
if (rightJoystickDx == 0 && rightJoystickDy == 0)
|
2018-07-29 04:35:36 +00:00
|
|
|
{
|
2019-02-11 12:00:32 +00:00
|
|
|
(rightJoystickDx, rightJoystickDy) = Configuration.Instance.GamepadControls.GetRightStick();
|
2018-07-29 04:35:36 +00:00
|
|
|
}
|
2018-08-16 23:47:36 +00:00
|
|
|
|
2018-10-31 01:43:02 +00:00
|
|
|
leftJoystick = new HidJoystickPosition
|
2018-02-04 23:08:20 +00:00
|
|
|
{
|
2018-12-06 11:16:24 +00:00
|
|
|
Dx = leftJoystickDx,
|
|
|
|
Dy = leftJoystickDy
|
2018-02-17 23:54:19 +00:00
|
|
|
};
|
2018-02-04 23:08:20 +00:00
|
|
|
|
2018-10-31 01:43:02 +00:00
|
|
|
rightJoystick = new HidJoystickPosition
|
2018-02-04 23:08:20 +00:00
|
|
|
{
|
2018-12-06 11:16:24 +00:00
|
|
|
Dx = rightJoystickDx,
|
|
|
|
Dy = rightJoystickDy
|
2018-02-17 23:54:19 +00:00
|
|
|
};
|
|
|
|
|
2018-12-07 20:59:38 +00:00
|
|
|
currentButton |= _device.Hid.UpdateStickButtons(leftJoystick, rightJoystick);
|
|
|
|
|
2018-10-31 01:43:02 +00:00
|
|
|
bool hasTouch = false;
|
2018-03-03 01:49:17 +00:00
|
|
|
|
2018-02-22 13:28:27 +00:00
|
|
|
//Get screen touch position from left mouse click
|
2018-03-03 01:49:17 +00:00
|
|
|
//OpenTK always captures mouse events, even if out of focus, so check if window is focused.
|
2018-10-31 01:43:02 +00:00
|
|
|
if (Focused && _mouse?.LeftButton == ButtonState.Pressed)
|
2018-03-03 01:49:17 +00:00
|
|
|
{
|
2018-10-31 01:43:02 +00:00
|
|
|
MouseState mouse = _mouse.Value;
|
2018-06-21 21:10:19 +00:00
|
|
|
|
2018-10-31 01:43:02 +00:00
|
|
|
int scrnWidth = Width;
|
|
|
|
int scrnHeight = Height;
|
2018-03-03 01:49:17 +00:00
|
|
|
|
2018-07-29 04:35:36 +00:00
|
|
|
if (Width > (Height * TouchScreenWidth) / TouchScreenHeight)
|
2018-02-22 13:28:27 +00:00
|
|
|
{
|
2018-10-31 01:43:02 +00:00
|
|
|
scrnWidth = (Height * TouchScreenWidth) / TouchScreenHeight;
|
2018-03-03 01:49:17 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2018-10-31 01:43:02 +00:00
|
|
|
scrnHeight = (Width * TouchScreenHeight) / TouchScreenWidth;
|
2018-03-03 01:49:17 +00:00
|
|
|
}
|
|
|
|
|
2018-10-31 01:43:02 +00:00
|
|
|
int startX = (Width - scrnWidth) >> 1;
|
|
|
|
int startY = (Height - scrnHeight) >> 1;
|
2018-03-03 01:49:17 +00:00
|
|
|
|
2018-10-31 01:43:02 +00:00
|
|
|
int endX = startX + scrnWidth;
|
|
|
|
int endY = startY + scrnHeight;
|
2018-03-03 01:49:17 +00:00
|
|
|
|
2018-10-31 01:43:02 +00:00
|
|
|
if (mouse.X >= startX &&
|
|
|
|
mouse.Y >= startY &&
|
|
|
|
mouse.X < endX &&
|
|
|
|
mouse.Y < endY)
|
2018-03-03 01:49:17 +00:00
|
|
|
{
|
2018-10-31 01:43:02 +00:00
|
|
|
int scrnMouseX = mouse.X - startX;
|
|
|
|
int scrnMouseY = mouse.Y - startY;
|
2018-03-03 01:49:17 +00:00
|
|
|
|
2018-10-31 01:43:02 +00:00
|
|
|
int mX = (scrnMouseX * TouchScreenWidth) / scrnWidth;
|
|
|
|
int mY = (scrnMouseY * TouchScreenHeight) / scrnHeight;
|
2018-03-03 01:49:17 +00:00
|
|
|
|
2018-10-31 01:43:02 +00:00
|
|
|
HidTouchPoint currentPoint = new HidTouchPoint
|
2018-02-22 13:28:27 +00:00
|
|
|
{
|
2018-10-31 01:43:02 +00:00
|
|
|
X = mX,
|
|
|
|
Y = mY,
|
2018-02-22 13:28:27 +00:00
|
|
|
|
|
|
|
//Placeholder values till more data is acquired
|
|
|
|
DiameterX = 10,
|
|
|
|
DiameterY = 10,
|
2018-03-03 01:49:17 +00:00
|
|
|
Angle = 90
|
2018-02-22 13:28:27 +00:00
|
|
|
};
|
2018-03-03 01:49:17 +00:00
|
|
|
|
2018-10-31 01:43:02 +00:00
|
|
|
hasTouch = true;
|
2018-03-03 01:49:17 +00:00
|
|
|
|
2018-10-31 01:43:02 +00:00
|
|
|
_device.Hid.SetTouchPoints(currentPoint);
|
2018-02-22 13:28:27 +00:00
|
|
|
}
|
2018-03-03 01:49:17 +00:00
|
|
|
}
|
2018-02-22 13:28:27 +00:00
|
|
|
|
2018-10-31 01:43:02 +00:00
|
|
|
if (!hasTouch)
|
2018-03-03 01:49:17 +00:00
|
|
|
{
|
2018-10-31 01:43:02 +00:00
|
|
|
_device.Hid.SetTouchPoints();
|
2018-03-03 01:49:17 +00:00
|
|
|
}
|
|
|
|
|
2018-11-20 00:01:36 +00:00
|
|
|
HidControllerBase controller = _device.Hid.PrimaryController;
|
|
|
|
|
|
|
|
controller.SendInput(currentButton, leftJoystick, rightJoystick);
|
2019-04-22 06:54:31 +00:00
|
|
|
|
|
|
|
// Toggle vsync
|
|
|
|
if (currentHotkeyButtons.HasFlag(HidHotkeyButtons.ToggleVSync) &&
|
|
|
|
!_prevHotkeyButtons.HasFlag(HidHotkeyButtons.ToggleVSync))
|
|
|
|
{
|
|
|
|
_device.EnableDeviceVsync = !_device.EnableDeviceVsync;
|
|
|
|
}
|
|
|
|
|
|
|
|
_prevHotkeyButtons = currentHotkeyButtons;
|
2018-02-04 23:08:20 +00:00
|
|
|
}
|
|
|
|
|
2018-07-12 17:03:52 +00:00
|
|
|
private new void RenderFrame()
|
2018-02-04 23:08:20 +00:00
|
|
|
{
|
2018-10-31 01:43:02 +00:00
|
|
|
_renderer.RenderTarget.Render();
|
2018-03-06 20:18:49 +00:00
|
|
|
|
2018-10-31 01:43:02 +00:00
|
|
|
_device.Statistics.RecordSystemFrameTime();
|
2018-02-09 00:43:22 +00:00
|
|
|
|
2018-10-31 01:43:02 +00:00
|
|
|
double hostFps = _device.Statistics.GetSystemFrameRate();
|
|
|
|
double gameFps = _device.Statistics.GetGameFrameRate();
|
2018-02-04 23:08:20 +00:00
|
|
|
|
2018-10-31 01:43:02 +00:00
|
|
|
string titleSection = string.IsNullOrWhiteSpace(_device.System.CurrentTitle) ? string.Empty
|
|
|
|
: " | " + _device.System.CurrentTitle;
|
2018-09-19 12:09:49 +00:00
|
|
|
|
2018-10-31 01:43:02 +00:00
|
|
|
_newTitle = $"Ryujinx{titleSection} | Host FPS: {hostFps:0.0} | Game FPS: {gameFps:0.0} | " +
|
|
|
|
$"Game Vsync: {(_device.EnableDeviceVsync ? "On" : "Off")}";
|
2018-07-12 17:03:52 +00:00
|
|
|
|
2018-10-31 01:43:02 +00:00
|
|
|
_titleEvent = true;
|
2018-03-06 20:18:49 +00:00
|
|
|
|
2018-06-24 00:39:25 +00:00
|
|
|
SwapBuffers();
|
2018-03-19 18:58:46 +00:00
|
|
|
|
2018-10-31 01:43:02 +00:00
|
|
|
_device.System.SignalVsync();
|
2018-09-09 23:38:56 +00:00
|
|
|
|
2018-10-31 01:43:02 +00:00
|
|
|
_device.VsyncEvent.Set();
|
2018-02-04 23:08:20 +00:00
|
|
|
}
|
|
|
|
|
2018-07-12 17:03:52 +00:00
|
|
|
protected override void OnUnload(EventArgs e)
|
|
|
|
{
|
2018-10-31 01:43:02 +00:00
|
|
|
_renderThread.Join();
|
2018-07-12 17:03:52 +00:00
|
|
|
|
|
|
|
base.OnUnload(e);
|
|
|
|
}
|
|
|
|
|
2018-02-20 10:52:35 +00:00
|
|
|
protected override void OnResize(EventArgs e)
|
|
|
|
{
|
2018-10-31 01:43:02 +00:00
|
|
|
_resizeEvent = true;
|
2018-02-04 23:08:20 +00:00
|
|
|
}
|
2018-06-21 21:10:19 +00:00
|
|
|
|
|
|
|
protected override void OnKeyDown(KeyboardKeyEventArgs e)
|
|
|
|
{
|
2018-10-31 01:43:02 +00:00
|
|
|
bool toggleFullscreen = e.Key == Key.F11 ||
|
2018-07-29 04:35:36 +00:00
|
|
|
(e.Modifiers.HasFlag(KeyModifiers.Alt) && e.Key == Key.Enter);
|
|
|
|
|
|
|
|
if (WindowState == WindowState.Fullscreen)
|
|
|
|
{
|
2018-10-31 01:43:02 +00:00
|
|
|
if (e.Key == Key.Escape || toggleFullscreen)
|
2018-07-29 04:35:36 +00:00
|
|
|
{
|
|
|
|
WindowState = WindowState.Normal;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (e.Key == Key.Escape)
|
|
|
|
{
|
|
|
|
Exit();
|
|
|
|
}
|
|
|
|
|
2018-10-31 01:43:02 +00:00
|
|
|
if (toggleFullscreen)
|
2018-07-29 04:35:36 +00:00
|
|
|
{
|
|
|
|
WindowState = WindowState.Fullscreen;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-10-31 01:43:02 +00:00
|
|
|
_keyboard = e.Keyboard;
|
2018-06-21 21:10:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
protected override void OnKeyUp(KeyboardKeyEventArgs e)
|
|
|
|
{
|
2018-10-31 01:43:02 +00:00
|
|
|
_keyboard = e.Keyboard;
|
2018-06-21 21:10:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
protected override void OnMouseDown(MouseButtonEventArgs e)
|
|
|
|
{
|
2018-10-31 01:43:02 +00:00
|
|
|
_mouse = e.Mouse;
|
2018-06-21 21:10:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
protected override void OnMouseUp(MouseButtonEventArgs e)
|
|
|
|
{
|
2018-10-31 01:43:02 +00:00
|
|
|
_mouse = e.Mouse;
|
2018-06-21 21:10:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
protected override void OnMouseMove(MouseMoveEventArgs e)
|
|
|
|
{
|
2018-10-31 01:43:02 +00:00
|
|
|
_mouse = e.Mouse;
|
2018-06-21 21:10:19 +00:00
|
|
|
}
|
2018-02-04 23:08:20 +00:00
|
|
|
}
|
|
|
|
}
|