Dashboard/Quik.OpenTK/OpenGLTexture.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

132 lines
4.3 KiB
C#

using System;
using Quik.OpenGL;
using static Quik.OpenGL.GLEnum;
namespace Quik.OpenTK
{
public class OpenGLTexture : QuikTexture
{
public int TextureId { get; private set; }
private OpenGLTextureManager Manager { get; }
private int _width;
private int _height;
private bool _mipmaps;
internal OpenGLTexture(OpenGLTextureManager manager, QuikImageFormat format, QuikVec2 size, bool mipmaps)
{
Manager = manager;
_mipmaps = mipmaps;
_width = (int)size.X;
_height = (int)size.Y;
TextureId = GL.GenTexture();
GL.BindTexture(GL_TEXTURE_2D, TextureId);
GL.TexParameter(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, (mipmaps ? GL_LINEAR_MIPMAP_NEAREST : GL_LINEAR));
GL.TexParameter(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
GL.TexImage2D(
GL_TEXTURE_2D,
0,
GetGlImageFormat(format),
Width, Height, 0,
GL_RGBA, GL_UNSIGNED_BYTE,
IntPtr.Zero);
}
~OpenGLTexture()
{
Dispose(false);
}
/// <inheritdoc />
public override bool Equals(QuikTexture other) =>
other is OpenGLTexture && ((OpenGLTexture)other).TextureId == TextureId;
private bool _isDisposed = false;
protected override void Dispose(bool disposing)
{
if (_isDisposed) return;
Manager?.Reclaim(this);
_isDisposed = true;
}
/// <inheritdoc />
public override int Width => _width;
/// <inheritdoc />
public override int Height => _height;
/// <inheritdoc />
public override bool Mipmaps => _mipmaps;
/// <inheritdoc />
public override void Image(IntPtr data, QuikImageFormat format, QuikVec2 size, int level, int alignment = 4)
{
GL.BindTexture(GL_TEXTURE_2D, TextureId);
GL.PixelStore(GL_UNPACK_ALIGNMENT, alignment);
GL.TexSubImage2D(GL_TEXTURE_2D, level, 0, 0, Width, Height, GetGlImageFormat(format), GetGlDataFormat(format), data);
}
/// <inheritdoc />
public override void SubImage(IntPtr data, QuikImageFormat format, QuikRectangle location, int level, int alignment = 4)
{
GL.BindTexture(GL_TEXTURE_2D, TextureId);
GL.PixelStore(GL_UNPACK_ALIGNMENT, alignment);
GL.TexSubImage2D(
GL_TEXTURE_2D,
level,
(int)location.Left,
(int)location.Bottom,
(int)location.Size.X,
(int)location.Size.Y,
GetGlImageFormat(format),
GetGlDataFormat(format),
data);
}
/// <inheritdoc />
public override void GenerateMipMaps()
{
GL.BindTexture(GL_TEXTURE_2D, TextureId);
GL.GenerateMipmap(GL_TEXTURE_2D);
}
private static GLEnum GetGlImageFormat(QuikImageFormat format)
{
switch (format)
{
case QuikImageFormat.RedF: case QuikImageFormat.RedU8:
return GL_RED;
case QuikImageFormat.RgbF: case QuikImageFormat.RgbU8:
return GL_RGB;
case QuikImageFormat.RgbaF: case QuikImageFormat.RgbaU8:
return GL_RGBA;
case QuikImageFormat.AlphaF: case QuikImageFormat.AlphaU8:
return GL_ALPHA;
default:
throw new ArgumentOutOfRangeException();
}
}
private static GLEnum GetGlDataFormat(QuikImageFormat format)
{
switch (format)
{
case QuikImageFormat.RedF:
case QuikImageFormat.RgbaF:
case QuikImageFormat.RgbF:
case QuikImageFormat.AlphaF:
return GL_FLOAT;
case QuikImageFormat.RedU8:
case QuikImageFormat.RgbaU8:
case QuikImageFormat.RgbU8:
case QuikImageFormat.AlphaU8:
return GL_UNSIGNED_BYTE;
default:
throw new ArgumentOutOfRangeException();
}
}
}
}