TextureStorage.cs
1 using OpenTK.Graphics.OpenGL; 2 using Ryujinx.Common.Logging; 3 using Ryujinx.Graphics.GAL; 4 5 namespace Ryujinx.Graphics.OpenGL.Image 6 { 7 class TextureStorage : ITextureInfo 8 { 9 public ITextureInfo Storage => this; 10 public int Handle { get; private set; } 11 12 public TextureCreateInfo Info { get; } 13 14 private readonly OpenGLRenderer _renderer; 15 16 private int _viewsCount; 17 18 internal ITexture DefaultView { get; private set; } 19 20 public TextureStorage(OpenGLRenderer renderer, TextureCreateInfo info) 21 { 22 _renderer = renderer; 23 Info = info; 24 25 Handle = GL.GenTexture(); 26 27 CreateImmutableStorage(); 28 } 29 30 private void CreateImmutableStorage() 31 { 32 TextureTarget target = Info.Target.Convert(); 33 34 GL.ActiveTexture(TextureUnit.Texture0); 35 36 GL.BindTexture(target, Handle); 37 38 FormatInfo format = FormatTable.GetFormatInfo(Info.Format); 39 40 SizedInternalFormat internalFormat; 41 42 if (format.IsCompressed) 43 { 44 internalFormat = (SizedInternalFormat)format.PixelFormat; 45 } 46 else 47 { 48 internalFormat = (SizedInternalFormat)format.PixelInternalFormat; 49 } 50 51 int levels = Info.Levels; 52 53 switch (Info.Target) 54 { 55 case Target.Texture1D: 56 GL.TexStorage1D( 57 TextureTarget1d.Texture1D, 58 levels, 59 internalFormat, 60 Info.Width); 61 break; 62 63 case Target.Texture1DArray: 64 GL.TexStorage2D( 65 TextureTarget2d.Texture1DArray, 66 levels, 67 internalFormat, 68 Info.Width, 69 Info.Height); 70 break; 71 72 case Target.Texture2D: 73 GL.TexStorage2D( 74 TextureTarget2d.Texture2D, 75 levels, 76 internalFormat, 77 Info.Width, 78 Info.Height); 79 break; 80 81 case Target.Texture2DArray: 82 GL.TexStorage3D( 83 TextureTarget3d.Texture2DArray, 84 levels, 85 internalFormat, 86 Info.Width, 87 Info.Height, 88 Info.Depth); 89 break; 90 91 case Target.Texture2DMultisample: 92 GL.TexStorage2DMultisample( 93 TextureTargetMultisample2d.Texture2DMultisample, 94 Info.Samples, 95 internalFormat, 96 Info.Width, 97 Info.Height, 98 true); 99 break; 100 101 case Target.Texture2DMultisampleArray: 102 GL.TexStorage3DMultisample( 103 TextureTargetMultisample3d.Texture2DMultisampleArray, 104 Info.Samples, 105 internalFormat, 106 Info.Width, 107 Info.Height, 108 Info.Depth, 109 true); 110 break; 111 112 case Target.Texture3D: 113 GL.TexStorage3D( 114 TextureTarget3d.Texture3D, 115 levels, 116 internalFormat, 117 Info.Width, 118 Info.Height, 119 Info.Depth); 120 break; 121 122 case Target.Cubemap: 123 GL.TexStorage2D( 124 TextureTarget2d.TextureCubeMap, 125 levels, 126 internalFormat, 127 Info.Width, 128 Info.Height); 129 break; 130 131 case Target.CubemapArray: 132 GL.TexStorage3D( 133 (TextureTarget3d)All.TextureCubeMapArray, 134 levels, 135 internalFormat, 136 Info.Width, 137 Info.Height, 138 Info.Depth); 139 break; 140 141 default: 142 Logger.Debug?.Print(LogClass.Gpu, $"Invalid or unsupported texture target: {target}."); 143 break; 144 } 145 } 146 147 public ITexture CreateDefaultView() 148 { 149 DefaultView = CreateView(Info, 0, 0); 150 151 return DefaultView; 152 } 153 154 public ITexture CreateView(TextureCreateInfo info, int firstLayer, int firstLevel) 155 { 156 IncrementViewsCount(); 157 158 return new TextureView(_renderer, this, info, firstLayer, firstLevel); 159 } 160 161 private void IncrementViewsCount() 162 { 163 _viewsCount++; 164 } 165 166 public void DecrementViewsCount() 167 { 168 // If we don't have any views, then the storage is now useless, delete it. 169 if (--_viewsCount == 0) 170 { 171 if (DefaultView == null) 172 { 173 Dispose(); 174 } 175 else 176 { 177 // If the default view still exists, we can put it into the resource pool. 178 Release(); 179 } 180 } 181 } 182 183 /// <summary> 184 /// Release the TextureStorage to the resource pool without disposing its handle. 185 /// </summary> 186 public void Release() 187 { 188 _viewsCount = 1; // When we are used again, we will have the default view. 189 190 _renderer.ResourcePool.AddTexture((TextureView)DefaultView); 191 } 192 193 public void DeleteDefault() 194 { 195 DefaultView = null; 196 } 197 198 public void Dispose() 199 { 200 DefaultView = null; 201 202 if (Handle != 0) 203 { 204 GL.DeleteTexture(Handle); 205 206 Handle = 0; 207 } 208 } 209 } 210 }