using StgSharp.Logic; using StgSharp.Math; using System; using System.Runtime.CompilerServices; using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; namespace StgSharp.Graphics { internal sealed class FrameOperationBuffer { private readonly unsafe GLcontext* currentContext; private IntPtr _func; private ConcurrentQueue _funcQueue; public unsafe bool CallNext() { if (_funcQueue.TryDequeue(out _func)) { ((delegate*)_func)(this, currentContext); return true; } else { return false; } } #region gl param queue private ConcurrentQueue paramQueue = new ConcurrentQueue(); private ConcurrentQueue streamQueue = new ConcurrentQueue(); [MethodImpl(MethodImplOptions.AggressiveInlining)] public void MethodEnqueue(IntPtr p) { _funcQueue.Enqueue(p); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void ParamEnqueue(Vec4d v) { paramQueue.Enqueue(v); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void ParamEnqueue(M128 m) { paramQueue.Enqueue(m); Console.WriteLine(paramQueue.Count + streamQueue.Count); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void ParamEnqueue(uint u0) { M128 m = default; m.Write(0, u0); this.ParamEnqueue(m); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void ParamEnqueue(uint u0, uint u1) { M128 m = default; m.Write(0, u0); m.Write(1, u1); this.ParamEnqueue(m); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void ParamEnqueue(ulong u0, ulong u1) { M128 m = default; m.Write(0, u0); m.Write(1, u1); this.ParamEnqueue(m); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void ParamEnqueue(uint u0, uint u1, uint u2) { M128 m = default; m.Write(0, u0); m.Write(1, u1); m.Write(2, u2); this.ParamEnqueue(m); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void ParamEnqueue(float f0, float f1, float f2) { M128 m = default; m.Write(0, f0); m.Write(1, f1); this.ParamEnqueue(m); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void ParamEnqueue(float f0, float f1, float f2, float f3) { M128 m = default; m.Write(0, f0); m.Write(1, f1); m.Write(2, f2); m.Write(3, f3); this.ParamEnqueue(m); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void ParamEnqueue(IntPtr p0, IntPtr p1) { M128 m = default; m.Write(0, (ulong)p0); m.Write(1, (ulong)p1); this.ParamEnqueue(m); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void ParamEnqueue(IntPtr p) { M128 m = default; m.Write(0, (ulong)p); this.ParamEnqueue(m); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe void ParamEnqueue(glHandle handle) { M128 m = default; m.Write(0, (ulong)handle.valuePtr); this.ParamEnqueue(m); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe void ParamEnqueue(glHandle handle, glHandle handle1) { M128 m = default; m.Write(0, (ulong)handle.valuePtr); m.Write(1, (ulong)handle1.valuePtr); this.ParamEnqueue(m); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void ParamEnqueue(int i0) { M128 m = default; m.Write(0, i0); this.ParamEnqueue(m); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void ParamEnqueue(int i0, int i1) { M128 m = default; m.Write(0, i0); m.Write(1, i1); this.ParamEnqueue(m); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void ParamEnqueue(int i0, int i1, int i2) { M128 m = default; m.Write(0, i0); m.Write(1, i1); m.Write(2, i2); this.ParamEnqueue(m); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void ParamEnqueue(int i0, int i1, int i2, int i3) { M128 m = default; m.Write(0, i0); m.Write(1, i1); m.Write(2, i2); m.Write(3, i3); this.ParamEnqueue(m); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void ParamEnqueue(string str) { byte[] code = Encoding.UTF8.GetBytes(str); streamQueue.Enqueue(glArrayHandle.Alloc(code)); Console.WriteLine(paramQueue.Count + streamQueue.Count); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void ParamEnqueue(T[] array) where T : struct { streamQueue.Enqueue(glArrayHandle.Alloc(array)); Console.WriteLine(paramQueue.Count + streamQueue.Count); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void TryDequeue(out glArrayHandle arrayHandle) { if (!streamQueue.TryDequeue(out arrayHandle)) { InternalIO.InternalWriteLog("No param in buffer when calling gl function:", LogType.Error); throw new Exception(); } } [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool TryDequeue(out M128 m) { bool ret = paramQueue.TryDequeue(out m); return ret; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public unsafe void TryDequeue(out Vec4d v) { M128 m; if (this.TryDequeue(out m)) { v = *(Vec4d*)&m; } else { InternalIO.InternalWriteLog("No param in buffer when calling gl function.", LogType.Error); throw new Exception(); } } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void TryDequeue(out T[] array) { glArrayHandle output = default; if (streamQueue.TryDequeue(out output)) { array = output.a as T[]; } else { InternalIO.InternalWriteLog("No param in buffer when calling gl function.", LogType.Error); throw new Exception(); } } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void TryDequeue(out int i0) { M128 ret; if (this.TryDequeue(out ret)) { i0 = ret.Read(0); } else { InternalIO.InternalWriteLog("No param in buffer when calling gl function.", LogType.Error); throw new Exception(); } } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void TryDequeue(out int i0, out int i1) { M128 ret; if (this.TryDequeue(out ret)) { i0 = ret.Read(0); i1 = ret.Read(1); } else { InternalIO.InternalWriteLog("No param in buffer when calling gl function.", LogType.Error); throw new Exception(); } } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void TryDequeue(out int i0, out int i1, out int i2) { M128 ret; if (this.TryDequeue(out ret)) { i0 = ret.Read(0); i1 = ret.Read(1); i2 = ret.Read(2); } else { InternalIO.InternalWriteLog("No param in buffer when calling gl function.", LogType.Error); throw new Exception(); } } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void TryDequeue(out int i0, out int i1, out int i2, out int i3) { M128 ret; if (this.TryDequeue(out ret)) { i0 = ret.Read(0); i1 = ret.Read(1); i2 = ret.Read(2); i3 = ret.Read(3); } else { InternalIO.InternalWriteLog("No param in buffer when calling gl function.", LogType.Error); throw new Exception(); } } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void TryDequeue(out IntPtr p) { M128 ret; if (this.TryDequeue(out ret)) { p = (IntPtr)ret.Read(0); } else { InternalIO.InternalWriteLog("No param in buffer when calling gl function.", LogType.Error); throw new Exception(); } } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void TryDequeue(out IntPtr p0, out IntPtr p1) { M128 ret; if (this.TryDequeue(out ret)) { p0 = (IntPtr)ret.Read(0); p1 = (IntPtr)ret.Read(1); } else { InternalIO.InternalWriteLog("No param in buffer when calling gl function.", LogType.Error); throw new Exception(); } } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void TryDequeue(out float f0, out float f1, out float f2, out float f3) { M128 ret; if (this.TryDequeue(out ret)) { f0 = ret.Read(0); f1 = ret.Read(1); f2 = ret.Read(2); f3 = ret.Read(3); } else { InternalIO.InternalWriteLog("No param in buffer when calling gl function.", LogType.Error); throw new Exception(); } } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void TryDequeue(out float f0, out float f1, out float f2) { M128 ret; if (this.TryDequeue(out ret)) { f0 = ret.Read(0); f1 = ret.Read(1); f2 = ret.Read(2); } else { InternalIO.InternalWriteLog("No param in buffer when calling gl function.", LogType.Error); throw new Exception(); } } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void TryDequeue(out uint u0) { M128 ret; if (this.TryDequeue(out ret)) { u0 = ret.Read(0); } else { InternalIO.InternalWriteLog("No param in buffer when calling gl function.", LogType.Error); throw new Exception(); } } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void TryDequeue(out uint u0, out uint u1) { M128 ret; if (this.TryDequeue(out ret)) { u0 = ret.Read(0); u1 = ret.Read(1); } else { InternalIO.InternalWriteLog("No param in buffer when calling gl function.", LogType.Error); throw new Exception(); } } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void TryDequeue(out uint u0, out uint u1, out uint u2) { M128 ret; if (this.TryDequeue(out ret)) { u0 = ret.Read(0); u1 = ret.Read(1); u2 = ret.Read(2); } else { InternalIO.InternalWriteLog("No param in buffer when calling gl function.", LogType.Error); throw new Exception(); } } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void TryDequeue(out uint u0, out uint u1, out uint u2, out uint u3) { M128 ret; if (this.TryDequeue(out ret)) { u0 = ret.Read(0); u1 = ret.Read(1); u2 = ret.Read(2); u3 = ret.Read(3); } else { InternalIO.InternalWriteLog("No param in buffer when calling gl function.", LogType.Error); throw new Exception(); } } /* internal void SetContext(GLcontext* p) { context = p; } /**/ #endregion gl param queue } internal sealed class FrameThread { private Thread _thread; private FrameOperationBuffer renderBuffer; private SemaphoreSlim renderCompleteSemaphore = new SemaphoreSlim(1, 1); private SemaphoreSlim renderStartSemaphore; private bool shouldTerminate; private FrameOperationBuffer updateBuffer; internal FrameThread(GLonUpdate gl) { updateBuffer = gl.ActivatedOperationBuffer; _thread = new Thread(new ThreadStart(PrivateMain)); } public bool IsRunning { get { return _thread.IsAlive; } } public void Start() { _thread.Start(); } public void Terminate() { shouldTerminate = true; } private void PrivateMain() { renderStartSemaphore.Wait(); while (shouldTerminate && renderBuffer.CallNext()) { } renderCompleteSemaphore.Release(); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void SetNext(FrameThread thread) { renderStartSemaphore = thread.renderCompleteSemaphore; } } }