aboutsummaryrefslogtreecommitdiff
path: root/src/Ryujinx.Gtk3/UI/VulkanRenderer.cs
blob: eefc5699988e3022b22aeb8ee2a4bea98e73e24b (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
using Gdk;
using Ryujinx.Common.Configuration;
using Ryujinx.Input.HLE;
using Ryujinx.UI.Helper;
using SPB.Graphics.Vulkan;
using SPB.Platform.Metal;
using SPB.Platform.Win32;
using SPB.Platform.X11;
using SPB.Windowing;
using System;
using System.Runtime.InteropServices;

namespace Ryujinx.UI
{
    public partial class VulkanRenderer : RendererWidgetBase
    {
        public NativeWindowBase NativeWindow { get; private set; }
        private UpdateBoundsCallbackDelegate _updateBoundsCallback;

        public VulkanRenderer(InputManager inputManager, GraphicsDebugLevel glLogLevel) : base(inputManager, glLogLevel) { }

        private NativeWindowBase RetrieveNativeWindow()
        {
            if (OperatingSystem.IsWindows())
            {
                IntPtr windowHandle = gdk_win32_window_get_handle(Window.Handle);

                return new SimpleWin32Window(new NativeHandle(windowHandle));
            }
            else if (OperatingSystem.IsLinux())
            {
                IntPtr displayHandle = gdk_x11_display_get_xdisplay(Display.Handle);
                IntPtr windowHandle = gdk_x11_window_get_xid(Window.Handle);

                return new SimpleX11Window(new NativeHandle(displayHandle), new NativeHandle(windowHandle));
            }
            else if (OperatingSystem.IsMacOS())
            {
                IntPtr metalLayer = MetalHelper.GetMetalLayer(Display, Window, out IntPtr nsView, out _updateBoundsCallback);

                return new SimpleMetalWindow(new NativeHandle(nsView), new NativeHandle(metalLayer));
            }

            throw new NotImplementedException();
        }

        [LibraryImport("libgdk-3-0.dll")]
        private static partial IntPtr gdk_win32_window_get_handle(IntPtr d);

        [LibraryImport("libgdk-3.so.0")]
        private static partial IntPtr gdk_x11_display_get_xdisplay(IntPtr gdkDisplay);

        [LibraryImport("libgdk-3.so.0")]
        private static partial IntPtr gdk_x11_window_get_xid(IntPtr gdkWindow);

        protected override bool OnConfigureEvent(EventConfigure evnt)
        {
            if (NativeWindow == null)
            {
                NativeWindow = RetrieveNativeWindow();

                WaitEvent.Set();
            }

            bool result = base.OnConfigureEvent(evnt);

            _updateBoundsCallback?.Invoke(Window);

            return result;
        }

        public unsafe IntPtr CreateWindowSurface(IntPtr instance)
        {
            return VulkanHelper.CreateWindowSurface(instance, NativeWindow);
        }

        public override void InitializeRenderer() { }

        public override void SwapBuffers() { }

        protected override string GetGpuBackendName()
        {
            return "Vulkan";
        }

        protected override void Dispose(bool disposing)
        {
            Device?.DisposeGpu();

            NpadManager.Dispose();
        }
    }
}