SizeInfo.cs
  1  using System;
  2  using System.Collections.Generic;
  3  
  4  namespace Ryujinx.Graphics.Texture
  5  {
  6      public readonly struct SizeInfo
  7      {
  8          private readonly int[] _mipOffsets;
  9  
 10          private readonly int _levels;
 11          private readonly int _depth;
 12          private readonly bool _is3D;
 13  
 14          public readonly int[] AllOffsets;
 15          public readonly int[] SliceSizes;
 16          public readonly int[] LevelSizes;
 17          public int LayerSize { get; }
 18          public int TotalSize { get; }
 19  
 20          public SizeInfo(int size)
 21          {
 22              _mipOffsets = new int[] { 0 };
 23              AllOffsets = new int[] { 0 };
 24              SliceSizes = new int[] { size };
 25              LevelSizes = new int[] { size };
 26              _depth = 1;
 27              _levels = 1;
 28              LayerSize = size;
 29              TotalSize = size;
 30              _is3D = false;
 31          }
 32  
 33          internal SizeInfo(
 34              int[] mipOffsets,
 35              int[] allOffsets,
 36              int[] sliceSizes,
 37              int[] levelSizes,
 38              int depth,
 39              int levels,
 40              int layerSize,
 41              int totalSize,
 42              bool is3D)
 43          {
 44              _mipOffsets = mipOffsets;
 45              AllOffsets = allOffsets;
 46              SliceSizes = sliceSizes;
 47              LevelSizes = levelSizes;
 48              _depth = depth;
 49              _levels = levels;
 50              LayerSize = layerSize;
 51              TotalSize = totalSize;
 52              _is3D = is3D;
 53          }
 54  
 55          public int GetMipOffset(int level)
 56          {
 57              if ((uint)level >= _mipOffsets.Length)
 58              {
 59                  throw new ArgumentOutOfRangeException(nameof(level));
 60              }
 61  
 62              return _mipOffsets[level];
 63          }
 64  
 65          public bool FindView(int offset, out int firstLayer, out int firstLevel)
 66          {
 67              int index = Array.BinarySearch(AllOffsets, offset);
 68  
 69              if (index < 0)
 70              {
 71                  firstLayer = 0;
 72                  firstLevel = 0;
 73  
 74                  return false;
 75              }
 76  
 77              if (_is3D)
 78              {
 79                  firstLayer = index;
 80                  firstLevel = 0;
 81  
 82                  int levelDepth = _depth;
 83  
 84                  while (firstLayer >= levelDepth)
 85                  {
 86                      firstLayer -= levelDepth;
 87                      firstLevel++;
 88                      levelDepth = Math.Max(levelDepth >> 1, 1);
 89                  }
 90              }
 91              else
 92              {
 93                  firstLayer = index / _levels;
 94                  firstLevel = index - (firstLayer * _levels);
 95              }
 96  
 97              return true;
 98          }
 99  
100          public IEnumerable<Region> AllRegions()
101          {
102              if (_is3D)
103              {
104                  for (int i = 0; i < _mipOffsets.Length; i++)
105                  {
106                      int maxSize = TotalSize - _mipOffsets[i];
107                      yield return new Region(_mipOffsets[i], Math.Min(maxSize, LevelSizes[i]));
108                  }
109              }
110              else
111              {
112                  for (int i = 0; i < AllOffsets.Length; i++)
113                  {
114                      yield return new Region(AllOffsets[i], SliceSizes[i % _levels]);
115                  }
116              }
117          }
118      }
119  }