From c86aacde76b5f8e503e2b412385c8491ecc86b3b Mon Sep 17 00:00:00 2001 From: gdkchan Date: Mon, 3 Dec 2018 00:38:47 -0200 Subject: NVDEC implementation using FFmpeg (#443) * Initial nvdec implementation using FFmpeg * Fix swapped channels on the video decoder and the G8R8 texture format * Fix texture samplers not being set properly (regression) * Rebased * Remove unused code introduced on the rebase * Add support for RGBA8 output format on the video image composer * Correct spacing * Some fixes for rebase and other tweaks * Allow size mismatch on frame copy * Get rid of GetHostAddress calls on VDec --- Ryujinx.Graphics/Vic/VideoImageComposer.cs | 107 +++++++++++++++++++++++++++++ 1 file changed, 107 insertions(+) create mode 100644 Ryujinx.Graphics/Vic/VideoImageComposer.cs (limited to 'Ryujinx.Graphics/Vic/VideoImageComposer.cs') diff --git a/Ryujinx.Graphics/Vic/VideoImageComposer.cs b/Ryujinx.Graphics/Vic/VideoImageComposer.cs new file mode 100644 index 00000000..758382fa --- /dev/null +++ b/Ryujinx.Graphics/Vic/VideoImageComposer.cs @@ -0,0 +1,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; + } + } +} \ No newline at end of file -- cgit v1.2.3