mirror of
https://github.com/amerkoleci/Vortice.Win32.git
synced 2026-01-14 16:16:04 +08:00
Generator: Add Enum and Struct
Win32: IUnknown and DXGI generation.
This commit is contained in:
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
[submodule "src/Generator/win32json"]
|
||||
path = src/Generator/win32json
|
||||
url = https://github.com/marlersoft/win32json.git
|
||||
64
src/Generator/ApiData.cs
Normal file
64
src/Generator/ApiData.cs
Normal file
@@ -0,0 +1,64 @@
|
||||
// Copyright © Amer Koleci and Contributors.
|
||||
// Licensed under the MIT License (MIT). See LICENSE in the repository root for more information.
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Generator;
|
||||
|
||||
public class ApiDataArrayShape
|
||||
{
|
||||
public int Size { get; set; }
|
||||
}
|
||||
|
||||
public class ApiDataType
|
||||
{
|
||||
public string Kind { get; set; }
|
||||
public string Name { get; set; }
|
||||
|
||||
// Kind == Array
|
||||
public ApiDataArrayShape Shape { get; set; }
|
||||
public ApiDataType Child { get; set; }
|
||||
}
|
||||
|
||||
public class ApiDataConstant
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public ApiDataType Type { get; set; }
|
||||
public string ValueType { get; set; }
|
||||
public object Value { get; set; }
|
||||
}
|
||||
|
||||
public class ApiEnumValue
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public object Value { get; set; }
|
||||
}
|
||||
|
||||
public class ApiStructField
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public ApiDataType Type { get; set; }
|
||||
}
|
||||
|
||||
public class ApiType
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public string Kind { get; set; }
|
||||
|
||||
// Enum
|
||||
public bool Flags { get; set; }
|
||||
public bool Scoped { get; set; }
|
||||
public string IntegerBase { get; set; }
|
||||
public ApiEnumValue[] Values { get; set; }
|
||||
|
||||
// Struct
|
||||
public int Size { get; set; }
|
||||
public int PackingSize { get; set; }
|
||||
public ApiStructField[] Fields { get; set; }
|
||||
}
|
||||
|
||||
public sealed class ApiData
|
||||
{
|
||||
public ApiDataConstant[] Constants { get; set; }
|
||||
public ApiType[] Types { get; set; }
|
||||
}
|
||||
@@ -12,7 +12,7 @@ public sealed class CodeWriter : IDisposable
|
||||
|
||||
public int IndentLevel { get; private set; }
|
||||
|
||||
public CodeWriter(string fileName, bool enableNullable, params string[] namespaces)
|
||||
public CodeWriter(string fileName, string ns, params string[] usingNamespaces)
|
||||
{
|
||||
_indentStrings = new string[10];
|
||||
for (int i = 0; i < _indentStrings.Length; i++)
|
||||
@@ -31,23 +31,18 @@ public sealed class CodeWriter : IDisposable
|
||||
_writer.WriteLine("// ------------------------------------------------------------------------------");
|
||||
_writer.WriteLine();
|
||||
|
||||
if (enableNullable)
|
||||
_writer.WriteLine($"using System;");
|
||||
_writer.WriteLine($"using System.Runtime.CompilerServices;");
|
||||
_writer.WriteLine($"using System.Diagnostics.CodeAnalysis;");
|
||||
|
||||
foreach (string usingNamespace in usingNamespaces)
|
||||
{
|
||||
_writer.WriteLine($"#nullable enable");
|
||||
_writer.WriteLine($"using {usingNamespace};");
|
||||
}
|
||||
|
||||
_writer.WriteLine();
|
||||
}
|
||||
|
||||
foreach (string ns in namespaces)
|
||||
{
|
||||
_writer.WriteLine($"using {ns};");
|
||||
}
|
||||
|
||||
if (namespaces.Length > 0)
|
||||
{
|
||||
_writer.WriteLine();
|
||||
}
|
||||
|
||||
_writer.WriteLine("namespace Vortice.Vulkan;");
|
||||
_writer.WriteLine($"namespace {ns};");
|
||||
_writer.WriteLine();
|
||||
}
|
||||
|
||||
@@ -79,6 +74,12 @@ public sealed class CodeWriter : IDisposable
|
||||
_shouldIndent = true;
|
||||
}
|
||||
|
||||
public void WriteUndindented(string @string)
|
||||
{
|
||||
_writer.WriteLine(@string);
|
||||
_shouldIndent = true;
|
||||
}
|
||||
|
||||
public void BeginBlock(string content)
|
||||
{
|
||||
WriteLine(content);
|
||||
|
||||
@@ -8,10 +8,11 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Include="vulkan/*.*">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="vk_video/*.*">
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.2-beta2" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Include="win32json/api/*.*">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
|
||||
@@ -1,10 +1,59 @@
|
||||
// Copyright © Amer Koleci and Contributors.
|
||||
// Licensed under the MIT License (MIT). See LICENSE in the repository root for more information.
|
||||
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Text;
|
||||
using System.Xml.Linq;
|
||||
using Microsoft.VisualBasic.FileIO;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Generator;
|
||||
|
||||
public static class Program
|
||||
{
|
||||
private static readonly string[] jsons = new[]
|
||||
{
|
||||
"Graphics.Dxgi.Common.json"
|
||||
};
|
||||
|
||||
private static readonly Dictionary<string, string> s_csNameMappings = new()
|
||||
{
|
||||
{"Void", "void" },
|
||||
{"Byte", "byte" },
|
||||
{"SByte", "sbyte" },
|
||||
{"Int8", "sbyte" },
|
||||
{"Int16", "short" },
|
||||
{"Int32", "int" },
|
||||
{"Int64", "long" },
|
||||
{"UInt8", "byte" },
|
||||
{"UInt16", "ushort" },
|
||||
{"UInt32", "uint" },
|
||||
{"UInt64", "ulong" },
|
||||
{"Single", "float" },
|
||||
{"Double", "double" },
|
||||
|
||||
{ "BOOL", "Bool32" },
|
||||
};
|
||||
|
||||
private static readonly Dictionary<string, string> s_knownTypesPrefixes = new()
|
||||
{
|
||||
{ "DXGI_COLOR_SPACE_TYPE", "DXGI_COLOR_SPACE" },
|
||||
};
|
||||
|
||||
private static readonly Dictionary<string, string> s_knownEnumValueNames = new()
|
||||
{
|
||||
{ "DXGI_FORMAT_420_OPAQUE", "Opaque420" }
|
||||
};
|
||||
|
||||
private static readonly HashSet<string> s_ignoredParts = new(StringComparer.OrdinalIgnoreCase)
|
||||
{
|
||||
"DXGI"
|
||||
};
|
||||
|
||||
private static readonly HashSet<string> s_preserveCaps = new(StringComparer.OrdinalIgnoreCase)
|
||||
{
|
||||
};
|
||||
|
||||
public static int Main(string[] args)
|
||||
{
|
||||
string outputPath = AppContext.BaseDirectory;
|
||||
@@ -23,6 +72,374 @@ public static class Program
|
||||
Directory.CreateDirectory(outputPath);
|
||||
}
|
||||
|
||||
foreach (string jsonFile in jsons)
|
||||
{
|
||||
string outputFolder = Path.Combine(outputPath, "Graphics");
|
||||
if (!Directory.Exists(outputFolder))
|
||||
{
|
||||
Directory.CreateDirectory(outputFolder);
|
||||
}
|
||||
|
||||
string finalPath = Path.Combine(AppContext.BaseDirectory, "win32json", "api", jsonFile);
|
||||
string jsonData = File.ReadAllText(finalPath);
|
||||
ApiData? api = JsonConvert.DeserializeObject<ApiData>(jsonData);
|
||||
Generate(api!, outputFolder);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
private static void Generate(ApiData api, string outputPath)
|
||||
{
|
||||
using var writer = new CodeWriter(
|
||||
Path.Combine(outputPath, "Dxgi.Common.cs"),
|
||||
"Win32.Graphics.Dxgi");
|
||||
|
||||
GenerateConstants(writer, api);
|
||||
GenerateTypes(writer, api);
|
||||
}
|
||||
|
||||
private static void GenerateConstants(CodeWriter writer, ApiData api)
|
||||
{
|
||||
using (writer.PushBlock($"public static partial class Apis"))
|
||||
{
|
||||
foreach (var constant in api.Constants)
|
||||
{
|
||||
if (ShouldSkipConstant(constant))
|
||||
continue;
|
||||
|
||||
string typeName = GetTypeName(constant.ValueType);
|
||||
writer.WriteLine($"public const {typeName} {constant.Name} = {constant.Value};");
|
||||
}
|
||||
}
|
||||
writer.WriteLine();
|
||||
}
|
||||
|
||||
private static void GenerateTypes(CodeWriter writer, ApiData api)
|
||||
{
|
||||
writer.WriteLine($"#region Enums");
|
||||
foreach (ApiType enumType in api.Types.Where(item => item.Kind.ToLowerInvariant() == "enum"))
|
||||
{
|
||||
GenerateEnum(writer, enumType);
|
||||
}
|
||||
writer.WriteLine($"#endregion Enums");
|
||||
writer.WriteLine();
|
||||
|
||||
writer.WriteLine($"#region Structs");
|
||||
foreach (ApiType structType in api.Types.Where(item => item.Kind.ToLowerInvariant() == "struct"))
|
||||
{
|
||||
GenerateStruct(writer, structType);
|
||||
}
|
||||
writer.WriteLine($"#endregion Structs");
|
||||
writer.WriteLine();
|
||||
}
|
||||
|
||||
private static void GenerateEnum(CodeWriter writer, ApiType enumType)
|
||||
{
|
||||
if (enumType.Flags)
|
||||
{
|
||||
writer.WriteLine("[Flags]");
|
||||
}
|
||||
|
||||
string csTypeName = GetDataTypeName(enumType.Name, out string enumPrefix);
|
||||
string baseTypeName = GetTypeName(enumType.IntegerBase);
|
||||
AddCsMapping(enumType.Name, csTypeName);
|
||||
|
||||
writer.WriteLine($"/// <unmanaged>{enumType.Name}</unmanaged>");
|
||||
using (writer.PushBlock($"public enum {csTypeName} : {baseTypeName}"))
|
||||
{
|
||||
foreach (ApiEnumValue value in enumType.Values)
|
||||
{
|
||||
if (value.Name.EndsWith("_FORCE_DWORD") ||
|
||||
value.Name.EndsWith("_FORCE_UINT"))
|
||||
continue;
|
||||
|
||||
string enumValueName = GetPrettyFieldName(value.Name, enumPrefix);
|
||||
writer.WriteLine($"/// <unmanaged>{value.Name}</unmanaged>");
|
||||
writer.WriteLine($"{enumValueName} = {value.Value},");
|
||||
}
|
||||
}
|
||||
|
||||
writer.WriteLine();
|
||||
}
|
||||
|
||||
private static void GenerateStruct(CodeWriter writer, ApiType structType)
|
||||
{
|
||||
string csTypeName = GetDataTypeName(structType.Name, out string structPrefix);
|
||||
AddCsMapping(structType.Name, csTypeName);
|
||||
|
||||
writer.WriteLine($"/// <unmanaged>{structType.Name}</unmanaged>");
|
||||
using (writer.PushBlock($"public partial struct {csTypeName}"))
|
||||
{
|
||||
foreach (ApiStructField field in structType.Fields)
|
||||
{
|
||||
if (field.Name.EndsWith("_FORCE_DWORD"))
|
||||
continue;
|
||||
|
||||
string fieldValueName = GetPrettyFieldName(field.Name, structPrefix);
|
||||
string fieldTypeName = GetTypeName(field.Type);
|
||||
//writer.WriteLine($"/// <unmanaged>{field.Name}</unmanaged>");
|
||||
|
||||
if (fieldTypeName == "Array")
|
||||
{
|
||||
bool canUseFixed = false;
|
||||
if (field.Type.Child.Kind == "Native")
|
||||
{
|
||||
canUseFixed = true;
|
||||
}
|
||||
|
||||
fieldTypeName = GetTypeName(field.Type.Child);
|
||||
|
||||
if (canUseFixed)
|
||||
{
|
||||
writer.WriteLine($"public unsafe fixed {fieldTypeName} {fieldValueName}[{field.Type.Shape.Size}];");
|
||||
}
|
||||
else
|
||||
{
|
||||
writer.WriteLine($"public {fieldValueName}__FixedBuffer {fieldValueName};");
|
||||
writer.WriteLine();
|
||||
|
||||
using (writer.PushBlock($"public unsafe struct {fieldValueName}__FixedBuffer"))
|
||||
{
|
||||
for (int i = 0; i < field.Type.Shape.Size; i++)
|
||||
{
|
||||
writer.WriteLine($"public {fieldTypeName} e{i};");
|
||||
}
|
||||
writer.WriteLine();
|
||||
|
||||
writer.WriteLine("[UnscopedRef]");
|
||||
using (writer.PushBlock($"public ref {fieldTypeName} this[int index]"))
|
||||
{
|
||||
writer.WriteLine("[MethodImpl(MethodImplOptions.AggressiveInlining)]");
|
||||
using (writer.PushBlock("get"))
|
||||
{
|
||||
writer.WriteLine($"return ref AsSpan()[index];");
|
||||
}
|
||||
}
|
||||
writer.WriteLine();
|
||||
|
||||
writer.WriteLine("[UnscopedRef]");
|
||||
writer.WriteLine("[MethodImpl(MethodImplOptions.AggressiveInlining)]");
|
||||
using (writer.PushBlock($"public Span<{fieldTypeName}> AsSpan()"))
|
||||
{
|
||||
writer.WriteUndindented("#if NET6_0_OR_GREATER");
|
||||
writer.WriteLine($"return MemoryMarshal.CreateSpan(ref e0, {field.Type.Shape.Size});");
|
||||
writer.WriteUndindented("#else");
|
||||
writer.WriteLine($"return new(Unsafe.AsPointer(ref e0), {field.Type.Shape.Size});");
|
||||
writer.WriteUndindented("#endif");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
writer.WriteLine($"public {fieldTypeName} {fieldValueName};");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
writer.WriteLine();
|
||||
}
|
||||
|
||||
private static bool ShouldSkipConstant(ApiDataConstant constant)
|
||||
{
|
||||
if (constant.Name == "_FACDXGI")
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static string GetDataTypeName(string typeName, out string prefix)
|
||||
{
|
||||
prefix = typeName;
|
||||
if (s_knownTypesPrefixes.TryGetValue(typeName, out string? knowPrefix))
|
||||
{
|
||||
prefix = knowPrefix!;
|
||||
}
|
||||
|
||||
string[] parts = typeName.Split(new[] { '_' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
|
||||
var sb = new StringBuilder();
|
||||
foreach (string part in parts)
|
||||
{
|
||||
if (s_ignoredParts.Contains(part))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (s_preserveCaps.Contains(part))
|
||||
{
|
||||
sb.Append(part);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (part.Equals("DESC", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
sb.Append("Description");
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.Append(char.ToUpper(part[0]));
|
||||
for (int i = 1; i < part.Length; i++)
|
||||
{
|
||||
sb.Append(char.ToLower(part[i]));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
string prettyName = sb.ToString();
|
||||
return (char.IsNumber(prettyName[0])) ? "_" + prettyName : prettyName;
|
||||
}
|
||||
|
||||
private static string GetPrettyFieldName(string value, string enumPrefix)
|
||||
{
|
||||
if (s_knownEnumValueNames.TryGetValue(value, out string? knownName))
|
||||
{
|
||||
return knownName;
|
||||
}
|
||||
|
||||
if (value.IndexOf(enumPrefix) != 0)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
bool isDXGIFormat = enumPrefix == "DXGI_FORMAT";
|
||||
|
||||
string[] parts = value[enumPrefix.Length..].Split(new[] { '_' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
|
||||
var sb = new StringBuilder();
|
||||
foreach (string part in parts)
|
||||
{
|
||||
if (s_ignoredParts.Contains(part))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (s_preserveCaps.Contains(part))
|
||||
{
|
||||
sb.Append(part);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (isDXGIFormat)
|
||||
{
|
||||
if (part.Equals("UNKNOWN", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
sb.Append("Unknown");
|
||||
}
|
||||
else if (part.Equals("TYPELESS", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
sb.Append("Typeless");
|
||||
}
|
||||
else if (part.Equals("UNORM", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
sb.Append("Unorm");
|
||||
}
|
||||
else if (part.Equals("SNORM", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
sb.Append("Snorm");
|
||||
}
|
||||
else if (part.Equals("UINT", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
sb.Append("Uint");
|
||||
}
|
||||
else if (part.Equals("SINT", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
sb.Append("Sint");
|
||||
}
|
||||
else if (part.Equals("FLOAT", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
sb.Append("Float");
|
||||
}
|
||||
else if (part.Equals("SRGB", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
sb.Append("Srgb");
|
||||
}
|
||||
else if (part.Equals("SHAREDEXP", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
sb.Append("SharedExp");
|
||||
}
|
||||
else if (part.Equals("SAMPLER", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
sb.Append("Sampler");
|
||||
}
|
||||
else if (part.Equals("FEEDBACK", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
sb.Append("Feedback");
|
||||
}
|
||||
else if (part.Equals("MIN", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
sb.Append("Min");
|
||||
}
|
||||
else if (part.Equals("MIP", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
sb.Append("Mip");
|
||||
}
|
||||
else if (part.Equals("OPAQUE", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
sb.Append("Opaque");
|
||||
}
|
||||
else if (part.Equals("REGION", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
sb.Append("Region");
|
||||
}
|
||||
else if (part.Equals("USED", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
sb.Append("Used");
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.Append(part);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.Append(char.ToUpper(part[0]));
|
||||
for (int i = 1; i < part.Length; i++)
|
||||
{
|
||||
sb.Append(char.ToLower(part[i]));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
string prettyName = sb.ToString();
|
||||
return (char.IsNumber(prettyName[0])) ? "_" + prettyName : prettyName;
|
||||
}
|
||||
|
||||
private static string GetTypeName(ApiDataType dataType)
|
||||
{
|
||||
if (dataType.Kind == "ApiRef")
|
||||
{
|
||||
return GetTypeName(dataType.Name);
|
||||
}
|
||||
else if (dataType.Kind == "Array")
|
||||
{
|
||||
return "Array";
|
||||
}
|
||||
else if (dataType.Kind == "PointerTo")
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
return GetTypeName(dataType.Name);
|
||||
}
|
||||
|
||||
private static void AddCsMapping(string typeName, string csTypeName)
|
||||
{
|
||||
s_csNameMappings[typeName] = csTypeName;
|
||||
}
|
||||
|
||||
private static string GetTypeName(string name)
|
||||
{
|
||||
if (s_csNameMappings.TryGetValue(name, out string? mappedName))
|
||||
{
|
||||
return mappedName;
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
||||
1
src/Generator/win32json
Submodule
1
src/Generator/win32json
Submodule
Submodule src/Generator/win32json added at d7c046e698
39
src/Vortice.Win32/Attributes.cs
Normal file
39
src/Vortice.Win32/Attributes.cs
Normal file
@@ -0,0 +1,39 @@
|
||||
// Copyright © Amer Koleci and Contributors.
|
||||
// Licensed under the MIT License (MIT). See LICENSE in the repository root for more information.
|
||||
// Copyright © Tanner Gooding and Contributors. Licensed under the MIT License (MIT). See License.md in the repository root for more information.
|
||||
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace Win32;
|
||||
|
||||
/// <summary>Defines the type of a member as it was used in the native signature.</summary>
|
||||
[AttributeUsage(AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.ReturnValue, AllowMultiple = false, Inherited = true)]
|
||||
[Conditional("DEBUG")]
|
||||
internal sealed partial class NativeTypeNameAttribute : Attribute
|
||||
{
|
||||
/// <summary>Initializes a new instance of the <see cref="NativeTypeNameAttribute" /> class.</summary>
|
||||
/// <param name="name">The name of the type that was used in the native signature.</param>
|
||||
public NativeTypeNameAttribute(string name)
|
||||
{
|
||||
Name = name;
|
||||
}
|
||||
|
||||
/// <summary>Gets the name of the type that was used in the native signature.</summary>
|
||||
public string Name { get; }
|
||||
}
|
||||
|
||||
/// <summary>Defines the vtbl index of a method as it was in the native signature.</summary>
|
||||
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
|
||||
[Conditional("DEBUG")]
|
||||
internal sealed partial class VtblIndexAttribute : Attribute
|
||||
{
|
||||
/// <summary>Initializes a new instance of the <see cref="VtblIndexAttribute" /> class.</summary>
|
||||
/// <param name="index">The vtbl index of a method as it was in the native signature.</param>
|
||||
public VtblIndexAttribute(uint index)
|
||||
{
|
||||
Index = index;
|
||||
}
|
||||
|
||||
/// <summary>Gets the vtbl index of a method as it was in the native signature.</summary>
|
||||
public uint Index { get; }
|
||||
}
|
||||
99
src/Vortice.Win32/Bool32.cs
Normal file
99
src/Vortice.Win32/Bool32.cs
Normal file
@@ -0,0 +1,99 @@
|
||||
// Copyright © Amer Koleci and Contributors.
|
||||
// Licensed under the MIT License (MIT). See LICENSE in the repository root for more information.
|
||||
|
||||
namespace Win32;
|
||||
|
||||
public readonly partial struct Bool32 : IComparable, IComparable<Bool32>, IEquatable<Bool32>, IFormattable
|
||||
{
|
||||
public readonly int Value;
|
||||
|
||||
public Bool32(int value)
|
||||
{
|
||||
Value = value;
|
||||
}
|
||||
|
||||
public static Bool32 True => new Bool32(1);
|
||||
public static Bool32 False => new Bool32(0);
|
||||
|
||||
public static bool operator ==(Bool32 left, Bool32 right) => left.Value == right.Value;
|
||||
|
||||
public static bool operator !=(Bool32 left, Bool32 right) => left.Value != right.Value;
|
||||
|
||||
public static bool operator <(Bool32 left, Bool32 right) => left.Value < right.Value;
|
||||
|
||||
public static bool operator <=(Bool32 left, Bool32 right) => left.Value <= right.Value;
|
||||
|
||||
public static bool operator >(Bool32 left, Bool32 right) => left.Value > right.Value;
|
||||
|
||||
public static bool operator >=(Bool32 left, Bool32 right) => left.Value >= right.Value;
|
||||
|
||||
public static implicit operator bool(Bool32 value) => value.Value != 0;
|
||||
|
||||
public static implicit operator Bool32(bool value) => new Bool32(value ? 1 : 0);
|
||||
|
||||
public static bool operator false(Bool32 value) => value.Value == 0;
|
||||
|
||||
public static bool operator true(Bool32 value) => value.Value != 0;
|
||||
|
||||
public static implicit operator Bool32(byte value) => new Bool32(value);
|
||||
|
||||
public static explicit operator byte(Bool32 value) => (byte)(value.Value);
|
||||
|
||||
public static implicit operator Bool32(short value) => new Bool32(value);
|
||||
|
||||
public static explicit operator short(Bool32 value) => (short)(value.Value);
|
||||
|
||||
public static implicit operator Bool32(int value) => new Bool32(value);
|
||||
|
||||
public static implicit operator int(Bool32 value) => value.Value;
|
||||
|
||||
public static explicit operator Bool32(long value) => new Bool32(unchecked((int)(value)));
|
||||
|
||||
public static implicit operator long(Bool32 value) => value.Value;
|
||||
|
||||
public static explicit operator Bool32(nint value) => new Bool32(unchecked((int)(value)));
|
||||
|
||||
public static implicit operator nint(Bool32 value) => value.Value;
|
||||
|
||||
public static implicit operator Bool32(sbyte value) => new Bool32(value);
|
||||
|
||||
public static explicit operator sbyte(Bool32 value) => (sbyte)(value.Value);
|
||||
|
||||
public static implicit operator Bool32(ushort value) => new Bool32(value);
|
||||
|
||||
public static explicit operator ushort(Bool32 value) => (ushort)(value.Value);
|
||||
|
||||
public static explicit operator Bool32(uint value) => new Bool32(unchecked((int)(value)));
|
||||
|
||||
public static explicit operator uint(Bool32 value) => (uint)(value.Value);
|
||||
|
||||
public static explicit operator Bool32(ulong value) => new Bool32(unchecked((int)(value)));
|
||||
|
||||
public static explicit operator ulong(Bool32 value) => (ulong)(value.Value);
|
||||
|
||||
public static explicit operator Bool32(nuint value) => new Bool32(unchecked((int)(value)));
|
||||
|
||||
public static explicit operator nuint(Bool32 value) => (nuint)(value.Value);
|
||||
|
||||
public int CompareTo(object? obj)
|
||||
{
|
||||
if (obj is Bool32 other)
|
||||
{
|
||||
return CompareTo(other);
|
||||
}
|
||||
|
||||
return (obj is null) ? 1 : throw new ArgumentException("obj is not an instance of Bool32.");
|
||||
}
|
||||
|
||||
public int CompareTo(Bool32 other) => Value.CompareTo(other.Value);
|
||||
|
||||
public override bool Equals(object? obj) => (obj is Bool32 other) && Equals(other);
|
||||
|
||||
public bool Equals(Bool32 other) => Value.Equals(other.Value);
|
||||
|
||||
public override int GetHashCode() => Value.GetHashCode();
|
||||
|
||||
public override string ToString() => Value.ToString();
|
||||
|
||||
public string ToString(string? format, IFormatProvider? formatProvider) => Value.ToString(format, formatProvider);
|
||||
}
|
||||
318
src/Vortice.Win32/ComPtr.cs
Normal file
318
src/Vortice.Win32/ComPtr.cs
Normal file
@@ -0,0 +1,318 @@
|
||||
// Copyright © Tanner Gooding and Contributors. Licensed under the MIT License (MIT). See License.md in the repository root for more information.
|
||||
// Ported from winrt/wrl/client.h in the Windows SDK for Windows 10.0.22621.0
|
||||
// Original source is Copyright © Microsoft. All rights reserved.
|
||||
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.CompilerServices;
|
||||
using static Win32.Apis;
|
||||
|
||||
namespace Win32;
|
||||
|
||||
/// <summary>A type that allows working with pointers to COM objects more securely.</summary>
|
||||
/// <typeparam name="T">The type to wrap in the current <see cref="ComPtr{T}"/> instance.</typeparam>
|
||||
/// <remarks>While this type is not marked as <see langword="ref"/> so that it can also be used in fields, make sure to keep the reference counts properly tracked if you do store <see cref="ComPtr{T}"/> instances on the heap.</remarks>
|
||||
public unsafe struct ComPtr<T> : IDisposable
|
||||
where T : unmanaged, IUnknown.Interface
|
||||
{
|
||||
/// <summary>The raw pointer to a COM object, if existing.</summary>
|
||||
private T* ptr_;
|
||||
|
||||
/// <summary>Creates a new <see cref="ComPtr{T}"/> instance from a raw pointer and increments the ref count.</summary>
|
||||
/// <param name="other">The raw pointer to wrap.</param>
|
||||
public ComPtr(T* other)
|
||||
{
|
||||
ptr_ = other;
|
||||
InternalAddRef();
|
||||
}
|
||||
|
||||
/// <summary>Creates a new <see cref="ComPtr{T}"/> instance from a second one and increments the ref count.</summary>
|
||||
/// <param name="other">The other <see cref="ComPtr{T}"/> instance to copy.</param>
|
||||
public ComPtr(ComPtr<T> other)
|
||||
{
|
||||
ptr_ = other.ptr_;
|
||||
InternalAddRef();
|
||||
}
|
||||
|
||||
/// <summary>Converts a raw pointer to a new <see cref="ComPtr{T}"/> instance and increments the ref count.</summary>
|
||||
/// <param name="other">The raw pointer to wrap.</param>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static implicit operator ComPtr<T>(T* other)
|
||||
=> new ComPtr<T>(other);
|
||||
|
||||
/// <summary>Unwraps a <see cref="ComPtr{T}"/> instance and returns the internal raw pointer.</summary>
|
||||
/// <param name="other">The <see cref="ComPtr{T}"/> instance to unwrap.</param>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static implicit operator T*(ComPtr<T> other)
|
||||
=> other.Get();
|
||||
|
||||
/// <summary>Converts the current object reference to type <typeparamref name="U"/> and assigns that to a target <see cref="ComPtr{T}"/> value.</summary>
|
||||
/// <typeparam name="U">The interface type to use to try casting the current COM object.</typeparam>
|
||||
/// <param name="p">A raw pointer to the target <see cref="ComPtr{T}"/> value to write to.</param>
|
||||
/// <returns>The result of <see cref="IUnknown.QueryInterface"/> for the target type <typeparamref name="U"/>.</returns>
|
||||
/// <remarks>This method will automatically release the target COM object pointed to by <paramref name="p"/>, if any.</remarks>
|
||||
public readonly HResult As<U>(ComPtr<U>* p)
|
||||
where U : unmanaged, IUnknown.Interface
|
||||
{
|
||||
return ptr_->QueryInterface(__uuidof<U>(), (void**)p->ReleaseAndGetAddressOf());
|
||||
}
|
||||
|
||||
/// <summary>Converts the current object reference to type <typeparamref name="U"/> and assigns that to a target <see cref="ComPtr{T}"/> value.</summary>
|
||||
/// <typeparam name="U">The interface type to use to try casting the current COM object.</typeparam>
|
||||
/// <param name="other">A reference to the target <see cref="ComPtr{T}"/> value to write to.</param>
|
||||
/// <returns>The result of <see cref="IUnknown.QueryInterface"/> for the target type <typeparamref name="U"/>.</returns>
|
||||
/// <remarks>This method will automatically release the target COM object pointed to by <paramref name="other"/>, if any.</remarks>
|
||||
public readonly HResult As<U>(ref ComPtr<U> other)
|
||||
where U : unmanaged, IUnknown.Interface
|
||||
{
|
||||
U* ptr;
|
||||
HResult result = ptr_->QueryInterface(__uuidof<U>(), (void**)&ptr);
|
||||
|
||||
other.Attach(ptr);
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>Converts the current object reference to a type indicated by the given IID and assigns that to a target <see cref="ComPtr{T}"/> value.</summary>
|
||||
/// <param name="riid">The IID indicating the interface type to convert the COM object reference to.</param>
|
||||
/// <param name="other">A raw pointer to the target <see cref="ComPtr{T}"/> value to write to.</param>
|
||||
/// <returns>The result of <see cref="IUnknown.QueryInterface"/> for the target IID.</returns>
|
||||
/// <remarks>This method will automatically release the target COM object pointed to by <paramref name="other"/>, if any.</remarks>
|
||||
public readonly HResult AsIID(Guid* riid, ComPtr<IUnknown>* other)
|
||||
{
|
||||
return ptr_->QueryInterface(riid, (void**)other->ReleaseAndGetAddressOf());
|
||||
}
|
||||
|
||||
/// <summary>Converts the current object reference to a type indicated by the given IID and assigns that to a target <see cref="ComPtr{T}"/> value.</summary>
|
||||
/// <param name="riid">The IID indicating the interface type to convert the COM object reference to.</param>
|
||||
/// <param name="other">A reference to the target <see cref="ComPtr{T}"/> value to write to.</param>
|
||||
/// <returns>The result of <see cref="IUnknown.QueryInterface"/> for the target IID.</returns>
|
||||
/// <remarks>This method will automatically release the target COM object pointed to by <paramref name="other"/>, if any.</remarks>
|
||||
public readonly HResult AsIID(Guid* riid, ref ComPtr<IUnknown> other)
|
||||
{
|
||||
IUnknown* ptr;
|
||||
HResult result = ptr_->QueryInterface(riid, (void**)&ptr);
|
||||
|
||||
other.Attach(ptr);
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>Releases the current COM object, if any, and replaces the internal pointer with an input raw pointer.</summary>
|
||||
/// <param name="other">The input raw pointer to wrap.</param>
|
||||
/// <remarks>This method will release the current raw pointer, if any, but it will not increment the references for <paramref name="other"/>.</remarks>
|
||||
public void Attach(T* other)
|
||||
{
|
||||
if (ptr_ != null)
|
||||
{
|
||||
var @ref = ptr_->Release();
|
||||
Debug.Assert((@ref != 0) || (ptr_ != other));
|
||||
}
|
||||
ptr_ = other;
|
||||
}
|
||||
|
||||
/// <summary>Returns the raw pointer wrapped by the current instance, and resets the current <see cref="ComPtr{T}"/> value.</summary>
|
||||
/// <returns>The raw pointer wrapped by the current <see cref="ComPtr{T}"/> value.</returns>
|
||||
/// <remarks>This method will not change the reference count for the COM object in use.</remarks>
|
||||
public T* Detach()
|
||||
{
|
||||
T* ptr = ptr_;
|
||||
ptr_ = null;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
/// <summary>Increments the reference count for the current COM object, if any, and copies its address to a target raw pointer.</summary>
|
||||
/// <param name="ptr">The target raw pointer to copy the address of the current COM object to.</param>
|
||||
/// <returns>This method always returns <see cref="HResult.Ok"/>.</returns>
|
||||
public readonly HResult CopyTo(T** ptr)
|
||||
{
|
||||
InternalAddRef();
|
||||
*ptr = ptr_;
|
||||
return HResult.Ok;
|
||||
}
|
||||
|
||||
/// <summary>Increments the reference count for the current COM object, if any, and copies its address to a target <see cref="ComPtr{T}"/>.</summary>
|
||||
/// <param name="p">The target raw pointer to copy the address of the current COM object to.</param>
|
||||
/// <returns>This method always returns <see cref="HResult.Ok"/>.</returns>
|
||||
public readonly HResult CopyTo(ComPtr<T>* p)
|
||||
{
|
||||
InternalAddRef();
|
||||
*p->ReleaseAndGetAddressOf() = ptr_;
|
||||
return HResult.Ok;
|
||||
}
|
||||
|
||||
/// <summary>Increments the reference count for the current COM object, if any, and copies its address to a target <see cref="ComPtr{T}"/>.</summary>
|
||||
/// <param name="other">The target reference to copy the address of the current COM object to.</param>
|
||||
/// <returns>This method always returns <see cref="HResult.Ok"/>.</returns>
|
||||
public readonly HResult CopyTo(ref ComPtr<T> other)
|
||||
{
|
||||
InternalAddRef();
|
||||
other.Attach(ptr_);
|
||||
return HResult.Ok;
|
||||
}
|
||||
|
||||
/// <summary>Converts the current COM object reference to a given interface type and assigns that to a target raw pointer.</summary>
|
||||
/// <param name="ptr">The target raw pointer to copy the address of the current COM object to.</param>
|
||||
/// <returns>The result of <see cref="IUnknown.QueryInterface"/> for the target type <typeparamref name="U"/>.</returns>
|
||||
public readonly HResult CopyTo<U>(U** ptr)
|
||||
where U : unmanaged, IUnknown.Interface
|
||||
{
|
||||
return ptr_->QueryInterface(__uuidof<U>(), (void**)ptr);
|
||||
}
|
||||
|
||||
/// <summary>Converts the current COM object reference to a given interface type and assigns that to a target <see cref="ComPtr{T}"/>.</summary>
|
||||
/// <param name="p">The target raw pointer to copy the address of the current COM object to.</param>
|
||||
/// <returns>The result of <see cref="IUnknown.QueryInterface"/> for the target type <typeparamref name="U"/>.</returns>
|
||||
public readonly HResult CopyTo<U>(ComPtr<U>* p)
|
||||
where U : unmanaged, IUnknown.Interface
|
||||
{
|
||||
return ptr_->QueryInterface(__uuidof<U>(), (void**)p->ReleaseAndGetAddressOf());
|
||||
}
|
||||
|
||||
/// <summary>Converts the current COM object reference to a given interface type and assigns that to a target <see cref="ComPtr{T}"/>.</summary>
|
||||
/// <param name="other">The target reference to copy the address of the current COM object to.</param>
|
||||
/// <returns>The result of <see cref="IUnknown.QueryInterface"/> for the target type <typeparamref name="U"/>.</returns>
|
||||
public readonly HResult CopyTo<U>(ref ComPtr<U> other)
|
||||
where U : unmanaged, IUnknown.Interface
|
||||
{
|
||||
U* ptr;
|
||||
HResult result = ptr_->QueryInterface(__uuidof<U>(), (void**)&ptr);
|
||||
|
||||
other.Attach(ptr);
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>Converts the current object reference to a type indicated by the given IID and assigns that to a target address.</summary>
|
||||
/// <param name="riid">The IID indicating the interface type to convert the COM object reference to.</param>
|
||||
/// <param name="ptr">The target raw pointer to copy the address of the current COM object to.</param>
|
||||
/// <returns>The result of <see cref="IUnknown.QueryInterface"/> for the target IID.</returns>
|
||||
public readonly HResult CopyTo(Guid* riid, void** ptr)
|
||||
{
|
||||
return ptr_->QueryInterface(riid, ptr);
|
||||
}
|
||||
|
||||
/// <summary>Converts the current object reference to a type indicated by the given IID and assigns that to a target <see cref="ComPtr{T}"/> value.</summary>
|
||||
/// <param name="riid">The IID indicating the interface type to convert the COM object reference to.</param>
|
||||
/// <param name="p">The target raw pointer to copy the address of the current COM object to.</param>
|
||||
/// <returns>The result of <see cref="IUnknown.QueryInterface"/> for the target IID.</returns>
|
||||
public readonly HResult CopyTo(Guid* riid, ComPtr<IUnknown>* p)
|
||||
{
|
||||
return ptr_->QueryInterface(riid, (void**)p->ReleaseAndGetAddressOf());
|
||||
}
|
||||
|
||||
/// <summary>Converts the current object reference to a type indicated by the given IID and assigns that to a target <see cref="ComPtr{T}"/> value.</summary>
|
||||
/// <param name="riid">The IID indicating the interface type to convert the COM object reference to.</param>
|
||||
/// <param name="other">The target reference to copy the address of the current COM object to.</param>
|
||||
/// <returns>The result of <see cref="IUnknown.QueryInterface"/> for the target IID.</returns>
|
||||
public readonly HResult CopyTo(Guid* riid, ref ComPtr<IUnknown> other)
|
||||
{
|
||||
IUnknown* ptr;
|
||||
HResult result = ptr_->QueryInterface(riid, (void**)&ptr);
|
||||
|
||||
other.Attach(ptr);
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void Dispose()
|
||||
{
|
||||
T* pointer = ptr_;
|
||||
|
||||
if (pointer != null)
|
||||
{
|
||||
ptr_ = null;
|
||||
_ = pointer->Release();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Gets the currently wrapped raw pointer to a COM object.</summary>
|
||||
/// <returns>The raw pointer wrapped by the current <see cref="ComPtr{T}"/> instance.</returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public readonly T* Get()
|
||||
{
|
||||
return ptr_;
|
||||
}
|
||||
|
||||
/// <summary>Gets the address of the current <see cref="ComPtr{T}"/> instance as a raw <typeparamref name="T"/> double pointer. This method is only valid when the current <see cref="ComPtr{T}"/> instance is on the stack or pinned.
|
||||
/// </summary>
|
||||
/// <returns>The raw pointer to the current <see cref="ComPtr{T}"/> instance.</returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public readonly T** GetAddressOf()
|
||||
{
|
||||
return (T**)Unsafe.AsPointer(ref Unsafe.AsRef(in this));
|
||||
}
|
||||
|
||||
/// <summary>Gets the address of the current <see cref="ComPtr{T}"/> instance as a raw <typeparamref name="T"/> double pointer.</summary>
|
||||
/// <returns>The raw pointer to the current <see cref="ComPtr{T}"/> instance.</returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
public readonly ref T* GetPinnableReference()
|
||||
{
|
||||
fixed (T** ptr = &ptr_)
|
||||
{
|
||||
return ref *ptr;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Releases the current COM object in use and gets the address of the <see cref="ComPtr{T}"/> instance as a raw <typeparamref name="T"/> double pointer. This method is only valid when the current <see cref="ComPtr{T}"/> instance is on the stack or pinned.</summary>
|
||||
/// <returns>The raw pointer to the current <see cref="ComPtr{T}"/> instance.</returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public T** ReleaseAndGetAddressOf()
|
||||
{
|
||||
_ = InternalRelease();
|
||||
return GetAddressOf();
|
||||
}
|
||||
|
||||
/// <summary>Resets the current instance by decrementing the reference count for the target COM object and setting the internal raw pointer to <see langword="null"/>.</summary>
|
||||
/// <returns>The updated reference count for the COM object that was in use, if any.</returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public uint Reset()
|
||||
{
|
||||
return InternalRelease();
|
||||
}
|
||||
|
||||
/// <summary>Swaps the current COM object reference with that of a given <see cref="ComPtr{T}"/> instance.</summary>
|
||||
/// <param name="r">The target <see cref="ComPtr{T}"/> instance to swap with the current one.</param>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void Swap(ComPtr<T>* r)
|
||||
{
|
||||
T* tmp = ptr_;
|
||||
ptr_ = r->ptr_;
|
||||
r->ptr_ = tmp;
|
||||
}
|
||||
|
||||
/// <summary>Swaps the current COM object reference with that of a given <see cref="ComPtr{T}"/> instance.</summary>
|
||||
/// <param name="other">The target <see cref="ComPtr{T}"/> instance to swap with the current one.</param>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void Swap(ref ComPtr<T> other)
|
||||
{
|
||||
T* tmp = ptr_;
|
||||
ptr_ = other.ptr_;
|
||||
other.ptr_ = tmp;
|
||||
}
|
||||
|
||||
// Increments the reference count for the current COM object, if any
|
||||
private readonly void InternalAddRef()
|
||||
{
|
||||
T* temp = ptr_;
|
||||
|
||||
if (temp != null)
|
||||
{
|
||||
_ = temp->AddRef();
|
||||
}
|
||||
}
|
||||
|
||||
// Decrements the reference count for the current COM object, if any
|
||||
private uint InternalRelease()
|
||||
{
|
||||
uint @ref = 0;
|
||||
T* temp = ptr_;
|
||||
|
||||
if (temp != null)
|
||||
{
|
||||
ptr_ = null;
|
||||
@ref = temp->Release();
|
||||
}
|
||||
|
||||
return @ref;
|
||||
}
|
||||
}
|
||||
1510
src/Vortice.Win32/Generated/Graphics/Dxgi.Common.cs
Normal file
1510
src/Vortice.Win32/Generated/Graphics/Dxgi.Common.cs
Normal file
File diff suppressed because it is too large
Load Diff
66
src/Vortice.Win32/Graphics/Dxgi.Common.Manual.cs
Normal file
66
src/Vortice.Win32/Graphics/Dxgi.Common.Manual.cs
Normal file
@@ -0,0 +1,66 @@
|
||||
// Copyright © Amer Koleci and Contributors.
|
||||
// Licensed under the MIT License (MIT). See LICENSE in the repository root for more information.
|
||||
|
||||
namespace Win32.Graphics.Dxgi;
|
||||
|
||||
public partial struct Rgb
|
||||
{
|
||||
/// <summary>
|
||||
/// Initialize instance of <see cref="Rgb"/> struct.
|
||||
/// </summary>
|
||||
/// <param name="red"></param>
|
||||
/// <param name="green"></param>
|
||||
/// <param name="blue"></param>
|
||||
public Rgb(float red, float green, float blue)
|
||||
{
|
||||
Red = red;
|
||||
Green = green;
|
||||
Blue = blue;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{nameof(Rgb)}(Red: {Red}, Green: {Green}, Blue: {Blue})";
|
||||
}
|
||||
}
|
||||
|
||||
public partial struct Rational
|
||||
{
|
||||
/// <summary>
|
||||
/// Initialize instance of <see cref="Rational"/> struct.
|
||||
/// </summary>
|
||||
/// <param name="numerator"></param>
|
||||
/// <param name="denominator"></param>
|
||||
public Rational(uint numerator, uint denominator)
|
||||
{
|
||||
Numerator = numerator;
|
||||
Denominator = denominator;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{nameof(Rational)}(Numerator: {Numerator}, Denominator: {Denominator})";
|
||||
}
|
||||
}
|
||||
|
||||
public partial struct SampleDescription
|
||||
{
|
||||
/// <summary>
|
||||
/// A <see cref="SampleDescription"/> with Count=1 and Quality=0.
|
||||
/// </summary>
|
||||
public static readonly SampleDescription Default = new(1, 0);
|
||||
|
||||
/// <summary>
|
||||
/// Create new instance of <see cref="SampleDescription"/> struct.
|
||||
/// </summary>
|
||||
/// <param name="count"></param>
|
||||
/// <param name="quality"></param>
|
||||
public SampleDescription(uint count, uint quality)
|
||||
{
|
||||
Count = count;
|
||||
Quality = quality;
|
||||
}
|
||||
|
||||
public override string ToString() => $"Count: {Count}, Quality: {Quality}";
|
||||
}
|
||||
|
||||
61
src/Vortice.Win32/HResult.Constants.cs
Normal file
61
src/Vortice.Win32/HResult.Constants.cs
Normal file
@@ -0,0 +1,61 @@
|
||||
// Copyright © Amer Koleci and Contributors.
|
||||
// Licensed under the MIT License (MIT). See LICENSE in the repository root for more information.
|
||||
|
||||
namespace Win32;
|
||||
|
||||
public readonly partial struct HResult
|
||||
{
|
||||
/// <unmanaged>S_OK</unmanaged>
|
||||
public static readonly HResult Ok = 0;
|
||||
|
||||
/// <unmanaged>S_FALSE</unmanaged>
|
||||
public static readonly HResult False = 1;
|
||||
|
||||
/// <unmanaged>E_ABORT</unmanaged>
|
||||
public static readonly HResult Abort = unchecked((int)0x80004004);
|
||||
|
||||
/// <unmanaged>E_ACCESSDENIED</unmanaged>
|
||||
public static readonly HResult AccessDenied = unchecked((int)0x80070005);
|
||||
|
||||
/// <unmanaged>E_FAIL</unmanaged>
|
||||
public static readonly HResult Fail = unchecked((int)0x80004005);
|
||||
|
||||
/// <unmanaged>E_HANDLE</unmanaged>
|
||||
public static readonly HResult Handle = unchecked((int)0x80070006);
|
||||
|
||||
/// <unmanaged>E_INVALIDARG</unmanaged>
|
||||
public static readonly HResult InvalidArg = unchecked((int)0x80070057);
|
||||
|
||||
/// <unmanaged>E_NOINTERFACE</unmanaged>
|
||||
public static readonly HResult NoInterface = unchecked((int)0x80004002);
|
||||
|
||||
/// <unmanaged>E_NOTIMPL</unmanaged>
|
||||
public static readonly HResult NotImplemented = unchecked((int)0x80004001);
|
||||
|
||||
/// <unmanaged>E_OUTOFMEMORY</unmanaged>
|
||||
public static readonly HResult OutOfMemory = unchecked((int)0x8007000E);
|
||||
|
||||
/// <unmanaged>E_POINTER</unmanaged>
|
||||
public static readonly HResult InvalidPointer = unchecked((int)0x80004003);
|
||||
|
||||
/// <unmanaged>E_UNEXPECTED</unmanaged>
|
||||
public static readonly HResult UnexpectedFailure = unchecked((int)0x8000FFFF);
|
||||
|
||||
/// <unmanaged>WAIT_ABANDONED</unmanaged>
|
||||
public static readonly HResult WaitAbandoned = unchecked((int)0x00000080);
|
||||
|
||||
/// <unmanaged>WAIT_TIMEOUT</unmanaged>
|
||||
public static readonly HResult WaitTimeout = unchecked((int)0x00000102);
|
||||
|
||||
/// <summary>
|
||||
/// The data necessary to complete this operation is not yet available.
|
||||
/// </summary>
|
||||
/// <unmanaged>E_PENDING</unmanaged>
|
||||
public static readonly HResult Pending = unchecked((int)0x8000000A);
|
||||
|
||||
/// <summary>
|
||||
/// The data area passed to a system call is too small.
|
||||
/// </summary>
|
||||
/// <unmanaged>E_NOT_SUFFICIENT_BUFFER</unmanaged>
|
||||
public static readonly HResult InsufficientBuffer = unchecked((int)0x8007007A);
|
||||
}
|
||||
92
src/Vortice.Win32/HResult.cs
Normal file
92
src/Vortice.Win32/HResult.cs
Normal file
@@ -0,0 +1,92 @@
|
||||
// Copyright © Amer Koleci and Contributors.
|
||||
// Licensed under the MIT License (MIT). See LICENSE in the repository root for more information.
|
||||
|
||||
namespace Win32;
|
||||
|
||||
public readonly partial struct HResult : IComparable, IComparable<HResult>, IEquatable<HResult>, IFormattable
|
||||
{
|
||||
public readonly int Value;
|
||||
|
||||
public HResult(int value)
|
||||
{
|
||||
Value = value;
|
||||
}
|
||||
|
||||
public static bool operator ==(HResult left, HResult right) => left.Value == right.Value;
|
||||
|
||||
public static bool operator !=(HResult left, HResult right) => left.Value != right.Value;
|
||||
|
||||
public static bool operator <(HResult left, HResult right) => left.Value < right.Value;
|
||||
|
||||
public static bool operator <=(HResult left, HResult right) => left.Value <= right.Value;
|
||||
|
||||
public static bool operator >(HResult left, HResult right) => left.Value > right.Value;
|
||||
|
||||
public static bool operator >=(HResult left, HResult right) => left.Value >= right.Value;
|
||||
|
||||
public static implicit operator HResult(byte value) => new HResult(value);
|
||||
|
||||
public static explicit operator byte(HResult value) => (byte)(value.Value);
|
||||
|
||||
public static implicit operator HResult(short value) => new HResult(value);
|
||||
|
||||
public static explicit operator short(HResult value) => (short)(value.Value);
|
||||
|
||||
public static implicit operator HResult(int value) => new HResult(value);
|
||||
|
||||
public static implicit operator int(HResult value) => value.Value;
|
||||
|
||||
public static explicit operator HResult(long value) => new HResult(unchecked((int)(value)));
|
||||
|
||||
public static implicit operator long(HResult value) => value.Value;
|
||||
|
||||
public static explicit operator HResult(nint value) => new HResult(unchecked((int)(value)));
|
||||
|
||||
public static implicit operator nint(HResult value) => value.Value;
|
||||
|
||||
public static implicit operator HResult(sbyte value) => new HResult(value);
|
||||
|
||||
public static explicit operator sbyte(HResult value) => (sbyte)(value.Value);
|
||||
|
||||
public static implicit operator HResult(ushort value) => new HResult(value);
|
||||
|
||||
public static explicit operator ushort(HResult value) => (ushort)(value.Value);
|
||||
|
||||
public static explicit operator HResult(uint value) => new HResult(unchecked((int)(value)));
|
||||
|
||||
public static explicit operator uint(HResult value) => (uint)(value.Value);
|
||||
|
||||
public static explicit operator HResult(ulong value) => new HResult(unchecked((int)(value)));
|
||||
|
||||
public static explicit operator ulong(HResult value) => (ulong)(value.Value);
|
||||
|
||||
public static explicit operator HResult(nuint value) => new HResult(unchecked((int)(value)));
|
||||
|
||||
public static explicit operator nuint(HResult value) => (nuint)(value.Value);
|
||||
|
||||
public int CompareTo(object? obj)
|
||||
{
|
||||
if (obj is HResult other)
|
||||
{
|
||||
return CompareTo(other);
|
||||
}
|
||||
|
||||
return (obj is null) ? 1 : throw new ArgumentException("obj is not an instance of HResult.");
|
||||
}
|
||||
|
||||
public int CompareTo(HResult other) => Value.CompareTo(other.Value);
|
||||
|
||||
public override bool Equals(object? obj) => (obj is HResult other) && Equals(other);
|
||||
|
||||
public bool Equals(HResult other) => Value.Equals(other.Value);
|
||||
|
||||
public override int GetHashCode() => Value.GetHashCode();
|
||||
|
||||
public override string ToString() => Value.ToString("X8");
|
||||
|
||||
public string ToString(string? format, IFormatProvider? formatProvider) => Value.ToString(format, formatProvider);
|
||||
|
||||
public bool Failure => Value < 0;
|
||||
|
||||
public bool Success => Value >= 0;
|
||||
}
|
||||
65
src/Vortice.Win32/IUnknown.cs
Normal file
65
src/Vortice.Win32/IUnknown.cs
Normal file
@@ -0,0 +1,65 @@
|
||||
// Copyright © Amer Koleci and Contributors.
|
||||
// Licensed under the MIT License (MIT). See LICENSE in the repository root for more information.
|
||||
|
||||
using System.Runtime.CompilerServices;
|
||||
using static Win32.Apis;
|
||||
|
||||
namespace Win32;
|
||||
|
||||
[Guid("00000000-0000-0000-C000-000000000046")]
|
||||
public unsafe partial struct IUnknown : IUnknown.Interface
|
||||
{
|
||||
public static Guid* NativeGuid => (Guid*)Unsafe.AsPointer(ref Unsafe.AsRef(in IID_IUnknown));
|
||||
|
||||
public void** lpVtbl;
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
[VtblIndex(0)]
|
||||
public HResult QueryInterface([NativeTypeName("const IID &")] Guid* riid, void** ppvObject)
|
||||
{
|
||||
return ((delegate* unmanaged[Stdcall]<IUnknown*, Guid*, void**, int>)(lpVtbl[0]))((IUnknown*)Unsafe.AsPointer(ref this), riid, ppvObject);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
[VtblIndex(1)]
|
||||
[return: NativeTypeName("ULONG")]
|
||||
public uint AddRef()
|
||||
{
|
||||
return ((delegate* unmanaged[Stdcall]<IUnknown*, uint>)(lpVtbl[1]))((IUnknown*)Unsafe.AsPointer(ref this));
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
[VtblIndex(2)]
|
||||
[return: NativeTypeName("ULONG")]
|
||||
public uint Release()
|
||||
{
|
||||
return ((delegate* unmanaged[Stdcall]<IUnknown*, uint>)(lpVtbl[2]))((IUnknown*)Unsafe.AsPointer(ref this));
|
||||
}
|
||||
|
||||
public interface Interface
|
||||
{
|
||||
[VtblIndex(0)]
|
||||
HResult QueryInterface([NativeTypeName("const IID &")] Guid* riid, void** ppvObject);
|
||||
|
||||
[VtblIndex(1)]
|
||||
[return: NativeTypeName("ULONG")]
|
||||
uint AddRef();
|
||||
|
||||
[VtblIndex(2)]
|
||||
[return: NativeTypeName("ULONG")]
|
||||
uint Release();
|
||||
}
|
||||
|
||||
public partial struct Vtbl<TSelf>
|
||||
where TSelf : unmanaged, Interface
|
||||
{
|
||||
[NativeTypeName("HRESULT (const IID &, void **) __attribute__((stdcall))")]
|
||||
public delegate* unmanaged[Stdcall]<TSelf*, Guid*, void**, int> QueryInterface;
|
||||
|
||||
[NativeTypeName("ULONG () __attribute__((stdcall))")]
|
||||
public delegate* unmanaged[Stdcall]<TSelf*, uint> AddRef;
|
||||
|
||||
[NativeTypeName("ULONG () __attribute__((stdcall))")]
|
||||
public delegate* unmanaged[Stdcall]<TSelf*, uint> Release;
|
||||
}
|
||||
}
|
||||
36
src/Vortice.Win32/UnscopedRefAttribute.cs
Normal file
36
src/Vortice.Win32/UnscopedRefAttribute.cs
Normal file
@@ -0,0 +1,36 @@
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
|
||||
namespace System.Diagnostics.CodeAnalysis;
|
||||
|
||||
/// <summary>
|
||||
/// Used to indicate a byref escapes and is not scoped.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// There are several cases where the C# compiler treats a <see langword="ref"/> as implicitly
|
||||
/// <see langword="scoped"/> - where the compiler does not allow the <see langword="ref"/> to escape the method.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// For example:
|
||||
/// <list type="number">
|
||||
/// <item><see langword="this"/> for <see langword="struct"/> instance methods.</item>
|
||||
/// <item><see langword="ref"/> parameters that refer to <see langword="ref"/> <see langword="struct"/> types.</item>
|
||||
/// <item><see langword="out"/> parameters.</item>
|
||||
/// </list>
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// This attribute is used in those instances where the <see langword="ref"/> should be allowed to escape.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// Applying this attribute, in any form, has impact on consumers of the applicable API. It is necessary for
|
||||
/// API authors to understand the lifetime implications of applying this attribute and how it may impact their users.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
[AttributeUsage(
|
||||
AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Parameter,
|
||||
AllowMultiple = false,
|
||||
Inherited = false)]
|
||||
internal sealed class UnscopedRefAttribute : Attribute
|
||||
{
|
||||
}
|
||||
110
src/Vortice.Win32/Win32.cs
Normal file
110
src/Vortice.Win32/Win32.cs
Normal file
@@ -0,0 +1,110 @@
|
||||
// Copyright © Amer Koleci and Contributors.
|
||||
// Licensed under the MIT License (MIT). See LICENSE in the repository root for more information.
|
||||
|
||||
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace Win32;
|
||||
|
||||
public static partial class Apis
|
||||
{
|
||||
public static ref readonly Guid IID_IUnknown
|
||||
{
|
||||
get
|
||||
{
|
||||
ReadOnlySpan<byte> data = new byte[] {
|
||||
0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00,
|
||||
0x00, 0x00,
|
||||
0xC0,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x00,
|
||||
0x46
|
||||
};
|
||||
|
||||
Debug.Assert(data.Length == Unsafe.SizeOf<Guid>());
|
||||
return ref Unsafe.As<byte, Guid>(ref MemoryMarshal.GetReference(data));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Retrieves the GUID of of a specified type.</summary>
|
||||
/// <param name="value">A value of type <typeparamref name="T"/>.</param>
|
||||
/// <typeparam name="T">The type to retrieve the GUID for.</typeparam>
|
||||
/// <returns>A <see cref="UuidOfType"/> value wrapping a pointer to the GUID data for the input type. This value can be either converted to a <see cref="Guid"/> pointer, or implicitly assigned to a <see cref="Guid"/> value.</returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static unsafe UuidOfType __uuidof<T>(T value) // for type inference similar to C++'s __uuidof
|
||||
where T : unmanaged
|
||||
{
|
||||
return new UuidOfType(UUID<T>.RIID);
|
||||
}
|
||||
|
||||
/// <summary>Retrieves the GUID of of a specified type.</summary>
|
||||
/// <param name="value">A pointer to a value of type <typeparamref name="T"/>.</param>
|
||||
/// <typeparam name="T">The type to retrieve the GUID for.</typeparam>
|
||||
/// <returns>A <see cref="UuidOfType"/> value wrapping a pointer to the GUID data for the input type. This value can be either converted to a <see cref="Guid"/> pointer, or implicitly assigned to a <see cref="Guid"/> value.</returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static unsafe UuidOfType __uuidof<T>(T* value) // for type inference similar to C++'s __uuidof
|
||||
where T : unmanaged
|
||||
{
|
||||
return new UuidOfType(UUID<T>.RIID);
|
||||
}
|
||||
|
||||
/// <summary>Retrieves the GUID of of a specified type.</summary>
|
||||
/// <typeparam name="T">The type to retrieve the GUID for.</typeparam>
|
||||
/// <returns>A <see cref="UuidOfType"/> value wrapping a pointer to the GUID data for the input type. This value can be either converted to a <see cref="Guid"/> pointer, or implicitly assigned to a <see cref="Guid"/> value.</returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static unsafe UuidOfType __uuidof<T>()
|
||||
where T : unmanaged
|
||||
{
|
||||
return new UuidOfType(UUID<T>.RIID);
|
||||
}
|
||||
|
||||
/// <summary>A proxy type that wraps a pointer to GUID data. Values of this type can be implicitly converted to and assigned to <see cref="Guid"/>* or <see cref="Guid"/> parameters.</summary>
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
public readonly unsafe ref struct UuidOfType
|
||||
{
|
||||
private readonly Guid* riid;
|
||||
|
||||
internal UuidOfType(Guid* riid)
|
||||
{
|
||||
this.riid = riid;
|
||||
}
|
||||
|
||||
/// <summary>Reads a <see cref="Guid"/> value from the GUID buffer for a given <see cref="UuidOfType"/> instance.</summary>
|
||||
/// <param name="guid">The input <see cref="UuidOfType"/> instance to read data for.</param>
|
||||
public static implicit operator Guid(UuidOfType guid) => *guid.riid;
|
||||
|
||||
/// <summary>Returns the <see cref="Guid"/>* pointer to the GUID buffer for a given <see cref="UuidOfType"/> instance.</summary>
|
||||
/// <param name="guid">The input <see cref="UuidOfType"/> instance to read data for.</param>
|
||||
public static implicit operator Guid*(UuidOfType guid) => guid.riid;
|
||||
}
|
||||
|
||||
/// <summary>A helper type to provide static GUID buffers for specific types.</summary>
|
||||
/// <typeparam name="T">The type to allocate a GUID buffer for.</typeparam>
|
||||
private static unsafe class UUID<T>
|
||||
where T : unmanaged
|
||||
{
|
||||
/// <summary>The pointer to the <see cref="Guid"/> value for the current type.</summary>
|
||||
/// <remarks>The target memory area should never be written to.</remarks>
|
||||
public static readonly Guid* RIID = CreateRIID();
|
||||
|
||||
/// <summary>Allocates memory for a <see cref="Guid"/> value and initializes it.</summary>
|
||||
/// <returns>A pointer to memory holding the <see cref="Guid"/> value for the current type.</returns>
|
||||
private static Guid* CreateRIID()
|
||||
{
|
||||
#if NET6_0_OR_GREATER
|
||||
var p = (Guid*)RuntimeHelpers.AllocateTypeAssociatedMemory(typeof(T), sizeof(Guid));
|
||||
#else
|
||||
var p = (Guid*)Marshal.AllocHGlobal(sizeof(Guid));
|
||||
#endif
|
||||
*p = typeof(T).GUID;
|
||||
return p;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user