/ src / Ryujinx.Graphics.Texture / OffsetCalculator.cs
OffsetCalculator.cs
  1  using Ryujinx.Common;
  2  using System;
  3  using System.Runtime.CompilerServices;
  4  using static Ryujinx.Graphics.Texture.BlockLinearConstants;
  5  
  6  namespace Ryujinx.Graphics.Texture
  7  {
  8      public class OffsetCalculator
  9      {
 10          private readonly int _width;
 11          private readonly int _height;
 12          private readonly int _stride;
 13          private readonly bool _isLinear;
 14          private readonly int _bytesPerPixel;
 15  
 16          private readonly BlockLinearLayout _layoutConverter;
 17  
 18          // Variables for built in iteration.
 19          private int _yPart;
 20  
 21          public OffsetCalculator(
 22              int width,
 23              int height,
 24              int stride,
 25              bool isLinear,
 26              int gobBlocksInY,
 27              int gobBlocksInZ,
 28              int bytesPerPixel)
 29          {
 30              _width = width;
 31              _height = height;
 32              _stride = stride;
 33              _isLinear = isLinear;
 34              _bytesPerPixel = bytesPerPixel;
 35  
 36              int wAlignment = GobStride / bytesPerPixel;
 37  
 38              int wAligned = BitUtils.AlignUp(width, wAlignment);
 39  
 40              if (!isLinear)
 41              {
 42                  _layoutConverter = new BlockLinearLayout(
 43                      wAligned,
 44                      height,
 45                      gobBlocksInY,
 46                      gobBlocksInZ,
 47                      bytesPerPixel);
 48              }
 49          }
 50  
 51          public OffsetCalculator(
 52              int width,
 53              int height,
 54              int stride,
 55              bool isLinear,
 56              int gobBlocksInY,
 57              int bytesPerPixel) : this(width, height, stride, isLinear, gobBlocksInY, 1, bytesPerPixel)
 58          {
 59          }
 60  
 61          public void SetY(int y)
 62          {
 63              if (_isLinear)
 64              {
 65                  _yPart = y * _stride;
 66              }
 67              else
 68              {
 69                  _layoutConverter.SetY(y);
 70              }
 71          }
 72  
 73          public int GetOffset(int x, int y)
 74          {
 75              if (_isLinear)
 76              {
 77                  return x * _bytesPerPixel + y * _stride;
 78              }
 79              else
 80              {
 81                  return _layoutConverter.GetOffset(x, y, 0);
 82              }
 83          }
 84  
 85          [MethodImpl(MethodImplOptions.AggressiveInlining)]
 86          public int GetOffset(int x)
 87          {
 88              if (_isLinear)
 89              {
 90                  return x * _bytesPerPixel + _yPart;
 91              }
 92              else
 93              {
 94                  return _layoutConverter.GetOffset(x);
 95              }
 96          }
 97  
 98          [MethodImpl(MethodImplOptions.AggressiveInlining)]
 99          public int GetOffsetWithLineOffset64(int x)
100          {
101              if (_isLinear)
102              {
103                  return x + _yPart;
104              }
105              else
106              {
107                  return _layoutConverter.GetOffsetWithLineOffset64(x);
108              }
109          }
110  
111          public (int offset, int size) GetRectangleRange(int x, int y, int width, int height)
112          {
113              if (_isLinear)
114              {
115                  int start = y * Math.Abs(_stride) + x * _bytesPerPixel;
116                  int end = (y + height - 1) * Math.Abs(_stride) + (x + width) * _bytesPerPixel;
117                  return (y * _stride + x * _bytesPerPixel, end - start);
118              }
119              else
120              {
121                  return _layoutConverter.GetRectangleRange(x, y, width, height);
122              }
123          }
124  
125          public bool LayoutMatches(OffsetCalculator other)
126          {
127              if (_isLinear)
128              {
129                  return other._isLinear &&
130                         _width == other._width &&
131                         _height == other._height &&
132                         _stride == other._stride &&
133                         _bytesPerPixel == other._bytesPerPixel;
134              }
135              else
136              {
137                  return !other._isLinear && _layoutConverter.LayoutMatches(other._layoutConverter);
138              }
139          }
140      }
141  }