2025-01-14 18:34:47 +01:00
|
|
|
using System.Runtime.InteropServices;
|
|
|
|
using OpenTK.Mathematics;
|
|
|
|
|
|
|
|
namespace Dashboard.Drawing.OpenGL
|
|
|
|
{
|
2025-01-18 18:43:23 +01:00
|
|
|
public class GradientUniformBuffer : IInitializer, IGLDisposable, IResourceManager
|
2025-01-14 18:34:47 +01:00
|
|
|
{
|
2025-01-18 18:43:23 +01:00
|
|
|
private bool _isDisposed;
|
2025-01-14 18:34:47 +01:00
|
|
|
private int _top = 0;
|
|
|
|
private readonly MappableBuffer<GradientUniformStruct> _buffer = new MappableBuffer<GradientUniformStruct>();
|
|
|
|
private readonly Dictionary<Gradient, Entry> _entries = new Dictionary<Gradient, Entry>();
|
|
|
|
|
2025-01-18 18:43:23 +01:00
|
|
|
public bool IsInitialized { get; private set; } = false;
|
|
|
|
|
2025-01-14 18:34:47 +01:00
|
|
|
public void Initialize()
|
|
|
|
{
|
2025-01-18 18:43:23 +01:00
|
|
|
if (IsInitialized)
|
|
|
|
return;
|
|
|
|
|
|
|
|
IsInitialized = true;
|
|
|
|
|
2025-01-14 18:34:47 +01:00
|
|
|
_buffer.Initialize();
|
|
|
|
}
|
|
|
|
|
|
|
|
public Entry InternGradient(Gradient gradient)
|
|
|
|
{
|
|
|
|
if (_entries.TryGetValue(gradient, out Entry entry))
|
|
|
|
return entry;
|
|
|
|
|
|
|
|
int count = gradient.Count;
|
|
|
|
int offset = _top;
|
|
|
|
_top += count;
|
|
|
|
|
|
|
|
_buffer.EnsureCapacity(_top);
|
|
|
|
_buffer.Map();
|
|
|
|
Span<GradientUniformStruct> span = _buffer.AsSpan()[offset.._top];
|
|
|
|
|
|
|
|
for (int i = 0; i < count; i++)
|
|
|
|
{
|
|
|
|
GradientStop stop = gradient[i];
|
|
|
|
span[i] = new GradientUniformStruct()
|
|
|
|
{
|
|
|
|
Position = stop.Position,
|
|
|
|
Color = new Vector4(
|
|
|
|
stop.Color.R / 255f,
|
|
|
|
stop.Color.G / 255f,
|
|
|
|
stop.Color.B / 255f,
|
|
|
|
stop.Color.A / 255f),
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
entry = new Entry(offset, count);
|
|
|
|
_entries.Add(gradient, entry);
|
|
|
|
|
|
|
|
return entry;
|
|
|
|
}
|
|
|
|
|
|
|
|
public void Clear()
|
|
|
|
{
|
|
|
|
_entries.Clear();
|
|
|
|
_top = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
public record struct Entry(int Offset, int Count);
|
2025-01-18 18:43:23 +01:00
|
|
|
|
|
|
|
public void Dispose() => Dispose(true);
|
|
|
|
|
|
|
|
public void Dispose(bool safeExit)
|
|
|
|
{
|
|
|
|
if (_isDisposed)
|
|
|
|
return;
|
|
|
|
_isDisposed = true;
|
|
|
|
|
|
|
|
_buffer.Dispose(safeExit);
|
|
|
|
}
|
|
|
|
|
|
|
|
string IResourceManager.Name { get; } = nameof(GradientUniformBuffer);
|
2025-01-14 18:34:47 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
[StructLayout(LayoutKind.Explicit, Size = 8 * sizeof(float))]
|
|
|
|
public struct GradientUniformStruct
|
|
|
|
{
|
|
|
|
[FieldOffset(0 * sizeof(float))]
|
|
|
|
public float Position;
|
|
|
|
|
|
|
|
[FieldOffset(4 * sizeof(float))]
|
|
|
|
public Vector4 Color;
|
|
|
|
}
|
|
|
|
}
|