|
@@ -20,6 +20,8 @@ using System.IO;
|
|
|
using System.Runtime.InteropServices;
|
|
using System.Runtime.InteropServices;
|
|
|
using System.Threading;
|
|
using System.Threading;
|
|
|
using static SDL2.SDL;
|
|
using static SDL2.SDL;
|
|
|
|
|
+using AntiAliasing = Ryujinx.Common.Configuration.AntiAliasing;
|
|
|
|
|
+using ScalingFilter = Ryujinx.Common.Configuration.ScalingFilter;
|
|
|
using Switch = Ryujinx.HLE.Switch;
|
|
using Switch = Ryujinx.HLE.Switch;
|
|
|
|
|
|
|
|
namespace Ryujinx.Headless.SDL2
|
|
namespace Ryujinx.Headless.SDL2
|
|
@@ -28,8 +30,9 @@ namespace Ryujinx.Headless.SDL2
|
|
|
{
|
|
{
|
|
|
protected const int DefaultWidth = 1280;
|
|
protected const int DefaultWidth = 1280;
|
|
|
protected const int DefaultHeight = 720;
|
|
protected const int DefaultHeight = 720;
|
|
|
- private const SDL_WindowFlags DefaultFlags = SDL_WindowFlags.SDL_WINDOW_ALLOW_HIGHDPI | SDL_WindowFlags.SDL_WINDOW_RESIZABLE | SDL_WindowFlags.SDL_WINDOW_INPUT_FOCUS | SDL_WindowFlags.SDL_WINDOW_SHOWN;
|
|
|
|
|
private const int TargetFps = 60;
|
|
private const int TargetFps = 60;
|
|
|
|
|
+ private SDL_WindowFlags DefaultFlags = SDL_WindowFlags.SDL_WINDOW_ALLOW_HIGHDPI | SDL_WindowFlags.SDL_WINDOW_RESIZABLE | SDL_WindowFlags.SDL_WINDOW_INPUT_FOCUS | SDL_WindowFlags.SDL_WINDOW_SHOWN;
|
|
|
|
|
+ private SDL_WindowFlags FullscreenFlag = 0;
|
|
|
|
|
|
|
|
private static readonly ConcurrentQueue<Action> _mainThreadActions = new();
|
|
private static readonly ConcurrentQueue<Action> _mainThreadActions = new();
|
|
|
|
|
|
|
@@ -54,7 +57,14 @@ namespace Ryujinx.Headless.SDL2
|
|
|
public IHostUiTheme HostUiTheme { get; }
|
|
public IHostUiTheme HostUiTheme { get; }
|
|
|
public int Width { get; private set; }
|
|
public int Width { get; private set; }
|
|
|
public int Height { get; private set; }
|
|
public int Height { get; private set; }
|
|
|
|
|
+ public int DisplayId { get; set; }
|
|
|
public bool IsFullscreen { get; set; }
|
|
public bool IsFullscreen { get; set; }
|
|
|
|
|
+ public bool IsExclusiveFullscreen { get; set; }
|
|
|
|
|
+ public int ExclusiveFullscreenWidth { get; set; }
|
|
|
|
|
+ public int ExclusiveFullscreenHeight { get; set; }
|
|
|
|
|
+ public AntiAliasing AntiAliasing { get; set; }
|
|
|
|
|
+ public ScalingFilter ScalingFilter { get; set; }
|
|
|
|
|
+ public int ScalingFilterLevel { get; set; }
|
|
|
|
|
|
|
|
protected SDL2MouseDriver MouseDriver;
|
|
protected SDL2MouseDriver MouseDriver;
|
|
|
private readonly InputManager _inputManager;
|
|
private readonly InputManager _inputManager;
|
|
@@ -158,9 +168,24 @@ namespace Ryujinx.Headless.SDL2
|
|
|
string titleIdSection = string.IsNullOrWhiteSpace(activeProcess.ProgramIdText) ? string.Empty : $" ({activeProcess.ProgramIdText.ToUpper()})";
|
|
string titleIdSection = string.IsNullOrWhiteSpace(activeProcess.ProgramIdText) ? string.Empty : $" ({activeProcess.ProgramIdText.ToUpper()})";
|
|
|
string titleArchSection = activeProcess.Is64Bit ? " (64-bit)" : " (32-bit)";
|
|
string titleArchSection = activeProcess.Is64Bit ? " (64-bit)" : " (32-bit)";
|
|
|
|
|
|
|
|
- SDL_WindowFlags fullscreenFlag = IsFullscreen ? SDL_WindowFlags.SDL_WINDOW_FULLSCREEN_DESKTOP : 0;
|
|
|
|
|
|
|
+ Width = DefaultWidth;
|
|
|
|
|
+ Height = DefaultHeight;
|
|
|
|
|
+
|
|
|
|
|
+ if (IsExclusiveFullscreen)
|
|
|
|
|
+ {
|
|
|
|
|
+ Width = ExclusiveFullscreenWidth;
|
|
|
|
|
+ Height = ExclusiveFullscreenHeight;
|
|
|
|
|
+
|
|
|
|
|
+ DefaultFlags = SDL_WindowFlags.SDL_WINDOW_ALLOW_HIGHDPI;
|
|
|
|
|
+ FullscreenFlag = SDL_WindowFlags.SDL_WINDOW_FULLSCREEN;
|
|
|
|
|
+ }
|
|
|
|
|
+ else if (IsFullscreen)
|
|
|
|
|
+ {
|
|
|
|
|
+ DefaultFlags = SDL_WindowFlags.SDL_WINDOW_ALLOW_HIGHDPI;
|
|
|
|
|
+ FullscreenFlag = SDL_WindowFlags.SDL_WINDOW_FULLSCREEN_DESKTOP;
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- WindowHandle = SDL_CreateWindow($"Ryujinx {Program.Version}{titleNameSection}{titleVersionSection}{titleIdSection}{titleArchSection}", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, DefaultWidth, DefaultHeight, DefaultFlags | fullscreenFlag | GetWindowFlags());
|
|
|
|
|
|
|
+ WindowHandle = SDL_CreateWindow($"Ryujinx {Program.Version}{titleNameSection}{titleVersionSection}{titleIdSection}{titleArchSection}", SDL_WINDOWPOS_CENTERED_DISPLAY(DisplayId), SDL_WINDOWPOS_CENTERED_DISPLAY(DisplayId), Width, Height, DefaultFlags | FullscreenFlag | GetWindowFlags());
|
|
|
|
|
|
|
|
if (WindowHandle == IntPtr.Zero)
|
|
if (WindowHandle == IntPtr.Zero)
|
|
|
{
|
|
{
|
|
@@ -175,9 +200,6 @@ namespace Ryujinx.Headless.SDL2
|
|
|
|
|
|
|
|
_windowId = SDL_GetWindowID(WindowHandle);
|
|
_windowId = SDL_GetWindowID(WindowHandle);
|
|
|
SDL2Driver.Instance.RegisterWindow(_windowId, HandleWindowEvent);
|
|
SDL2Driver.Instance.RegisterWindow(_windowId, HandleWindowEvent);
|
|
|
-
|
|
|
|
|
- Width = DefaultWidth;
|
|
|
|
|
- Height = DefaultHeight;
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
private void HandleWindowEvent(SDL_Event evnt)
|
|
private void HandleWindowEvent(SDL_Event evnt)
|
|
@@ -189,8 +211,8 @@ namespace Ryujinx.Headless.SDL2
|
|
|
case SDL_WindowEventID.SDL_WINDOWEVENT_SIZE_CHANGED:
|
|
case SDL_WindowEventID.SDL_WINDOWEVENT_SIZE_CHANGED:
|
|
|
// Unlike on Windows, this event fires on macOS when triggering fullscreen mode.
|
|
// Unlike on Windows, this event fires on macOS when triggering fullscreen mode.
|
|
|
// And promptly crashes the process because `Renderer?.window.SetSize` is undefined.
|
|
// And promptly crashes the process because `Renderer?.window.SetSize` is undefined.
|
|
|
- // As we don't need this to fire in either case we can test for isFullscreen.
|
|
|
|
|
- if (!IsFullscreen)
|
|
|
|
|
|
|
+ // As we don't need this to fire in either case we can test for fullscreen.
|
|
|
|
|
+ if (!IsFullscreen && !IsExclusiveFullscreen)
|
|
|
{
|
|
{
|
|
|
Width = evnt.window.data1;
|
|
Width = evnt.window.data1;
|
|
|
Height = evnt.window.data2;
|
|
Height = evnt.window.data2;
|
|
@@ -225,6 +247,17 @@ namespace Ryujinx.Headless.SDL2
|
|
|
return Renderer.GetHardwareInfo().GpuVendor;
|
|
return Renderer.GetHardwareInfo().GpuVendor;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ private void SetAntiAliasing()
|
|
|
|
|
+ {
|
|
|
|
|
+ Renderer?.Window.SetAntiAliasing((Graphics.GAL.AntiAliasing)AntiAliasing);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private void SetScalingFilter()
|
|
|
|
|
+ {
|
|
|
|
|
+ Renderer?.Window.SetScalingFilter((Graphics.GAL.ScalingFilter)ScalingFilter);
|
|
|
|
|
+ Renderer?.Window.SetScalingFilterLevel(ScalingFilterLevel);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
public void Render()
|
|
public void Render()
|
|
|
{
|
|
{
|
|
|
InitializeWindowRenderer();
|
|
InitializeWindowRenderer();
|
|
@@ -233,6 +266,10 @@ namespace Ryujinx.Headless.SDL2
|
|
|
|
|
|
|
|
InitializeRenderer();
|
|
InitializeRenderer();
|
|
|
|
|
|
|
|
|
|
+ SetAntiAliasing();
|
|
|
|
|
+
|
|
|
|
|
+ SetScalingFilter();
|
|
|
|
|
+
|
|
|
_gpuVendorName = GetGpuVendorName();
|
|
_gpuVendorName = GetGpuVendorName();
|
|
|
|
|
|
|
|
Device.Gpu.Renderer.RunLoop(() =>
|
|
Device.Gpu.Renderer.RunLoop(() =>
|