//----------------------------------------------------------------------- //----------------------------------------------------------------------- // file="TextureGL.cs" // Project: StgSharp // AuthorGroup: Nitload Space // Copyright (c) Nitload Space. All rights reserved. // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation // files (the “Software”), to deal in the Software without restriction, // including without limitation the rights to use, copy, modify, merge, // publish, distribute, sublicense, and/or sell copies of the Software, // and to permit persons to whom the Software is furnished to do so, // subject to the following conditions: // // The above copyright notice and // this permission notice shall be included in all copies // or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED “AS IS”, // WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, // ARISING FROM, OUT OF OR IN CONNECTION WITH // THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // //----------------------------------------------------------------------- //----------------------------------------------------------------------- using StgSharp.HighPerformance; using System; using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; namespace StgSharp.Graphics.OpenGL { public sealed unsafe class TextureGL { private int currentEditingTextureIndex; private OpenGLFunction _gl; internal GlHandle[] _textureHandle; internal TextureGL( int count, glRender binding ) { //sourceList = new Image[count]; this._gl = binding.GL; _textureHandle = _gl.GenTextures( count ); } public GlHandle this[ int index ] { get => _textureHandle[ index ]; } public int Count { get => _textureHandle.Length; } //internal Image[] sourceList; public int IndexOfCurrentTexture { get => currentEditingTextureIndex; } internal OpenGLFunction GL => _gl; public void ActivateAs( TextureUnit unit ) { _gl.ActiveTextureUnit( ( uint )unit ); } public void Bind2D( int index ) { currentEditingTextureIndex = index; _gl.BindTexture( glConst.TEXTURE_2D, _textureHandle[ index ] ); } /// /// Load an to certain texture. /// /// /// /// /// /// /// public unsafe void LoadTexture( int index, Image i ) { byte[] handle = i.PixelBuffer; _gl.TextureImage2d( Texture2DTarget.Texture2D, 0, i.Channel, ( uint )i.Width, ( uint )i.Height, i.Channel, i.PixelLayout, pixels: handle ); _gl.GenerateMipmap( Texture2DTarget.Texture2D ); } #region texture setting [MethodImpl( MethodImplOptions.AggressiveInlining )] public void Set2dFilterProperty( int index, TextureFilter onMinify, TextureFilter onMagnify ) { #if DEBUG if( index != currentEditingTextureIndex ) { throw new InvalidOperationException( "Texture to be editted is not the one being activated." ); } #endif _gl.TextureParameter( glConst.TEXTURE_2D, glConst.TEXTURE_MIN_FILTER, ( int )onMinify ); _gl.TextureParameter( glConst.TEXTURE_2D, glConst.TEXTURE_MAG_FILTER, ( int )onMagnify ); } [MethodImpl( MethodImplOptions.AggressiveInlining )] public void Set2dWrapProperty( int index, TextureWrap onHorizontial, TextureWrap onVertical ) { #if DEBUG if( index != currentEditingTextureIndex ) { throw new InvalidOperationException( "Texture to be editted is not the one being activated." ); } #endif _gl.TextureParameter( glConst.TEXTURE_2D, glConst.TEXTURE_WRAP_S, ( int )onHorizontial ); _gl.TextureParameter( glConst.TEXTURE_2D, glConst.TEXTURE_WRAP_T, ( int )onVertical ); } [MethodImpl( MethodImplOptions.AggressiveInlining )] public void Set2dProperty( int index, TextureProperty property ) { Set2dFilterProperty( index, property.FilterOnMinify, property.FilterOnMagnify ); Set2dWrapProperty( index, property.WrapOnHorizontial, property.WrapOnVertical ); } #endregion texture setting } [StructLayout( LayoutKind.Explicit )] public struct TextureProperty { [FieldOffset( 0 )] private M128 mask; [FieldOffset( 0 )] private TextureFilter mag; [FieldOffset( 4 )] private TextureFilter min; [FieldOffset( 8 )] private TextureWrap hori; [FieldOffset( 12 )] private TextureWrap vert; public TextureProperty( TextureFilter onMagnify, TextureFilter onMinify, TextureWrap onHorizontial, TextureWrap onVertical ) { FilterOnMagnify = onMagnify; FilterOnMinify = onMinify; WrapOnHorizontial = onHorizontial; WrapOnVertical = onVertical; } public TextureFilter FilterOnMagnify { get => mag; set => mag = value; } public TextureFilter FilterOnMinify { get => min; set => min = value; } public TextureWrap WrapOnHorizontial { get => hori; set => hori = value; } public TextureWrap WrapOnVertical { get => vert; set => vert = value; } public override bool Equals( [NotNullWhen( true )] object obj ) { return base.Equals( obj ); } public override int GetHashCode() { return HashCode.Combine( FilterOnMagnify, FilterOnMagnify, WrapOnHorizontial, WrapOnVertical ); } public override string ToString() { return $"FilterOnMagnify:{FilterOnMagnify}, " + $"FilterOnMagnify:{FilterOnMagnify}, " + $"WrapOnHorizontial:{WrapOnHorizontial}, " + $"WrapOnVertical:{WrapOnVertical}"; } public static bool operator !=( TextureProperty left, TextureProperty right ) { return left.mask != right.mask; } public static bool operator ==( TextureProperty left, TextureProperty right ) { return left.mask == right.mask; } public static implicit operator TextureProperty( ( TextureFilter onMagnify, TextureFilter onMinify, TextureWrap onHorizontial, TextureWrap onVertical ) propertyValueTuple ) { return new TextureProperty( propertyValueTuple.onMagnify, propertyValueTuple.onMinify, propertyValueTuple.onHorizontial, propertyValueTuple.onVertical ); } } #pragma warning disable CA1008 public enum TextureFilter #pragma warning restore CA1008 { Nearest = glConst.NEAREST, Linear = glConst.LINEAR, NearestLinearMipmap = glConst.NEAREST_MIPMAP_LINEAR, LinearLinearMipmap = glConst.LINEAR_MIPMAP_LINEAR, NearestNearestMipmap = glConst.NEAREST_MIPMAP_NEAREST, LinearNearestMipmap = glConst.LINEAR_MIPMAP_NEAREST, } #pragma warning disable CA1008 public enum TextureUnit #pragma warning restore CA1008 { Unit0 = glConst.TEXTURE0, Unit1 = glConst.TEXTURE1, Unit2 = glConst.TEXTURE2, Unit3 = glConst.TEXTURE3, Unit4 = glConst.TEXTURE4, Unit5 = glConst.TEXTURE5, Unit6 = glConst.TEXTURE6, Unit7 = glConst.TEXTURE7, Unit8 = glConst.TEXTURE8, Unit9 = glConst.TEXTURE9, Unit10 = glConst.TEXTURE10, Unit11 = glConst.TEXTURE11, Unit12 = glConst.TEXTURE12, Unit13 = glConst.TEXTURE13, Unit14 = glConst.TEXTURE14, Unit15 = glConst.TEXTURE15, } #pragma warning disable CA1008 public enum TextureWrap #pragma warning restore CA1008 { Repeat = glConst.REPEAT, MirroredRepeat = glConst.MIRRORED_REPEAT, ClampToEdge = glConst.CLAMP_TO_EDGE, ClampToBorder = glConst.CLAMP_TO_BORDER, } }