From c19c8bbadea027e4f31a0739fac0f2a27fbe6dbf Mon Sep 17 00:00:00 2001 From: Theun de Bruijn Date: Thu, 6 Jul 2023 20:10:15 +1000 Subject: [PATCH] Headless: Add support for fullscreen option (#5339) * Headless: Added support for fullscreen option * Headless: cleanup of fullscreen support * Headless: fullscreen support : implemented proposed changes * Headless: fullscreen support: cleanup * Headless: fullscreen support: fix for OpenGL scaling * Headless: fullscreen support: cleanup * Headless: fullscreen support: cleanup * Headless: fullscreen support: add. macOS fullscreen fix * Headless: fullscreen support: cleanup * Headless: fullscreen support: cleanup * Headless: fullscreen support: cleanup --- .../OpenGL/OpenGLWindow.cs | 18 ++++++++++++++++-- src/Ryujinx.Headless.SDL2/Options.cs | 3 +++ src/Ryujinx.Headless.SDL2/Program.cs | 5 +++++ src/Ryujinx.Headless.SDL2/WindowBase.cs | 19 ++++++++++++++----- 4 files changed, 38 insertions(+), 7 deletions(-) diff --git a/src/Ryujinx.Headless.SDL2/OpenGL/OpenGLWindow.cs b/src/Ryujinx.Headless.SDL2/OpenGL/OpenGLWindow.cs index 199f723e..355dcf6c 100644 --- a/src/Ryujinx.Headless.SDL2/OpenGL/OpenGLWindow.cs +++ b/src/Ryujinx.Headless.SDL2/OpenGL/OpenGLWindow.cs @@ -151,8 +151,22 @@ namespace Ryujinx.Headless.SDL2.OpenGL GL.Clear(ClearBufferMask.ColorBufferBit); SwapBuffers(); - Renderer?.Window.SetSize(DefaultWidth, DefaultHeight); - MouseDriver.SetClientSize(DefaultWidth, DefaultHeight); + if (IsFullscreen) + { + // NOTE: grabbing the main display's dimensions directly as OpenGL doesn't scale along like the VulkanWindow. + // we might have to amend this if people run this on a non-primary display set to a different resolution. + SDL_Rect displayBounds; + SDL_GetDisplayBounds(0, out displayBounds); + + Renderer?.Window.SetSize(displayBounds.w, displayBounds.h); + MouseDriver.SetClientSize(displayBounds.w, displayBounds.h); + } + + else + { + Renderer?.Window.SetSize(DefaultWidth, DefaultHeight); + MouseDriver.SetClientSize(DefaultWidth, DefaultHeight); + } } protected override void InitializeRenderer() { } diff --git a/src/Ryujinx.Headless.SDL2/Options.cs b/src/Ryujinx.Headless.SDL2/Options.cs index 86a6c63c..e44cedec 100644 --- a/src/Ryujinx.Headless.SDL2/Options.cs +++ b/src/Ryujinx.Headless.SDL2/Options.cs @@ -14,6 +14,9 @@ namespace Ryujinx.Headless.SDL2 [Option("profile", Required = false, HelpText = "Set the user profile to launch the game with.")] public string UserProfile { get; set; } + [Option("fullscreen", Required = false, HelpText = "Launch the game in fullscreen mode.")] + public bool IsFullscreen { get; set; } + // Input [Option("input-profile-1", Required = false, HelpText = "Set the input profile in use for Player 1.")] diff --git a/src/Ryujinx.Headless.SDL2/Program.cs b/src/Ryujinx.Headless.SDL2/Program.cs index 39eae14a..98cc5abf 100644 --- a/src/Ryujinx.Headless.SDL2/Program.cs +++ b/src/Ryujinx.Headless.SDL2/Program.cs @@ -64,6 +64,9 @@ namespace Ryujinx.Headless.SDL2 { Version = ReleaseInformation.GetVersion(); + // Make process DPI aware for proper window sizing on high-res screens. + ForceDpiAware.Windows(); + Console.Title = $"Ryujinx Console {Version} (Headless SDL2)"; if (OperatingSystem.IsMacOS() || OperatingSystem.IsLinux()) @@ -592,6 +595,8 @@ namespace Ryujinx.Headless.SDL2 _window = window; + _window.IsFullscreen = options.IsFullscreen; + _emulationContext = InitializeEmulationContext(window, renderer, options); SystemVersion firmwareVersion = _contentManager.GetCurrentFirmwareVersion(); diff --git a/src/Ryujinx.Headless.SDL2/WindowBase.cs b/src/Ryujinx.Headless.SDL2/WindowBase.cs index 2fcd00f8..c542a4e6 100644 --- a/src/Ryujinx.Headless.SDL2/WindowBase.cs +++ b/src/Ryujinx.Headless.SDL2/WindowBase.cs @@ -55,6 +55,7 @@ namespace Ryujinx.Headless.SDL2 public IHostUiTheme HostUiTheme { get; } public int Width { get; private set; } public int Height { get; private set; } + public bool IsFullscreen { get; set; } protected SDL2MouseDriver MouseDriver; private readonly InputManager _inputManager; @@ -158,7 +159,9 @@ namespace Ryujinx.Headless.SDL2 string titleIdSection = string.IsNullOrWhiteSpace(activeProcess.ProgramIdText) ? string.Empty : $" ({activeProcess.ProgramIdText.ToUpper()})"; string titleArchSection = activeProcess.Is64Bit ? " (64-bit)" : " (32-bit)"; - WindowHandle = SDL_CreateWindow($"Ryujinx {Program.Version}{titleNameSection}{titleVersionSection}{titleIdSection}{titleArchSection}", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, DefaultWidth, DefaultHeight, DefaultFlags | GetWindowFlags()); + SDL_WindowFlags fullscreenFlag = IsFullscreen ? SDL_WindowFlags.SDL_WINDOW_FULLSCREEN_DESKTOP : 0; + + WindowHandle = SDL_CreateWindow($"Ryujinx {Program.Version}{titleNameSection}{titleVersionSection}{titleIdSection}{titleArchSection}", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, DefaultWidth, DefaultHeight, DefaultFlags | fullscreenFlag | GetWindowFlags()); if (WindowHandle == IntPtr.Zero) { @@ -185,10 +188,16 @@ namespace Ryujinx.Headless.SDL2 switch (evnt.window.windowEvent) { case SDL_WindowEventID.SDL_WINDOWEVENT_SIZE_CHANGED: - Width = evnt.window.data1; - Height = evnt.window.data2; - Renderer?.Window.SetSize(Width, Height); - MouseDriver.SetClientSize(Width, Height); + // Unlike on Windows, this event fires on macOS when triggering fullscreen mode. + // 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) + { + Width = evnt.window.data1; + Height = evnt.window.data2; + Renderer?.Window.SetSize(Width, Height); + MouseDriver.SetClientSize(Width, Height); + } break; case SDL_WindowEventID.SDL_WINDOWEVENT_CLOSE: