using System.Collections.Immutable; using System.Diagnostics.CodeAnalysis; using System.Drawing; using System.Numerics; namespace Dashboard.Drawing { public enum MeshPrimitive { Point, Line, Triangle, TriangleFan, TriangleStrip, } public enum WindingOrder { Clockwise, Counterclockwise, } public enum FaceCulling { None, Front, Back, Both, } public enum VertexAttributeType { UnsignedByte, UnsignedShort, UnsignedInt, Byte, Short, Int, Half, Float, Double, } public enum IndexType { UnsignedShort, UnsignedInt, UnsignedLong, Short, Int, } public enum BlendFunction { One, Zero, SourceAlpha, OneMinusSourceAlpha, DestinationAlpha, OneMinusDestinationAlpha, SourceColor, OneMinusSourceColor, DestinationColor, OneMinusDestinationColor, ConstantColor, OneMinusConstantColor, ConstantAlpha, OneMinusConstantAlpha, } public enum BlendEquation { Add, Subtract, ReverseSubtract, Min, Max, } public enum TestFunction { Never, LessThan, LessThanOrEqual, Equal, NotEqual, GreaterThanOrEqual, Greater, Always, } public enum StencilOperation { Keep, Zero, Replace, Increment, UncheckedIncrement, Decrement, UncheckedDecrement, Invert, } public enum UniformType { U1, U2, U3, U4, I1, I2, I3, I4, F1, F2, F3, F4, Mat2, Mat3, Mat4, Buffer, } public readonly record struct DepthMode(bool Test, bool Mask, TestFunction Function) { public static readonly DepthMode Off = new DepthMode(false, false, TestFunction.Always); public static readonly DepthMode WriteOnly = new DepthMode(false, true, TestFunction.LessThan); public static readonly DepthMode Equal = new DepthMode(true, false, TestFunction.Equal); public static readonly DepthMode Enabled = new DepthMode(true, true, TestFunction.LessThan); } public readonly record struct BlendFactor(BlendFunction Source, BlendFunction Destination) { public static readonly BlendFactor Default = new BlendFactor(BlendFunction.SourceAlpha, BlendFunction.OneMinusSourceAlpha); } public readonly record struct BlendMode(bool Enabled, BlendFactor Color, BlendFactor Alpha) { [MemberNotNullWhen(false, nameof(Unified), nameof(UnifiedEquation))] public bool IsSeparate => Color != Alpha; public BlendFactor? Unified => IsSeparate ? null : Color; public BlendEquation? UnifiedEquation => IsSeparate ? null : ColorEquation; public BlendEquation ColorEquation { get; init; } = BlendEquation.Add; public BlendEquation AlphaEquation { get; init; } = BlendEquation.Add; public Color Constant { get; init; } = System.Drawing.Color.Black; public BlendMode(BlendFunction source, BlendFunction destination) : this(true, new BlendFactor(source, destination), new BlendFactor(source, destination)) { } public static readonly BlendMode Off = new BlendMode(false, BlendFactor.Default, BlendFactor.Default); public static readonly BlendMode Normal = new BlendMode(true, BlendFactor.Default, BlendFactor.Default); } public readonly record struct StencilMode(bool Enabled, TestFunction Function) { public int Reference { get; init; } = 0; public int Mask { get; init; } = ~0; public StencilOperation Pass { get; init; } = StencilOperation.Keep; public StencilOperation DepthFail { get; init; } = StencilOperation.Keep; public StencilOperation Fail { get; init; } = StencilOperation.Keep; public static readonly StencilMode Off = new StencilMode(false, TestFunction.Always); } public record struct VertexAttribute( int Location, int Components, VertexAttributeType Type, long Offset, long Stride) { public int Divisor { get; init; } = 1; } public record VertexSpecification( ImmutableList Attributes, ImmutableList VertexBuffers ) { public IBuffer? ElementBuffer { get; init; } = null; } public record struct UniformDescriptor(int Location, UniformType Type, long Offset, long Size); public struct PipelineState() { public Box2d ViewportRegion { get; init; } = new Box2d(Vector2.Zero, Vector2.PositiveInfinity); public Box2d ScissorRegion { get; init; } = new Box2d(Vector2.PositiveInfinity, Vector2.PositiveInfinity); public WindingOrder FrontFace { get; init; } = WindingOrder.Counterclockwise; public FaceCulling CullMode { get; init; } = FaceCulling.Back; public BlendMode BlendMode { get; init; } = BlendMode.Normal; public DepthMode DepthMode { get; init; } = DepthMode.Enabled; public StencilMode StencilMode { get; init; } = StencilMode.Off; public bool RedMask { get; init; } = true; public bool GreenMask { get; init; } = true; public bool BlueMask { get; init; } = true; public bool AlphaMask { get; init; } = true; public float PointSize { get; init; }= 1.0f; public float LineWidth { get; init; }= 1.0f; } public struct DrawCall(MeshPrimitive primitive, VertexSpecification vertexSpec, int first, int count) { public IShader? ShaderPipeline { get; init; } public PipelineState PipelineState { get; init; } = new PipelineState(); public VertexSpecification VertexSpecification { get; init; } = vertexSpec; public MeshPrimitive Primitive { get; init; } = primitive; public int First { get; init; } = first; public int Count { get; init; } = count; public int BaseVertex { get; init; } = 0; public long Offset { get; init; } = 0; public bool EnableRestart { get; init; } = false; public long RestartIndex { get; init; } = -1; public Box2d ViewportRegion => PipelineState.ViewportRegion; public Box2d ScissorRegion => PipelineState.ScissorRegion; public WindingOrder FrontFace => PipelineState.FrontFace; public FaceCulling CullMode => PipelineState.CullMode; public BlendMode BlendMode => PipelineState.BlendMode; public DepthMode DepthMode => PipelineState.DepthMode; public StencilMode StencilMode => PipelineState.StencilMode; public bool RedMask => PipelineState.RedMask; public bool GreenMask => PipelineState.GreenMask; public bool BlueMask => PipelineState.BlueMask; public bool AlphaMask => PipelineState.AlphaMask; public float PointSize => PipelineState.PointSize; public float LineWidth => PipelineState.LineWidth; public List Textures { get; init; } = []; public List Uniforms { get; init; } = []; public IndexType IndexType { get; init; } = IndexType.UnsignedShort; public ReadOnlyMemory UniformData { get; init; } = ReadOnlyMemory.Empty; public IBuffer? UniformBuffer { get; init; } } }