From 9c9efc6eeb43163a5d5e8afd5353b881baeaf2ec Mon Sep 17 00:00:00 2001 From: "H. Utku Maden" Date: Mon, 8 Apr 2024 23:50:05 +0300 Subject: [PATCH] Convert command queue to a command list. --- Quik.OpenTK/OpenTKPort.cs | 2 +- Quik/CommandMachine/CommandEngine.cs | 42 ++++---- Quik/CommandMachine/CommandHandler.cs | 2 +- .../{CommandQueue.cs => CommandList.cs} | 96 ++++++++++++++++++- Quik/Controls/UIBase.cs | 6 +- Quik/PAL/IQuikPort.cs | 2 +- Quik/QuikApplication.cs | 3 +- Quik/VertexGenerator/VertexCommandEngine.cs | 12 +-- 8 files changed, 131 insertions(+), 34 deletions(-) rename Quik/CommandMachine/{CommandQueue.cs => CommandList.cs} (72%) diff --git a/Quik.OpenTK/OpenTKPort.cs b/Quik.OpenTK/OpenTKPort.cs index ca5153f..ae529a7 100644 --- a/Quik.OpenTK/OpenTKPort.cs +++ b/Quik.OpenTK/OpenTKPort.cs @@ -65,7 +65,7 @@ namespace Quik.OpenTK _window.Focus(); } - public void Paint(CommandQueue queue) + public void Paint(CommandList queue) { QRectangle view = new QRectangle(Size, new QVec2(0, 0)); diff --git a/Quik/CommandMachine/CommandEngine.cs b/Quik/CommandMachine/CommandEngine.cs index eb66dcb..e2d4c18 100644 --- a/Quik/CommandMachine/CommandEngine.cs +++ b/Quik/CommandMachine/CommandEngine.cs @@ -34,10 +34,12 @@ namespace Quik.CommandMachine return id; } - public void ProcessCommands(QRectangle bounds, CommandQueue queue) + public void ProcessCommands(QRectangle bounds, CommandList queue) { - if (!queue.Peek().IsCommand) - throw new ArgumentException("The first element in the queue must be a command frame."); + CommandEnumerator iterator = queue.GetEnumerator(); + + if (!iterator.Peek().IsCommand) + throw new ArgumentException("The first element in the iterator must be a command frame."); Reset(); @@ -45,7 +47,7 @@ namespace Quik.CommandMachine _viewportStack.Push(_viewport); Frame frame; - while (queue.TryDequeue(out frame)) + while (iterator.TryDequeue(out frame)) { Command cmd = (Command)frame; switch (cmd) @@ -53,28 +55,28 @@ namespace Quik.CommandMachine default: if (cmd > Command.CustomCommandBase) { - _customCommands[cmd - Command.CustomCommandBase].Invoke(this, queue); + _customCommands[cmd - Command.CustomCommandBase].Invoke(this, iterator); } else { - ChildProcessCommand(cmd, queue); + ChildProcessCommand(cmd, iterator); } break; - case Command.ConditionalBegin: ConditionalHandler(queue); break; + case Command.ConditionalBegin: ConditionalHandler(iterator); break; case Command.ConditionalEnd: /* nop */ break; case Command.Invoke: - queue.Dequeue().As().Invoke(this, queue); + iterator.Dequeue().As().Invoke(this, iterator); break; case Command.PushViewport: _viewportStack.Push(_viewport); break; case Command.IntersectViewport: - _viewport = QRectangle.Intersect((QRectangle)queue.Dequeue(), _viewport); + _viewport = QRectangle.Intersect((QRectangle)iterator.Dequeue(), _viewport); break; case Command.StoreViewport: - _viewport = (QRectangle)queue.Dequeue(); + _viewport = (QRectangle)iterator.Dequeue(); break; case Command.PopViewport: _viewport = _viewportStack.TryPop(out QRectangle viewport) ? viewport : bounds; @@ -86,10 +88,10 @@ namespace Quik.CommandMachine _zIndex++; break; case Command.AddZ: - _zIndex += (int)queue.Dequeue(); + _zIndex += (int)iterator.Dequeue(); break; case Command.StoreZ: - _zIndex = (int)queue.Dequeue(); + _zIndex = (int)iterator.Dequeue(); break; case Command.DecrementZ: _zIndex--; @@ -101,7 +103,7 @@ namespace Quik.CommandMachine } } - protected virtual void ChildProcessCommand(Command name, CommandQueue queue) + protected virtual void ChildProcessCommand(Command name, CommandEnumerator queue) { } @@ -110,16 +112,16 @@ namespace Quik.CommandMachine _zIndex = 0; _zStack.Clear(); - _viewport = new QRectangle(float.MaxValue, float.MaxValue, float.MinValue, float.MinValue); + _viewport = new QRectangle(float.MaxValue, float.MinValue, float.MinValue, float.MaxValue); _viewportStack.Clear(); _matrixStack.Clear(); _matrixStack.Push(QMat4.Identity); } - private void ConditionalHandler(CommandQueue queue) + private void ConditionalHandler(CommandEnumerator iterator) { - Frame frame = queue.Dequeue(); + Frame frame = iterator.Dequeue(); if ( frame.IsInteger && (int)frame != 0 || @@ -131,11 +133,11 @@ namespace Quik.CommandMachine // Skip this branch. int depth = 1; - while (queue.TryPeek(out frame)) + while (iterator.TryPeek(out frame)) { if (!frame.IsCommand) { - queue.Dequeue(); + iterator.Dequeue(); continue; } @@ -149,13 +151,13 @@ namespace Quik.CommandMachine // Decrement condional depth, exit if zero. if (--depth == 0) { - queue.Dequeue(); + iterator.Dequeue(); return; } break; } - queue.Dequeue(); + iterator.Dequeue(); } } } diff --git a/Quik/CommandMachine/CommandHandler.cs b/Quik/CommandMachine/CommandHandler.cs index 62f31ac..2909385 100644 --- a/Quik/CommandMachine/CommandHandler.cs +++ b/Quik/CommandMachine/CommandHandler.cs @@ -4,5 +4,5 @@ namespace Quik.CommandMachine /// A delegate for a QUIK command. /// /// The current stack. - public delegate void QuikCommandHandler(CommandEngine state, CommandQueue queue); + public delegate void QuikCommandHandler(CommandEngine state, CommandEnumerator queue); } \ No newline at end of file diff --git a/Quik/CommandMachine/CommandQueue.cs b/Quik/CommandMachine/CommandList.cs similarity index 72% rename from Quik/CommandMachine/CommandQueue.cs rename to Quik/CommandMachine/CommandList.cs index 6caa034..8d43531 100644 --- a/Quik/CommandMachine/CommandQueue.cs +++ b/Quik/CommandMachine/CommandList.cs @@ -1,10 +1,25 @@ using System; +using System.Collections; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Reflection.Emit; namespace Quik.CommandMachine { - public class CommandQueue : Queue + public class CommandList : IEnumerable { + private readonly List _frames = new List(); + + public void Clear() + { + _frames.Clear(); + } + + protected void Enqueue(in Frame frame) + { + _frames.Add(frame); + } + public void Invoke(QuikCommandHandler handler) { Enqueue(Command.Invoke); @@ -243,5 +258,84 @@ namespace Quik.CommandMachine Enqueue(uvs[i]); } } + + public void Splice(CommandList queue) + { + foreach (Frame frame in queue) + { + Enqueue(frame); + } + } + + public CommandEnumerator GetEnumerator() => new CommandEnumerator(_frames); + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + } + + public class CommandEnumerator : IEnumerator + { + private readonly IReadOnlyList _frames; + private int _current; + + public Frame Current => _frames[_current]; + + object IEnumerator.Current => Current; + + public CommandEnumerator(IReadOnlyList frames) + { + _current = -1; + _frames = frames; + } + + public void Dispose() + { + } + + public bool TryDequeue([NotNullWhen(true)] out Frame frame) + { + if (MoveNext()) + { + frame = Current; + return true; + } + else + { + frame = default; + return false; + } + } + + public Frame Dequeue() => TryDequeue(out Frame frame) ? frame : throw new Exception("No more frames left."); + + public bool TryPeek([NotNullWhen(true)] out Frame frame) + { + if (_current + 1 < _frames.Count) + { + frame = _frames[_current + 1]; + return true; + } + else + { + frame = default; + return false; + } + } + + public Frame Peek() => TryPeek(out Frame frame) ? frame : throw new Exception("No more frames left."); + + public bool MoveNext() + { + if (_current + 1 < _frames.Count) + { + _current++; + return true; + } + return false; + } + + public void Reset() + { + _current = -1; + } } } \ No newline at end of file diff --git a/Quik/Controls/UIBase.cs b/Quik/Controls/UIBase.cs index 5068608..a5d4e65 100644 --- a/Quik/Controls/UIBase.cs +++ b/Quik/Controls/UIBase.cs @@ -44,20 +44,20 @@ namespace Quik.Controls { } - protected virtual void PaintBegin(CommandQueue cmd) + protected virtual void PaintBegin(CommandList cmd) { cmd.PushViewport(); cmd.StoreViewport(AbsoluteBounds); cmd.PushZ(); } - protected virtual void PaintEnd(CommandQueue cmd) + protected virtual void PaintEnd(CommandList cmd) { cmd.PopZ(); cmd.PopViewport(); } - public void Paint(CommandQueue cmd) + public void Paint(CommandList cmd) { PaintBegin(cmd); PaintEnd(cmd); diff --git a/Quik/PAL/IQuikPort.cs b/Quik/PAL/IQuikPort.cs index 75c0099..a8c65fe 100644 --- a/Quik/PAL/IQuikPort.cs +++ b/Quik/PAL/IQuikPort.cs @@ -44,6 +44,6 @@ namespace Quik.PAL /// Paint the given command queue onto the port. /// /// The command queue to paint. - void Paint(CommandQueue queue); + void Paint(CommandList queue); } } \ No newline at end of file diff --git a/Quik/QuikApplication.cs b/Quik/QuikApplication.cs index 804ff7f..734d581 100644 --- a/Quik/QuikApplication.cs +++ b/Quik/QuikApplication.cs @@ -50,7 +50,7 @@ namespace Quik public void Run(View mainView) { IQuikPort port = Platform.CreatePort(); - CommandQueue cmd = new CommandQueue(); + CommandList cmd = new CommandList(); MainView = mainView; @@ -61,6 +61,7 @@ namespace Quik Platform.ProcessEvents(false); if (port.IsValid) { + cmd.Clear(); MainView.Paint(cmd); port.Paint(cmd); } diff --git a/Quik/VertexGenerator/VertexCommandEngine.cs b/Quik/VertexGenerator/VertexCommandEngine.cs index acbac08..ce2351e 100644 --- a/Quik/VertexGenerator/VertexCommandEngine.cs +++ b/Quik/VertexGenerator/VertexCommandEngine.cs @@ -30,7 +30,7 @@ namespace Quik.VertexGenerator DrawQueue.Clear(); } - protected override void ChildProcessCommand(Command name, CommandQueue queue) + protected override void ChildProcessCommand(Command name, CommandEnumerator queue) { base.ChildProcessCommand(name, queue); @@ -55,7 +55,7 @@ namespace Quik.VertexGenerator } private readonly List LineList = new List(); - private void LineProc(CommandQueue queue) + private void LineProc(CommandEnumerator queue) { Frame frame = queue.Dequeue(); @@ -280,7 +280,7 @@ namespace Quik.VertexGenerator } private readonly List BezierList = new List(); - private void BezierProc(CommandQueue queue) + private void BezierProc(CommandEnumerator queue) { Frame a = queue.Dequeue(); Frame b; @@ -397,7 +397,7 @@ namespace Quik.VertexGenerator } private readonly List RectangleList = new List(); - private void RectangleProc(CommandQueue queue) + private void RectangleProc(CommandEnumerator queue) { Frame frame = queue.Dequeue(); RectangleList.Clear(); @@ -422,8 +422,8 @@ namespace Quik.VertexGenerator { QRectangle outer = RectangleList[i]; QRectangle inner = new QRectangle( - outer.Right - stroke, outer.Top - stroke, - outer.Left + stroke, outer.Bottom + stroke); + outer.Right - stroke, outer.Bottom + stroke, + outer.Left + stroke, outer.Top - stroke); GenerateRectangleBase(inner, Math.Max(radius - stroke, 0.0f));