AstcPixel.cs 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. using System;
  2. using System.Diagnostics;
  3. namespace Ryujinx.Graphics.Texture
  4. {
  5. class AstcPixel
  6. {
  7. public short R { get; set; }
  8. public short G { get; set; }
  9. public short B { get; set; }
  10. public short A { get; set; }
  11. byte[] _bitDepth = new byte[4];
  12. public AstcPixel(short a, short r, short g, short b)
  13. {
  14. A = a;
  15. R = r;
  16. G = g;
  17. B = b;
  18. for (int i = 0; i < 4; i++)
  19. _bitDepth[i] = 8;
  20. }
  21. public void ClampByte()
  22. {
  23. R = Math.Min(Math.Max(R, (short)0), (short)255);
  24. G = Math.Min(Math.Max(G, (short)0), (short)255);
  25. B = Math.Min(Math.Max(B, (short)0), (short)255);
  26. A = Math.Min(Math.Max(A, (short)0), (short)255);
  27. }
  28. public short GetComponent(int index)
  29. {
  30. switch(index)
  31. {
  32. case 0: return A;
  33. case 1: return R;
  34. case 2: return G;
  35. case 3: return B;
  36. }
  37. return 0;
  38. }
  39. public void SetComponent(int index, int value)
  40. {
  41. switch (index)
  42. {
  43. case 0:
  44. A = (short)value;
  45. break;
  46. case 1:
  47. R = (short)value;
  48. break;
  49. case 2:
  50. G = (short)value;
  51. break;
  52. case 3:
  53. B = (short)value;
  54. break;
  55. }
  56. }
  57. public void ChangeBitDepth(byte[] depth)
  58. {
  59. for (int i = 0; i< 4; i++)
  60. {
  61. int value = ChangeBitDepth(GetComponent(i), _bitDepth[i], depth[i]);
  62. SetComponent(i, value);
  63. _bitDepth[i] = depth[i];
  64. }
  65. }
  66. short ChangeBitDepth(short value, byte oldDepth, byte newDepth)
  67. {
  68. Debug.Assert(newDepth <= 8);
  69. Debug.Assert(oldDepth <= 8);
  70. if (oldDepth == newDepth)
  71. {
  72. // Do nothing
  73. return value;
  74. }
  75. else if (oldDepth == 0 && newDepth != 0)
  76. {
  77. return (short)((1 << newDepth) - 1);
  78. }
  79. else if (newDepth > oldDepth)
  80. {
  81. return (short)BitArrayStream.Replicate(value, oldDepth, newDepth);
  82. }
  83. else
  84. {
  85. // oldDepth > newDepth
  86. if (newDepth == 0)
  87. {
  88. return 0xFF;
  89. }
  90. else
  91. {
  92. byte bitsWasted = (byte)(oldDepth - newDepth);
  93. short tempValue = value;
  94. tempValue = (short)((tempValue + (1 << (bitsWasted - 1))) >> bitsWasted);
  95. tempValue = Math.Min(Math.Max((short)0, tempValue), (short)((1 << newDepth) - 1));
  96. return (byte)(tempValue);
  97. }
  98. }
  99. }
  100. public int Pack()
  101. {
  102. AstcPixel newPixel = new AstcPixel(A, R, G, B);
  103. byte[] eightBitDepth = { 8, 8, 8, 8 };
  104. newPixel.ChangeBitDepth(eightBitDepth);
  105. return (byte)newPixel.A << 24 |
  106. (byte)newPixel.B << 16 |
  107. (byte)newPixel.G << 8 |
  108. (byte)newPixel.R << 0;
  109. }
  110. // Adds more precision to the blue channel as described
  111. // in C.2.14
  112. public static AstcPixel BlueContract(int a, int r, int g, int b)
  113. {
  114. return new AstcPixel((short)(a),
  115. (short)((r + b) >> 1),
  116. (short)((g + b) >> 1),
  117. (short)(b));
  118. }
  119. }
  120. }