SwizzleAddr.cs 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. using System;
  2. namespace Ryujinx.Graphics.Gal.Texture
  3. {
  4. class SwizzleAddr
  5. {
  6. private int Width;
  7. private int XB;
  8. private int YB;
  9. public SwizzleAddr(int Width, int Height, int Pad)
  10. {
  11. int W = Pow2RoundUp(Width);
  12. int H = Pow2RoundUp(Height);
  13. XB = CountZeros(W);
  14. YB = CountZeros(H);
  15. int HH = H >> 1;
  16. if (!IsPow2(Height) && Height <= HH + HH / 3 && YB > 3)
  17. {
  18. YB--;
  19. }
  20. this.Width = RoundSize(Width, Pad);
  21. }
  22. private static int Pow2RoundUp(int Value)
  23. {
  24. Value--;
  25. Value |= (Value >> 1);
  26. Value |= (Value >> 2);
  27. Value |= (Value >> 4);
  28. Value |= (Value >> 8);
  29. Value |= (Value >> 16);
  30. return ++Value;
  31. }
  32. private static bool IsPow2(int Value)
  33. {
  34. return Value != 0 && (Value & (Value - 1)) == 0;
  35. }
  36. private static int CountZeros(int Value)
  37. {
  38. int Count = 0;
  39. for (int i = 0; i < 32; i++)
  40. {
  41. if ((Value & (1 << i)) != 0)
  42. {
  43. break;
  44. }
  45. Count++;
  46. }
  47. return Count;
  48. }
  49. private static int RoundSize(int Size, int Pad)
  50. {
  51. int Mask = Pad - 1;
  52. if ((Size & Mask) != 0)
  53. {
  54. Size &= ~Mask;
  55. Size += Pad;
  56. }
  57. return Size;
  58. }
  59. public int GetSwizzledAddress8(int X, int Y)
  60. {
  61. return GetSwizzledAddress(X, Y, 4);
  62. }
  63. public int GetSwizzledAddress16(int X, int Y)
  64. {
  65. return GetSwizzledAddress(X, Y, 3);
  66. }
  67. public int GetSwizzledAddress32(int X, int Y)
  68. {
  69. return GetSwizzledAddress(X, Y, 2);
  70. }
  71. public int GetSwizzledAddress64(int X, int Y)
  72. {
  73. return GetSwizzledAddress(X, Y, 1);
  74. }
  75. public int GetSwizzledAddress128(int X, int Y)
  76. {
  77. return GetSwizzledAddress(X, Y, 0);
  78. }
  79. private int GetSwizzledAddress(int X, int Y, int XBase)
  80. {
  81. /*
  82. * Examples of patterns:
  83. * x x y x y y x y 0 0 0 0 64 x 64 dxt5
  84. * x x x x x y y y y x y y x y 0 0 0 0 512 x 512 dxt5
  85. * y x x x x x x y y y y x y y x y 0 0 0 0 1024 x 1024 dxt5
  86. * y y x x x x x x y y y y x y y x y x 0 0 0 2048 x 2048 dxt1
  87. * y y y x x x x x x y y y y x y y x y x x 0 0 1024 x 1024 rgba8888
  88. *
  89. * Read from right to left, LSB first.
  90. */
  91. int XCnt = XBase;
  92. int YCnt = 1;
  93. int XUsed = 0;
  94. int YUsed = 0;
  95. int Address = 0;
  96. while (XUsed < XBase + 2 && XUsed + XCnt < XB)
  97. {
  98. int XMask = (1 << XCnt) - 1;
  99. int YMask = (1 << YCnt) - 1;
  100. Address |= (X & XMask) << XUsed + YUsed;
  101. Address |= (Y & YMask) << XUsed + YUsed + XCnt;
  102. X >>= XCnt;
  103. Y >>= YCnt;
  104. XUsed += XCnt;
  105. YUsed += YCnt;
  106. XCnt = Math.Min(XB - XUsed, 1);
  107. YCnt = Math.Min(YB - YUsed, YCnt << 1);
  108. }
  109. Address |= (X + Y * (Width >> XUsed)) << (XUsed + YUsed);
  110. return Address;
  111. }
  112. }
  113. }