OffsetCalculator.cs 3.7 KB

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