Dashboard/Quik.OpenTK/GL30Driver.cs
H. Utku Maden a50650e54a Create custom OpenGL bindings.
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.
2023-06-22 23:11:32 +03:00

148 lines
5.0 KiB
C#

using System;
using System.IO;
using System.Reflection;
using Quik.OpenGL;
using static Quik.OpenGL.GLEnum;
namespace Quik.OpenTK
{
public class GL30Driver : IDisposable
{
public GL30Driver()
{
Assembly asm = typeof(GL30Driver).Assembly;
using (StreamReader vert = new StreamReader(asm.GetManifestResourceStream("Quik.OpenTK.glsl.glsl130.vert")))
using (StreamReader frag = new StreamReader(asm.GetManifestResourceStream("Quik.OpenTK.glsl.glsl130.frag")))
{
int vs;
int fs;
vs = GL.CreateShader(GL_VERTEX_SHADER);
fs = GL.CreateShader(GL_FRAGMENT_SHADER);
_sp = GL.CreateProgram();
GL.ShaderSource(vs, vert.ReadToEnd());
GL.ShaderSource(fs, frag.ReadToEnd());
GL.CompileShader(vs);
GL.CompileShader(fs);
#if DEBUG
int status;
GL.GetShader(vs, GL_COMPILE_STATUS, out status);
if (status == 0)
{
throw new Exception(GL.GetShaderInfoLog(vs));
}
GL.GetShader(fs, GL_COMPILE_STATUS, out status);
if (status == 0)
{
throw new Exception(GL.GetShaderInfoLog(fs));
}
#endif
GL.AttachShader(_sp, vs);
GL.AttachShader(_sp, fs);
GL.LinkProgram(_sp);
#if DEBUG
GL.GetProgram(_sp, GL_LINK_STATUS, out status);
if (status == 0)
{
throw new Exception(GL.GetProgramInfoLog(_sp));
}
#endif
GL.DetachShader(_sp, vs);
GL.DetachShader(_sp, fs);
GL.DeleteShader(vs);
GL.DeleteShader(fs);
}
LoadUniform(_nameM4View, out _locM4View);
LoadUniform(_nameM4Model, out _locM4Model);
LoadUniform(_nameIFlags, out _locIFlags);
LoadUniform(_nameFSdfThreshold, out _locFSdfThreshold);
LoadUniform(_nameFSdfAuxilliaryThreshold, out _locFSdfAuxilliaryThreshold);
LoadUniform(_nameV4SdfAuxilliaryColor, out _locV4SdfAuxilliaryColor);
LoadUniform(_nameX2Texture, out _locX2Texture);
LoadUniform(_nameV2TextureOffset, out _locV2TextureOffset);
LoadAttribute(_nameV2Postion, out _locV2Position);
LoadAttribute(_nameV2Texture, out _locV2Texture);
LoadAttribute(_nameV4Color, out _locV4Color);
void LoadUniform(string name, out int location)
{
location = GL.GetUniformLocation(_sp, name);
}
void LoadAttribute(string name, out int location)
{
location = GL.GetAttribLocation(_sp, name);
}
}
private readonly int _sp;
private const string _nameM4View = "m4View";
private readonly int _locM4View;
private const string _nameM4Model = "m4Model";
private readonly int _locM4Model;
private const string _nameV2Postion = "v2Position";
private readonly int _locV2Position;
private const string _nameV2Texture = "v2Texture";
private readonly int _locV2Texture;
private const string _nameV4Color = "v4Color";
private readonly int _locV4Color;
private const string _nameIFlags = "iFlags";
private readonly int _locIFlags;
private const string _nameFSdfThreshold = "fSdfThreshold";
private readonly int _locFSdfThreshold;
private const string _nameFSdfAuxilliaryThreshold = "fSdfAuxilliaryThreshold";
private readonly int _locFSdfAuxilliaryThreshold;
private const string _nameV4SdfAuxilliaryColor = "v4SdfAuxilliaryColor";
private readonly int _locV4SdfAuxilliaryColor;
private const string _nameX2Texture = "x2Texture";
private readonly int _locX2Texture;
private const string _nameV2TextureOffset = "v2TextureOffset";
private readonly int _locV2TextureOffset;
[Flags]
private enum Flags : int
{
Texture = 1 << 0,
DiscardEnable = 1 << 1,
Sdf = 1 << 2,
SdfAuxEnable = 1 << 3,
}
private bool _isDisposed = false;
private void Dispose(bool disposing)
{
if (_isDisposed) return;
if (disposing)
{
GL.DeleteProgram(_sp);
}
else
{
throw new Exception("OpenGL resource is leaked. Dispose unreferenced OpenGL objects in the context thread.");
}
_isDisposed = true;
}
public void Dispose() => Dispose(true);
~GL30Driver()
{
Dispose(false);
}
}
}