aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Graphics/Vic/VideoImageComposer.cs
blob: 758382fa8882f8ef6016f3b853a7d54832f8a131 (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
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
using Ryujinx.Graphics.Memory;

namespace Ryujinx.Graphics.Vic
{
    class VideoImageComposer
    {
        private NvGpu Gpu;

        private long ConfigStructAddress;
        private long OutputSurfaceLumaAddress;
        private long OutputSurfaceChromaUAddress;
        private long OutputSurfaceChromaVAddress;

        public VideoImageComposer(NvGpu Gpu)
        {
            this.Gpu = Gpu;
        }

        public void Process(NvGpuVmm Vmm, int MethodOffset, int[] Arguments)
        {
            VideoImageComposerMeth Method = (VideoImageComposerMeth)MethodOffset;

            switch (Method)
            {
                case VideoImageComposerMeth.Execute:
                    Execute(Vmm, Arguments);
                    break;

                case VideoImageComposerMeth.SetConfigStructOffset:
                    SetConfigStructOffset(Vmm, Arguments);
                    break;

                case VideoImageComposerMeth.SetOutputSurfaceLumaOffset:
                    SetOutputSurfaceLumaOffset(Vmm, Arguments);
                    break;

                case VideoImageComposerMeth.SetOutputSurfaceChromaUOffset:
                    SetOutputSurfaceChromaUOffset(Vmm, Arguments);
                    break;

                case VideoImageComposerMeth.SetOutputSurfaceChromaVOffset:
                    SetOutputSurfaceChromaVOffset(Vmm, Arguments);
                    break;
            }
        }

        private void Execute(NvGpuVmm Vmm, int[] Arguments)
        {
            StructUnpacker Unpacker = new StructUnpacker(Vmm, ConfigStructAddress + 0x20);

            SurfacePixelFormat PixelFormat = (SurfacePixelFormat)Unpacker.Read(7);

            int ChromaLocHoriz = Unpacker.Read(2);
            int ChromaLocVert  = Unpacker.Read(2);

            int BlockLinearKind       = Unpacker.Read(4);
            int BlockLinearHeightLog2 = Unpacker.Read(4);

            int Reserved0 = Unpacker.Read(3);
            int Reserved1 = Unpacker.Read(10);

            int SurfaceWidthMinus1  = Unpacker.Read(14);
            int SurfaceHeightMinus1 = Unpacker.Read(14);

            int GobBlockHeight = 1 << BlockLinearHeightLog2;

            int SurfaceWidth  = SurfaceWidthMinus1  + 1;
            int SurfaceHeight = SurfaceHeightMinus1 + 1;

            SurfaceOutputConfig OutputConfig = new SurfaceOutputConfig(
                PixelFormat,
                SurfaceWidth,
                SurfaceHeight,
                GobBlockHeight,
                OutputSurfaceLumaAddress,
                OutputSurfaceChromaUAddress,
                OutputSurfaceChromaVAddress);

            Gpu.VideoDecoder.CopyPlanes(Vmm, OutputConfig);
        }

        private void SetConfigStructOffset(NvGpuVmm Vmm, int[] Arguments)
        {
            ConfigStructAddress = GetAddress(Arguments);
        }

        private void SetOutputSurfaceLumaOffset(NvGpuVmm Vmm, int[] Arguments)
        {
            OutputSurfaceLumaAddress = GetAddress(Arguments);
        }

        private void SetOutputSurfaceChromaUOffset(NvGpuVmm Vmm, int[] Arguments)
        {
            OutputSurfaceChromaUAddress = GetAddress(Arguments);
        }

        private void SetOutputSurfaceChromaVOffset(NvGpuVmm Vmm, int[] Arguments)
        {
            OutputSurfaceChromaVAddress = GetAddress(Arguments);
        }

        private static long GetAddress(int[] Arguments)
        {
            return (long)(uint)Arguments[0] << 8;
        }
    }
}