diff --git a/Directory.Packages.props b/Directory.Packages.props index c2ac358ed..17a1ecdc2 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -14,10 +14,10 @@ - - + + - + @@ -41,7 +41,6 @@ - @@ -58,4 +57,4 @@ - + \ No newline at end of file diff --git a/src/Ryujinx.Input.SDL3/SDL3GamepadDriver.cs b/src/Ryujinx.Input.SDL3/SDL3GamepadDriver.cs index b0167896d..14526cc77 100644 --- a/src/Ryujinx.Input.SDL3/SDL3GamepadDriver.cs +++ b/src/Ryujinx.Input.SDL3/SDL3GamepadDriver.cs @@ -8,7 +8,7 @@ using System.Text; using System.Threading; using static SDL3.SDL; -namespace Ryujinx.Input.SDl3 +namespace Ryujinx.Input.SDL3 { public class SDL3GamepadDriver : IGamepadDriver { diff --git a/src/Ryujinx.SDL3-CS/SDL3.cs b/src/Ryujinx.SDL3-CS/SDL3.cs index d5699c2a9..793cfa5d1 100644 --- a/src/Ryujinx.SDL3-CS/SDL3.cs +++ b/src/Ryujinx.SDL3-CS/SDL3.cs @@ -1998,7 +1998,19 @@ public static unsafe partial class SDL public const string SDL_PROP_WINDOW_X11_DISPLAY_POINTER = "SDL.window.x11.display"; public const string SDL_PROP_WINDOW_X11_SCREEN_NUMBER = "SDL.window.x11.screen"; public const string SDL_PROP_WINDOW_X11_WINDOW_NUMBER = "SDL.window.x11.window"; - + + [Flags] + public enum SDL_GLProfile + { + SDL_GL_CONTEXT_PROFILE_COMPATIBILITY = 2 + } + + [Flags] + public enum SDL_GLcontext + { + SDL_GL_CONTEXT_DEBUG_FLAG = 1, + } + public enum SDL_SystemTheme { SDL_SYSTEM_THEME_UNKNOWN = 0, @@ -8054,4 +8066,14 @@ public static unsafe partial class SDL [LibraryImport(nativeLibName)] [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])] public static partial int SDL_EnterAppMainCallbacks(int argc, IntPtr argv, SDL_AppInit_func appinit, SDL_AppIterate_func appiter, SDL_AppEvent_func appevent, SDL_AppQuit_func appquit); + + // include/SDL3/SDL_vulkan.h + [LibraryImport(nativeLibName)] + [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])] + public static partial SDLBool SDL_Vulkan_CreateSurface(IntPtr window, IntPtr instance, IntPtr allocator, + out ulong surface); + + [LibraryImport(nativeLibName)] + [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])] + public static partial IntPtr SDL_Vulkan_GetInstanceExtensions(out uint count); } diff --git a/src/Ryujinx/AppHost.cs b/src/Ryujinx/AppHost.cs index baf805d6a..6247e44a3 100644 --- a/src/Ryujinx/AppHost.cs +++ b/src/Ryujinx/AppHost.cs @@ -8,7 +8,6 @@ using LibHac.Ns; using LibHac.Tools.FsSystem; using Ryujinx.Audio.Backends.Dummy; using Ryujinx.Audio.Backends.OpenAL; -using Ryujinx.Audio.Backends.SDL2; using Ryujinx.Audio.Backends.SDL3; using Ryujinx.Audio.Backends.SoundIo; using Ryujinx.Audio.Integration; @@ -959,7 +958,6 @@ namespace Ryujinx.Ava var availableBackends = new List { AudioBackend.SDL3, - AudioBackend.SDL2, AudioBackend.SoundIo, AudioBackend.OpenAl, AudioBackend.Dummy, @@ -999,7 +997,6 @@ namespace Ryujinx.Ava deviceDriver = currentBackend switch { AudioBackend.SDL3 => InitializeAudioBackend(AudioBackend.SDL3, nextBackend), - AudioBackend.SDL2 => InitializeAudioBackend(AudioBackend.SDL2, nextBackend), AudioBackend.SoundIo => InitializeAudioBackend(AudioBackend.SoundIo, nextBackend), AudioBackend.OpenAl => InitializeAudioBackend(AudioBackend.OpenAl, nextBackend), _ => new DummyHardwareDeviceDriver(), diff --git a/src/Ryujinx/Headless/HeadlessRyujinx.Init.cs b/src/Ryujinx/Headless/HeadlessRyujinx.Init.cs index 86df593d1..0b6e68819 100644 --- a/src/Ryujinx/Headless/HeadlessRyujinx.Init.cs +++ b/src/Ryujinx/Headless/HeadlessRyujinx.Init.cs @@ -1,6 +1,6 @@ using DiscordRPC; using LibHac.Tools.FsSystem; -using Ryujinx.Audio.Backends.SDL2; +using Ryujinx.Audio.Backends.SDL3; using Ryujinx.Ava; using Ryujinx.Ava.Utilities.Configuration; using Ryujinx.Common.Configuration; @@ -335,7 +335,7 @@ namespace Ryujinx.Headless _accountManager, _userChannelPersistence, renderer, - new SDL2HardwareDeviceDriver(), + new SDL3HardwareDeviceDriver(), options.DramSize, window, options.SystemLanguage, diff --git a/src/Ryujinx/Headless/HeadlessRyujinx.cs b/src/Ryujinx/Headless/HeadlessRyujinx.cs index 5730254f7..7fe800135 100644 --- a/src/Ryujinx/Headless/HeadlessRyujinx.cs +++ b/src/Ryujinx/Headless/HeadlessRyujinx.cs @@ -21,8 +21,8 @@ using Ryujinx.HLE.HOS; using Ryujinx.HLE.HOS.Services.Account.Acc; using Ryujinx.Input; using Ryujinx.Input.HLE; -using Ryujinx.Input.SDL2; -using Ryujinx.SDL2.Common; +using Ryujinx.Input.SDL3; +using Ryujinx.SDL3.Common; using System; using System.Collections.Generic; using System.IO; @@ -59,7 +59,7 @@ namespace Ryujinx.Headless AutoResetEvent invoked = new(false); // MacOS must perform SDL polls from the main thread. - SDL2Driver.MainThreadDispatcher = action => + SDL3Driver.MainThreadDispatcher = action => { invoked.Reset(); @@ -180,7 +180,7 @@ namespace Ryujinx.Headless _accountManager = new AccountManager(_libHacHorizonManager.RyujinxClient, option.UserProfile); _userChannelPersistence = new UserChannelPersistence(); - _inputManager = new InputManager(new SDL2KeyboardDriver(), new SDL2GamepadDriver()); + _inputManager = new InputManager(new SDL3KeyboardDriver(), new SDL3GamepadDriver()); GraphicsConfig.EnableShaderCache = !option.DisableShaderCache; diff --git a/src/Ryujinx/Headless/Metal/MetalWindow.cs b/src/Ryujinx/Headless/Metal/MetalWindow.cs index a2693c69d..c91c66681 100644 --- a/src/Ryujinx/Headless/Metal/MetalWindow.cs +++ b/src/Ryujinx/Headless/Metal/MetalWindow.cs @@ -1,9 +1,9 @@ using Ryujinx.Common.Configuration; using Ryujinx.Input.HLE; -using Ryujinx.SDL2.Common; +using Ryujinx.SDL3.Common; using SharpMetal.QuartzCore; using System.Runtime.Versioning; -using static SDL2.SDL; +using static SDL3.SDL; namespace Ryujinx.Headless { @@ -35,7 +35,7 @@ namespace Ryujinx.Headless _caMetalLayer = new CAMetalLayer(SDL_Metal_GetLayer(SDL_Metal_CreateView(WindowHandle))); } - SDL2Driver.MainThreadDispatcher?.Invoke(CreateLayer); + SDL3Driver.MainThreadDispatcher?.Invoke(CreateLayer); } protected override void InitializeRenderer() { } diff --git a/src/Ryujinx/Headless/OpenGL/OpenGLWindow.cs b/src/Ryujinx/Headless/OpenGL/OpenGLWindow.cs index c00a0648f..52217694e 100644 --- a/src/Ryujinx/Headless/OpenGL/OpenGLWindow.cs +++ b/src/Ryujinx/Headless/OpenGL/OpenGLWindow.cs @@ -5,15 +5,15 @@ using Ryujinx.Common.Logging; using Ryujinx.Graphics.OpenGL; using Ryujinx.Input.HLE; using System; -using static SDL2.SDL; +using static SDL3.SDL; namespace Ryujinx.Headless { class OpenGLWindow : WindowBase { - private static void CheckResult(int result) + private static void CheckResult(bool result) { - if (result < 0) + if (!result) { throw new InvalidOperationException($"SDL_GL function returned an error: {SDL_GetError()}"); } @@ -21,21 +21,21 @@ namespace Ryujinx.Headless private static void SetupOpenGLAttributes(bool sharedContext, GraphicsDebugLevel debugLevel) { - CheckResult(SDL_GL_SetAttribute(SDL_GLattr.SDL_GL_CONTEXT_MAJOR_VERSION, 3)); - CheckResult(SDL_GL_SetAttribute(SDL_GLattr.SDL_GL_CONTEXT_MINOR_VERSION, 3)); - CheckResult(SDL_GL_SetAttribute(SDL_GLattr.SDL_GL_CONTEXT_PROFILE_MASK, SDL_GLprofile.SDL_GL_CONTEXT_PROFILE_COMPATIBILITY)); - CheckResult(SDL_GL_SetAttribute(SDL_GLattr.SDL_GL_CONTEXT_FLAGS, debugLevel != GraphicsDebugLevel.None ? (int)SDL_GLcontext.SDL_GL_CONTEXT_DEBUG_FLAG : 0)); - CheckResult(SDL_GL_SetAttribute(SDL_GLattr.SDL_GL_SHARE_WITH_CURRENT_CONTEXT, sharedContext ? 1 : 0)); + CheckResult(SDL_GL_SetAttribute(SDL_GLAttr.SDL_GL_CONTEXT_MAJOR_VERSION, 3)); + CheckResult(SDL_GL_SetAttribute(SDL_GLAttr.SDL_GL_CONTEXT_MINOR_VERSION, 3)); + CheckResult(SDL_GL_SetAttribute(SDL_GLAttr.SDL_GL_CONTEXT_PROFILE_MASK, (int)SDL_GLProfile.SDL_GL_CONTEXT_PROFILE_COMPATIBILITY)); + CheckResult(SDL_GL_SetAttribute(SDL_GLAttr.SDL_GL_CONTEXT_FLAGS, debugLevel != GraphicsDebugLevel.None ? (int)SDL_GLcontext.SDL_GL_CONTEXT_DEBUG_FLAG : 0)); + CheckResult(SDL_GL_SetAttribute(SDL_GLAttr.SDL_GL_SHARE_WITH_CURRENT_CONTEXT, sharedContext ? 1 : 0)); - CheckResult(SDL_GL_SetAttribute(SDL_GLattr.SDL_GL_ACCELERATED_VISUAL, 1)); - CheckResult(SDL_GL_SetAttribute(SDL_GLattr.SDL_GL_RED_SIZE, 8)); - CheckResult(SDL_GL_SetAttribute(SDL_GLattr.SDL_GL_GREEN_SIZE, 8)); - CheckResult(SDL_GL_SetAttribute(SDL_GLattr.SDL_GL_BLUE_SIZE, 8)); - CheckResult(SDL_GL_SetAttribute(SDL_GLattr.SDL_GL_ALPHA_SIZE, 8)); - CheckResult(SDL_GL_SetAttribute(SDL_GLattr.SDL_GL_DEPTH_SIZE, 16)); - CheckResult(SDL_GL_SetAttribute(SDL_GLattr.SDL_GL_STENCIL_SIZE, 0)); - CheckResult(SDL_GL_SetAttribute(SDL_GLattr.SDL_GL_DOUBLEBUFFER, 1)); - CheckResult(SDL_GL_SetAttribute(SDL_GLattr.SDL_GL_STEREO, 0)); + CheckResult(SDL_GL_SetAttribute(SDL_GLAttr.SDL_GL_ACCELERATED_VISUAL, 1)); + CheckResult(SDL_GL_SetAttribute(SDL_GLAttr.SDL_GL_RED_SIZE, 8)); + CheckResult(SDL_GL_SetAttribute(SDL_GLAttr.SDL_GL_GREEN_SIZE, 8)); + CheckResult(SDL_GL_SetAttribute(SDL_GLAttr.SDL_GL_BLUE_SIZE, 8)); + CheckResult(SDL_GL_SetAttribute(SDL_GLAttr.SDL_GL_ALPHA_SIZE, 8)); + CheckResult(SDL_GL_SetAttribute(SDL_GLAttr.SDL_GL_DEPTH_SIZE, 16)); + CheckResult(SDL_GL_SetAttribute(SDL_GLAttr.SDL_GL_STENCIL_SIZE, 0)); + CheckResult(SDL_GL_SetAttribute(SDL_GLAttr.SDL_GL_DOUBLEBUFFER, 1)); + CheckResult(SDL_GL_SetAttribute(SDL_GLAttr.SDL_GL_STEREO, 0)); } private class OpenToolkitBindingsContext : IBindingsContext @@ -46,35 +46,35 @@ namespace Ryujinx.Headless } } - private class SDL2OpenGLContext : IOpenGLContext + private class SDL3OpenGLContext : IOpenGLContext { private readonly nint _context; private readonly nint _window; private readonly bool _shouldDisposeWindow; - public SDL2OpenGLContext(nint context, nint window, bool shouldDisposeWindow = true) + public SDL3OpenGLContext(nint context, nint window, bool shouldDisposeWindow = true) { _context = context; _window = window; _shouldDisposeWindow = shouldDisposeWindow; } - public static SDL2OpenGLContext CreateBackgroundContext(SDL2OpenGLContext sharedContext) + public static SDL3OpenGLContext CreateBackgroundContext(SDL3OpenGLContext sharedContext) { sharedContext.MakeCurrent(); // Ensure we share our contexts. SetupOpenGLAttributes(true, GraphicsDebugLevel.None); - nint windowHandle = SDL_CreateWindow("Ryujinx background context window", 0, 0, 1, 1, SDL_WindowFlags.SDL_WINDOW_OPENGL | SDL_WindowFlags.SDL_WINDOW_HIDDEN); + nint windowHandle = SDL_CreateWindow("Ryujinx background context window", 1, 1, SDL_WindowFlags.SDL_WINDOW_OPENGL | SDL_WindowFlags.SDL_WINDOW_HIDDEN); nint context = SDL_GL_CreateContext(windowHandle); GL.LoadBindings(new OpenToolkitBindingsContext()); - CheckResult(SDL_GL_SetAttribute(SDL_GLattr.SDL_GL_SHARE_WITH_CURRENT_CONTEXT, 0)); + CheckResult(SDL_GL_SetAttribute(SDL_GLAttr.SDL_GL_SHARE_WITH_CURRENT_CONTEXT, 0)); CheckResult(SDL_GL_MakeCurrent(windowHandle, nint.Zero)); - return new SDL2OpenGLContext(context, windowHandle); + return new SDL3OpenGLContext(context, windowHandle); } public void MakeCurrent() @@ -84,9 +84,7 @@ namespace Ryujinx.Headless return; } - int res = SDL_GL_MakeCurrent(_window, _context); - - if (res != 0) + if (!SDL_GL_MakeCurrent(_window, _context)) { string errorMessage = $"SDL_GL_CreateContext failed with error \"{SDL_GetError()}\""; @@ -100,7 +98,7 @@ namespace Ryujinx.Headless public void Dispose() { - SDL_GL_DeleteContext(_context); + SDL_GL_DestroyContext(_context); if (_shouldDisposeWindow) { @@ -110,7 +108,7 @@ namespace Ryujinx.Headless } private readonly GraphicsDebugLevel _glLogLevel; - private SDL2OpenGLContext _openGLContext; + private SDL3OpenGLContext _openGLContext; public OpenGLWindow( InputManager inputManager, @@ -143,10 +141,10 @@ namespace Ryujinx.Headless } // NOTE: The window handle needs to be disposed by the thread that created it and is handled separately. - _openGLContext = new SDL2OpenGLContext(context, WindowHandle, false); + _openGLContext = new SDL3OpenGLContext(context, WindowHandle, false); // First take exclusivity on the OpenGL context. - ((OpenGLRenderer)Renderer).InitializeBackgroundContext(SDL2OpenGLContext.CreateBackgroundContext(_openGLContext)); + ((OpenGLRenderer)Renderer).InitializeBackgroundContext(SDL3OpenGLContext.CreateBackgroundContext(_openGLContext)); _openGLContext.MakeCurrent(); @@ -162,7 +160,7 @@ namespace Ryujinx.Headless else if (IsFullscreen) { // NOTE: grabbing the main display's dimensions directly as OpenGL doesn't scale along like the VulkanWindow. - if (SDL_GetDisplayBounds(DisplayId, out SDL_Rect displayBounds) < 0) + if (SDL_GetDisplayBounds((uint)DisplayId, out SDL_Rect displayBounds)) { Logger.Warning?.Print(LogClass.Application, $"Could not retrieve display bounds: {SDL_GetError()}"); diff --git a/src/Ryujinx/Headless/Vulkan/VulkanWindow.cs b/src/Ryujinx/Headless/Vulkan/VulkanWindow.cs index 92caad34e..6b455c7c9 100644 --- a/src/Ryujinx/Headless/Vulkan/VulkanWindow.cs +++ b/src/Ryujinx/Headless/Vulkan/VulkanWindow.cs @@ -1,10 +1,10 @@ using Ryujinx.Common.Configuration; using Ryujinx.Common.Logging; using Ryujinx.Input.HLE; -using Ryujinx.SDL2.Common; +using Ryujinx.SDL3.Common; using System; using System.Runtime.InteropServices; -using static SDL2.SDL; +using static SDL3.SDL; namespace Ryujinx.Headless { @@ -53,7 +53,7 @@ namespace Ryujinx.Headless void CreateSurface() { - if (SDL_Vulkan_CreateSurface(WindowHandle, instance, out surfaceHandle) == SDL_bool.SDL_FALSE) + if (!SDL_Vulkan_CreateSurface(WindowHandle, instance, IntPtr.Zero, out surfaceHandle)) { string errorMessage = $"SDL_Vulkan_CreateSurface failed with error \"{SDL_GetError()}\""; @@ -63,9 +63,9 @@ namespace Ryujinx.Headless } } - if (SDL2Driver.MainThreadDispatcher != null) + if (SDL3Driver.MainThreadDispatcher != null) { - SDL2Driver.MainThreadDispatcher(CreateSurface); + SDL3Driver.MainThreadDispatcher(CreateSurface); } else { @@ -77,23 +77,19 @@ namespace Ryujinx.Headless public unsafe string[] GetRequiredInstanceExtensions() { - if (SDL_Vulkan_GetInstanceExtensions(WindowHandle, out uint extensionsCount, nint.Zero) == SDL_bool.SDL_TRUE) + nint rawExtensions = SDL_Vulkan_GetInstanceExtensions(out uint count); + IntPtr[] extensionPointers = new IntPtr[count]; + + Marshal.Copy(rawExtensions, extensionPointers, 0, (int)count); + if (rawExtensions != nint.Zero) { - nint[] rawExtensions = new nint[(int)extensionsCount]; - string[] extensions = new string[(int)extensionsCount]; - - fixed (nint* rawExtensionsPtr = rawExtensions) + string[] extensions = new string[(int)count]; + for (int i = 0; i < extensions.Length; i++) { - if (SDL_Vulkan_GetInstanceExtensions(WindowHandle, out extensionsCount, (nint)rawExtensionsPtr) == SDL_bool.SDL_TRUE) - { - for (int i = 0; i < extensions.Length; i++) - { - extensions[i] = Marshal.PtrToStringUTF8(rawExtensions[i]); - } - - return extensions; - } + extensions[i] = Marshal.PtrToStringUTF8(extensionPointers[i]); } + + return extensions; } string errorMessage = $"SDL_Vulkan_GetInstanceExtensions failed with error \"{SDL_GetError()}\""; diff --git a/src/Ryujinx/Headless/WindowBase.cs b/src/Ryujinx/Headless/WindowBase.cs index e6436b0a2..58c84fa15 100644 --- a/src/Ryujinx/Headless/WindowBase.cs +++ b/src/Ryujinx/Headless/WindowBase.cs @@ -1,5 +1,5 @@ using Humanizer; -using LibHac.Tools.Fs; +using LibHac.Util; using Ryujinx.Ava; using Ryujinx.Common.Configuration; using Ryujinx.Common.Configuration.Hid; @@ -13,8 +13,7 @@ using Ryujinx.HLE.HOS.Services.Am.AppletOE.ApplicationProxyService.ApplicationPr using Ryujinx.HLE.UI; using Ryujinx.Input; using Ryujinx.Input.HLE; -using Ryujinx.Input.SDL2; -using Ryujinx.SDL2.Common; +using Ryujinx.Input.SDL3; using Ryujinx.SDL3.Common; using System; using System.Collections.Concurrent; @@ -23,7 +22,7 @@ using System.Diagnostics; using System.IO; using System.Runtime.InteropServices; using System.Threading; -using static SDL2.SDL; +using static SDL3.SDL; using AntiAliasing = Ryujinx.Common.Configuration.AntiAliasing; using ScalingFilter = Ryujinx.Common.Configuration.ScalingFilter; using Switch = Ryujinx.HLE.Switch; @@ -35,15 +34,15 @@ namespace Ryujinx.Headless protected const int DefaultWidth = 1280; protected const int DefaultHeight = 720; 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 DefaultFlags = SDL_WindowFlags.SDL_WINDOW_HIGH_PIXEL_DENSITY | + SDL_WindowFlags.SDL_WINDOW_RESIZABLE | + SDL_WindowFlags.SDL_WINDOW_INPUT_FOCUS; + private SDL_WindowFlags FullscreenFlag = 0; private static readonly ConcurrentQueue _mainThreadActions = new(); - [LibraryImport("SDL2")] - // TODO: Remove this as soon as SDL2-CS was updated to expose this method publicly - private static partial nint SDL_LoadBMP_RW(nint src, int freesrc); - public static void QueueMainThreadAction(Action action) { _mainThreadActions.Enqueue(action); @@ -70,7 +69,7 @@ namespace Ryujinx.Headless public ScalingFilter ScalingFilter { get; set; } public int ScalingFilterLevel { get; set; } - protected SDL2MouseDriver MouseDriver; + protected SDL3MouseDriver MouseDriver; private readonly InputManager _inputManager; private readonly IKeyboard _keyboardInterface; private readonly GraphicsDebugLevel _glLogLevel; @@ -99,7 +98,7 @@ namespace Ryujinx.Headless HideCursorMode hideCursorMode, bool ignoreControllerApplet) { - MouseDriver = new SDL2MouseDriver(hideCursorMode); + MouseDriver = new SDL3MouseDriver(hideCursorMode); _inputManager = inputManager; _inputManager.SetMouseDriver(MouseDriver); NpadManager = _inputManager.CreateNpadManager(); @@ -116,7 +115,6 @@ namespace Ryujinx.Headless _ignoreControllerApplet = ignoreControllerApplet; HostUITheme = new HeadlessHostUiTheme(); - SDL2Driver.Instance.Initialize(); SDL3Driver.Instance.Initialize(); } @@ -156,11 +154,11 @@ namespace Ryujinx.Headless { fixed (byte* iconPtr = iconBytes) { - nint rwOpsStruct = SDL_RWFromConstMem((nint)iconPtr, iconBytes.Length); - nint iconHandle = SDL_LoadBMP_RW(rwOpsStruct, 1); + nint rwOpsStruct = SDL_IOFromConstMem((nint)iconPtr, (nuint)iconBytes.Length); + SDL_Surface* iconHandle = SDL_LoadBMP_IO(rwOpsStruct, true); - SDL_SetWindowIcon(WindowHandle, iconHandle); - SDL_FreeSurface(iconHandle); + SDL_SetWindowIcon(WindowHandle, (nint)iconHandle); + SDL_DestroySurface((nint)iconHandle); } } } @@ -171,9 +169,15 @@ namespace Ryujinx.Headless var nacp = activeProcess.ApplicationControlProperties; int desiredLanguage = (int)Device.System.State.DesiredTitleLanguage; - string titleNameSection = string.IsNullOrWhiteSpace(nacp.Title[desiredLanguage].NameString.ToString()) ? string.Empty : $" - {nacp.Title[desiredLanguage].NameString.ToString()}"; - string titleVersionSection = string.IsNullOrWhiteSpace(nacp.DisplayVersionString.ToString()) ? string.Empty : $" v{nacp.DisplayVersionString.ToString()}"; - string titleIdSection = string.IsNullOrWhiteSpace(activeProcess.ProgramIdText) ? string.Empty : $" ({activeProcess.ProgramIdText.ToUpper()})"; + string titleNameSection = string.IsNullOrWhiteSpace(nacp.Title[desiredLanguage].NameString.ToString()) + ? string.Empty + : $" - {nacp.Title[desiredLanguage].NameString.ToString()}"; + string titleVersionSection = string.IsNullOrWhiteSpace(nacp.DisplayVersionString.ToString()) + ? string.Empty + : $" v{nacp.DisplayVersionString.ToString()}"; + string titleIdSection = string.IsNullOrWhiteSpace(activeProcess.ProgramIdText) + ? string.Empty + : $" ({activeProcess.ProgramIdText.ToUpper()})"; string titleArchSection = activeProcess.Is64Bit ? " (64-bit)" : " (32-bit)"; Width = DefaultWidth; @@ -184,16 +188,19 @@ namespace Ryujinx.Headless Width = ExclusiveFullscreenWidth; Height = ExclusiveFullscreenHeight; - DefaultFlags = SDL_WindowFlags.SDL_WINDOW_ALLOW_HIGHDPI; + DefaultFlags = SDL_WindowFlags.SDL_WINDOW_HIGH_PIXEL_DENSITY; FullscreenFlag = SDL_WindowFlags.SDL_WINDOW_FULLSCREEN; } else if (IsFullscreen) { - DefaultFlags = SDL_WindowFlags.SDL_WINDOW_ALLOW_HIGHDPI; - FullscreenFlag = SDL_WindowFlags.SDL_WINDOW_FULLSCREEN_DESKTOP; + DefaultFlags = SDL_WindowFlags.SDL_WINDOW_HIGH_PIXEL_DENSITY; + FullscreenFlag = SDL_WindowFlags.SDL_WINDOW_FULLSCREEN; } - 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()); + WindowHandle = + SDL_CreateWindow( + $"Ryujinx {Program.Version}{titleNameSection}{titleVersionSection}{titleIdSection}{titleArchSection}", + Width, Height, DefaultFlags | FullscreenFlag | GetWindowFlags()); if (WindowHandle == nint.Zero) { @@ -207,16 +214,18 @@ namespace Ryujinx.Headless SetWindowIcon(); _windowId = SDL_GetWindowID(WindowHandle); - SDL2Driver.Instance.RegisterWindow(_windowId, HandleWindowEvent); + SDL3Driver.Instance.RegisterWindow(_windowId, HandleWindowEvent); } private void HandleWindowEvent(SDL_Event evnt) { - if (evnt.type == SDL_EventType.SDL_WINDOWEVENT) + if (evnt.type >= (uint)SDL_EventType.SDL_EVENT_WINDOW_FIRST && + evnt.type <= (uint)SDL_EventType.SDL_EVENT_WINDOW_LAST) { - switch (evnt.window.windowEvent) + switch (evnt.window.type) { - case SDL_WindowEventID.SDL_WINDOWEVENT_SIZE_CHANGED: + case SDL_EventType.SDL_EVENT_WINDOW_RESIZED: + case SDL_EventType.SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED: // 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 fullscreen. @@ -227,9 +236,10 @@ namespace Ryujinx.Headless Renderer?.Window.SetSize(Width, Height); MouseDriver.SetClientSize(Width, Height); } + break; - case SDL_WindowEventID.SDL_WINDOWEVENT_CLOSE: + case SDL_EventType.SDL_EVENT_WINDOW_CLOSE_REQUESTED: Exit(); break; } @@ -424,7 +434,9 @@ namespace Ryujinx.Headless // Get screen touch position if (!_enableMouse) { - hasTouch = TouchScreenManager.Update(true, (_inputManager.MouseDriver as SDL2MouseDriver).IsButtonPressed(MouseButton.Button1), _aspectRatio.ToFloat()); + hasTouch = TouchScreenManager.Update(true, + (_inputManager.MouseDriver as SDL3MouseDriver).IsButtonPressed(MouseButton.Button1), + _aspectRatio.ToFloat()); } if (!hasTouch) @@ -447,19 +459,13 @@ namespace Ryujinx.Headless InitializeWindow(); - Thread renderLoopThread = new(Render) - { - Name = "GUI.RenderLoop", - }; + Thread renderLoopThread = new(Render) { Name = "GUI.RenderLoop", }; renderLoopThread.Start(); Thread nvidiaStutterWorkaround = null; if (Renderer is OpenGLRenderer) { - nvidiaStutterWorkaround = new Thread(NvidiaStutterWorkaround) - { - Name = "GUI.NvidiaStutterWorkaround", - }; + nvidiaStutterWorkaround = new Thread(NvidiaStutterWorkaround) { Name = "GUI.NvidiaStutterWorkaround", }; nvidiaStutterWorkaround.Start(); } @@ -499,20 +505,24 @@ namespace Ryujinx.Headless public void DisplayCabinetMessageDialog() { - SDL_ShowSimpleMessageBox(SDL_MessageBoxFlags.SDL_MESSAGEBOX_INFORMATION, "Cabinet Dialog", "Please scan your Amiibo now.", WindowHandle); + SDL_ShowSimpleMessageBox(SDL_MessageBoxFlags.SDL_MESSAGEBOX_INFORMATION, "Cabinet Dialog", + "Please scan your Amiibo now.", WindowHandle); } public bool DisplayMessageDialog(ControllerAppletUIArgs args) { if (_ignoreControllerApplet) return false; - - string playerCount = args.PlayerCountMin == args.PlayerCountMax ? $"exactly {args.PlayerCountMin}" : $"{args.PlayerCountMin}-{args.PlayerCountMax}"; - string message = $"Application requests {playerCount} {"player".ToQuantity(args.PlayerCountMin + args.PlayerCountMax, ShowQuantityAs.None)} with:\n\n" - + $"TYPES: {args.SupportedStyles}\n\n" - + $"PLAYERS: {string.Join(", ", args.SupportedPlayers)}\n\n" - + (args.IsDocked ? "Docked mode set. Handheld is also invalid.\n\n" : string.Empty) - + "Please reconfigure Input now and then press OK."; + string playerCount = args.PlayerCountMin == args.PlayerCountMax + ? $"exactly {args.PlayerCountMin}" + : $"{args.PlayerCountMin}-{args.PlayerCountMax}"; + + string message = + $"Application requests {playerCount} {"player".ToQuantity(args.PlayerCountMin + args.PlayerCountMax, ShowQuantityAs.None)} with:\n\n" + + $"TYPES: {args.SupportedStyles}\n\n" + + $"PLAYERS: {string.Join(", ", args.SupportedPlayers)}\n\n" + + (args.IsDocked ? "Docked mode set. Handheld is also invalid.\n\n" : string.Empty) + + "Please reconfigure Input now and then press OK."; return DisplayMessageDialog("Controller Applet", message); } @@ -531,25 +541,33 @@ namespace Ryujinx.Headless public bool DisplayErrorAppletDialog(string title, string message, string[] buttonsText) { - SDL_MessageBoxData data = new() + SDL_MessageBoxButtonData[] buttons = new SDL_MessageBoxButtonData[buttonsText.Length]; + unsafe { - title = title, - message = message, - buttons = new SDL_MessageBoxButtonData[buttonsText.Length], - numbuttons = buttonsText.Length, - window = WindowHandle, - }; - - for (int i = 0; i < buttonsText.Length; i++) - { - data.buttons[i] = new SDL_MessageBoxButtonData + for (int i = 0; i < buttonsText.Length; i++) { - buttonid = i, - text = buttonsText[i], - }; - } + fixed (byte* button = buttonsText[i].ToBytes()) + { + buttons[i] = new SDL_MessageBoxButtonData { buttonID = i, text = button, }; + } + } - SDL_ShowMessageBox(ref data, out int _); + fixed (byte* t = title.ToBytes()) + fixed (byte* m = message.ToBytes()) + fixed (SDL_MessageBoxButtonData* b = buttons) + { + SDL_MessageBoxData data = new() + { + title = t, + message = m, + buttons = b, + numbuttons = buttonsText.Length, + window = WindowHandle, + }; + + SDL_ShowMessageBox(ref data, out int _); + } + } return true; } @@ -567,11 +585,11 @@ namespace Ryujinx.Headless TouchScreenManager?.Dispose(); NpadManager.Dispose(); - SDL2Driver.Instance.UnregisterWindow(_windowId); + SDL3Driver.Instance.UnregisterWindow(_windowId); SDL_DestroyWindow(WindowHandle); - SDL2Driver.Instance.Dispose(); + SDL3Driver.Instance.Dispose(); } } } diff --git a/src/Ryujinx/Program.cs b/src/Ryujinx/Program.cs index 1d56521e0..56915cc8e 100644 --- a/src/Ryujinx/Program.cs +++ b/src/Ryujinx/Program.cs @@ -5,11 +5,9 @@ using Gommon; using Projektanker.Icons.Avalonia; using Projektanker.Icons.Avalonia.FontAwesome; using Projektanker.Icons.Avalonia.MaterialDesign; -using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.UI.Helpers; using Ryujinx.Ava.UI.Windows; using Ryujinx.Ava.Utilities; -using Ryujinx.Ava.Utilities.AppLibrary; using Ryujinx.Ava.Utilities.Configuration; using Ryujinx.Ava.Utilities.SystemInfo; using Ryujinx.Common; @@ -19,7 +17,6 @@ using Ryujinx.Common.Logging; using Ryujinx.Common.SystemInterop; using Ryujinx.Graphics.Vulkan.MoltenVK; using Ryujinx.Headless; -using Ryujinx.SDL2.Common; using Ryujinx.SDL3.Common; using System; using System.Collections.Generic; @@ -127,9 +124,6 @@ namespace Ryujinx.Ava // Initialize Discord integration. DiscordIntegrationModule.Initialize(); - // Initialize SDL2 driver - SDL2Driver.MainThreadDispatcher = action => Dispatcher.UIThread.InvokeAsync(action, DispatcherPriority.Input); - // Initialize SDL3 driver SDL3Driver.MainThreadDispatcher = action => Dispatcher.UIThread.InvokeAsync(action, DispatcherPriority.Input); diff --git a/src/Ryujinx/Ryujinx.csproj b/src/Ryujinx/Ryujinx.csproj index 106124cb7..5c0f8af27 100644 --- a/src/Ryujinx/Ryujinx.csproj +++ b/src/Ryujinx/Ryujinx.csproj @@ -70,13 +70,11 @@ - - diff --git a/src/Ryujinx/UI/ViewModels/SettingsViewModel.cs b/src/Ryujinx/UI/ViewModels/SettingsViewModel.cs index 612c014d1..739a4cfe9 100644 --- a/src/Ryujinx/UI/ViewModels/SettingsViewModel.cs +++ b/src/Ryujinx/UI/ViewModels/SettingsViewModel.cs @@ -5,7 +5,6 @@ using CommunityToolkit.Mvvm.ComponentModel; using Gommon; using LibHac.Tools.FsSystem; using Ryujinx.Audio.Backends.OpenAL; -using Ryujinx.Audio.Backends.SDL2; using Ryujinx.Audio.Backends.SDL3; using Ryujinx.Audio.Backends.SoundIo; using Ryujinx.Ava.Common.Locale; @@ -212,7 +211,6 @@ namespace Ryujinx.Ava.UI.ViewModels public bool EnableDebug { get; set; } public bool IsOpenAlEnabled { get; set; } public bool IsSoundIoEnabled { get; set; } - public bool IsSDL2Enabled { get; set; } public bool IsSDL3Enabled { get; set; } public bool IsCustomResolutionScaleActive => _resolutionScale == 4; public bool IsScalingFilterActive => _scalingFilter == (int)Ryujinx.Common.Configuration.ScalingFilter.Fsr; @@ -374,14 +372,13 @@ namespace Ryujinx.Ava.UI.ViewModels { IsOpenAlEnabled = OpenALHardwareDeviceDriver.IsSupported; IsSoundIoEnabled = SoundIoHardwareDeviceDriver.IsSupported; - IsSDL2Enabled = SDL2HardwareDeviceDriver.IsSupported; IsSDL3Enabled = SDL3HardwareDeviceDriver.IsSupported; await Dispatcher.UIThread.InvokeAsync(() => { OnPropertyChanged(nameof(IsOpenAlEnabled)); OnPropertyChanged(nameof(IsSoundIoEnabled)); - OnPropertyChanged(nameof(IsSDL2Enabled)); + OnPropertyChanged(nameof(IsSDL3Enabled)); }); } diff --git a/src/Ryujinx/UI/Views/Settings/SettingsAudioView.axaml b/src/Ryujinx/UI/Views/Settings/SettingsAudioView.axaml index 52fb12abf..d72ea598a 100644 --- a/src/Ryujinx/UI/Views/Settings/SettingsAudioView.axaml +++ b/src/Ryujinx/UI/Views/Settings/SettingsAudioView.axaml @@ -43,9 +43,6 @@ - - - diff --git a/src/Ryujinx/UI/Windows/MainWindow.axaml.cs b/src/Ryujinx/UI/Windows/MainWindow.axaml.cs index fb5e8ab1c..3d06066d1 100644 --- a/src/Ryujinx/UI/Windows/MainWindow.axaml.cs +++ b/src/Ryujinx/UI/Windows/MainWindow.axaml.cs @@ -27,8 +27,7 @@ using Ryujinx.HLE.FileSystem; using Ryujinx.HLE.HOS; using Ryujinx.HLE.HOS.Services.Account.Acc; using Ryujinx.Input.HLE; -using Ryujinx.Input.SDL2; -using Ryujinx.Input.SDl3; +using Ryujinx.Input.SDL3; using System; using System.Collections.Generic; using System.Linq; @@ -109,9 +108,6 @@ namespace Ryujinx.Ava.UI.Windows { InputManager = new InputManager(new AvaloniaKeyboardDriver(this), new SDL3GamepadDriver()); - //TODO: after sdl3 delete it - new SDL2GamepadDriver(); - _ = this.GetObservable(IsActiveProperty).Subscribe(it => ViewModel.IsActive = it); this.ScalingChanged += OnScalingChanged; } diff --git a/src/Ryujinx/Utilities/Compat/CompatibilityViewModel.cs b/src/Ryujinx/Utilities/Compat/CompatibilityViewModel.cs index 4bd97cc35..0e73e2d7c 100644 --- a/src/Ryujinx/Utilities/Compat/CompatibilityViewModel.cs +++ b/src/Ryujinx/Utilities/Compat/CompatibilityViewModel.cs @@ -1,5 +1,4 @@ using CommunityToolkit.Mvvm.ComponentModel; -using ExCSS; using Gommon; using Ryujinx.Ava.Utilities.AppLibrary; using System.Collections.Generic; diff --git a/src/Ryujinx/Utilities/Configuration/AudioBackend.cs b/src/Ryujinx/Utilities/Configuration/AudioBackend.cs index 836725d3d..29e0f673e 100644 --- a/src/Ryujinx/Utilities/Configuration/AudioBackend.cs +++ b/src/Ryujinx/Utilities/Configuration/AudioBackend.cs @@ -9,7 +9,6 @@ namespace Ryujinx.Ava.Utilities.Configuration Dummy, OpenAl, SoundIo, - SDL2, SDL3, } } diff --git a/src/Ryujinx/Utilities/Configuration/ConfigurationState.cs b/src/Ryujinx/Utilities/Configuration/ConfigurationState.cs index 95ec62e83..45962becf 100644 --- a/src/Ryujinx/Utilities/Configuration/ConfigurationState.cs +++ b/src/Ryujinx/Utilities/Configuration/ConfigurationState.cs @@ -194,7 +194,7 @@ namespace Ryujinx.Ava.Utilities.Configuration System.EnableInternetAccess.Value = false; System.EnableFsIntegrityChecks.Value = true; System.FsGlobalAccessLogMode.Value = 0; - System.AudioBackend.Value = AudioBackend.SDL2; + System.AudioBackend.Value = AudioBackend.SDL3; System.AudioVolume.Value = 1; System.MemoryManagerMode.Value = MemoryManagerMode.HostMappedUnsafe; System.DramSize.Value = MemoryConfiguration.MemoryConfiguration4GiB;