aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Graphics/Texture/IntegerEncoded.cs
diff options
context:
space:
mode:
authorReinUsesLisp <reinuseslisp@airmail.cc>2018-09-08 14:51:50 -0300
committergdkchan <gab.dark.100@gmail.com>2018-09-08 14:51:50 -0300
commitce1d5be212e6f71a7ca32c3bd7b48e32d9f51b9a (patch)
tree759fe422127ce08c545d4616ccc9691f668032ec /Ryujinx.Graphics/Texture/IntegerEncoded.cs
parenta0c78f792012cdea060444d7cb6a36dbabb04d52 (diff)
Move GPU emulation from Ryujinx.HLE to Ryujinx.Graphics and misc changes (#402)
* Move GPU LLE emulation from HLE to Graphics * Graphics: Move Gal/Texture to Texture * Remove Engines/ directory and namespace * Use tables for image formats * Abstract OpCode decoding * Simplify image table * Do not leak Read* symbols in TextureReader * Fixups * Rename IGalFrameBuffer -> IGalRenderTarget * Remove MaxBpp hardcoded value * Change yet again texture data and add G8R8 flipping * Rename GalFrameBufferFormat to GalSurfaceFormat * Unident EnsureSetup in ImageHandler * Add IsCompressed * Address some feedback
Diffstat (limited to 'Ryujinx.Graphics/Texture/IntegerEncoded.cs')
-rw-r--r--Ryujinx.Graphics/Texture/IntegerEncoded.cs269
1 files changed, 269 insertions, 0 deletions
diff --git a/Ryujinx.Graphics/Texture/IntegerEncoded.cs b/Ryujinx.Graphics/Texture/IntegerEncoded.cs
new file mode 100644
index 00000000..683cb770
--- /dev/null
+++ b/Ryujinx.Graphics/Texture/IntegerEncoded.cs
@@ -0,0 +1,269 @@
+using System.Collections;
+using System.Collections.Generic;
+
+namespace Ryujinx.Graphics.Texture
+{
+ public struct IntegerEncoded
+ {
+ public enum EIntegerEncoding
+ {
+ JustBits,
+ Quint,
+ Trit
+ }
+
+ EIntegerEncoding Encoding;
+ public int NumberBits { get; private set; }
+ public int BitValue { get; private set; }
+ public int TritValue { get; private set; }
+ public int QuintValue { get; private set; }
+
+ public IntegerEncoded(EIntegerEncoding _Encoding, int NumBits)
+ {
+ Encoding = _Encoding;
+ NumberBits = NumBits;
+ BitValue = 0;
+ TritValue = 0;
+ QuintValue = 0;
+ }
+
+ public bool MatchesEncoding(IntegerEncoded Other)
+ {
+ return Encoding == Other.Encoding && NumberBits == Other.NumberBits;
+ }
+
+ public EIntegerEncoding GetEncoding()
+ {
+ return Encoding;
+ }
+
+ public int GetBitLength(int NumberVals)
+ {
+ int TotalBits = NumberBits * NumberVals;
+ if (Encoding == EIntegerEncoding.Trit)
+ {
+ TotalBits += (NumberVals * 8 + 4) / 5;
+ }
+ else if (Encoding == EIntegerEncoding.Quint)
+ {
+ TotalBits += (NumberVals * 7 + 2) / 3;
+ }
+ return TotalBits;
+ }
+
+ public static IntegerEncoded CreateEncoding(int MaxVal)
+ {
+ while (MaxVal > 0)
+ {
+ int Check = MaxVal + 1;
+
+ // Is maxVal a power of two?
+ if ((Check & (Check - 1)) == 0)
+ {
+ return new IntegerEncoded(EIntegerEncoding.JustBits, BitArrayStream.PopCnt(MaxVal));
+ }
+
+ // Is maxVal of the type 3*2^n - 1?
+ if ((Check % 3 == 0) && ((Check / 3) & ((Check / 3) - 1)) == 0)
+ {
+ return new IntegerEncoded(EIntegerEncoding.Trit, BitArrayStream.PopCnt(Check / 3 - 1));
+ }
+
+ // Is maxVal of the type 5*2^n - 1?
+ if ((Check % 5 == 0) && ((Check / 5) & ((Check / 5) - 1)) == 0)
+ {
+ return new IntegerEncoded(EIntegerEncoding.Quint, BitArrayStream.PopCnt(Check / 5 - 1));
+ }
+
+ // Apparently it can't be represented with a bounded integer sequence...
+ // just iterate.
+ MaxVal--;
+ }
+
+ return new IntegerEncoded(EIntegerEncoding.JustBits, 0);
+ }
+
+ public static void DecodeTritBlock(
+ BitArrayStream BitStream,
+ List<IntegerEncoded> ListIntegerEncoded,
+ int NumberBitsPerValue)
+ {
+ // Implement the algorithm in section C.2.12
+ int[] m = new int[5];
+ int[] t = new int[5];
+ int T;
+
+ // Read the trit encoded block according to
+ // table C.2.14
+ m[0] = BitStream.ReadBits(NumberBitsPerValue);
+ T = BitStream.ReadBits(2);
+ m[1] = BitStream.ReadBits(NumberBitsPerValue);
+ T |= BitStream.ReadBits(2) << 2;
+ m[2] = BitStream.ReadBits(NumberBitsPerValue);
+ T |= BitStream.ReadBits(1) << 4;
+ m[3] = BitStream.ReadBits(NumberBitsPerValue);
+ T |= BitStream.ReadBits(2) << 5;
+ m[4] = BitStream.ReadBits(NumberBitsPerValue);
+ T |= BitStream.ReadBits(1) << 7;
+
+ int C = 0;
+
+ BitArrayStream Tb = new BitArrayStream(new BitArray(new int[] { T }));
+ if (Tb.ReadBits(2, 4) == 7)
+ {
+ C = (Tb.ReadBits(5, 7) << 2) | Tb.ReadBits(0, 1);
+ t[4] = t[3] = 2;
+ }
+ else
+ {
+ C = Tb.ReadBits(0, 4);
+ if (Tb.ReadBits(5, 6) == 3)
+ {
+ t[4] = 2;
+ t[3] = Tb.ReadBit(7);
+ }
+ else
+ {
+ t[4] = Tb.ReadBit(7);
+ t[3] = Tb.ReadBits(5, 6);
+ }
+ }
+
+ BitArrayStream Cb = new BitArrayStream(new BitArray(new int[] { C }));
+ if (Cb.ReadBits(0, 1) == 3)
+ {
+ t[2] = 2;
+ t[1] = Cb.ReadBit(4);
+ t[0] = (Cb.ReadBit(3) << 1) | (Cb.ReadBit(2) & ~Cb.ReadBit(3));
+ }
+ else if (Cb.ReadBits(2, 3) == 3)
+ {
+ t[2] = 2;
+ t[1] = 2;
+ t[0] = Cb.ReadBits(0, 1);
+ }
+ else
+ {
+ t[2] = Cb.ReadBit(4);
+ t[1] = Cb.ReadBits(2, 3);
+ t[0] = (Cb.ReadBit(1) << 1) | (Cb.ReadBit(0) & ~Cb.ReadBit(1));
+ }
+
+ for (int i = 0; i < 5; i++)
+ {
+ IntegerEncoded IntEncoded = new IntegerEncoded(EIntegerEncoding.Trit, NumberBitsPerValue)
+ {
+ BitValue = m[i],
+ TritValue = t[i]
+ };
+ ListIntegerEncoded.Add(IntEncoded);
+ }
+ }
+
+ public static void DecodeQuintBlock(
+ BitArrayStream BitStream,
+ List<IntegerEncoded> ListIntegerEncoded,
+ int NumberBitsPerValue)
+ {
+ // Implement the algorithm in section C.2.12
+ int[] m = new int[3];
+ int[] q = new int[3];
+ int Q;
+
+ // Read the trit encoded block according to
+ // table C.2.15
+ m[0] = BitStream.ReadBits(NumberBitsPerValue);
+ Q = BitStream.ReadBits(3);
+ m[1] = BitStream.ReadBits(NumberBitsPerValue);
+ Q |= BitStream.ReadBits(2) << 3;
+ m[2] = BitStream.ReadBits(NumberBitsPerValue);
+ Q |= BitStream.ReadBits(2) << 5;
+
+ BitArrayStream Qb = new BitArrayStream(new BitArray(new int[] { Q }));
+ if (Qb.ReadBits(1, 2) == 3 && Qb.ReadBits(5, 6) == 0)
+ {
+ q[0] = q[1] = 4;
+ q[2] = (Qb.ReadBit(0) << 2) | ((Qb.ReadBit(4) & ~Qb.ReadBit(0)) << 1) | (Qb.ReadBit(3) & ~Qb.ReadBit(0));
+ }
+ else
+ {
+ int C = 0;
+ if (Qb.ReadBits(1, 2) == 3)
+ {
+ q[2] = 4;
+ C = (Qb.ReadBits(3, 4) << 3) | ((~Qb.ReadBits(5, 6) & 3) << 1) | Qb.ReadBit(0);
+ }
+ else
+ {
+ q[2] = Qb.ReadBits(5, 6);
+ C = Qb.ReadBits(0, 4);
+ }
+
+ BitArrayStream Cb = new BitArrayStream(new BitArray(new int[] { C }));
+ if (Cb.ReadBits(0, 2) == 5)
+ {
+ q[1] = 4;
+ q[0] = Cb.ReadBits(3, 4);
+ }
+ else
+ {
+ q[1] = Cb.ReadBits(3, 4);
+ q[0] = Cb.ReadBits(0, 2);
+ }
+ }
+
+ for (int i = 0; i < 3; i++)
+ {
+ IntegerEncoded IntEncoded = new IntegerEncoded(EIntegerEncoding.Quint, NumberBitsPerValue)
+ {
+ BitValue = m[i],
+ QuintValue = q[i]
+ };
+ ListIntegerEncoded.Add(IntEncoded);
+ }
+ }
+
+ public static void DecodeIntegerSequence(
+ List<IntegerEncoded> DecodeIntegerSequence,
+ BitArrayStream BitStream,
+ int MaxRange,
+ int NumberValues)
+ {
+ // Determine encoding parameters
+ IntegerEncoded IntEncoded = CreateEncoding(MaxRange);
+
+ // Start decoding
+ int NumberValuesDecoded = 0;
+ while (NumberValuesDecoded < NumberValues)
+ {
+ switch (IntEncoded.GetEncoding())
+ {
+ case EIntegerEncoding.Quint:
+ {
+ DecodeQuintBlock(BitStream, DecodeIntegerSequence, IntEncoded.NumberBits);
+ NumberValuesDecoded += 3;
+
+ break;
+ }
+
+ case EIntegerEncoding.Trit:
+ {
+ DecodeTritBlock(BitStream, DecodeIntegerSequence, IntEncoded.NumberBits);
+ NumberValuesDecoded += 5;
+
+ break;
+ }
+
+ case EIntegerEncoding.JustBits:
+ {
+ IntEncoded.BitValue = BitStream.ReadBits(IntEncoded.NumberBits);
+ DecodeIntegerSequence.Add(IntEncoded);
+ NumberValuesDecoded++;
+
+ break;
+ }
+ }
+ }
+ }
+ }
+}