diff options
Diffstat (limited to 'src/Ryujinx.Graphics.OpenGL/Image/TextureStorage.cs')
-rw-r--r-- | src/Ryujinx.Graphics.OpenGL/Image/TextureStorage.cs | 212 |
1 files changed, 212 insertions, 0 deletions
diff --git a/src/Ryujinx.Graphics.OpenGL/Image/TextureStorage.cs b/src/Ryujinx.Graphics.OpenGL/Image/TextureStorage.cs new file mode 100644 index 00000000..c058ac88 --- /dev/null +++ b/src/Ryujinx.Graphics.OpenGL/Image/TextureStorage.cs @@ -0,0 +1,212 @@ +using OpenTK.Graphics.OpenGL; +using Ryujinx.Common.Logging; +using Ryujinx.Graphics.GAL; + +namespace Ryujinx.Graphics.OpenGL.Image +{ + class TextureStorage : ITextureInfo + { + public ITextureInfo Storage => this; + public int Handle { get; private set; } + public float ScaleFactor { get; private set; } + + public TextureCreateInfo Info { get; } + + private readonly OpenGLRenderer _renderer; + + private int _viewsCount; + + internal ITexture DefaultView { get; private set; } + + public TextureStorage(OpenGLRenderer renderer, TextureCreateInfo info, float scaleFactor) + { + _renderer = renderer; + Info = info; + + Handle = GL.GenTexture(); + ScaleFactor = scaleFactor; + + CreateImmutableStorage(); + } + + private void CreateImmutableStorage() + { + TextureTarget target = Info.Target.Convert(); + + GL.ActiveTexture(TextureUnit.Texture0); + + GL.BindTexture(target, Handle); + + FormatInfo format = FormatTable.GetFormatInfo(Info.Format); + + SizedInternalFormat internalFormat; + + if (format.IsCompressed) + { + internalFormat = (SizedInternalFormat)format.PixelFormat; + } + else + { + internalFormat = (SizedInternalFormat)format.PixelInternalFormat; + } + + int levels = Info.GetLevelsClamped(); + + switch (Info.Target) + { + case Target.Texture1D: + GL.TexStorage1D( + TextureTarget1d.Texture1D, + levels, + internalFormat, + Info.Width); + break; + + case Target.Texture1DArray: + GL.TexStorage2D( + TextureTarget2d.Texture1DArray, + levels, + internalFormat, + Info.Width, + Info.Height); + break; + + case Target.Texture2D: + GL.TexStorage2D( + TextureTarget2d.Texture2D, + levels, + internalFormat, + Info.Width, + Info.Height); + break; + + case Target.Texture2DArray: + GL.TexStorage3D( + TextureTarget3d.Texture2DArray, + levels, + internalFormat, + Info.Width, + Info.Height, + Info.Depth); + break; + + case Target.Texture2DMultisample: + GL.TexStorage2DMultisample( + TextureTargetMultisample2d.Texture2DMultisample, + Info.Samples, + internalFormat, + Info.Width, + Info.Height, + true); + break; + + case Target.Texture2DMultisampleArray: + GL.TexStorage3DMultisample( + TextureTargetMultisample3d.Texture2DMultisampleArray, + Info.Samples, + internalFormat, + Info.Width, + Info.Height, + Info.Depth, + true); + break; + + case Target.Texture3D: + GL.TexStorage3D( + TextureTarget3d.Texture3D, + levels, + internalFormat, + Info.Width, + Info.Height, + Info.Depth); + break; + + case Target.Cubemap: + GL.TexStorage2D( + TextureTarget2d.TextureCubeMap, + levels, + internalFormat, + Info.Width, + Info.Height); + break; + + case Target.CubemapArray: + GL.TexStorage3D( + (TextureTarget3d)All.TextureCubeMapArray, + levels, + internalFormat, + Info.Width, + Info.Height, + Info.Depth); + break; + + default: + Logger.Debug?.Print(LogClass.Gpu, $"Invalid or unsupported texture target: {target}."); + break; + } + } + + public ITexture CreateDefaultView() + { + DefaultView = CreateView(Info, 0, 0); + + return DefaultView; + } + + public ITexture CreateView(TextureCreateInfo info, int firstLayer, int firstLevel) + { + IncrementViewsCount(); + + return new TextureView(_renderer, this, info, firstLayer, firstLevel); + } + + private void IncrementViewsCount() + { + _viewsCount++; + } + + public void DecrementViewsCount() + { + // If we don't have any views, then the storage is now useless, delete it. + if (--_viewsCount == 0) + { + if (DefaultView == null) + { + Dispose(); + } + else + { + // If the default view still exists, we can put it into the resource pool. + Release(); + } + } + } + + /// <summary> + /// Release the TextureStorage to the resource pool without disposing its handle. + /// </summary> + public void Release() + { + _viewsCount = 1; // When we are used again, we will have the default view. + + _renderer.ResourcePool.AddTexture((TextureView)DefaultView); + } + + public void DeleteDefault() + { + DefaultView = null; + } + + public void Dispose() + { + DefaultView = null; + + if (Handle != 0) + { + GL.DeleteTexture(Handle); + + Handle = 0; + } + } + } +} |