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 }