Skip to content

Commit

Permalink
macOS support for CreateWebGPUSurface (#1612)
Browse files Browse the repository at this point in the history
  • Loading branch information
AsgardXIV authored Aug 17, 2023
1 parent 3e737f2 commit a78d8e3
Show file tree
Hide file tree
Showing 8 changed files with 370 additions and 3 deletions.
187 changes: 187 additions & 0 deletions src/Core/Silk.NET.Core/Miscellaneous/Bool8.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System;

namespace Silk.NET.Core
{
/// <summary>
/// A 8-bit boolean.
/// </summary>
public readonly struct Bool8 : IEquatable<Bool8>, IEquatable<byte>, IEquatable<bool>
{
/// <summary>
/// Gets the 8-bit value for this boolean.
/// </summary>
public byte Value { get; }

/// <summary>
/// Returns the hash code for this instance.
/// </summary>
/// <returns> A 32-bit signed integer hash code.</returns>
public override int GetHashCode()
{
return Value.GetHashCode();
}

/// <summary>
/// Compares the current <see cref="Bool8"/> to another <see cref="object"/>. Returns true if they are equal.
/// </summary>
/// <param name="obj"></param>
/// <returns>True if <paramref name="obj"/> is equal to the current <see cref="Bool8"/>.</returns>
public override bool Equals(object obj) => obj switch
{
Bool8 val => Equals(val),
bool val => Equals(val),
byte val => Equals(val),
_ => base.Equals(obj)
};

/// <summary>
/// Compares the current <see cref="Bool8"/> to another <see cref="Bool8"/>. Returns true if they are equal.
/// </summary>
/// <param name="other">The other value.</param>
/// <returns>True if the current <see cref="Bool8"/> is equal to the provided <see cref="bool"/> value.</returns>
public bool Equals(Bool8 other) => Value == other.Value;

/// <summary>
/// Compares the current <see cref="Bool8"/> to a <see cref="byte"/>. Returns true if they are equal.
/// </summary>
/// <param name="other">The other value.</param>
/// <returns>True if the current <see cref="Bool8"/> is equal to the provided <see cref="byte"/> value.</returns>
public bool Equals(byte other) => Value == other;

/// <summary>
/// Compares the current <see cref="Bool8"/> to a <see cref="bool"/>. Returns true if they are equal.
/// </summary>
/// <param name="other">The other value.</param>
/// <returns>True if the current <see cref="Bool8"/> is equal to the provided <see cref="bool"/> value.</returns>
public bool Equals(bool other) => Value == (other ? 1U : 0U);

#region Cast operators
/// <summary>
/// Creates a 8-bit boolean from the given byte.
/// </summary>
/// <param name="val">The byte value.</param>
public Bool8(byte val) => Value = val;

/// <summary>
/// Creates a 8-bit boolean from the given managed boolean.
/// </summary>
/// <param name="val">The boolean value.</param>
public Bool8(bool val) => Value = val ? (byte) 1 : (byte) 0;

/// <summary>
/// Converts this 8-bit boolean to a managed boolean.
/// </summary>
/// <param name="val">The 8-bit boolean.</param>
/// <returns>The managed boolean.</returns>
public static implicit operator bool(Bool8 val) => val.Value == 1;

/// <summary>
/// Converts this 8-bit boolean to a byte.
/// </summary>
/// <param name="val">The 8-bit boolean.</param>
/// <returns>The byte.</returns>
public static implicit operator byte(Bool8 val) => val.Value;

/// <summary>
/// Creates a 8-bit boolean from the given managed boolean.
/// </summary>
/// <param name="val">The boolean value.</param>
public static implicit operator Bool8(bool val) => new Bool8(val);

/// <summary>
/// Creates a 8-bit boolean from the given byte.
/// </summary>
/// <param name="val">The byte value.</param>
public static implicit operator Bool8(byte val) => new Bool8(val);
#endregion

#region Bool8 vs Bool8 equality
/// <summary>
/// Compares a <see cref="Bool8"/> to a <see cref="Bool8"/> for equality.
/// </summary>
/// <param name="left">The left-hand <see cref="Bool8"/>.</param>
/// <param name="right">The right-hand <see cref="Bool8"/>.</param>
/// <returns></returns>
public static bool operator ==(Bool8 left, Bool8 right) => left.Value == right.Value;

/// <summary>
/// Compares a <see cref="Bool8"/> to a <see cref="Bool8"/> for inequality.
/// </summary>
/// <param name="left">The left-hand <see cref="Bool8"/>.</param>
/// <param name="right">The right-hand <see cref="Bool8"/>.</param>
/// <returns></returns>
public static bool operator !=(Bool8 left, Bool8 right) => left.Value != right.Value;
#endregion

#region Bool8 vs bool equality
/// <summary>
/// Compares a <see cref="Bool8"/> to a <see cref="bool"/> for equality.
/// </summary>
/// <param name="left">The left-hand <see cref="Bool8"/>.</param>
/// <param name="right">The right-hand <see cref="bool"/>.</param>
/// <returns></returns>
public static bool operator ==(Bool8 left, bool right) => left.Value == (right ? 1U : 0U);

/// <summary>
/// Compares a <see cref="Bool8"/> to a <see cref="bool"/> for inequality.
/// </summary>
/// <param name="left">The left-hand <see cref="Bool8"/>.</param>
/// <param name="right">The right-hand <see cref="bool"/>.</param>
/// <returns></returns>
public static bool operator !=(Bool8 left, bool right) => left.Value != (right ? 1U : 0U);

/// <summary>
/// Compares a <see cref="bool"/> to a <see cref="Bool8"/> for equality.
/// </summary>
/// <param name="left">The left-hand <see cref="bool"/>.</param>
/// <param name="right">The right-hand <see cref="Bool8"/>.</param>
/// <returns></returns>
public static bool operator ==(bool left, Bool8 right) => right.Value == (left ? 1U : 0U);

/// <summary>
/// Compares a <see cref="bool"/> to a <see cref="Bool8"/> for equality.
/// </summary>
/// <param name="left">The left-hand <see cref="bool"/>.</param>
/// <param name="right">The right-hand <see cref="Bool8"/>.</param>
/// <returns></returns>
public static bool operator !=(bool left, Bool8 right) => right.Value != (left ? 1U : 0U);
#endregion

#region Bool8 vs byte equality
/// <summary>
/// Compares a <see cref="Bool8"/> to a <see cref="byte"/> for equality.
/// </summary>
/// <param name="left">The left-hand <see cref="Bool8"/>.</param>
/// <param name="right">The right-hand <see cref="byte"/>.</param>
/// <returns></returns>
public static bool operator ==(Bool8 left, byte right) => left.Value == right;

/// <summary>
/// Compares a <see cref="Bool8"/> to a <see cref="byte"/> for inequality.
/// </summary>
/// <param name="left">The left-hand <see cref="Bool8"/>.</param>
/// <param name="right">The right-hand <see cref="byte"/>.</param>
/// <returns></returns>
public static bool operator !=(Bool8 left, byte right) => left.Value != right;

/// <summary>
/// Compares a <see cref="byte"/> to a <see cref="Bool8"/> for equality.
/// </summary>
/// <param name="left">The left-hand <see cref="byte"/>.</param>
/// <param name="right">The right-hand <see cref="Bool8"/>.</param>
/// <returns></returns>
public static bool operator ==(byte left, Bool8 right) => left == right.Value;

/// <summary>
/// Compares a <see cref="byte"/> to a <see cref="Bool8"/> for inequality.
/// </summary>
/// <param name="left">The left-hand <see cref="byte"/>.</param>
/// <param name="right">The right-hand <see cref="Bool8"/>.</param>
/// <returns></returns>
public static bool operator !=(byte left, Bool8 right) => left != right.Value;
#endregion
}
}
21 changes: 21 additions & 0 deletions src/WebGPU/Silk.NET.WebGPU/Platforms/MacOS/CAMetalLayer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

namespace Silk.NET.WebGPU.Platforms.MacOS;

internal struct CAMetalLayer
{
public readonly nint NativePtr;

public CAMetalLayer(nint ptr)
{
NativePtr = ptr;
}

public static CAMetalLayer New()
{
return s_class.AllocInit<CAMetalLayer>();
}

private static readonly ObjectiveCClass s_class = new(nameof(CAMetalLayer));
}
33 changes: 33 additions & 0 deletions src/WebGPU/Silk.NET.WebGPU/Platforms/MacOS/NSView.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using Silk.NET.Core;

namespace Silk.NET.WebGPU.Platforms.MacOS;

internal struct NSView
{
public readonly nint NativePtr;

public static implicit operator nint(NSView nsView)
{
return nsView.NativePtr;
}

public NSView(nint ptr)
{
NativePtr = ptr;
}

public Bool8 wantsLayer
{
get => ObjectiveCRuntime.bool8_objc_msgSend(NativePtr, "wantsLayer");
set => ObjectiveCRuntime.objc_msgSend(NativePtr, "setWantsLayer:", value);
}

public nint layer
{
get => ObjectiveCRuntime.ptr_objc_msgSend(NativePtr, "layer");
set => ObjectiveCRuntime.ptr_objc_msgSend(NativePtr, "setLayer:", value);
}
}
16 changes: 16 additions & 0 deletions src/WebGPU/Silk.NET.WebGPU/Platforms/MacOS/NSWindow.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

namespace Silk.NET.WebGPU.Platforms.MacOS;

internal class NSWindow
{
public readonly nint NativePtr;

public NSWindow(nint ptr)
{
NativePtr = ptr;
}

public NSView contentView => ObjectiveCRuntime.objc_msgSend<NSView>(NativePtr, "contentView");
}
31 changes: 31 additions & 0 deletions src/WebGPU/Silk.NET.WebGPU/Platforms/MacOS/ObjectiveCClass.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Runtime.CompilerServices;
using Silk.NET.Core.Native;

namespace Silk.NET.WebGPU.Platforms.MacOS;

internal unsafe struct ObjectiveCClass
{
public readonly nint NativePtr;

public static implicit operator nint(ObjectiveCClass c)
{
return c.NativePtr;
}

public ObjectiveCClass(string name)
{
var namePtr = SilkMarshal.StringToPtr(name);
NativePtr = ObjectiveCRuntime.objc_getClass(namePtr);
SilkMarshal.Free(namePtr);
}

public T AllocInit<T>() where T : struct
{
var value = ObjectiveCRuntime.ptr_objc_msgSend(NativePtr, "alloc");
ObjectiveCRuntime.objc_msgSend(value, "init");
return Unsafe.AsRef<T>(&value);
}
}
43 changes: 43 additions & 0 deletions src/WebGPU/Silk.NET.WebGPU/Platforms/MacOS/ObjectiveCRuntime.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using Silk.NET.Core;

namespace Silk.NET.WebGPU.Platforms.MacOS;

internal static unsafe class ObjectiveCRuntime
{
private const string ObjCLibrary = "/usr/lib/libobjc.A.dylib";

[DllImport(ObjCLibrary)]
public static extern nint sel_registerName(nint namePtr);

[DllImport(ObjCLibrary)]
public static extern byte* sel_getName(nint selector);

[DllImport(ObjCLibrary, EntryPoint = "objc_msgSend")]
public static extern Bool8 bool8_objc_msgSend(nint receiver, Selector selector);

[DllImport(ObjCLibrary, EntryPoint = "objc_msgSend")]
public static extern nint ptr_objc_msgSend(nint receiver, Selector selector);

[DllImport(ObjCLibrary, EntryPoint = "objc_msgSend")]
public static extern nint ptr_objc_msgSend(nint receiver, Selector selector, nint a);

[DllImport(ObjCLibrary, EntryPoint = "objc_msgSend")]
public static extern void objc_msgSend(nint receiver, Selector selector, byte b);

[DllImport(ObjCLibrary, EntryPoint = "objc_msgSend")]
public static extern void objc_msgSend(nint receiver, Selector selector);

[DllImport(ObjCLibrary)]
public static extern nint objc_getClass(nint namePtr);

public static T objc_msgSend<T>(nint receiver, Selector selector) where T : struct
{
var value = ptr_objc_msgSend(receiver, selector);
return Unsafe.AsRef<T>(&value);
}
}
28 changes: 28 additions & 0 deletions src/WebGPU/Silk.NET.WebGPU/Platforms/MacOS/Selector.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using Silk.NET.Core.Native;

namespace Silk.NET.WebGPU.Platforms.MacOS;

internal struct Selector
{
public readonly nint NativePtr;

public Selector(nint ptr)
{
NativePtr = ptr;
}

public Selector(string name)
{
var namePtr = SilkMarshal.StringToPtr(name);
NativePtr = ObjectiveCRuntime.sel_registerName(namePtr);
SilkMarshal.Free(namePtr);
}

public static implicit operator Selector(string s)
{
return new Selector(s);
}
}
Loading

0 comments on commit a78d8e3

Please sign in to comment.