H. Utku Maden
a50650e54a
This removes the hard dependency on OpenTK for a core component of QUIK. Although not all environments are going to be using OpenGL, having it be independent from a vendor library would be more benefitial for more people.
110 lines
3.9 KiB
C#
110 lines
3.9 KiB
C#
using System;
|
|
using System.Runtime.CompilerServices;
|
|
using System.Runtime.InteropServices;
|
|
using System.Text;
|
|
using static Quik.OpenGL.GLEnum;
|
|
|
|
namespace Quik.OpenGL
|
|
{
|
|
public unsafe static partial class GL
|
|
{
|
|
private delegate int CreateShaderProc(GLEnum type);
|
|
private delegate void ShaderSourceProc(int shader, int count, byte** strings, int* length);
|
|
private delegate void CompileShaderProc(int shader);
|
|
private delegate void GetShaderProc(int shader, GLEnum pname, int* value);
|
|
private delegate void GetShaderInfoLogProc(int shader, int maxLength, int* length, byte* infoLog);
|
|
private delegate void DeleteShaderProc(int id);
|
|
|
|
private static CreateShaderProc _createShader;
|
|
private static ShaderSourceProc _shaderSource;
|
|
private static CompileShaderProc _compileShader;
|
|
private static GetShaderProc _getShader;
|
|
private static GetShaderInfoLogProc _getShaderInfoLog;
|
|
private static DeleteShaderProc _deleteShader;
|
|
|
|
private static void LoadShader()
|
|
{
|
|
_createShader = GetProcAddress<CreateShaderProc>("glCreateShader");
|
|
_shaderSource = GetProcAddress<ShaderSourceProc>("glShaderSource");
|
|
_compileShader = GetProcAddress<CompileShaderProc>("glCompileShader");
|
|
_getShader = GetProcAddress<GetShaderProc>("glGetShaderiv");
|
|
_getShaderInfoLog = GetProcAddress<GetShaderInfoLogProc>("glGetShaderInfoLog");
|
|
_deleteShader = GetProcAddress<DeleteShaderProc>("glDeleteShader");
|
|
}
|
|
|
|
[MethodImpl(AggressiveInlining)]
|
|
public static int CreateShader(GLEnum type) => _createShader(type);
|
|
|
|
[MethodImpl(AggressiveInlining)]
|
|
public static void ShaderSource(int shader, string source)
|
|
{
|
|
byte[] sourceUTF8 = Encoding.UTF8.GetBytes(source);
|
|
int length = sourceUTF8.Length;
|
|
|
|
fixed (byte* ptr = &sourceUTF8[0])
|
|
{
|
|
_shaderSource(shader, 1, &ptr, &length);
|
|
}
|
|
}
|
|
|
|
[MethodImpl(AggressiveInlining)]
|
|
public static void ShaderSource(int shader, string[] sources)
|
|
{
|
|
int count = sources.Length;
|
|
byte*[] pointers = new byte*[count];
|
|
int[] lengths = new int[count];
|
|
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
byte[] decoded = Encoding.UTF8.GetBytes(sources[i]);
|
|
int length = lengths[i] = decoded.Length;
|
|
IntPtr memory = Marshal.AllocHGlobal(decoded.Length);
|
|
|
|
Marshal.Copy(decoded, 0, memory, length);
|
|
pointers[i] = (byte*)memory;
|
|
}
|
|
|
|
try
|
|
{
|
|
fixed (byte** ptr = &pointers[0])
|
|
fixed (int * len = &lengths[0])
|
|
{
|
|
_shaderSource(shader, count, ptr, len);
|
|
}
|
|
}
|
|
finally
|
|
{
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
Marshal.FreeHGlobal((IntPtr)pointers[i]);
|
|
}
|
|
}
|
|
}
|
|
|
|
[MethodImpl(AggressiveInlining)]
|
|
public static void CompileShader(int shader) => _compileShader(shader);
|
|
|
|
[MethodImpl(AggressiveInlining)]
|
|
public static void GetShader(int shader, GLEnum pname, out int value)
|
|
{
|
|
value = default;
|
|
fixed (int *ptr = &value)
|
|
_getShader(shader, pname, ptr);
|
|
}
|
|
|
|
[MethodImpl(AggressiveInlining)]
|
|
public static string GetShaderInfoLog(int shader)
|
|
{
|
|
GetShader(shader, GL_INFO_LOG_LENGTH, out int length);
|
|
byte[] infoLog = new byte[length];
|
|
|
|
fixed (byte *ptr = infoLog)
|
|
_getShaderInfoLog(shader, length, &length, ptr);
|
|
|
|
return Encoding.UTF8.GetString(infoLog);
|
|
}
|
|
|
|
[MethodImpl(AggressiveInlining)]
|
|
public static void DeleteShader(int shader) => _deleteShader(shader);
|
|
}
|
|
} |