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, QVec2 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); } /// 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; } /// public override int Width => _width; /// public override int Height => _height; /// public override bool Mipmaps => _mipmaps; /// public override void Image(IntPtr data, QuikImageFormat format, QVec2 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); } /// public override void SubImage(IntPtr data, QuikImageFormat format, QRectangle 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); } /// 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(); } } } }