Generator: Completed initial step of Com Types generation and various improvements.

This commit is contained in:
Amer Koleci
2022-09-02 18:03:31 +02:00
parent 9d535bd98e
commit 3737620e92
12 changed files with 12307 additions and 79 deletions

View File

@@ -3,6 +3,8 @@
#nullable disable #nullable disable
using System.Text;
namespace Generator; namespace Generator;
public class ApiDataArrayShape public class ApiDataArrayShape
@@ -20,6 +22,11 @@ public class ApiDataType
// Kind == Array // Kind == Array
public ApiDataArrayShape Shape { get; set; } public ApiDataArrayShape Shape { get; set; }
public ApiDataType Child { get; set; } public ApiDataType Child { get; set; }
// Kind == LPArray
public bool NullNullTerm { get; set; }
public int CountParamIndex { get; set; }
public int CountConst { get; set; }
} }
public class ApiDataConstant public class ApiDataConstant
@@ -46,6 +53,7 @@ public class ApiParameter
{ {
public string Name { get; set; } public string Name { get; set; }
public ApiDataType Type { get; set; } public ApiDataType Type { get; set; }
public List<object> Attrs { get; set; } = new();
} }
public class ApiFunction public class ApiFunction
@@ -55,6 +63,34 @@ public class ApiFunction
public ApiDataType ReturnType { get; set; } public ApiDataType ReturnType { get; set; }
public IList<ApiParameter> Params { get; set; } = new List<ApiParameter>(); public IList<ApiParameter> Params { get; set; } = new List<ApiParameter>();
public List<object> Attrs { get; set; } public List<object> Attrs { get; set; }
private string _toString = default;
public override string ToString()
{
if (string.IsNullOrEmpty(_toString))
{
StringBuilder builder = new();
builder.Append(ReturnType.Name).Append(' ');
builder.Append(Name).Append('(');
int parameterIndex = 0;
foreach (var parameter in Params)
{
// TODO: Handle PointerTo, Array etc
builder.Append(parameter.Type.Name).Append(' ').Append(parameter.Name);
if (parameterIndex < Params.Count - 1)
{
builder.Append(", ");
}
parameterIndex++;
}
builder.Append(')');
_toString = builder.ToString();
}
return _toString;
}
} }
public class ApiType public class ApiType

View File

@@ -1,14 +1,17 @@
// Copyright © Amer Koleci and Contributors. // Copyright © Amer Koleci and Contributors.
// Licensed under the MIT License (MIT). See LICENSE in the repository root for more information. // Licensed under the MIT License (MIT). See LICENSE in the repository root for more information.
using System.Text;
namespace Generator; namespace Generator;
public sealed class CodeWriter : IDisposable public sealed class CodeWriter : IDisposable
{ {
private readonly string _fileName;
private bool _shouldIndent = true; private bool _shouldIndent = true;
private readonly string[] _indentStrings; private readonly string[] _indentStrings;
private string _indentString = ""; private string _indentString = "";
private readonly StreamWriter _writer; private readonly StringBuilder _builder = new();
public int IndentLevel { get; private set; } public int IndentLevel { get; private set; }
public string Api { get; } public string Api { get; }
@@ -16,6 +19,7 @@ public sealed class CodeWriter : IDisposable
public CodeWriter(string fileName, string api, string docFileName, string ns, params string[] usingNamespaces) public CodeWriter(string fileName, string api, string docFileName, string ns, params string[] usingNamespaces)
{ {
_fileName = fileName;
Api = api; Api = api;
DocFileName = docFileName; DocFileName = docFileName;
@@ -25,40 +29,40 @@ public sealed class CodeWriter : IDisposable
_indentStrings[i] = new string('\t', i); _indentStrings[i] = new string('\t', i);
} }
_writer = File.CreateText(fileName); _builder.AppendLine("// ------------------------------------------------------------------------------");
_writer.WriteLine("// ------------------------------------------------------------------------------"); _builder.AppendLine("// <auto-generated>");
_writer.WriteLine("// <auto-generated>"); _builder.AppendLine("// This code was generated by a tool.");
_writer.WriteLine("// This code was generated by a tool."); _builder.AppendLine("//");
_writer.WriteLine("//"); _builder.AppendLine("// Changes to this file may cause incorrect behavior and will be lost if");
_writer.WriteLine("// Changes to this file may cause incorrect behavior and will be lost if"); _builder.AppendLine("// the code is regenerated.");
_writer.WriteLine("// the code is regenerated."); _builder.AppendLine("// </auto-generated>");
_writer.WriteLine("// </auto-generated>"); _builder.AppendLine("// ------------------------------------------------------------------------------");
_writer.WriteLine("// ------------------------------------------------------------------------------"); _builder.AppendLine();
_writer.WriteLine();
_writer.WriteLine($"using System;"); _builder.AppendLine($"using System;");
_writer.WriteLine($"using System.Diagnostics;"); _builder.AppendLine($"using System.Diagnostics;");
_writer.WriteLine($"using System.Runtime.CompilerServices;"); _builder.AppendLine($"using System.Runtime.CompilerServices;");
_writer.WriteLine($"using System.Diagnostics.CodeAnalysis;"); _builder.AppendLine($"using System.Diagnostics.CodeAnalysis;");
foreach (string usingNamespace in usingNamespaces) foreach (string usingNamespace in usingNamespaces)
{ {
_writer.WriteLine($"using {usingNamespace};"); _builder.AppendLine($"using {usingNamespace};");
} }
_writer.WriteLine(); _builder.AppendLine();
_writer.WriteLine("#if !NET6_0_OR_GREATER"); _builder.AppendLine("#if !NET6_0_OR_GREATER");
_writer.WriteLine("using MemoryMarshal = Win32.MemoryMarshal;"); _builder.AppendLine("using MemoryMarshal = Win32.MemoryMarshal;");
_writer.WriteLine("#endif"); _builder.AppendLine("#endif");
_writer.WriteLine(); _builder.AppendLine();
_writer.WriteLine($"namespace {ns};"); _builder.AppendLine($"namespace {ns};");
_writer.WriteLine(); _builder.AppendLine();
} }
public void Dispose() public void Dispose()
{ {
_writer.Dispose(); string content = _builder.ToString();
File.WriteAllText(_fileName, content);
} }
public void Write(char chr) public void Write(char chr)
@@ -73,20 +77,20 @@ public sealed class CodeWriter : IDisposable
public void WriteLine() public void WriteLine()
{ {
_writer.WriteLine(); _builder.AppendLine();
_shouldIndent = true; _shouldIndent = true;
} }
public void WriteLine(string @string) public void WriteLine(string @string)
{ {
WriteIndented(@string); WriteIndented(@string);
_writer.WriteLine(); _builder.AppendLine();
_shouldIndent = true; _shouldIndent = true;
} }
public void WriteLineUndindented(string @string) public void WriteLineUndindented(string @string)
{ {
_writer.WriteLine(@string); _builder.AppendLine(@string);
_shouldIndent = true; _shouldIndent = true;
} }
@@ -139,22 +143,22 @@ public sealed class CodeWriter : IDisposable
{ {
if (_shouldIndent) if (_shouldIndent)
{ {
_writer.Write(_indentString); _builder.Append(_indentString);
_shouldIndent = false; _shouldIndent = false;
} }
_writer.Write(chr); _builder.Append(chr);
} }
private void WriteIndented(string @string) private void WriteIndented(string @string)
{ {
if (_shouldIndent) if (_shouldIndent)
{ {
_writer.Write(_indentString); _builder.Append(_indentString);
_shouldIndent = false; _shouldIndent = false;
} }
_writer.Write(@string); _builder.Append(@string);
} }
private class CodeBlock : IDisposable private class CodeBlock : IDisposable

View File

@@ -1,6 +1,7 @@
// Copyright © Amer Koleci and Contributors. // Copyright © Amer Koleci and Contributors.
// Licensed under the MIT License (MIT). See LICENSE in the repository root for more information. // Licensed under the MIT License (MIT). See LICENSE in the repository root for more information.
using System.ComponentModel.DataAnnotations;
using System.Text; using System.Text;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using System.Xml; using System.Xml;
@@ -66,6 +67,7 @@ public static class Program
{ "Foundation.SIZE", "System.Drawing.Size" }, { "Foundation.SIZE", "System.Drawing.Size" },
{ "Graphics.Gdi.HMONITOR", "IntPtr" }, { "Graphics.Gdi.HMONITOR", "IntPtr" },
{ "Graphics.Gdi.HDC", "IntPtr" },
}; };
private static readonly Dictionary<string, string> s_knownTypesPrefixes = new() private static readonly Dictionary<string, string> s_knownTypesPrefixes = new()
@@ -130,6 +132,9 @@ public static class Program
{ "DXGI_SWAP_CHAIN_DESC1::Flags", "DXGI_SWAP_CHAIN_FLAG" }, { "DXGI_SWAP_CHAIN_DESC1::Flags", "DXGI_SWAP_CHAIN_FLAG" },
}; };
private static readonly HashSet<string> s_visitedEnums = new();
private static readonly HashSet<string> s_visitedStructs = new();
private static bool s_generateUnmanagedDocs = true; private static bool s_generateUnmanagedDocs = true;
public static int Main(string[] args) public static int Main(string[] args)
@@ -443,7 +448,10 @@ public static class Program
foreach (ApiType enumType in api.Types.Where(item => item.Kind.ToLowerInvariant() == "enum")) foreach (ApiType enumType in api.Types.Where(item => item.Kind.ToLowerInvariant() == "enum"))
{ {
GenerateEnum(writer, enumType, false); GenerateEnum(writer, enumType, false);
s_visitedEnums.Add($"{writer.Api}.{enumType.Name}");
} }
writer.WriteLine($"#endregion Enums"); writer.WriteLine($"#endregion Enums");
writer.WriteLine(); writer.WriteLine();
@@ -504,6 +512,8 @@ public static class Program
foreach (ApiType structType in api.Types.Where(item => item.Kind.ToLowerInvariant() == "struct")) foreach (ApiType structType in api.Types.Where(item => item.Kind.ToLowerInvariant() == "struct"))
{ {
GenerateStruct(writer, structType); GenerateStruct(writer, structType);
s_visitedStructs.Add($"{writer.Api}.{structType.Name}");
} }
writer.WriteLine($"#endregion Structs"); writer.WriteLine($"#endregion Structs");
writer.WriteLine(); writer.WriteLine();
@@ -512,10 +522,35 @@ public static class Program
writer.WriteLine($"#region COM Types"); writer.WriteLine($"#region COM Types");
foreach (ApiType comType in api.Types.Where(item => item.Kind.ToLowerInvariant() == "com")) foreach (ApiType comType in api.Types.Where(item => item.Kind.ToLowerInvariant() == "com"))
{ {
GenerateComType(writer, comType); //if (comType.Name != "IDXGIObject" &&
// comType.Name != "IDXGIDeviceSubObject")
//{
// break;
//}
// Generate methods
List<KeyValuePair<ApiFunction, string>> methodsToGenerate = new();
ApiType iterateType = comType;
while (iterateType.Interface != null && iterateType.Interface.Name != "IUnknown")
{
iterateType = api.Types.First(item => item.Name == iterateType.Interface.Name);
foreach (var method in iterateType.Methods)
{
methodsToGenerate.Add(new(method, iterateType.Name));
} }
writer.WriteLine($"#endregion COM Types");
writer.WriteLine(); }
foreach (var method in comType.Methods)
{
methodsToGenerate.Add(new(method, comType.Name));
}
GenerateComType(api, writer, comType, methodsToGenerate);
}
writer.WriteLine($"#endregion Com Types");
} }
private static void GenerateEnum(CodeWriter writer, ApiType enumType, bool autoGenerated) private static void GenerateEnum(CodeWriter writer, ApiType enumType, bool autoGenerated)
@@ -671,20 +706,20 @@ public static class Program
writer.WriteLine($"public {unsafePrefix}{fieldTypeName} {fieldValueName};"); writer.WriteLine($"public {unsafePrefix}{fieldTypeName} {fieldValueName};");
} }
writer.WriteLine();
} }
} }
writer.WriteLine(); writer.WriteLine();
} }
private static void GenerateComType(CodeWriter writer, ApiType comType) private static void GenerateComType(
ApiData api,
CodeWriter writer,
ApiType comType,
List<KeyValuePair<ApiFunction, string>> methodsToGenerate)
{ {
if (comType.Name != "IDXGIObject" /*&&
comType.Name != "IDXGIDeviceSubObject"*/)
{
return;
}
string csTypeName = comType.Name; string csTypeName = comType.Name;
//AddCsMapping(writer.Api, comType.Name, csTypeName); //AddCsMapping(writer.Api, comType.Name, csTypeName);
@@ -701,7 +736,6 @@ public static class Program
using (writer.PushBlock($"public unsafe partial struct {csTypeName} : {csTypeName}.Interface")) using (writer.PushBlock($"public unsafe partial struct {csTypeName} : {csTypeName}.Interface"))
{ {
// Generate IID // Generate IID
writer.WriteLine($"[NativeTypeName(\"const GUID\")]");
using (writer.PushBlock($"public static ref readonly Guid IID_{csTypeName}")) using (writer.PushBlock($"public static ref readonly Guid IID_{csTypeName}"))
{ {
writer.WriteLine("[MethodImpl(MethodImplOptions.AggressiveInlining)]"); writer.WriteLine("[MethodImpl(MethodImplOptions.AggressiveInlining)]");
@@ -756,7 +790,17 @@ public static class Program
writer.WriteLine(); writer.WriteLine();
int vtblIndex = 0; int vtblIndex = 0;
if (comType.Interface.Name == "IUnknown")
bool generateIUnknown = false;
var iterateType = comType;
while (iterateType != null)
{
generateIUnknown = iterateType.Interface.Name == "IUnknown";
iterateType = api.Types.FirstOrDefault(item => item.Name == iterateType.Interface.Name);
}
if (generateIUnknown)
{ {
writer.WriteLine("/// <inheritdoc cref=\"IUnknown.QueryInterface\" />"); writer.WriteLine("/// <inheritdoc cref=\"IUnknown.QueryInterface\" />");
writer.WriteLine("[MethodImpl(MethodImplOptions.AggressiveInlining)]"); writer.WriteLine("[MethodImpl(MethodImplOptions.AggressiveInlining)]");
@@ -791,8 +835,11 @@ public static class Program
vtblIndex = 3; vtblIndex = 3;
} }
foreach (var method in comType.Methods) foreach (var methodPair in methodsToGenerate)
{ {
var method = methodPair.Key;
string docName = methodPair.Value;
// TODO: Handle inherit // TODO: Handle inherit
string returnType = GetTypeName(method.ReturnType); string returnType = GetTypeName(method.ReturnType);
@@ -801,12 +848,43 @@ public static class Program
StringBuilder argumentsNameBuilder = new(); StringBuilder argumentsNameBuilder = new();
int parameterIndex = 0; int parameterIndex = 0;
if (method.Name == "SetEvictionPriority")
{
Console.WriteLine();
}
foreach (var parameter in method.Params) foreach (var parameter in method.Params)
{ {
string parameterType = GetTypeName(parameter.Type); bool asPointer = false;
if (parameter.Type.Kind == "ApiRef")
{
string fullTypeName = $"{parameter.Type.Api}.{parameter.Type.Name}";
if (!IsEnum(fullTypeName))
{
asPointer = true;
}
//string typeName = GetTypeName($"{dataType.Api}.{dataType.Name}");
}
string parameterType = GetTypeName(parameter.Type, asPointer);
parameterType = NormalizeTypeName(writer.Api, parameterType);
string parameterName = parameter.Name; string parameterName = parameter.Name;
bool isOptional = parameter.Attrs.Any(item => item is string str && str == "Optional");
if (parameter.Attrs.Any(item => item is string str && str == "ComOutPtr"))
{
if (!IsPrimitive(parameter.Type))
{
parameterType += "*";
}
}
argumentBuilder.Append(parameterType).Append(' ').Append(parameterName); argumentBuilder.Append(parameterType).Append(' ').Append(parameterName);
if (isOptional == true)
{
//argumentBuilder.Append(" = default");
}
argumentsTypesBuilder.Append(parameterType); argumentsTypesBuilder.Append(parameterType);
argumentsNameBuilder.Append(parameterName); argumentsNameBuilder.Append(parameterName);
@@ -827,13 +905,30 @@ public static class Program
returnMarshalType = "int"; returnMarshalType = "int";
} }
argumentsTypesBuilder.Append(", ").Append(returnMarshalType); if (method.Params.Count > 0)
{
argumentsTypesBuilder.Append(", ");
}
argumentsTypesBuilder.Append(returnMarshalType);
string argumentsString = argumentBuilder.ToString(); string argumentsString = argumentBuilder.ToString();
string argumentTypesString = argumentsTypesBuilder.ToString(); string argumentTypesString = argumentsTypesBuilder.ToString();
string argumentNamesString = argumentsNameBuilder.ToString(); string argumentNamesString = argumentsNameBuilder.ToString();
if (method.Params.Count > 0)
{
argumentNamesString = ", " + argumentNamesString;
}
if (comType.Name == docName)
{
writer.WriteLine($"/// <include file='../{writer.DocFileName}.xml' path='doc/member[@name=\"{comType.Name}::{method.Name}\"]/*' />"); writer.WriteLine($"/// <include file='../{writer.DocFileName}.xml' path='doc/member[@name=\"{comType.Name}::{method.Name}\"]/*' />");
}
else
{
writer.WriteLine($"/// <inheritdoc cref=\"{docName}.{method.Name}\" />");
}
writer.WriteLine("[MethodImpl(MethodImplOptions.AggressiveInlining)]"); writer.WriteLine("[MethodImpl(MethodImplOptions.AggressiveInlining)]");
writer.WriteLine($"[VtblIndex({vtblIndex})]"); writer.WriteLine($"[VtblIndex({vtblIndex})]");
using (writer.PushBlock($"public {returnType} {method.Name}({argumentsString})")) using (writer.PushBlock($"public {returnType} {method.Name}({argumentsString})"))
@@ -841,14 +936,13 @@ public static class Program
writer.WriteLineUndindented("#if NET6_0_OR_GREATER"); writer.WriteLineUndindented("#if NET6_0_OR_GREATER");
if (returnType != "void") if (returnType != "void")
writer.Write("return "); writer.Write("return ");
writer.WriteLine($"((delegate* unmanaged<{comType.Name}*, {argumentTypesString}>)(lpVtbl[{vtblIndex}]))(({comType.Name}*)Unsafe.AsPointer(ref this), {argumentNamesString});"); writer.WriteLine($"((delegate* unmanaged<{comType.Name}*, {argumentTypesString}>)(lpVtbl[{vtblIndex}]))(({comType.Name}*)Unsafe.AsPointer(ref this){argumentNamesString});");
writer.WriteLineUndindented("#else"); writer.WriteLineUndindented("#else");
if (returnType != "void") if (returnType != "void")
writer.Write("return "); writer.Write("return ");
writer.WriteLine($"((delegate* unmanaged[Stdcall]<{comType.Name}*, {argumentTypesString}>)(lpVtbl[{vtblIndex}]))(({comType.Name}*)Unsafe.AsPointer(ref this), {argumentNamesString});"); writer.WriteLine($"((delegate* unmanaged[Stdcall]<{comType.Name}*, {argumentTypesString}>)(lpVtbl[{vtblIndex}]))(({comType.Name}*)Unsafe.AsPointer(ref this){argumentNamesString});");
writer.WriteLineUndindented("#endif"); writer.WriteLineUndindented("#endif");
} }
writer.WriteLine(); writer.WriteLine();
vtblIndex++; vtblIndex++;
@@ -857,7 +951,7 @@ public static class Program
using (writer.PushBlock($"public interface Interface : {comType.Interface.Name}.Interface")) using (writer.PushBlock($"public interface Interface : {comType.Interface.Name}.Interface"))
{ {
} }
writer.WriteLine(); //writer.WriteLine();
} }
writer.WriteLine(); writer.WriteLine();
@@ -877,7 +971,9 @@ public static class Program
private static string NormalizeTypeName(string api, string typeName) private static string NormalizeTypeName(string api, string typeName)
{ {
if (!typeName.StartsWith(api)) if (!typeName.StartsWith(api))
{
return typeName; return typeName;
}
return typeName.Replace(api + ".", ""); return typeName.Replace(api + ".", "");
} }
@@ -1084,17 +1180,21 @@ public static class Program
return $"new Guid({a}, {b}, {c}, {d}, {e}, {f}, {g}, {h}, {i}, {j}, {k})"; return $"new Guid({a}, {b}, {c}, {d}, {e}, {f}, {g}, {h}, {i}, {j}, {k})";
} }
private static string GetTypeName(ApiDataType dataType, bool asPointer = false)
private static string GetTypeName(ApiDataType dataType)
{ {
if (dataType.Kind == "ApiRef") if (dataType.Kind == "ApiRef")
{ {
return GetTypeName($"{dataType.Api}.{dataType.Name}"); string typeName = GetTypeName($"{dataType.Api}.{dataType.Name}");
return asPointer ? typeName + "*" : typeName;
} }
else if (dataType.Kind == "Array") else if (dataType.Kind == "Array")
{ {
return "Array"; return "Array";
} }
else if (dataType.Kind == "LPArray")
{
return GetTypeName(dataType.Child) + "*";
}
else if (dataType.Kind == "PointerTo") else if (dataType.Kind == "PointerTo")
{ {
return GetTypeName(dataType.Child) + "*"; return GetTypeName(dataType.Child) + "*";
@@ -1103,6 +1203,48 @@ public static class Program
return GetTypeName(dataType.Name); return GetTypeName(dataType.Name);
} }
private static bool IsPrimitive(ApiDataType dataType)
{
if (dataType.Kind == "ApiRef")
{
string apiRefType = GetTypeName($"{dataType.Api}.{dataType.Name}");
}
else if (dataType.Kind == "PointerTo")
{
return IsPrimitive(dataType.Child);
}
if (dataType.Kind != "Native")
{
return false;
}
string typeName = GetTypeName(dataType.Name);
switch (typeName)
{
case "void":
case "int":
case "uint":
return true;
case "nint":
case "nuint":
return true;
}
return false;
}
private static bool IsEnum(string typeName)
{
return s_visitedEnums.Contains(typeName);
}
private static bool IsStruct(string typeName)
{
return s_visitedStructs.Contains(typeName);
}
private static void AddCsMapping(string api, string typeName, string csTypeName) private static void AddCsMapping(string api, string typeName, string csTypeName)
{ {
s_csNameMappings[$"{api}.{typeName}"] = $"{api}.{csTypeName}"; s_csNameMappings[$"{api}.{typeName}"] = $"{api}.{csTypeName}";

View File

@@ -3,7 +3,7 @@
namespace Win32; namespace Win32;
public readonly partial struct Bool32 : IComparable, IComparable<Bool32>, IEquatable<Bool32>, IFormattable public readonly partial struct Bool32 : IComparable, IComparable<Bool32>, IEquatable<Bool32>
{ {
public readonly int Value; public readonly int Value;
@@ -93,7 +93,5 @@ public readonly partial struct Bool32 : IComparable, IComparable<Bool32>, IEquat
public override int GetHashCode() => Value.GetHashCode(); public override int GetHashCode() => Value.GetHashCode();
public override string ToString() => Value.ToString(); public override string ToString() => Value != 0 ? "True" : "False";
public string ToString(string? format, IFormatProvider? formatProvider) => Value.ToString(format, formatProvider);
} }

View File

@@ -577,8 +577,10 @@ public partial struct Rational
{ {
/// <include file='../DXGI.xml' path='doc/member[@name="DXGI_RATIONAL::Numerator"]/*' /> /// <include file='../DXGI.xml' path='doc/member[@name="DXGI_RATIONAL::Numerator"]/*' />
public uint Numerator; public uint Numerator;
/// <include file='../DXGI.xml' path='doc/member[@name="DXGI_RATIONAL::Denominator"]/*' /> /// <include file='../DXGI.xml' path='doc/member[@name="DXGI_RATIONAL::Denominator"]/*' />
public uint Denominator; public uint Denominator;
} }
/// <include file='../DXGI.xml' path='doc/member[@name="DXGI_SAMPLE_DESC"]/*' /> /// <include file='../DXGI.xml' path='doc/member[@name="DXGI_SAMPLE_DESC"]/*' />
@@ -587,8 +589,10 @@ public partial struct SampleDescription
{ {
/// <include file='../DXGI.xml' path='doc/member[@name="DXGI_SAMPLE_DESC::Count"]/*' /> /// <include file='../DXGI.xml' path='doc/member[@name="DXGI_SAMPLE_DESC::Count"]/*' />
public uint Count; public uint Count;
/// <include file='../DXGI.xml' path='doc/member[@name="DXGI_SAMPLE_DESC::Quality"]/*' /> /// <include file='../DXGI.xml' path='doc/member[@name="DXGI_SAMPLE_DESC::Quality"]/*' />
public uint Quality; public uint Quality;
} }
/// <include file='../DXGI.xml' path='doc/member[@name="DXGI_RGB"]/*' /> /// <include file='../DXGI.xml' path='doc/member[@name="DXGI_RGB"]/*' />
@@ -597,10 +601,13 @@ public partial struct Rgb
{ {
/// <include file='../DXGI.xml' path='doc/member[@name="DXGI_RGB::Red"]/*' /> /// <include file='../DXGI.xml' path='doc/member[@name="DXGI_RGB::Red"]/*' />
public float Red; public float Red;
/// <include file='../DXGI.xml' path='doc/member[@name="DXGI_RGB::Green"]/*' /> /// <include file='../DXGI.xml' path='doc/member[@name="DXGI_RGB::Green"]/*' />
public float Green; public float Green;
/// <include file='../DXGI.xml' path='doc/member[@name="DXGI_RGB::Blue"]/*' /> /// <include file='../DXGI.xml' path='doc/member[@name="DXGI_RGB::Blue"]/*' />
public float Blue; public float Blue;
} }
/// <include file='../DXGI.xml' path='doc/member[@name="DXGI_GAMMA_CONTROL"]/*' /> /// <include file='../DXGI.xml' path='doc/member[@name="DXGI_GAMMA_CONTROL"]/*' />
@@ -609,8 +616,10 @@ public partial struct GammaControl
{ {
/// <include file='../DXGI.xml' path='doc/member[@name="DXGI_GAMMA_CONTROL::Scale"]/*' /> /// <include file='../DXGI.xml' path='doc/member[@name="DXGI_GAMMA_CONTROL::Scale"]/*' />
public Rgb Scale; public Rgb Scale;
/// <include file='../DXGI.xml' path='doc/member[@name="DXGI_GAMMA_CONTROL::Offset"]/*' /> /// <include file='../DXGI.xml' path='doc/member[@name="DXGI_GAMMA_CONTROL::Offset"]/*' />
public Rgb Offset; public Rgb Offset;
/// <include file='../DXGI.xml' path='doc/member[@name="DXGI_GAMMA_CONTROL::GammaCurve"]/*' /> /// <include file='../DXGI.xml' path='doc/member[@name="DXGI_GAMMA_CONTROL::GammaCurve"]/*' />
public GammaCurve__FixedBuffer GammaCurve; public GammaCurve__FixedBuffer GammaCurve;
@@ -1659,6 +1668,7 @@ public partial struct GammaControl
return MemoryMarshal.CreateSpan(ref e0, 1025); return MemoryMarshal.CreateSpan(ref e0, 1025);
} }
} }
} }
/// <include file='../DXGI.xml' path='doc/member[@name="DXGI_GAMMA_CONTROL_CAPABILITIES"]/*' /> /// <include file='../DXGI.xml' path='doc/member[@name="DXGI_GAMMA_CONTROL_CAPABILITIES"]/*' />
@@ -1667,14 +1677,19 @@ public partial struct GammaControlCapabilities
{ {
/// <include file='../DXGI.xml' path='doc/member[@name="DXGI_GAMMA_CONTROL_CAPABILITIES::ScaleAndOffsetSupported"]/*' /> /// <include file='../DXGI.xml' path='doc/member[@name="DXGI_GAMMA_CONTROL_CAPABILITIES::ScaleAndOffsetSupported"]/*' />
public Bool32 ScaleAndOffsetSupported; public Bool32 ScaleAndOffsetSupported;
/// <include file='../DXGI.xml' path='doc/member[@name="DXGI_GAMMA_CONTROL_CAPABILITIES::MaxConvertedValue"]/*' /> /// <include file='../DXGI.xml' path='doc/member[@name="DXGI_GAMMA_CONTROL_CAPABILITIES::MaxConvertedValue"]/*' />
public float MaxConvertedValue; public float MaxConvertedValue;
/// <include file='../DXGI.xml' path='doc/member[@name="DXGI_GAMMA_CONTROL_CAPABILITIES::MinConvertedValue"]/*' /> /// <include file='../DXGI.xml' path='doc/member[@name="DXGI_GAMMA_CONTROL_CAPABILITIES::MinConvertedValue"]/*' />
public float MinConvertedValue; public float MinConvertedValue;
/// <include file='../DXGI.xml' path='doc/member[@name="DXGI_GAMMA_CONTROL_CAPABILITIES::NumGammaControlPoints"]/*' /> /// <include file='../DXGI.xml' path='doc/member[@name="DXGI_GAMMA_CONTROL_CAPABILITIES::NumGammaControlPoints"]/*' />
public uint NumGammaControlPoints; public uint NumGammaControlPoints;
/// <include file='../DXGI.xml' path='doc/member[@name="DXGI_GAMMA_CONTROL_CAPABILITIES::ControlPointPositions"]/*' /> /// <include file='../DXGI.xml' path='doc/member[@name="DXGI_GAMMA_CONTROL_CAPABILITIES::ControlPointPositions"]/*' />
public unsafe fixed float ControlPointPositions[1025]; public unsafe fixed float ControlPointPositions[1025];
} }
/// <include file='../DXGI.xml' path='doc/member[@name="DXGI_MODE_DESC"]/*' /> /// <include file='../DXGI.xml' path='doc/member[@name="DXGI_MODE_DESC"]/*' />
@@ -1683,16 +1698,22 @@ public partial struct ModeDescription
{ {
/// <include file='../DXGI.xml' path='doc/member[@name="DXGI_MODE_DESC::Width"]/*' /> /// <include file='../DXGI.xml' path='doc/member[@name="DXGI_MODE_DESC::Width"]/*' />
public uint Width; public uint Width;
/// <include file='../DXGI.xml' path='doc/member[@name="DXGI_MODE_DESC::Height"]/*' /> /// <include file='../DXGI.xml' path='doc/member[@name="DXGI_MODE_DESC::Height"]/*' />
public uint Height; public uint Height;
/// <include file='../DXGI.xml' path='doc/member[@name="DXGI_MODE_DESC::RefreshRate"]/*' /> /// <include file='../DXGI.xml' path='doc/member[@name="DXGI_MODE_DESC::RefreshRate"]/*' />
public Rational RefreshRate; public Rational RefreshRate;
/// <include file='../DXGI.xml' path='doc/member[@name="DXGI_MODE_DESC::Format"]/*' /> /// <include file='../DXGI.xml' path='doc/member[@name="DXGI_MODE_DESC::Format"]/*' />
public Format Format; public Format Format;
/// <include file='../DXGI.xml' path='doc/member[@name="DXGI_MODE_DESC::ScanlineOrdering"]/*' /> /// <include file='../DXGI.xml' path='doc/member[@name="DXGI_MODE_DESC::ScanlineOrdering"]/*' />
public ModeScanlineOrder ScanlineOrdering; public ModeScanlineOrder ScanlineOrdering;
/// <include file='../DXGI.xml' path='doc/member[@name="DXGI_MODE_DESC::Scaling"]/*' /> /// <include file='../DXGI.xml' path='doc/member[@name="DXGI_MODE_DESC::Scaling"]/*' />
public ModeScaling Scaling; public ModeScaling Scaling;
} }
/// <include file='../DXGI.xml' path='doc/member[@name="DXGI_JPEG_DC_HUFFMAN_TABLE"]/*' /> /// <include file='../DXGI.xml' path='doc/member[@name="DXGI_JPEG_DC_HUFFMAN_TABLE"]/*' />
@@ -1701,8 +1722,10 @@ public partial struct JpegDcHuffmanTable
{ {
/// <include file='../DXGI.xml' path='doc/member[@name="DXGI_JPEG_DC_HUFFMAN_TABLE::CodeCounts"]/*' /> /// <include file='../DXGI.xml' path='doc/member[@name="DXGI_JPEG_DC_HUFFMAN_TABLE::CodeCounts"]/*' />
public unsafe fixed byte CodeCounts[12]; public unsafe fixed byte CodeCounts[12];
/// <include file='../DXGI.xml' path='doc/member[@name="DXGI_JPEG_DC_HUFFMAN_TABLE::CodeValues"]/*' /> /// <include file='../DXGI.xml' path='doc/member[@name="DXGI_JPEG_DC_HUFFMAN_TABLE::CodeValues"]/*' />
public unsafe fixed byte CodeValues[12]; public unsafe fixed byte CodeValues[12];
} }
/// <include file='../DXGI.xml' path='doc/member[@name="DXGI_JPEG_AC_HUFFMAN_TABLE"]/*' /> /// <include file='../DXGI.xml' path='doc/member[@name="DXGI_JPEG_AC_HUFFMAN_TABLE"]/*' />
@@ -1711,8 +1734,10 @@ public partial struct JpegAcHuffmanTable
{ {
/// <include file='../DXGI.xml' path='doc/member[@name="DXGI_JPEG_AC_HUFFMAN_TABLE::CodeCounts"]/*' /> /// <include file='../DXGI.xml' path='doc/member[@name="DXGI_JPEG_AC_HUFFMAN_TABLE::CodeCounts"]/*' />
public unsafe fixed byte CodeCounts[16]; public unsafe fixed byte CodeCounts[16];
/// <include file='../DXGI.xml' path='doc/member[@name="DXGI_JPEG_AC_HUFFMAN_TABLE::CodeValues"]/*' /> /// <include file='../DXGI.xml' path='doc/member[@name="DXGI_JPEG_AC_HUFFMAN_TABLE::CodeValues"]/*' />
public unsafe fixed byte CodeValues[162]; public unsafe fixed byte CodeValues[162];
} }
/// <include file='../DXGI.xml' path='doc/member[@name="DXGI_JPEG_QUANTIZATION_TABLE"]/*' /> /// <include file='../DXGI.xml' path='doc/member[@name="DXGI_JPEG_QUANTIZATION_TABLE"]/*' />
@@ -1721,10 +1746,10 @@ public partial struct JpegQuantizationTable
{ {
/// <include file='../DXGI.xml' path='doc/member[@name="DXGI_JPEG_QUANTIZATION_TABLE::Elements"]/*' /> /// <include file='../DXGI.xml' path='doc/member[@name="DXGI_JPEG_QUANTIZATION_TABLE::Elements"]/*' />
public unsafe fixed byte Elements[64]; public unsafe fixed byte Elements[64];
} }
#endregion Structs #endregion Structs
#region COM Types #region COM Types
#endregion COM Types #endregion Com Types

File diff suppressed because it is too large Load Diff

View File

@@ -4,3 +4,36 @@
using static Win32.Graphics.Dxgi.Apis; using static Win32.Graphics.Dxgi.Apis;
namespace Win32.Graphics.Dxgi; namespace Win32.Graphics.Dxgi;
public unsafe partial struct IDXGIFactory5
{
public TFeature CheckFeatureSupport<TFeature>(Feature feature)
where TFeature : unmanaged
{
TFeature featureData = default;
CheckFeatureSupport(feature, &featureData, (uint)sizeof(TFeature)).ThrowIfFailed();
return featureData;
}
}
public unsafe partial struct IDXGIFactory6
{
public TFeature CheckFeatureSupport<TFeature>(Feature feature)
where TFeature : unmanaged
{
TFeature featureData = default;
CheckFeatureSupport(feature, &featureData, (uint)sizeof(TFeature)).ThrowIfFailed();
return featureData;
}
}
public unsafe partial struct IDXGIFactory7
{
public TFeature CheckFeatureSupport<TFeature>(Feature feature)
where TFeature : unmanaged
{
TFeature featureData = default;
CheckFeatureSupport(feature, &featureData, (uint)sizeof(TFeature)).ThrowIfFailed();
return featureData;
}
}

View File

@@ -1,6 +1,9 @@
// Copyright © Amer Koleci and Contributors. // Copyright © Amer Koleci and Contributors.
// Licensed under the MIT License (MIT). See LICENSE in the repository root for more information. // Licensed under the MIT License (MIT). See LICENSE in the repository root for more information.
using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;
namespace Win32; namespace Win32;
public readonly partial struct HResult : IComparable, IComparable<HResult>, IEquatable<HResult>, IFormattable public readonly partial struct HResult : IComparable, IComparable<HResult>, IEquatable<HResult>, IFormattable
@@ -89,4 +92,22 @@ public readonly partial struct HResult : IComparable, IComparable<HResult>, IEqu
public bool Failure => Value < 0; public bool Failure => Value < 0;
public bool Success => Value >= 0; public bool Success => Value >= 0;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void ThrowIfFailed([CallerMemberName] string? method = null)
{
if (Failure)
{
ThrowExternalException(method ?? "Method", this);
}
}
#if NET6_0_OR_GREATER
[DoesNotReturn]
#endif
private static void ThrowExternalException(string methodName, int errorCode)
{
string message = string.Format("'{0}' failed with an error code of '{1}'", methodName, errorCode);
throw new ExternalException(message, errorCode);
}
} }

View File

@@ -15,7 +15,7 @@ public unsafe partial struct IUnknown : IUnknown.Interface
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
[VtblIndex(0)] [VtblIndex(0)]
public HResult QueryInterface([NativeTypeName("const IID &")] Guid* riid, void** ppvObject) public HResult QueryInterface(Guid* riid, void** ppvObject)
{ {
#if NET6_0_OR_GREATER #if NET6_0_OR_GREATER
return ((delegate* unmanaged<IUnknown*, Guid*, void**, int>)(lpVtbl[0]))((IUnknown*)Unsafe.AsPointer(ref this), riid, ppvObject); return ((delegate* unmanaged<IUnknown*, Guid*, void**, int>)(lpVtbl[0]))((IUnknown*)Unsafe.AsPointer(ref this), riid, ppvObject);
@@ -26,7 +26,6 @@ public unsafe partial struct IUnknown : IUnknown.Interface
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
[VtblIndex(1)] [VtblIndex(1)]
[return: NativeTypeName("ULONG")]
public uint AddRef() public uint AddRef()
{ {
#if NET6_0_OR_GREATER #if NET6_0_OR_GREATER
@@ -38,7 +37,6 @@ public unsafe partial struct IUnknown : IUnknown.Interface
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
[VtblIndex(2)] [VtblIndex(2)]
[return: NativeTypeName("ULONG")]
public uint Release() public uint Release()
{ {
#if NET6_0_OR_GREATER #if NET6_0_OR_GREATER
@@ -51,14 +49,12 @@ public unsafe partial struct IUnknown : IUnknown.Interface
public interface Interface public interface Interface
{ {
[VtblIndex(0)] [VtblIndex(0)]
HResult QueryInterface([NativeTypeName("const IID &")] Guid* riid, void** ppvObject); HResult QueryInterface(Guid* riid, void** ppvObject);
[VtblIndex(1)] [VtblIndex(1)]
[return: NativeTypeName("ULONG")]
uint AddRef(); uint AddRef();
[VtblIndex(2)] [VtblIndex(2)]
[return: NativeTypeName("ULONG")]
uint Release(); uint Release();
} }
@@ -66,22 +62,16 @@ public unsafe partial struct IUnknown : IUnknown.Interface
where TSelf : unmanaged, Interface where TSelf : unmanaged, Interface
{ {
#if NET6_0_OR_GREATER #if NET6_0_OR_GREATER
[NativeTypeName("HRESULT (const IID &, void **) __attribute__((stdcall))")]
public delegate* unmanaged<TSelf*, Guid*, void**, int> QueryInterface; public delegate* unmanaged<TSelf*, Guid*, void**, int> QueryInterface;
[NativeTypeName("ULONG () __attribute__((stdcall))")]
public delegate* unmanaged<TSelf*, uint> AddRef; public delegate* unmanaged<TSelf*, uint> AddRef;
[NativeTypeName("ULONG () __attribute__((stdcall))")]
public delegate* unmanaged<TSelf*, uint> Release; public delegate* unmanaged<TSelf*, uint> Release;
#else #else
[NativeTypeName("HRESULT (const IID &, void **) __attribute__((stdcall))")]
public delegate* unmanaged[Stdcall]<TSelf*, Guid*, void**, int> QueryInterface; public delegate* unmanaged[Stdcall]<TSelf*, Guid*, void**, int> QueryInterface;
[NativeTypeName("ULONG () __attribute__((stdcall))")]
public delegate* unmanaged[Stdcall]<TSelf*, uint> AddRef; public delegate* unmanaged[Stdcall]<TSelf*, uint> AddRef;
[NativeTypeName("ULONG () __attribute__((stdcall))")]
public delegate* unmanaged[Stdcall]<TSelf*, uint> Release; public delegate* unmanaged[Stdcall]<TSelf*, uint> Release;
#endif #endif
} }

View File

@@ -0,0 +1,17 @@
// Copyright © Amer Koleci and Contributors.
// Licensed under the MIT License (MIT). See LICENSE in the repository root for more information.
namespace Win32.Security;
public unsafe partial struct SECURITY_ATTRIBUTES
{
[NativeTypeName("DWORD")]
public uint nLength;
[NativeTypeName("LPVOID")]
public void* lpSecurityDescriptor;
[NativeTypeName("BOOL")]
public Bool32 bInheritHandle;
}

View File

@@ -20,4 +20,8 @@
<PackageReference Include="Microsoft.Bcl.HashCode" Version="1.1.1" /> <PackageReference Include="Microsoft.Bcl.HashCode" Version="1.1.1" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<Folder Include="Security\" />
</ItemGroup>
</Project> </Project>

View File

@@ -1,8 +1,10 @@
// Copyright © Amer Koleci and Contributors. // Copyright © Amer Koleci and Contributors.
// Licensed under the MIT License (MIT). See LICENSE in the repository root for more information. // Licensed under the MIT License (MIT). See LICENSE in the repository root for more information.
using System.Runtime.InteropServices;
using Win32;
using Win32.Graphics.Dxgi; using Win32.Graphics.Dxgi;
using Win32.Graphics.Dxgi.Common; using static Win32.Apis;
namespace ClearScreen; namespace ClearScreen;
@@ -10,5 +12,29 @@ public static unsafe class Program
{ {
public static void Main() public static void Main()
{ {
using ComPtr<IDXGIFactory1> factory = default;
HResult hr = CreateDXGIFactory1(__uuidof<IDXGIFactory4>(), (void**)&factory);
{
using ComPtr<IDXGIFactory5> factory5 = default;
if (factory.CopyTo(&factory5).Success)
{
Bool32 isTearingSupported = factory5.Get()->CheckFeatureSupport<Bool32>(Feature.PresentAllowTearing);
} }
}
using ComPtr<IDXGIAdapter1> adapter = default;
for (uint adapterIndex = 0;
factory.Get()->EnumAdapters1(adapterIndex, adapter.ReleaseAndGetAddressOf()).Success;
adapterIndex++)
{
AdapterDescription1 desc = default;
adapter.Get()->GetDesc1(&desc);
}
}
[DllImport("dxgi", ExactSpelling = true)]
public static extern HResult CreateDXGIFactory1(Guid* riid, void** ppFactory);
} }