/ src / Ryujinx.Graphics.OpenGL / Image / TextureStorage.cs
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  }