using System; using System.Collections.Generic; using System.Data.Common; using System.Linq; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security.AccessControl; using System.Text; using System.Threading.Tasks; namespace StgSharp.Graphics { //TODO 发现一个大问题,paramQueue大多数时候取出的是数组,不是数组句柄,也就是说其内存将被长期固定且不能回收,这是内存泄漏 public unsafe class glArrayHandle { internal readonly Array copy; internal GCHandle handle; [MethodImpl(MethodImplOptions.AggressiveInlining)] public IntPtr AddressOfArray() { return handle.AddrOfPinnedObject(); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static glArrayHandle Alloc(T[] array) where T : struct { Array copy = new T[array.Length]; array.CopyTo(copy, 0); return new glArrayHandle(copy); } internal glArrayHandle(Array array) { copy = array; handle = GCHandle.Alloc(array, GCHandleType.Pinned); } } /// /// A handle to an OpenGL object, /// must be indexed from a . /// Direct call will cause /// public unsafe struct glHandle { internal glHandleSet source; internal uint* valuePtr; [Obsolete("Cannot init instance of this type", true)] public glHandle() { } internal glHandle(uint* val, glHandleSet set) { source = set; valuePtr = val; } private glHandle(IntPtr handle) { this.valuePtr = (uint*)handle; source = null; } public static glHandle Zero { get { return Alloc(0); } } public IntPtr Handle { get { if (source.handle == (uint*)0) { throw new InvalidOperationException($"Handle set {nameof(source)} is not pinned."); } return (IntPtr)valuePtr; } } public uint Value { get { if (source.handle == (uint*)0) { throw new InvalidOperationException($"Handle set {nameof(source)} is not pinned."); } return *valuePtr; } set { if (source.handle == (uint*)0) { throw new InvalidOperationException($"Handle set {nameof(source)} is not pinned."); } *valuePtr = value; } } internal uint DirectValue { get { return *valuePtr; } } public static glHandle Alloc(uint value) { glHandle ret = default; ret.source = new glHandleSet(1); ret.valuePtr = ret.source.handle; *ret.valuePtr = value; return ret; } [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static glHandle Alloc(IntPtr handle) { return new glHandle(handle); } } public unsafe struct glSHandle { internal glHandleSet source; internal int* valuePtr; internal glSHandle(int* val, glHandleSet set) { source = set; valuePtr = val; } public static glSHandle Zero { get { return Alloc(1); } } internal int DirectValue { get { return *valuePtr; } } public static glSHandle Alloc(int value) { glSHandle ret = default; ret.source = new glHandleSet(1); ret.valuePtr = (int*)ret.source.handle; *ret.valuePtr = (int)value; return ret; } } /// /// A handle to an OpenGL object. /// public unsafe class glHandleSet { internal uint* handle; internal int length; private readonly uint[] _value; public glHandleSet(int count) { _value = new uint[count]; length = count; handle = (uint*)GCHandle.Alloc(_value, GCHandleType.Pinned).AddrOfPinnedObject(); } public glHandle this[int index] { get { if (index > length) { throw new IndexOutOfRangeException(); } return new glHandle(handle + index, this); } } public glSHandle this[uint index] { get { if (index > length) { throw new IndexOutOfRangeException(); } return new glSHandle((int*)handle + index, this); } } public static void Copy(in glHandleSet source, glHandleSet target) { if (source == null || target == null) { throw new NullReferenceException(); } if (source.length != target.length) { throw new Exception($"Lengths of {nameof(source)} and {nameof(target)} are not equal."); } for (int i = 0; i < source.length; i++) { target._value[i] = source._value[i]; } } /// /// temporarily release the handle of GLhandle sets. /// Please call method before indexing. /// public void Free() { if (_value == null) { return; } GCHandle h = GCHandle.FromIntPtr((IntPtr)handle); h.Free(); handle = (uint*)0; } public void Pin() { if (_value == null) { return; } handle = (uint*)GCHandle.Alloc(_value, GCHandleType.Pinned).AddrOfPinnedObject(); } /// /// Realse all resource in this handle. /// This will release all resource in this . /// This will be not usable. /// public void Release() { if (_value == null) { return; } else { GCHandle.FromIntPtr((IntPtr)handle).Free(); handle = (uint*)IntPtr.Zero; } } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void SetValue(int index, uint value) { _value[index] = value; } } }