using System; using OpenTK.Graphics.OpenGL4; namespace Quik.OpenTK { public class OpenGLTexture : IQuikTexture { public int TextureId { get; private set; } private OpenGLTextureManager Manager { get; } 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(TextureTarget.Texture2D, TextureId); GL.TexParameter( TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int) (mipmaps ? TextureMinFilter.LinearMipmapNearest : TextureMinFilter.Linear)); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear); GL.TexImage2D( TextureTarget.Texture2D, 0, (PixelInternalFormat)GetGlImageFormat(format), Width, Height, 0, PixelFormat.Rgba, PixelType.UnsignedByte, IntPtr.Zero); } ~OpenGLTexture() { Dispose(false); } /// public bool Equals(IQuikTexture other) => other is OpenGLTexture && ((OpenGLTexture)other).TextureId == TextureId; private bool _isDisposed = false; private void Dispose(bool disposing) { if (_isDisposed) return; Manager?.Reclaim(this); _isDisposed = true; } /// public void Dispose() => Dispose(true); /// public int Width { get; } /// public int Height { get; } /// public bool Mipmaps { get; } /// public void Image(IntPtr data, QuikImageFormat format, QuikVec2 size, int level) { GL.BindTexture(TextureTarget.Texture2D, TextureId); GL.TexSubImage2D(TextureTarget.Texture2D, level, 0, 0, Width, Height, GetGlImageFormat(format), GetGlDataFormat(format), data); } /// public void SubImage(IntPtr data, QuikImageFormat format, QuikRectangle location, int level) { GL.BindTexture(TextureTarget.Texture2D, TextureId); GL.TexSubImage2D( TextureTarget.Texture2D, level, (int)location.Left, (int)location.Bottom, (int)location.Size.X, (int)location.Size.Y, GetGlImageFormat(format), GetGlDataFormat(format), data); } /// public void GenerateMipMaps() { GL.BindTexture(TextureTarget.Texture2D, TextureId); GL.GenerateMipmap(GenerateMipmapTarget.Texture2D); } private static PixelFormat GetGlImageFormat(QuikImageFormat format) { switch (format) { case QuikImageFormat.RedF: case QuikImageFormat.RedU8: return PixelFormat.Red; case QuikImageFormat.RgbF: case QuikImageFormat.RgbU8: return PixelFormat.Rgb; case QuikImageFormat.RgbaF: case QuikImageFormat.RgbaU8: return PixelFormat.Rgba; default: throw new ArgumentOutOfRangeException(); } } private static PixelType GetGlDataFormat(QuikImageFormat format) { switch (format) { case QuikImageFormat.RedF: case QuikImageFormat.RgbaF: case QuikImageFormat.RgbF: return PixelType.Float; case QuikImageFormat.RedU8: case QuikImageFormat.RgbaU8: case QuikImageFormat.RgbU8: return PixelType.UnsignedByte; default: throw new ArgumentOutOfRangeException(); } } } }