diff --git a/src/Ryujinx.Headless.SDL2/Metal/MetalWindow.cs b/src/Ryujinx.Headless.SDL2/Metal/MetalWindow.cs new file mode 100644 index 0000000000..c37bf2472a --- /dev/null +++ b/src/Ryujinx.Headless.SDL2/Metal/MetalWindow.cs @@ -0,0 +1,49 @@ +using Ryujinx.Common.Configuration; +using Ryujinx.Input.HLE; +using Ryujinx.SDL2.Common; +using SharpMetal.QuartzCore; +using System.Runtime.Versioning; +using static SDL2.SDL; + +namespace Ryujinx.Headless.SDL2.Metal +{ + [SupportedOSPlatform("macos")] + class MetalWindow : WindowBase + { + private CAMetalLayer _caMetalLayer; + + public CAMetalLayer GetLayer() + { + return _caMetalLayer; + } + + public MetalWindow( + InputManager inputManager, + GraphicsDebugLevel glLogLevel, + AspectRatio aspectRatio, + bool enableMouse, + HideCursorMode hideCursorMode) + : base(inputManager, glLogLevel, aspectRatio, enableMouse, hideCursorMode) { } + + public override SDL_WindowFlags GetWindowFlags() => SDL_WindowFlags.SDL_WINDOW_METAL; + + protected override void InitializeWindowRenderer() + { + void CreateLayer() + { + _caMetalLayer = new CAMetalLayer(SDL_Metal_GetLayer(SDL_Metal_CreateView(WindowHandle))); + } + + if (SDL2Driver.MainThreadDispatcher != null) + { + SDL2Driver.MainThreadDispatcher(CreateLayer); + } + } + + protected override void InitializeRenderer() { } + + protected override void FinalizeWindowRenderer() { } + + protected override void SwapBuffers() { } + } +} diff --git a/src/Ryujinx.Headless.SDL2/Program.cs b/src/Ryujinx.Headless.SDL2/Program.cs index 4ee2712037..27b91418d9 100644 --- a/src/Ryujinx.Headless.SDL2/Program.cs +++ b/src/Ryujinx.Headless.SDL2/Program.cs @@ -20,6 +20,8 @@ using Ryujinx.Graphics.Gpu.Shader; using Ryujinx.Graphics.OpenGL; using Ryujinx.Graphics.Vulkan; using Ryujinx.Graphics.Vulkan.MoltenVK; +using Ryujinx.Graphics.Metal; +using Ryujinx.Headless.SDL2.Metal; using Ryujinx.Headless.SDL2.OpenGL; using Ryujinx.Headless.SDL2.Vulkan; using Ryujinx.HLE; @@ -507,9 +509,12 @@ namespace Ryujinx.Headless.SDL2 private static WindowBase CreateWindow(Options options) { - return options.GraphicsBackend == GraphicsBackend.Vulkan - ? new VulkanWindow(_inputManager, options.LoggingGraphicsDebugLevel, options.AspectRatio, options.EnableMouse, options.HideCursorMode) - : new OpenGLWindow(_inputManager, options.LoggingGraphicsDebugLevel, options.AspectRatio, options.EnableMouse, options.HideCursorMode); + return options.GraphicsBackend switch + { + GraphicsBackend.Vulkan => new VulkanWindow(_inputManager, options.LoggingGraphicsDebugLevel, options.AspectRatio, options.EnableMouse, options.HideCursorMode), + GraphicsBackend.Metal => new MetalWindow(_inputManager, options.LoggingGraphicsDebugLevel, options.AspectRatio, options.EnableKeyboard, options.HideCursorMode), + _ => new OpenGLWindow(_inputManager, options.LoggingGraphicsDebugLevel, options.AspectRatio, options.EnableMouse, options.HideCursorMode) + }; } private static IRenderer CreateRenderer(Options options, WindowBase window) @@ -541,6 +546,11 @@ namespace Ryujinx.Headless.SDL2 preferredGpuId); } + if (options.GraphicsBackend == GraphicsBackend.Metal && window is MetalWindow metalWindow && OperatingSystem.IsMacOS()) + { + return new MetalRenderer(metalWindow.GetLayer); + } + return new OpenGLRenderer(); } diff --git a/src/Ryujinx.Headless.SDL2/Ryujinx.Headless.SDL2.csproj b/src/Ryujinx.Headless.SDL2/Ryujinx.Headless.SDL2.csproj index 6102295444..6846a6f7fb 100644 --- a/src/Ryujinx.Headless.SDL2/Ryujinx.Headless.SDL2.csproj +++ b/src/Ryujinx.Headless.SDL2/Ryujinx.Headless.SDL2.csproj @@ -29,6 +29,7 @@ +