MetalHelper.cs 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. using System;
  2. using System.Runtime.Versioning;
  3. using System.Runtime.InteropServices;
  4. using Avalonia;
  5. namespace Ryujinx.Ava.UI.Helpers
  6. {
  7. public delegate void UpdateBoundsCallbackDelegate(Rect rect);
  8. [SupportedOSPlatform("macos")]
  9. static partial class MetalHelper
  10. {
  11. private const string LibObjCImport = "/usr/lib/libobjc.A.dylib";
  12. private struct Selector
  13. {
  14. public readonly IntPtr NativePtr;
  15. public unsafe Selector(string value)
  16. {
  17. int size = System.Text.Encoding.UTF8.GetMaxByteCount(value.Length);
  18. byte* data = stackalloc byte[size];
  19. fixed (char* pValue = value)
  20. {
  21. System.Text.Encoding.UTF8.GetBytes(pValue, value.Length, data, size);
  22. }
  23. NativePtr = sel_registerName(data);
  24. }
  25. public static implicit operator Selector(string value) => new Selector(value);
  26. }
  27. private static unsafe IntPtr GetClass(string value)
  28. {
  29. int size = System.Text.Encoding.UTF8.GetMaxByteCount(value.Length);
  30. byte* data = stackalloc byte[size];
  31. fixed (char* pValue = value)
  32. {
  33. System.Text.Encoding.UTF8.GetBytes(pValue, value.Length, data, size);
  34. }
  35. return objc_getClass(data);
  36. }
  37. private struct NSPoint
  38. {
  39. public double X;
  40. public double Y;
  41. public NSPoint(double x, double y)
  42. {
  43. X = x;
  44. Y = y;
  45. }
  46. }
  47. private struct NSRect
  48. {
  49. public NSPoint Pos;
  50. public NSPoint Size;
  51. public NSRect(double x, double y, double width, double height)
  52. {
  53. Pos = new NSPoint(x, y);
  54. Size = new NSPoint(width, height);
  55. }
  56. }
  57. public static IntPtr GetMetalLayer(out IntPtr nsView, out UpdateBoundsCallbackDelegate updateBounds)
  58. {
  59. // Create a new CAMetalLayer.
  60. IntPtr layerClass = GetClass("CAMetalLayer");
  61. IntPtr metalLayer = IntPtr_objc_msgSend(layerClass, "alloc");
  62. objc_msgSend(metalLayer, "init");
  63. // Create a child NSView to render into.
  64. IntPtr nsViewClass = GetClass("NSView");
  65. IntPtr child = IntPtr_objc_msgSend(nsViewClass, "alloc");
  66. objc_msgSend(child, "init", new NSRect(0, 0, 0, 0));
  67. // Make its renderer our metal layer.
  68. objc_msgSend(child, "setWantsLayer:", (byte)1);
  69. objc_msgSend(child, "setLayer:", metalLayer);
  70. objc_msgSend(metalLayer, "setContentsScale:", Program.DesktopScaleFactor);
  71. // Ensure the scale factor is up to date.
  72. updateBounds = (Rect rect) => {
  73. objc_msgSend(metalLayer, "setContentsScale:", Program.DesktopScaleFactor);
  74. };
  75. nsView = child;
  76. return metalLayer;
  77. }
  78. public static void DestroyMetalLayer(IntPtr nsView, IntPtr metalLayer)
  79. {
  80. // TODO
  81. }
  82. [LibraryImport(LibObjCImport)]
  83. private static unsafe partial IntPtr sel_registerName(byte* data);
  84. [LibraryImport(LibObjCImport)]
  85. private static unsafe partial IntPtr objc_getClass(byte* data);
  86. [LibraryImport(LibObjCImport)]
  87. private static partial void objc_msgSend(IntPtr receiver, Selector selector);
  88. [LibraryImport(LibObjCImport)]
  89. private static partial void objc_msgSend(IntPtr receiver, Selector selector, byte value);
  90. [LibraryImport(LibObjCImport)]
  91. private static partial void objc_msgSend(IntPtr receiver, Selector selector, IntPtr value);
  92. [LibraryImport(LibObjCImport)]
  93. private static partial void objc_msgSend(IntPtr receiver, Selector selector, NSRect point);
  94. [LibraryImport(LibObjCImport)]
  95. private static partial void objc_msgSend(IntPtr receiver, Selector selector, double value);
  96. [LibraryImport(LibObjCImport, EntryPoint = "objc_msgSend")]
  97. private static partial IntPtr IntPtr_objc_msgSend(IntPtr receiver, Selector selector);
  98. }
  99. }