179 lines
5.3 KiB
C#
179 lines
5.3 KiB
C#
using System.Drawing;
|
|
using Dashboard.Drawing.OpenGL.Executors;
|
|
|
|
namespace Dashboard.Drawing.OpenGL
|
|
{
|
|
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
|
|
{
|
|
public GLEngine Engine { get; }
|
|
public IGLContext Context { get; }
|
|
public ContextResourcePool ResourcePool { get; }
|
|
public TransformStack TransformStack { get; } = new TransformStack();
|
|
protected bool IsDisposed { get; private set; } = false;
|
|
public bool IsInitialized { get; private set; } = false;
|
|
|
|
private readonly List<ICommandExecutor> _executorsList = new List<ICommandExecutor>();
|
|
|
|
private readonly Dictionary<string, ICommandExecutor> _executorsMap = new Dictionary<string, ICommandExecutor>();
|
|
|
|
public ContextExecutor(GLEngine engine, IGLContext context)
|
|
{
|
|
Engine = engine;
|
|
Context = context;
|
|
|
|
ResourcePool = Engine.ResourcePoolManager.Get(context);
|
|
ResourcePool.IncrementReference();
|
|
|
|
AddExecutor(new BaseCommandExecutor());
|
|
}
|
|
|
|
~ContextExecutor()
|
|
{
|
|
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);
|
|
}
|
|
|
|
public void Initialize()
|
|
{
|
|
if (IsInitialized)
|
|
return;
|
|
IsInitialized = true;
|
|
|
|
foreach (ICommandExecutor executor in _executorsList)
|
|
{
|
|
if (executor is IInitializer initializer)
|
|
initializer.Initialize();
|
|
}
|
|
}
|
|
|
|
public virtual void BeginFrame()
|
|
{
|
|
foreach (ICommandExecutor executor in _executorsList)
|
|
executor.BeginFrame();
|
|
}
|
|
|
|
protected virtual void BeginDraw()
|
|
{
|
|
foreach (ICommandExecutor executor in _executorsList)
|
|
executor.BeginDraw();
|
|
}
|
|
|
|
protected virtual void EndDraw()
|
|
{
|
|
foreach (ICommandExecutor executor in _executorsList)
|
|
executor.EndDraw();
|
|
}
|
|
|
|
public virtual void EndFrame()
|
|
{
|
|
ResourcePool.Collector.Dispose();
|
|
TransformStack.Clear();
|
|
|
|
foreach (ICommandExecutor executor in _executorsList)
|
|
executor.EndFrame();
|
|
}
|
|
|
|
public void Draw(DrawQueue drawqueue) => Draw(drawqueue, new RectangleF(new PointF(0f,0f), Context.FramebufferSize));
|
|
|
|
public virtual void Draw(DrawQueue drawQueue, RectangleF bounds)
|
|
{
|
|
BeginDraw();
|
|
|
|
foreach (ICommandFrame frame in drawQueue)
|
|
{
|
|
if (_executorsMap.TryGetValue(frame.Command.Extension.Name, out ICommandExecutor? executor))
|
|
executor.ProcessCommand(frame);
|
|
}
|
|
|
|
EndDraw();
|
|
}
|
|
|
|
private void DisposeInvoker(bool safeExit, bool disposing)
|
|
{
|
|
if (!IsDisposed)
|
|
return;
|
|
|
|
IsDisposed = true;
|
|
|
|
if (disposing)
|
|
GC.SuppressFinalize(this);
|
|
|
|
Dispose(safeExit, disposing);
|
|
}
|
|
|
|
protected virtual void Dispose(bool safeExit, bool disposing)
|
|
{
|
|
if (disposing)
|
|
{
|
|
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();
|
|
}
|
|
}
|
|
|
|
public void Dispose() => DisposeInvoker(true, true);
|
|
|
|
public void Dispose(bool safeExit) => DisposeInvoker(safeExit, true);
|
|
}
|
|
}
|