aboutsummaryrefslogtreecommitdiff
path: root/src/Ryujinx.Graphics.Texture/Astc/AstcPixel.cs
blob: b16cb00266aedf848d40779940e63f2f4dc7f7b1 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

namespace Ryujinx.Graphics.Texture.Astc
{
    [StructLayout(LayoutKind.Sequential)]
    struct AstcPixel
    {
        internal const int StructSize = 12;

        public short A;
        public short R;
        public short G;
        public short B;

        private uint _bitDepthInt;

        private Span<byte> BitDepth => MemoryMarshal.CreateSpan(ref Unsafe.As<uint, byte>(ref _bitDepthInt), 4);
        private Span<short> Components => MemoryMarshal.CreateSpan(ref A, 4);

        public AstcPixel(short a, short r, short g, short b)
        {
            A = a;
            R = r;
            G = g;
            B = b;

            _bitDepthInt = 0x08080808;
        }

        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)
        {
            return Components[index];
        }

        public void SetComponent(int index, int value)
        {
            Components[index] = (short)value;
        }

        public readonly int Pack()
        {
            return A << 24 |
                   B << 16 |
                   G << 8 |
                   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));
        }
    }
}