daily update on 20240403 by nitload youmu
This commit is contained in:
@@ -41,9 +41,8 @@ namespace StgSharp.Graphics
|
||||
/// </summary>
|
||||
public abstract class BufferObjectBase : IDisposable
|
||||
{
|
||||
|
||||
protected IntPtr binding;
|
||||
protected glHandleSet _bufferHandle;
|
||||
protected IglFunc binding;
|
||||
|
||||
/// <summary>
|
||||
/// Get the only handle to one of the Object instance
|
||||
|
||||
@@ -48,27 +48,27 @@ namespace StgSharp.Graphics
|
||||
|
||||
internal ElementBuffer(int n, Form binding)
|
||||
{
|
||||
this.binding = binding.GL;
|
||||
_bufferHandle = this.binding.GenBuffers(n);
|
||||
this.binding = binding.graphicContextID;
|
||||
_bufferHandle = GL.GenBuffers(n);
|
||||
}
|
||||
|
||||
public override sealed void Bind(int index)
|
||||
{
|
||||
binding.BindBuffer(BufferType.ELEMENT_ARRAY_BUFFER, _bufferHandle[index]);
|
||||
GL.BindBuffer(BufferType.ELEMENT_ARRAY_BUFFER, _bufferHandle[index]);
|
||||
}
|
||||
|
||||
public void SetValue<T>(int index, T[] bufferArray, BufferUsage usage)
|
||||
where T : struct, IConvertible
|
||||
{
|
||||
binding.BindBuffer(BufferType.ELEMENT_ARRAY_BUFFER, _bufferHandle[index]);
|
||||
binding.SetBufferData(BufferType.ELEMENT_ARRAY_BUFFER, bufferArray, usage);
|
||||
GL.BindBuffer(BufferType.ELEMENT_ARRAY_BUFFER, _bufferHandle[index]);
|
||||
GL.SetBufferData(BufferType.ELEMENT_ARRAY_BUFFER, bufferArray, usage);
|
||||
}
|
||||
|
||||
protected override sealed void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
binding.DeleteBuffers(_bufferHandle);
|
||||
GL.DeleteBuffers(_bufferHandle);
|
||||
_bufferHandle.Release();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,26 +40,26 @@ namespace StgSharp.Graphics
|
||||
|
||||
internal VertexArray(int n, Form binding)
|
||||
{
|
||||
this.binding = binding.GL;
|
||||
_bufferHandle = this.binding.GenVertexArrays(n);
|
||||
this.binding = binding.graphicContextID;
|
||||
_bufferHandle = GL.GenVertexArrays(n);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public override sealed void Bind(int index)
|
||||
{
|
||||
binding.BindVertexArray(_bufferHandle[index]);
|
||||
GL.BindVertexArray(_bufferHandle[index]);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void BindNull()
|
||||
{
|
||||
binding.BindVertexArray(glHandle.Zero);
|
||||
GL.BindVertexArray(glHandle.Zero);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void SetVertexAttribute(uint index, int vertexLength, TypeCode dataType, bool isNomalized, uint stride, int pointer)
|
||||
{
|
||||
binding.SetVertexAttribute(
|
||||
GL.SetVertexAttribute(
|
||||
index, vertexLength, dataType,
|
||||
isNomalized,
|
||||
stride, pointer);
|
||||
@@ -69,7 +69,7 @@ namespace StgSharp.Graphics
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
binding.DeleteVertexArrays(_bufferHandle);
|
||||
GL.DeleteVertexArrays(_bufferHandle);
|
||||
_bufferHandle.Release();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,13 +45,13 @@ namespace StgSharp.Graphics
|
||||
|
||||
internal VertexBuffer(int n, Form binding)
|
||||
{
|
||||
this.binding = binding.GL;
|
||||
_bufferHandle = this.binding.GenBuffers(n);
|
||||
this.binding = binding.graphicContextID;
|
||||
_bufferHandle = GL.GenBuffers(n);
|
||||
}
|
||||
|
||||
public override sealed void Bind(int index)
|
||||
{
|
||||
binding.BindBuffer(BufferType.ARRAY_BUFFER, _bufferHandle[index]);
|
||||
GL.BindBuffer(BufferType.ARRAY_BUFFER, _bufferHandle[index]);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -63,8 +63,8 @@ namespace StgSharp.Graphics
|
||||
/// <param name="usage">How OpenGL use these data, defined by <see cref="BufferUsage"/></param>
|
||||
public void SetValue<T>(int index, T bufferData, BufferUsage usage) where T : struct, IMat
|
||||
{
|
||||
binding.BindBuffer(BufferType.ARRAY_BUFFER, _bufferHandle[index]);
|
||||
binding.SetBufferData(BufferType.ARRAY_BUFFER, bufferData, usage);
|
||||
GL.BindBuffer(BufferType.ARRAY_BUFFER, _bufferHandle[index]);
|
||||
GL.SetBufferData(BufferType.ARRAY_BUFFER, bufferData, usage);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -76,8 +76,8 @@ namespace StgSharp.Graphics
|
||||
/// <param name="usage">How OpenGL use these data, defined by <see cref="BufferUsage"/></param>
|
||||
public void SetValueArray<T>(int index, T[] bufferArray, BufferUsage usage) where T : struct, IConvertible
|
||||
{
|
||||
binding.BindBuffer(BufferType.ARRAY_BUFFER, _bufferHandle[index]);
|
||||
binding.SetBufferData(BufferType.ARRAY_BUFFER, bufferArray, usage);
|
||||
GL.BindBuffer(BufferType.ARRAY_BUFFER, _bufferHandle[index]);
|
||||
GL.SetBufferData(BufferType.ARRAY_BUFFER, bufferArray, usage);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -86,14 +86,14 @@ namespace StgSharp.Graphics
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void Unbind()
|
||||
{
|
||||
binding.BindBuffer(BufferType.ARRAY_BUFFER, glHandle.Zero);
|
||||
GL.BindBuffer(BufferType.ARRAY_BUFFER, glHandle.Zero);
|
||||
}
|
||||
|
||||
protected override sealed void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
binding.DeleteBuffers(_bufferHandle);
|
||||
GL.DeleteBuffers(_bufferHandle);
|
||||
_bufferHandle.Release();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,25 +44,25 @@ namespace StgSharp.Graphics
|
||||
{
|
||||
|
||||
internal static bool[] unitActivated = new bool[16];
|
||||
private Form binding;
|
||||
private IntPtr binding;
|
||||
internal glHandleSet _textureHandle;
|
||||
internal Image[] sourceList;
|
||||
|
||||
internal Texture(int n, Form binding)
|
||||
{
|
||||
sourceList = new Image[n];
|
||||
this.binding = binding;
|
||||
_textureHandle = binding.GL.GenTextures(n);
|
||||
this.binding = binding.graphicContextID;
|
||||
_textureHandle = GL.GenTextures(n);
|
||||
}
|
||||
|
||||
public void Activate(TextureUnit unit)
|
||||
{
|
||||
binding.GL.ActiveTexture((uint)unit);
|
||||
GL.ActiveTexture((uint)unit);
|
||||
}
|
||||
|
||||
public void Bind2D(int index)
|
||||
{
|
||||
binding.GL.BindTexture(GLconst.TEXTURE_2D, _textureHandle[index]);
|
||||
GL.BindTexture(GLconst.TEXTURE_2D, _textureHandle[index]);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -72,7 +72,7 @@ namespace StgSharp.Graphics
|
||||
/// <param name="loader"> </param>
|
||||
public unsafe void LoadTexture(int index, string name, ImageLoader loader)
|
||||
{
|
||||
Image.ImageInfo info = default;
|
||||
ImageInfo info = default;
|
||||
InternalIO.InternalLoadImage(name, &info, loader);
|
||||
sourceList[index] = new Image(info);
|
||||
if (sourceList[index].info.pixelPtr != IntPtr.Zero)
|
||||
@@ -92,7 +92,7 @@ namespace StgSharp.Graphics
|
||||
channel = 0;
|
||||
break;
|
||||
}
|
||||
binding.GL.TextureImage2d<byte>(
|
||||
GL.TextureImage2d<byte>(
|
||||
GLconst.TEXTURE_2D, 0, channel,
|
||||
(uint)sourceList[index].Width, (uint)sourceList[index].Height,
|
||||
channel, GLconst.UNSIGNED_BYTE,
|
||||
@@ -111,15 +111,15 @@ namespace StgSharp.Graphics
|
||||
public void Set2dFilterProperty(
|
||||
Filter onMinify, Filter onMagnify)
|
||||
{
|
||||
binding.GL.TextureParameter(GLconst.TEXTURE_2D, GLconst.TEXTURE_MIN_FILTER, (int)onMinify);
|
||||
binding.GL.TextureParameter(GLconst.TEXTURE_2D, GLconst.TEXTURE_MAG_FILTER, (int)onMagnify);
|
||||
GL.TextureParameter(GLconst.TEXTURE_2D, GLconst.TEXTURE_MIN_FILTER, (int)onMinify);
|
||||
GL.TextureParameter(GLconst.TEXTURE_2D, GLconst.TEXTURE_MAG_FILTER, (int)onMagnify);
|
||||
}
|
||||
|
||||
public void Set2dWrapProperty(
|
||||
Wrap onHorizontial, Wrap onVertical)
|
||||
{
|
||||
binding.GL.TextureParameter(GLconst.TEXTURE_2D, GLconst.TEXTURE_WRAP_S, (int)onHorizontial);
|
||||
binding.GL.TextureParameter(GLconst.TEXTURE_2D, GLconst.TEXTURE_WRAP_T, (int)onVertical);
|
||||
GL.TextureParameter(GLconst.TEXTURE_2D, GLconst.TEXTURE_WRAP_S, (int)onHorizontial);
|
||||
GL.TextureParameter(GLconst.TEXTURE_2D, GLconst.TEXTURE_WRAP_T, (int)onVertical);
|
||||
}
|
||||
|
||||
#endregion texture setting
|
||||
|
||||
@@ -44,39 +44,27 @@ namespace StgSharp.Graphics
|
||||
/// <summary>
|
||||
/// A handle to an OpenGL object,
|
||||
/// must be indexed from a <see cref="glHandleSet"/>.
|
||||
/// Direct call will cause <see langword="InvalidOperationException"/>
|
||||
/// Attempt at direct creating an instance will cause <see cref="InvalidOperationException"/>
|
||||
/// </summary>
|
||||
public unsafe struct glHandle
|
||||
{
|
||||
|
||||
internal glHandleSet source;
|
||||
internal uint* valuePtr;
|
||||
|
||||
private glHandle(IntPtr handle)
|
||||
internal glHandle(int index, GCHandle arrayHandle)
|
||||
{
|
||||
this.valuePtr = (uint*)handle;
|
||||
source = null;
|
||||
}
|
||||
|
||||
internal glHandle(uint* val, glHandleSet set)
|
||||
{
|
||||
source = set;
|
||||
valuePtr = val;
|
||||
valuePtr = ((uint*)GCHandle.ToIntPtr(arrayHandle)) + index;
|
||||
}
|
||||
|
||||
[Obsolete("Cannot init instance of this type", true)]
|
||||
public glHandle()
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
|
||||
public IntPtr Handle
|
||||
{
|
||||
get
|
||||
{
|
||||
if (source.handle == (uint*)0)
|
||||
{
|
||||
throw new InvalidOperationException($"Handle set {nameof(source)} is not pinned.");
|
||||
}
|
||||
return (IntPtr)valuePtr;
|
||||
}
|
||||
}
|
||||
@@ -85,68 +73,29 @@ namespace StgSharp.Graphics
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
public static glHandle Zero => Alloc(0);
|
||||
|
||||
internal uint DirectValue => *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)
|
||||
internal glSHandle(int index, glHandleSet set)
|
||||
{
|
||||
source = set;
|
||||
valuePtr = val;
|
||||
|
||||
}
|
||||
|
||||
public static glSHandle Zero => Alloc(0);
|
||||
|
||||
internal int DirectValue => *valuePtr;
|
||||
|
||||
public static glSHandle Alloc(int value)
|
||||
{
|
||||
glSHandle ret = default;
|
||||
ret.source = new glHandleSet(1);
|
||||
ret.valuePtr = (int*)ret.source.handle;
|
||||
*ret.valuePtr = value;
|
||||
return ret;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public unsafe class glArrayHandle
|
||||
@@ -202,15 +151,20 @@ namespace StgSharp.Graphics
|
||||
public unsafe class glHandleSet
|
||||
{
|
||||
|
||||
private readonly uint[] _value;
|
||||
internal uint* handle;
|
||||
private uint[] _value;
|
||||
internal GCHandle handle;
|
||||
internal int length;
|
||||
|
||||
public glHandleSet(int count)
|
||||
{
|
||||
_value = new uint[count];
|
||||
length = count;
|
||||
handle = (uint*)GCHandle.Alloc(_value, GCHandleType.Pinned).AddrOfPinnedObject();
|
||||
handle = GCHandle.Alloc(_value);
|
||||
}
|
||||
|
||||
public IntPtr Handle
|
||||
{
|
||||
get => GCHandle.ToIntPtr(handle);
|
||||
}
|
||||
|
||||
public glHandle this[int index]
|
||||
@@ -221,7 +175,7 @@ namespace StgSharp.Graphics
|
||||
{
|
||||
throw new IndexOutOfRangeException();
|
||||
}
|
||||
return new glHandle(handle + index, this);
|
||||
return new glHandle(index, this.handle);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -233,7 +187,7 @@ namespace StgSharp.Graphics
|
||||
{
|
||||
throw new IndexOutOfRangeException();
|
||||
}
|
||||
return new glSHandle(((int*)handle) + index, this);
|
||||
return new glSHandle((int)index, this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -253,30 +207,6 @@ namespace StgSharp.Graphics
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// temporarily release the handle of GLhandle sets.
|
||||
/// Please call <see cref="Pin"/> method before indexing.
|
||||
/// </summary>
|
||||
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();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Release all resource in this handle.
|
||||
/// This will release all resource in this <see cref="glHandle"/>.
|
||||
@@ -284,17 +214,19 @@ namespace StgSharp.Graphics
|
||||
/// </summary>
|
||||
public void Release()
|
||||
{
|
||||
if (_value == null)
|
||||
if (handle == default)
|
||||
{
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
GCHandle.FromIntPtr((IntPtr)handle).Free();
|
||||
handle = (uint*)IntPtr.Zero;
|
||||
handle.Free();
|
||||
_value = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void SetValue(int index, uint value)
|
||||
{
|
||||
|
||||
@@ -40,89 +40,72 @@ using System.Text;
|
||||
|
||||
namespace StgSharp.Graphics
|
||||
{
|
||||
internal unsafe partial class GLpack : IglFunc
|
||||
internal unsafe static partial class GL
|
||||
{
|
||||
|
||||
private FrameTimeoutException refreshSIgnal = new FrameTimeoutException();
|
||||
internal GLcontext* api;
|
||||
|
||||
internal GLpack(GLcontext* context)
|
||||
{
|
||||
api = context;
|
||||
}
|
||||
internal static GLcontext* api;
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
void IglFunc.ActiveTexture(uint type)
|
||||
public static void ActiveTexture(uint type)
|
||||
{
|
||||
api->glActiveTexture(type);
|
||||
}
|
||||
|
||||
void IglFunc.AfterAlign(Form form, Action action)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
void IglFunc.AlignFrame(Form form)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
void IglFunc.AttachShader(glHandle program, glHandle shader)
|
||||
public static void AttachShader(glHandle program, glHandle shader)
|
||||
{
|
||||
api->glAttachShader(*program.valuePtr, shader.DirectValue);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
void IglFunc.BindBuffer(BufferType bufferType, glHandle handle)
|
||||
public static void BindBuffer(BufferType bufferType, glHandle handle)
|
||||
{
|
||||
api->glBindBuffer((uint)bufferType, handle.DirectValue);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
void IglFunc.BindTexture(uint type, glHandle texture)
|
||||
public static void BindTexture(uint type, glHandle texture)
|
||||
{
|
||||
api->glBindTexture(type, texture.DirectValue);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
void IglFunc.BindVertexArray(glHandle handle)
|
||||
public static void BindVertexArray(glHandle handle)
|
||||
{
|
||||
api->glBindVertexArray(handle.Value);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
void IglFunc.Clear(MaskBufferBit mask)
|
||||
public static void Clear(MaskBufferBit mask)
|
||||
{
|
||||
api->glClear((uint)mask);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
unsafe void IglFunc.ClearColor(float R, float G, float B, float A)
|
||||
unsafe public static void ClearColor(float R, float G, float B, float A)
|
||||
{
|
||||
api->glClearColor(R, G, B, A);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
unsafe void IglFunc.ClearGraphicError()
|
||||
unsafe public static void ClearGraphicError()
|
||||
{
|
||||
while (api->glGetError() != 0) { }
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
void IglFunc.CompileShader(glHandle shaderhandle)
|
||||
public static void CompileShader(glHandle shaderhandle)
|
||||
{
|
||||
api->glCompileShader(shaderhandle.DirectValue);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
glHandle IglFunc.CreateProgram()
|
||||
public static glHandle CreateProgram()
|
||||
{
|
||||
return glHandle.Alloc(api->glCreateProgram());
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
unsafe glHandleSet IglFunc.CreateProgram(int count)
|
||||
public static unsafe glHandleSet CreateProgram(int count)
|
||||
{
|
||||
glHandleSet h = new glHandleSet(count);
|
||||
for (int i = 0; i < count; i++)
|
||||
@@ -133,7 +116,7 @@ namespace StgSharp.Graphics
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
glHandleSet IglFunc.CreateShaderSet(int count, ShaderType type)
|
||||
public static glHandleSet CreateShaderSet(int count, ShaderType type)
|
||||
{
|
||||
glHandleSet ret = new glHandleSet(count);
|
||||
uint t = (uint)type;
|
||||
@@ -151,7 +134,7 @@ namespace StgSharp.Graphics
|
||||
return ret;
|
||||
}
|
||||
|
||||
unsafe IntPtr IglFunc.CreateWindowHandle(
|
||||
public static unsafe IntPtr CreateWindowHandle(
|
||||
int width, int height, string tittle, IntPtr monitor, Form share)
|
||||
{
|
||||
byte[] tittleBytes = Encoding.UTF8.GetBytes(tittle);
|
||||
@@ -178,33 +161,33 @@ namespace StgSharp.Graphics
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
unsafe glHandle IglFunc.CreatGraphicProgram()
|
||||
public static unsafe glHandle CreateGraphicProgram()
|
||||
{
|
||||
return glHandle.Alloc(api->glCreateProgram());
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
unsafe void IglFunc.DeleteBuffer(glHandle handle)
|
||||
unsafe public static void DeleteBuffer(glHandle handle)
|
||||
{
|
||||
api->glDeleteBuffers(1, (uint*)handle.Handle);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
unsafe void IglFunc.DeleteBuffers(glHandleSet handle)
|
||||
unsafe public static void DeleteBuffers(glHandleSet handle)
|
||||
{
|
||||
api->glDeleteBuffers((uint)handle.length, handle.handle);
|
||||
handle.Free();
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
unsafe void IglFunc.DeleteVertexArrays(glHandleSet arrays)
|
||||
unsafe public static void DeleteVertexArrays(glHandleSet arrays)
|
||||
{
|
||||
api->glDeleteVertexArrays((uint)arrays.length, arrays.handle);
|
||||
arrays.Free();
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
unsafe void IglFunc.DrawElements(GepmetryType mode, uint count, TypeCode type, IntPtr ptr)
|
||||
unsafe public static void DrawElements(GepmetryType mode, uint count, TypeCode type, IntPtr ptr)
|
||||
{
|
||||
uint a;
|
||||
switch (type)
|
||||
@@ -230,13 +213,8 @@ namespace StgSharp.Graphics
|
||||
api->glDrawElements((uint)mode, count, a, (void*)ptr);
|
||||
}
|
||||
|
||||
void IglFunc.frameworkHandleEnqueue(System.IntPtr handle, params M128[] param)
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
unsafe glHandleSet IglFunc.GenBuffers(int count)
|
||||
public static unsafe glHandleSet GenBuffers(int count)
|
||||
{
|
||||
glHandleSet h = new glHandleSet(count);
|
||||
api->glGenBuffers((uint)count, h.handle);
|
||||
@@ -244,15 +222,15 @@ namespace StgSharp.Graphics
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
unsafe glHandleSet IglFunc.GenTextures(int count)
|
||||
public static unsafe glHandleSet GenTextures(int count)
|
||||
{
|
||||
glHandleSet h = new glHandleSet(count);
|
||||
api->glGenTextures((uint)count, h.handle);
|
||||
api->glGenTextures(count, (uint*)h.Handle);
|
||||
return h;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
unsafe glHandleSet IglFunc.GenVertexArrays(int count)
|
||||
public static unsafe glHandleSet GenVertexArrays(int count)
|
||||
{
|
||||
glHandleSet h = new glHandleSet(count);
|
||||
api->glGenVertexArrays((uint)count, h.handle);
|
||||
@@ -260,7 +238,7 @@ namespace StgSharp.Graphics
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
unsafe glSHandle IglFunc.GetUniformLocation(glHandle program, string name)
|
||||
public static unsafe glSHandle GetUniformLocation(glHandle program, string name)
|
||||
{
|
||||
byte[] code = Encoding.UTF8.GetBytes(name);
|
||||
fixed (byte* ptr = code)
|
||||
@@ -270,13 +248,7 @@ namespace StgSharp.Graphics
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
unsafe bool IglFunc.GetWindowShouldClose(Form form)
|
||||
{
|
||||
return InternalIO.glfwWindowShouldClose(form.id) == 0;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
unsafe void IglFunc.LoadShaderSource(glHandle shaderHandle, string codeStream)
|
||||
unsafe public static void LoadShaderSource(glHandle shaderHandle, string codeStream)
|
||||
{
|
||||
byte[] stream = Encoding.UTF8.GetBytes(codeStream);
|
||||
fixed (byte* streamPtr = stream)
|
||||
@@ -286,7 +258,7 @@ namespace StgSharp.Graphics
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
unsafe void IglFunc.MakeContexCurrent(Form form)
|
||||
public unsafe static void MakeContexCurrent(Form form)
|
||||
{
|
||||
if (form.WindowID == IntPtr.Zero)
|
||||
{
|
||||
@@ -297,7 +269,7 @@ namespace StgSharp.Graphics
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
unsafe void IglFunc.SetBufferData<T>(BufferType bufferType, T bufferData, BufferUsage usage)
|
||||
public unsafe static void SetBufferData<T>(BufferType bufferType, T bufferData, BufferUsage usage)
|
||||
{
|
||||
int size = Marshal.SizeOf<T>();
|
||||
T* p = &bufferData;
|
||||
@@ -309,7 +281,7 @@ namespace StgSharp.Graphics
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
unsafe void IglFunc.SetBufferData<T>(BufferType bufferType, T[] bufferArray, BufferUsage usage)
|
||||
public unsafe static void SetBufferData<T>(BufferType bufferType, T[] bufferArray, BufferUsage usage)
|
||||
{
|
||||
int size = bufferArray.Length * Marshal.SizeOf(typeof(T));
|
||||
if (bufferArray == null)
|
||||
@@ -327,16 +299,15 @@ namespace StgSharp.Graphics
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
void IglFunc.SetVertexAttribute(uint index, int size, TypeCode t, bool normalized, uint stride, int pointer)
|
||||
public static void SetVertexAttribute(uint index, int size, TypeCode t, bool normalized, uint stride, int pointer)
|
||||
{
|
||||
uint type = InternalIO.GLtype[t];
|
||||
api->glVertexAttribPointer(index, size, type, normalized ? 1 : 0, stride, (void*)pointer);
|
||||
api->glEnableVertexAttribArray(index);
|
||||
}
|
||||
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
void IglFunc.TextureImage2d<T>(int target, int level, uint internalformat, uint width, uint height, uint format, uint type, glHandle pixels)
|
||||
public static void TextureImage2d<T>(int target, int level, uint internalformat, uint width, uint height, uint format, uint type, glHandle pixels)
|
||||
{
|
||||
api->glTexImage2D(
|
||||
(uint)target, level, internalformat, width, height, 0, format, type, pixels.valuePtr
|
||||
@@ -344,25 +315,22 @@ namespace StgSharp.Graphics
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
void IglFunc.TextureParameter(int target, uint pname, int param)
|
||||
public static void TextureParameter(int target, uint pname, int param)
|
||||
{
|
||||
api->glTexParameteri((uint)target, pname, param);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
void IglFunc.UseProgram(glHandle program)
|
||||
public static void UseProgram(glHandle program)
|
||||
{
|
||||
api->glUseProgram(program.DirectValue);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
void IglFunc.Viewport(int x, int y, uint width, uint height)
|
||||
public static void Viewport(int x, int y, uint width, uint height)
|
||||
{
|
||||
api->glViewport(x, y, width, height);
|
||||
}
|
||||
|
||||
GLcontext* IglFunc.Context
|
||||
=> api;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ namespace StgSharp.Graphics
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
protected Shader CreateShader(ShaderType type, int count)
|
||||
{
|
||||
return new Shader(this.gl, gl.CreateShaderSet(count, type), type);
|
||||
return new Shader( GL.CreateShaderSet(count, type), type);
|
||||
}
|
||||
/// <summary>
|
||||
/// Create an instance of <see cref="Shader"/> program
|
||||
@@ -61,23 +61,22 @@ namespace StgSharp.Graphics
|
||||
public class Shader
|
||||
{
|
||||
|
||||
private readonly IglFunc GL;
|
||||
internal readonly glHandleSet handle;
|
||||
private readonly IntPtr context;
|
||||
internal readonly GLhandle handle;
|
||||
public readonly ShaderType type;
|
||||
|
||||
internal Shader(IglFunc gl, glHandleSet handle, ShaderType usage)
|
||||
internal unsafe Shader(uint[] handle, ShaderType usage)
|
||||
{
|
||||
this.handle = handle;
|
||||
GL = gl;
|
||||
context = (IntPtr)GL.api;
|
||||
type = usage;
|
||||
}
|
||||
|
||||
//TODO:写链接着色器的文档注释
|
||||
/// <summary>
|
||||
///
|
||||
/// Attach one shader code to a shader program.
|
||||
/// </summary>
|
||||
/// <param name="target"></param>
|
||||
/// <param name="index"></param>
|
||||
/// <param name="target">Shader program to attach</param>
|
||||
/// <param name="index">Index of shader code in current shader code set.</param>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void AttachTo(int index, ShaderProgram target)
|
||||
{
|
||||
@@ -105,7 +104,7 @@ namespace StgSharp.Graphics
|
||||
public class ShaderProgram
|
||||
{
|
||||
|
||||
private readonly Form binding;
|
||||
private readonly IntPtr binding;
|
||||
internal readonly glHandle handle;
|
||||
|
||||
/// <summary>
|
||||
@@ -113,8 +112,8 @@ namespace StgSharp.Graphics
|
||||
/// </summary>
|
||||
internal unsafe ShaderProgram(Form binding)
|
||||
{
|
||||
this.binding = binding;
|
||||
handle = binding.GL.CreateProgram();
|
||||
this.binding = binding.graphicContextID;
|
||||
handle = GL.CreateProgram();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -153,7 +152,21 @@ namespace StgSharp.Graphics
|
||||
where U : struct
|
||||
where V : struct
|
||||
{
|
||||
return new Uniform<T, U, V>(this, name, binding);
|
||||
return new Uniform<T, U, V>(this, name);
|
||||
}
|
||||
/// <summary>
|
||||
/// Get a uniform form current shader,
|
||||
/// the value type of the uniform should be provided.
|
||||
/// </summary>
|
||||
/// <param name="name">Name of the Uniform in shader code</param>
|
||||
/// <returns></returns>
|
||||
public unsafe Uniform<T, U, V, W> GetUniform<T, U, V, W>(string name)
|
||||
where T : struct
|
||||
where U : struct
|
||||
where V : struct
|
||||
where W : struct
|
||||
{
|
||||
return new Uniform<T, U, V, W>(this, name);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -161,7 +174,7 @@ namespace StgSharp.Graphics
|
||||
/// </summary>
|
||||
public unsafe void Link()
|
||||
{
|
||||
if (InternalIO.InternalLinkShaderProgram(binding.GL.Context, handle.Value) == 0)
|
||||
if (InternalIO.InternalLinkShaderProgram((GLcontext*)this.binding, handle.Value) == 0)
|
||||
{
|
||||
IntPtr logPtr = InternalIO.InternalReadSSCLog();
|
||||
try
|
||||
@@ -185,7 +198,7 @@ namespace StgSharp.Graphics
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public unsafe void Use()
|
||||
{
|
||||
binding.GL.UseProgram(handle);
|
||||
GL.UseProgram(handle);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
using StgSharp.Graphics;
|
||||
using StgSharp.Math;
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
@@ -37,16 +38,19 @@ using System.Runtime.Serialization;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace StgSharp.Graphics.GL.ShaderEdit
|
||||
namespace StgSharp.Graphics.ShaderEdit
|
||||
{
|
||||
public class ShaderGenerator
|
||||
{
|
||||
|
||||
private Dictionary<int,ShaderParameter> uniformDefine;
|
||||
private List<string> codeList;
|
||||
private List<ShaderFunction> usedShaderFunctions;
|
||||
|
||||
public Uniform<T> DefineUniform<T>() where T : struct
|
||||
public Uniform<T> DefineUniform<T>(string name, int index) where T : struct
|
||||
{
|
||||
ShaderParameter p = new ShaderParameter(name,ShaderParameter.TypeMarshal<T>());
|
||||
uniformDefine.Add(index,p);
|
||||
//return new Uniform<T>();
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
@@ -54,7 +58,6 @@ namespace StgSharp.Graphics.GL.ShaderEdit
|
||||
|
||||
public class ShaderFunction
|
||||
{
|
||||
|
||||
private List<string> codeList;
|
||||
private List<ShaderParameter> inputList;
|
||||
private string name;
|
||||
@@ -100,7 +103,6 @@ namespace StgSharp.Graphics.GL.ShaderEdit
|
||||
|
||||
public class ShaderParameter
|
||||
{
|
||||
|
||||
public static readonly ShaderParameter Void = new ShaderParameter(string.Empty, InternalShaderType.Void);
|
||||
internal readonly bool isReadOnly;
|
||||
internal readonly string name;
|
||||
@@ -125,6 +127,48 @@ namespace StgSharp.Graphics.GL.ShaderEdit
|
||||
}
|
||||
}
|
||||
|
||||
public static InternalShaderType TypeMarshal<T>() where T : struct
|
||||
{
|
||||
switch (Type.GetTypeCode(typeof(T)))
|
||||
{
|
||||
case TypeCode.Single:
|
||||
return InternalShaderType.Float;
|
||||
case TypeCode.Double:
|
||||
return InternalShaderType.Double;
|
||||
case TypeCode.Int32:
|
||||
return InternalShaderType.Int;
|
||||
case TypeCode.UInt32:
|
||||
return InternalShaderType.UInt;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
switch (typeof(T).Name)
|
||||
{
|
||||
case "Vec4d":
|
||||
return InternalShaderType.Vector4;
|
||||
case "Matrix2x2":
|
||||
return InternalShaderType.Matrix2x2;
|
||||
case "Matrix2x3":
|
||||
return InternalShaderType.Matrix2x3;
|
||||
case "Matrix2x4":
|
||||
return InternalShaderType.Matrix2x4;
|
||||
case "Matrix3x2":
|
||||
return InternalShaderType.Matrix3x2;
|
||||
case "Matrix3x3":
|
||||
return InternalShaderType.Matrix3x3;
|
||||
case "Matrix3x4":
|
||||
return InternalShaderType.Matrix3x4;
|
||||
case "Matrix4x2":
|
||||
return InternalShaderType.Matrix4x2;
|
||||
case "Matrix4x3":
|
||||
return InternalShaderType.Matrix4x3;
|
||||
case "Matrix4x4":
|
||||
return InternalShaderType.Matrix4x4;
|
||||
default:
|
||||
throw new ArgumentException("Not supported shader data type.");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public enum InternalShaderType
|
||||
|
||||
@@ -42,7 +42,7 @@ namespace StgSharp.Graphics
|
||||
public class Uniform<T> where T : struct
|
||||
{
|
||||
|
||||
private Form binding;
|
||||
private IntPtr binding;
|
||||
internal glSHandle id;
|
||||
|
||||
internal unsafe Uniform(glSHandle id)
|
||||
@@ -52,9 +52,15 @@ namespace StgSharp.Graphics
|
||||
|
||||
internal unsafe Uniform(
|
||||
ShaderProgram program, string name, Form binding)
|
||||
{
|
||||
this.binding = binding.graphicContextID;
|
||||
id = GL.GetUniformLocation(program.handle, name);
|
||||
}
|
||||
internal unsafe Uniform(
|
||||
ShaderProgram program, string name, IntPtr binding)
|
||||
{
|
||||
this.binding = binding;
|
||||
id = binding.GL.GetUniformLocation(program.handle, name);
|
||||
id = GL.GetUniformLocation(program.handle, name);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -64,7 +70,7 @@ namespace StgSharp.Graphics
|
||||
where U : struct
|
||||
{
|
||||
|
||||
private Form binding;
|
||||
private IntPtr binding;
|
||||
internal glSHandle id;
|
||||
|
||||
internal unsafe Uniform(glSHandle id)
|
||||
@@ -74,9 +80,16 @@ namespace StgSharp.Graphics
|
||||
|
||||
internal unsafe Uniform(
|
||||
ShaderProgram program, string name, Form binding)
|
||||
{
|
||||
this.binding = binding.graphicContextID;
|
||||
id = GL.GetUniformLocation(program.handle, name);
|
||||
}
|
||||
|
||||
internal unsafe Uniform(
|
||||
ShaderProgram program, string name, IntPtr binding)
|
||||
{
|
||||
this.binding = binding;
|
||||
id = binding.GL.GetUniformLocation(program.handle, name);
|
||||
id = GL.GetUniformLocation(program.handle, name);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -87,7 +100,7 @@ namespace StgSharp.Graphics
|
||||
where V : struct
|
||||
{
|
||||
|
||||
private Form binding;
|
||||
private IntPtr binding;
|
||||
internal glSHandle id;
|
||||
|
||||
internal unsafe Uniform(glSHandle id)
|
||||
@@ -95,10 +108,17 @@ namespace StgSharp.Graphics
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
internal unsafe Uniform(
|
||||
ShaderProgram program, string name)
|
||||
{
|
||||
this.binding = (IntPtr)GL.api;
|
||||
id = GL.GetUniformLocation(program.handle, name);
|
||||
}
|
||||
|
||||
public unsafe Uniform(ShaderProgram program, string name, Form binding)
|
||||
{
|
||||
this.binding = binding;
|
||||
id = binding.GL.GetUniformLocation(program.handle, name);
|
||||
this.binding = binding.graphicContextID;
|
||||
id = GL.GetUniformLocation(program.handle, name);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -110,7 +130,7 @@ namespace StgSharp.Graphics
|
||||
where W : struct
|
||||
{
|
||||
|
||||
private Form binding;
|
||||
private IntPtr binding;
|
||||
internal glSHandle id;
|
||||
|
||||
internal unsafe Uniform(glSHandle id)
|
||||
@@ -120,55 +140,62 @@ namespace StgSharp.Graphics
|
||||
|
||||
internal unsafe Uniform(ShaderProgram program, string name, Form binding)
|
||||
{
|
||||
this.binding = binding;
|
||||
id = binding.GL.GetUniformLocation(program.handle, name);
|
||||
this.binding = binding.graphicContextID;
|
||||
id = GL.GetUniformLocation(program.handle, name);
|
||||
}
|
||||
|
||||
internal unsafe Uniform(
|
||||
ShaderProgram program, string name)
|
||||
{
|
||||
this.binding = (IntPtr)GL.api;
|
||||
id = GL.GetUniformLocation(program.handle, name);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
internal partial class GLpack : IglFunc
|
||||
internal static partial class GL
|
||||
{
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public unsafe void SetValue(Uniform<float, float, float, float> uniform, Vec4d vec)
|
||||
public unsafe static void SetValue(Uniform<float, float, float, float> uniform, Vec4d vec)
|
||||
{
|
||||
api->glUniform1fv(uniform.id.DirectValue, 4, &vec);
|
||||
api->glUniform1fv(uniform.id.DirectValue , 4, &vec);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public unsafe void SetValue(Uniform<Vec4d> uniform, Vec4d vec)
|
||||
public unsafe static void SetValue(Uniform<Vec4d> uniform, Vec4d vec)
|
||||
{
|
||||
api->glUniform1fv(uniform.id.DirectValue, 4, &vec);
|
||||
api->glUniform1fv(uniform.id.DirectValue , 4, &vec);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
unsafe void IglFunc.SetValue(Uniform<float> uniform, float v0)
|
||||
public static unsafe void SetValue(Uniform<float> uniform, float v0)
|
||||
{
|
||||
api->glUniform1f(uniform.id.DirectValue, v0);
|
||||
api->glUniform1f(uniform.id.DirectValue , v0);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
unsafe void IglFunc.SetValue(Uniform<int> uniform, int i0)
|
||||
public static unsafe void SetValue(Uniform<int> uniform, int i0)
|
||||
{
|
||||
api->glUniform1i(uniform.id.DirectValue, i0);
|
||||
api->glUniform1i(uniform.id.DirectValue , i0);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
unsafe void IglFunc.SetValue(Uniform<float, float> uniform, float v0, float v1)
|
||||
public static unsafe void SetValue(Uniform<float, float> uniform, float v0, float v1)
|
||||
{
|
||||
api->glUniform2f(uniform.id.DirectValue, v0, v1);
|
||||
api->glUniform2f(uniform.id.DirectValue , v0, v1);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
unsafe void IglFunc.SetValue(Uniform<float, float, float> uniform, float v0, float v1, float v2)
|
||||
public static unsafe void SetValue(Uniform<float, float, float> uniform, float v0, float v1, float v2)
|
||||
{
|
||||
api->glUniform3f(uniform.id.DirectValue, v0, v1, v2);
|
||||
api->glUniform3f(uniform.id.DirectValue , v0, v1, v2);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
unsafe void IglFunc.SetValue(Uniform<float, float, float, float> uniform, float v0, float v1, float v2, float v3)
|
||||
public static unsafe void SetValue(Uniform<float, float, float, float> uniform, float v0, float v1, float v2, float v3)
|
||||
{
|
||||
api->glUniform4f(uniform.id.DirectValue, v0, v1, v2, v3);
|
||||
api->glUniform4f(uniform.id.DirectValue , v0, v1, v2, v3);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -60,13 +60,10 @@ namespace StgSharp.Graphics
|
||||
/// </summary>
|
||||
/// <param name="form">The <see cref="Form"/> used as current OpenGL context</param>
|
||||
/// <param name="loader">A delegate to get address of OprnGL api</param>
|
||||
public static unsafe void LoadGLapi(this Form form, GLfuncLoader loader)
|
||||
public static unsafe void LoadGLapi(this Form form)
|
||||
{
|
||||
GLcontext* context = (GLcontext*)form.graphicContextID;
|
||||
if (loader == null)
|
||||
{
|
||||
loader = InternalIO.glfwGetProcAddress;
|
||||
}
|
||||
GLfuncLoader loader = InternalIO.glfwGetProcAddress;
|
||||
#pragma warning disable CS8909
|
||||
if (((GLcontext*)form.graphicContextID)->glGetString != (delegate*<uint, IntPtr>)IntPtr.Zero)
|
||||
#pragma warning restore CS8909
|
||||
|
||||
Reference in New Issue
Block a user