| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345 |
- using System;
- using System.Numerics;
- namespace Ryujinx.Graphics.Texture.Astc
- {
- internal struct IntegerEncoded
- {
- internal const int StructSize = 8;
- private static readonly IntegerEncoded[] Encodings;
- public enum EIntegerEncoding : byte
- {
- JustBits,
- Quint,
- Trit
- }
- EIntegerEncoding _encoding;
- public byte NumberBits { get; private set; }
- public byte TritValue { get; private set; }
- public byte QuintValue { get; private set; }
- public int BitValue { get; private set; }
- static IntegerEncoded()
- {
- Encodings = new IntegerEncoded[0x100];
- for (int i = 0; i < Encodings.Length; i++)
- {
- Encodings[i] = CreateEncodingCalc(i);
- }
- }
- public IntegerEncoded(EIntegerEncoding encoding, int numBits)
- {
- _encoding = encoding;
- NumberBits = (byte)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)
- {
- return Encodings[maxVal];
- }
- private static IntegerEncoded CreateEncodingCalc(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, BitOperations.PopCount((uint)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, BitOperations.PopCount((uint)(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, BitOperations.PopCount((uint)(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(
- ref BitStream128 bitStream,
- ref IntegerSequence listIntegerEncoded,
- int numberBitsPerValue)
- {
- // Implement the algorithm in section C.2.12
- Span<int> m = stackalloc int[5];
- m[0] = bitStream.ReadBits(numberBitsPerValue);
- int encoded = bitStream.ReadBits(2);
- m[1] = bitStream.ReadBits(numberBitsPerValue);
- encoded |= bitStream.ReadBits(2) << 2;
- m[2] = bitStream.ReadBits(numberBitsPerValue);
- encoded |= bitStream.ReadBits(1) << 4;
- m[3] = bitStream.ReadBits(numberBitsPerValue);
- encoded |= bitStream.ReadBits(2) << 5;
- m[4] = bitStream.ReadBits(numberBitsPerValue);
- encoded |= bitStream.ReadBits(1) << 7;
- ReadOnlySpan<byte> encodings = GetTritEncoding(encoded);
- IntegerEncoded intEncoded = new IntegerEncoded(EIntegerEncoding.Trit, numberBitsPerValue);
- for (int i = 0; i < 5; i++)
- {
- intEncoded.BitValue = m[i];
- intEncoded.TritValue = encodings[i];
- listIntegerEncoded.Add(ref intEncoded);
- }
- }
- public static void DecodeQuintBlock(
- ref BitStream128 bitStream,
- ref IntegerSequence listIntegerEncoded,
- int numberBitsPerValue)
- {
- ReadOnlySpan<byte> interleavedBits = new byte[] { 3, 2, 2 };
- // Implement the algorithm in section C.2.12
- Span<int> m = stackalloc int[3];
- ulong encoded = 0;
- int encodedBitsRead = 0;
- for (int i = 0; i < m.Length; i++)
- {
- m[i] = bitStream.ReadBits(numberBitsPerValue);
- uint encodedBits = (uint)bitStream.ReadBits(interleavedBits[i]);
- encoded |= encodedBits << encodedBitsRead;
- encodedBitsRead += interleavedBits[i];
- }
- ReadOnlySpan<byte> encodings = GetQuintEncoding((int)encoded);
- for (int i = 0; i < 3; i++)
- {
- IntegerEncoded intEncoded = new IntegerEncoded(EIntegerEncoding.Quint, numberBitsPerValue)
- {
- BitValue = m[i],
- QuintValue = encodings[i]
- };
- listIntegerEncoded.Add(ref intEncoded);
- }
- }
- public static void DecodeIntegerSequence(
- ref IntegerSequence decodeIntegerSequence,
- ref BitStream128 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(ref bitStream, ref decodeIntegerSequence, intEncoded.NumberBits);
- numberValuesDecoded += 3;
- break;
- }
- case EIntegerEncoding.Trit:
- {
- DecodeTritBlock(ref bitStream, ref decodeIntegerSequence, intEncoded.NumberBits);
- numberValuesDecoded += 5;
- break;
- }
- case EIntegerEncoding.JustBits:
- {
- intEncoded.BitValue = bitStream.ReadBits(intEncoded.NumberBits);
- decodeIntegerSequence.Add(ref intEncoded);
- numberValuesDecoded++;
- break;
- }
- }
- }
- }
- private static ReadOnlySpan<byte> GetTritEncoding(int index)
- {
- return TritEncodings.Slice(index * 5, 5);
- }
- private static ReadOnlySpan<byte> GetQuintEncoding(int index)
- {
- return QuintEncodings.Slice(index * 3, 3);
- }
- private static ReadOnlySpan<byte> TritEncodings => new byte[]
- {
- 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 2, 0, 0, 0, 0,
- 0, 0, 2, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0,
- 2, 1, 0, 0, 0, 1, 0, 2, 0, 0, 0, 2, 0, 0, 0,
- 1, 2, 0, 0, 0, 2, 2, 0, 0, 0, 2, 0, 2, 0, 0,
- 0, 2, 2, 0, 0, 1, 2, 2, 0, 0, 2, 2, 2, 0, 0,
- 2, 0, 2, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0,
- 2, 0, 1, 0, 0, 0, 1, 2, 0, 0, 0, 1, 1, 0, 0,
- 1, 1, 1, 0, 0, 2, 1, 1, 0, 0, 1, 1, 2, 0, 0,
- 0, 2, 1, 0, 0, 1, 2, 1, 0, 0, 2, 2, 1, 0, 0,
- 2, 1, 2, 0, 0, 0, 0, 0, 2, 2, 1, 0, 0, 2, 2,
- 2, 0, 0, 2, 2, 0, 0, 2, 2, 2, 0, 0, 0, 1, 0,
- 1, 0, 0, 1, 0, 2, 0, 0, 1, 0, 0, 0, 2, 1, 0,
- 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 2, 1, 0, 1, 0,
- 1, 0, 2, 1, 0, 0, 2, 0, 1, 0, 1, 2, 0, 1, 0,
- 2, 2, 0, 1, 0, 2, 0, 2, 1, 0, 0, 2, 2, 1, 0,
- 1, 2, 2, 1, 0, 2, 2, 2, 1, 0, 2, 0, 2, 1, 0,
- 0, 0, 1, 1, 0, 1, 0, 1, 1, 0, 2, 0, 1, 1, 0,
- 0, 1, 2, 1, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0,
- 2, 1, 1, 1, 0, 1, 1, 2, 1, 0, 0, 2, 1, 1, 0,
- 1, 2, 1, 1, 0, 2, 2, 1, 1, 0, 2, 1, 2, 1, 0,
- 0, 1, 0, 2, 2, 1, 1, 0, 2, 2, 2, 1, 0, 2, 2,
- 1, 0, 2, 2, 2, 0, 0, 0, 2, 0, 1, 0, 0, 2, 0,
- 2, 0, 0, 2, 0, 0, 0, 2, 2, 0, 0, 1, 0, 2, 0,
- 1, 1, 0, 2, 0, 2, 1, 0, 2, 0, 1, 0, 2, 2, 0,
- 0, 2, 0, 2, 0, 1, 2, 0, 2, 0, 2, 2, 0, 2, 0,
- 2, 0, 2, 2, 0, 0, 2, 2, 2, 0, 1, 2, 2, 2, 0,
- 2, 2, 2, 2, 0, 2, 0, 2, 2, 0, 0, 0, 1, 2, 0,
- 1, 0, 1, 2, 0, 2, 0, 1, 2, 0, 0, 1, 2, 2, 0,
- 0, 1, 1, 2, 0, 1, 1, 1, 2, 0, 2, 1, 1, 2, 0,
- 1, 1, 2, 2, 0, 0, 2, 1, 2, 0, 1, 2, 1, 2, 0,
- 2, 2, 1, 2, 0, 2, 1, 2, 2, 0, 0, 2, 0, 2, 2,
- 1, 2, 0, 2, 2, 2, 2, 0, 2, 2, 2, 0, 2, 2, 2,
- 0, 0, 0, 0, 2, 1, 0, 0, 0, 2, 2, 0, 0, 0, 2,
- 0, 0, 2, 0, 2, 0, 1, 0, 0, 2, 1, 1, 0, 0, 2,
- 2, 1, 0, 0, 2, 1, 0, 2, 0, 2, 0, 2, 0, 0, 2,
- 1, 2, 0, 0, 2, 2, 2, 0, 0, 2, 2, 0, 2, 0, 2,
- 0, 2, 2, 0, 2, 1, 2, 2, 0, 2, 2, 2, 2, 0, 2,
- 2, 0, 2, 0, 2, 0, 0, 1, 0, 2, 1, 0, 1, 0, 2,
- 2, 0, 1, 0, 2, 0, 1, 2, 0, 2, 0, 1, 1, 0, 2,
- 1, 1, 1, 0, 2, 2, 1, 1, 0, 2, 1, 1, 2, 0, 2,
- 0, 2, 1, 0, 2, 1, 2, 1, 0, 2, 2, 2, 1, 0, 2,
- 2, 1, 2, 0, 2, 0, 2, 2, 2, 2, 1, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 0, 0, 0, 0, 1,
- 1, 0, 0, 0, 1, 2, 0, 0, 0, 1, 0, 0, 2, 0, 1,
- 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 2, 1, 0, 0, 1,
- 1, 0, 2, 0, 1, 0, 2, 0, 0, 1, 1, 2, 0, 0, 1,
- 2, 2, 0, 0, 1, 2, 0, 2, 0, 1, 0, 2, 2, 0, 1,
- 1, 2, 2, 0, 1, 2, 2, 2, 0, 1, 2, 0, 2, 0, 1,
- 0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 2, 0, 1, 0, 1,
- 0, 1, 2, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1,
- 2, 1, 1, 0, 1, 1, 1, 2, 0, 1, 0, 2, 1, 0, 1,
- 1, 2, 1, 0, 1, 2, 2, 1, 0, 1, 2, 1, 2, 0, 1,
- 0, 0, 1, 2, 2, 1, 0, 1, 2, 2, 2, 0, 1, 2, 2,
- 0, 1, 2, 2, 2, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1,
- 2, 0, 0, 1, 1, 0, 0, 2, 1, 1, 0, 1, 0, 1, 1,
- 1, 1, 0, 1, 1, 2, 1, 0, 1, 1, 1, 0, 2, 1, 1,
- 0, 2, 0, 1, 1, 1, 2, 0, 1, 1, 2, 2, 0, 1, 1,
- 2, 0, 2, 1, 1, 0, 2, 2, 1, 1, 1, 2, 2, 1, 1,
- 2, 2, 2, 1, 1, 2, 0, 2, 1, 1, 0, 0, 1, 1, 1,
- 1, 0, 1, 1, 1, 2, 0, 1, 1, 1, 0, 1, 2, 1, 1,
- 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1,
- 1, 1, 2, 1, 1, 0, 2, 1, 1, 1, 1, 2, 1, 1, 1,
- 2, 2, 1, 1, 1, 2, 1, 2, 1, 1, 0, 1, 1, 2, 2,
- 1, 1, 1, 2, 2, 2, 1, 1, 2, 2, 1, 1, 2, 2, 2,
- 0, 0, 0, 2, 1, 1, 0, 0, 2, 1, 2, 0, 0, 2, 1,
- 0, 0, 2, 2, 1, 0, 1, 0, 2, 1, 1, 1, 0, 2, 1,
- 2, 1, 0, 2, 1, 1, 0, 2, 2, 1, 0, 2, 0, 2, 1,
- 1, 2, 0, 2, 1, 2, 2, 0, 2, 1, 2, 0, 2, 2, 1,
- 0, 2, 2, 2, 1, 1, 2, 2, 2, 1, 2, 2, 2, 2, 1,
- 2, 0, 2, 2, 1, 0, 0, 1, 2, 1, 1, 0, 1, 2, 1,
- 2, 0, 1, 2, 1, 0, 1, 2, 2, 1, 0, 1, 1, 2, 1,
- 1, 1, 1, 2, 1, 2, 1, 1, 2, 1, 1, 1, 2, 2, 1,
- 0, 2, 1, 2, 1, 1, 2, 1, 2, 1, 2, 2, 1, 2, 1,
- 2, 1, 2, 2, 1, 0, 2, 1, 2, 2, 1, 2, 1, 2, 2,
- 2, 2, 1, 2, 2, 2, 1, 2, 2, 2, 0, 0, 0, 1, 2,
- 1, 0, 0, 1, 2, 2, 0, 0, 1, 2, 0, 0, 2, 1, 2,
- 0, 1, 0, 1, 2, 1, 1, 0, 1, 2, 2, 1, 0, 1, 2,
- 1, 0, 2, 1, 2, 0, 2, 0, 1, 2, 1, 2, 0, 1, 2,
- 2, 2, 0, 1, 2, 2, 0, 2, 1, 2, 0, 2, 2, 1, 2,
- 1, 2, 2, 1, 2, 2, 2, 2, 1, 2, 2, 0, 2, 1, 2,
- 0, 0, 1, 1, 2, 1, 0, 1, 1, 2, 2, 0, 1, 1, 2,
- 0, 1, 2, 1, 2, 0, 1, 1, 1, 2, 1, 1, 1, 1, 2,
- 2, 1, 1, 1, 2, 1, 1, 2, 1, 2, 0, 2, 1, 1, 2,
- 1, 2, 1, 1, 2, 2, 2, 1, 1, 2, 2, 1, 2, 1, 2,
- 0, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 1, 2, 2, 2
- };
- private static ReadOnlySpan<byte> QuintEncodings => new byte[]
- {
- 0, 0, 0, 1, 0, 0, 2, 0, 0, 3, 0, 0, 4, 0, 0,
- 0, 4, 0, 4, 4, 0, 4, 4, 4, 0, 1, 0, 1, 1, 0,
- 2, 1, 0, 3, 1, 0, 4, 1, 0, 1, 4, 0, 4, 4, 1,
- 4, 4, 4, 0, 2, 0, 1, 2, 0, 2, 2, 0, 3, 2, 0,
- 4, 2, 0, 2, 4, 0, 4, 4, 2, 4, 4, 4, 0, 3, 0,
- 1, 3, 0, 2, 3, 0, 3, 3, 0, 4, 3, 0, 3, 4, 0,
- 4, 4, 3, 4, 4, 4, 0, 0, 1, 1, 0, 1, 2, 0, 1,
- 3, 0, 1, 4, 0, 1, 0, 4, 1, 4, 0, 4, 0, 4, 4,
- 0, 1, 1, 1, 1, 1, 2, 1, 1, 3, 1, 1, 4, 1, 1,
- 1, 4, 1, 4, 1, 4, 1, 4, 4, 0, 2, 1, 1, 2, 1,
- 2, 2, 1, 3, 2, 1, 4, 2, 1, 2, 4, 1, 4, 2, 4,
- 2, 4, 4, 0, 3, 1, 1, 3, 1, 2, 3, 1, 3, 3, 1,
- 4, 3, 1, 3, 4, 1, 4, 3, 4, 3, 4, 4, 0, 0, 2,
- 1, 0, 2, 2, 0, 2, 3, 0, 2, 4, 0, 2, 0, 4, 2,
- 2, 0, 4, 3, 0, 4, 0, 1, 2, 1, 1, 2, 2, 1, 2,
- 3, 1, 2, 4, 1, 2, 1, 4, 2, 2, 1, 4, 3, 1, 4,
- 0, 2, 2, 1, 2, 2, 2, 2, 2, 3, 2, 2, 4, 2, 2,
- 2, 4, 2, 2, 2, 4, 3, 2, 4, 0, 3, 2, 1, 3, 2,
- 2, 3, 2, 3, 3, 2, 4, 3, 2, 3, 4, 2, 2, 3, 4,
- 3, 3, 4, 0, 0, 3, 1, 0, 3, 2, 0, 3, 3, 0, 3,
- 4, 0, 3, 0, 4, 3, 0, 0, 4, 1, 0, 4, 0, 1, 3,
- 1, 1, 3, 2, 1, 3, 3, 1, 3, 4, 1, 3, 1, 4, 3,
- 0, 1, 4, 1, 1, 4, 0, 2, 3, 1, 2, 3, 2, 2, 3,
- 3, 2, 3, 4, 2, 3, 2, 4, 3, 0, 2, 4, 1, 2, 4,
- 0, 3, 3, 1, 3, 3, 2, 3, 3, 3, 3, 3, 4, 3, 3,
- 3, 4, 3, 0, 3, 4, 1, 3, 4
- };
- }
- }
|