aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Graphics/Texture/ASTCPixel.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Ryujinx.Graphics/Texture/ASTCPixel.cs')
-rw-r--r--Ryujinx.Graphics/Texture/ASTCPixel.cs138
1 files changed, 138 insertions, 0 deletions
diff --git a/Ryujinx.Graphics/Texture/ASTCPixel.cs b/Ryujinx.Graphics/Texture/ASTCPixel.cs
new file mode 100644
index 00000000..c43eaf93
--- /dev/null
+++ b/Ryujinx.Graphics/Texture/ASTCPixel.cs
@@ -0,0 +1,138 @@
+using System;
+using System.Diagnostics;
+
+namespace Ryujinx.Graphics.Texture
+{
+ class ASTCPixel
+ {
+ public short R { get; set; }
+ public short G { get; set; }
+ public short B { get; set; }
+ public short A { get; set; }
+
+ byte[] BitDepth = new byte[4];
+
+ public ASTCPixel(short _A, short _R, short _G, short _B)
+ {
+ A = _A;
+ R = _R;
+ G = _G;
+ B = _B;
+
+ for (int i = 0; i < 4; i++)
+ BitDepth[i] = 8;
+ }
+
+ public void ClampByte()
+ {
+ R = Math.Min(Math.Max(R, (short)0), (short)255);
+ G = Math.Min(Math.Max(G, (short)0), (short)255);
+ B = Math.Min(Math.Max(B, (short)0), (short)255);
+ A = Math.Min(Math.Max(A, (short)0), (short)255);
+ }
+
+ public short GetComponent(int Index)
+ {
+ switch(Index)
+ {
+ case 0: return A;
+ case 1: return R;
+ case 2: return G;
+ case 3: return B;
+ }
+
+ return 0;
+ }
+
+ public void SetComponent(int Index, int Value)
+ {
+ switch (Index)
+ {
+ case 0:
+ A = (short)Value;
+ break;
+ case 1:
+ R = (short)Value;
+ break;
+ case 2:
+ G = (short)Value;
+ break;
+ case 3:
+ B = (short)Value;
+ break;
+ }
+ }
+
+ public void ChangeBitDepth(byte[] Depth)
+ {
+ for(int i = 0; i< 4; i++)
+ {
+ int Value = ChangeBitDepth(GetComponent(i), BitDepth[i], Depth[i]);
+
+ SetComponent(i, Value);
+ BitDepth[i] = Depth[i];
+ }
+ }
+
+ short ChangeBitDepth(short Value, byte OldDepth, byte NewDepth)
+ {
+ Debug.Assert(NewDepth <= 8);
+ Debug.Assert(OldDepth <= 8);
+
+ if (OldDepth == NewDepth)
+ {
+ // Do nothing
+ return Value;
+ }
+ else if (OldDepth == 0 && NewDepth != 0)
+ {
+ return (short)((1 << NewDepth) - 1);
+ }
+ else if (NewDepth > OldDepth)
+ {
+ return (short)BitArrayStream.Replicate(Value, OldDepth, NewDepth);
+ }
+ else
+ {
+ // oldDepth > newDepth
+ if (NewDepth == 0)
+ {
+ return 0xFF;
+ }
+ else
+ {
+ byte BitsWasted = (byte)(OldDepth - NewDepth);
+ short TempValue = Value;
+
+ TempValue = (short)((TempValue + (1 << (BitsWasted - 1))) >> BitsWasted);
+ TempValue = Math.Min(Math.Max((short)0, TempValue), (short)((1 << NewDepth) - 1));
+
+ return (byte)(TempValue);
+ }
+ }
+ }
+
+ public int Pack()
+ {
+ ASTCPixel NewPixel = new ASTCPixel(A, R, G, B);
+ byte[] eightBitDepth = { 8, 8, 8, 8 };
+
+ NewPixel.ChangeBitDepth(eightBitDepth);
+
+ return (byte)NewPixel.A << 24 |
+ (byte)NewPixel.B << 16 |
+ (byte)NewPixel.G << 8 |
+ (byte)NewPixel.R << 0;
+ }
+
+ // Adds more precision to the blue channel as described
+ // in C.2.14
+ public static ASTCPixel BlueContract(int a, int r, int g, int b)
+ {
+ return new ASTCPixel((short)(a),
+ (short)((r + b) >> 1),
+ (short)((g + b) >> 1),
+ (short)(b));
+ }
+ }
+}