Dashboard/Dashboard.Drawing.OpenGL/ContextExecutor.cs

179 lines
5.3 KiB
C#
Raw Normal View History

2025-01-14 18:34:47 +01:00
using System.Drawing;
2025-01-18 21:30:56 +01:00
using Dashboard.Drawing.OpenGL.Executors;
2025-01-14 18:34:47 +01:00
namespace Dashboard.Drawing.OpenGL
{
2025-01-18 21:30:56 +01:00
public interface ICommandExecutor
{
IEnumerable<string> Extensions { get; }
IContextExecutor Executor { get; }
void SetContextExecutor(IContextExecutor executor);
void BeginFrame();
void BeginDraw();
void EndDraw();
void EndFrame();
void ProcessCommand(ICommandFrame frame);
}
public interface IContextExecutor : IInitializer, IGLDisposable
{
GLEngine Engine { get; }
IGLContext Context { get; }
ContextResourcePool ResourcePool { get; }
TransformStack TransformStack { get; }
}
public class ContextExecutor : IContextExecutor
2025-01-14 18:34:47 +01:00
{
public GLEngine Engine { get; }
public IGLContext Context { get; }
public ContextResourcePool ResourcePool { get; }
2025-01-18 21:30:56 +01:00
public TransformStack TransformStack { get; } = new TransformStack();
2025-01-14 18:34:47 +01:00
protected bool IsDisposed { get; private set; } = false;
public bool IsInitialized { get; private set; } = false;
2025-01-18 21:30:56 +01:00
private readonly List<ICommandExecutor> _executorsList = new List<ICommandExecutor>();
private readonly Dictionary<string, ICommandExecutor> _executorsMap = new Dictionary<string, ICommandExecutor>();
2025-01-14 18:34:47 +01:00
public ContextExecutor(GLEngine engine, IGLContext context)
{
Engine = engine;
Context = context;
ResourcePool = Engine.ResourcePoolManager.Get(context);
ResourcePool.IncrementReference();
2025-01-18 21:30:56 +01:00
AddExecutor(new BaseCommandExecutor());
2025-01-14 18:34:47 +01:00
}
~ContextExecutor()
{
2025-01-18 21:30:56 +01:00
DisposeInvoker(true, false);
}
public void AddExecutor(ICommandExecutor executor, bool overwrite = false)
{
if (IsInitialized)
throw new Exception("This context executor is already initialized. Cannot add new command executors.");
IInitializer? initializer = executor as IInitializer;
if (initializer?.IsInitialized == true)
throw new InvalidOperationException("This command executor has already been initialized, cannot add here.");
if (!overwrite)
{
foreach (string extension in executor.Extensions)
{
if (_executorsMap.ContainsKey(extension))
throw new InvalidOperationException("An executor already handles this extension.");
}
}
foreach (string extension in executor.Extensions)
{
_executorsMap[extension] = executor;
}
_executorsList.Add(executor);
executor.SetContextExecutor(this);
2025-01-14 18:34:47 +01:00
}
public void Initialize()
{
if (IsInitialized)
return;
IsInitialized = true;
2025-01-18 21:30:56 +01:00
foreach (ICommandExecutor executor in _executorsList)
{
if (executor is IInitializer initializer)
initializer.Initialize();
}
2025-01-14 18:34:47 +01:00
}
2025-01-18 21:30:56 +01:00
public virtual void BeginFrame()
2025-01-14 18:34:47 +01:00
{
2025-01-18 21:30:56 +01:00
foreach (ICommandExecutor executor in _executorsList)
executor.BeginFrame();
2025-01-14 18:34:47 +01:00
}
2025-01-18 21:30:56 +01:00
protected virtual void BeginDraw()
2025-01-14 18:34:47 +01:00
{
2025-01-18 21:30:56 +01:00
foreach (ICommandExecutor executor in _executorsList)
executor.BeginDraw();
2025-01-14 18:34:47 +01:00
}
2025-01-18 21:30:56 +01:00
protected virtual void EndDraw()
2025-01-14 18:34:47 +01:00
{
2025-01-18 21:30:56 +01:00
foreach (ICommandExecutor executor in _executorsList)
executor.EndDraw();
2025-01-14 18:34:47 +01:00
}
2025-01-18 21:30:56 +01:00
public virtual void EndFrame()
2025-01-14 18:34:47 +01:00
{
2025-01-18 21:30:56 +01:00
ResourcePool.Collector.Dispose();
TransformStack.Clear();
2025-01-14 18:34:47 +01:00
2025-01-18 21:30:56 +01:00
foreach (ICommandExecutor executor in _executorsList)
executor.EndFrame();
2025-01-14 18:34:47 +01:00
}
2025-01-18 21:30:56 +01:00
public void Draw(DrawQueue drawqueue) => Draw(drawqueue, new RectangleF(new PointF(0f,0f), Context.FramebufferSize));
2025-01-14 18:34:47 +01:00
2025-01-18 21:30:56 +01:00
public virtual void Draw(DrawQueue drawQueue, RectangleF bounds)
2025-01-14 18:34:47 +01:00
{
2025-01-18 21:30:56 +01:00
BeginDraw();
2025-01-14 18:34:47 +01:00
2025-01-18 21:30:56 +01:00
foreach (ICommandFrame frame in drawQueue)
2025-01-14 18:34:47 +01:00
{
2025-01-18 21:30:56 +01:00
if (_executorsMap.TryGetValue(frame.Command.Extension.Name, out ICommandExecutor? executor))
executor.ProcessCommand(frame);
2025-01-14 18:34:47 +01:00
}
2025-01-18 21:30:56 +01:00
EndDraw();
2025-01-14 18:34:47 +01:00
}
2025-01-18 21:30:56 +01:00
private void DisposeInvoker(bool safeExit, bool disposing)
2025-01-14 18:34:47 +01:00
{
2025-01-18 21:30:56 +01:00
if (!IsDisposed)
return;
2025-01-14 18:34:47 +01:00
2025-01-18 21:30:56 +01:00
IsDisposed = true;
2025-01-14 18:34:47 +01:00
2025-01-18 21:30:56 +01:00
if (disposing)
GC.SuppressFinalize(this);
2025-01-14 18:34:47 +01:00
2025-01-18 21:30:56 +01:00
Dispose(safeExit, disposing);
}
2025-01-14 18:34:47 +01:00
2025-01-18 21:30:56 +01:00
protected virtual void Dispose(bool safeExit, bool disposing)
{
if (disposing)
2025-01-14 18:34:47 +01:00
{
2025-01-18 21:30:56 +01:00
foreach (ICommandExecutor executor in _executorsList)
{
if (executor is IGLDisposable glDisposable)
glDisposable.Dispose(safeExit);
else if (executor is IDisposable disposable)
disposable.Dispose();
}
if (ResourcePool.DecrementReference())
Dispose();
2025-01-14 18:34:47 +01:00
}
}
2025-01-18 21:30:56 +01:00
public void Dispose() => DisposeInvoker(true, true);
public void Dispose(bool safeExit) => DisposeInvoker(safeExit, true);
2025-01-14 18:34:47 +01:00
}
}