aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Graphics.Nvdec
diff options
context:
space:
mode:
Diffstat (limited to 'Ryujinx.Graphics.Nvdec')
-rw-r--r--Ryujinx.Graphics.Nvdec/H264Decoder.cs19
-rw-r--r--Ryujinx.Graphics.Nvdec/Image/SurfaceWriter.cs49
-rw-r--r--Ryujinx.Graphics.Nvdec/Types/H264/PictureInfo.cs6
3 files changed, 70 insertions, 4 deletions
diff --git a/Ryujinx.Graphics.Nvdec/H264Decoder.cs b/Ryujinx.Graphics.Nvdec/H264Decoder.cs
index 69eeb494..6efeb899 100644
--- a/Ryujinx.Graphics.Nvdec/H264Decoder.cs
+++ b/Ryujinx.Graphics.Nvdec/H264Decoder.cs
@@ -31,7 +31,24 @@ namespace Ryujinx.Graphics.Nvdec
if (decoder.Decode(ref info, outputSurface, bitstream))
{
- SurfaceWriter.Write(rm.Gmm, outputSurface, lumaOffset, chromaOffset);
+ if (outputSurface.Field == FrameField.Progressive)
+ {
+ SurfaceWriter.Write(
+ rm.Gmm,
+ outputSurface,
+ lumaOffset + pictureInfo.LumaFrameOffset,
+ chromaOffset + pictureInfo.ChromaFrameOffset);
+ }
+ else
+ {
+ SurfaceWriter.WriteInterlaced(
+ rm.Gmm,
+ outputSurface,
+ lumaOffset + pictureInfo.LumaTopFieldOffset,
+ chromaOffset + pictureInfo.ChromaTopFieldOffset,
+ lumaOffset + pictureInfo.LumaBottomFieldOffset,
+ chromaOffset + pictureInfo.ChromaBottomFieldOffset);
+ }
}
rm.Cache.Put(outputSurface);
diff --git a/Ryujinx.Graphics.Nvdec/Image/SurfaceWriter.cs b/Ryujinx.Graphics.Nvdec/Image/SurfaceWriter.cs
index 5c294621..cc5c251b 100644
--- a/Ryujinx.Graphics.Nvdec/Image/SurfaceWriter.cs
+++ b/Ryujinx.Graphics.Nvdec/Image/SurfaceWriter.cs
@@ -38,6 +38,55 @@ namespace Ryujinx.Graphics.Nvdec.Image
surface.UvHeight);
}
+ public static void WriteInterlaced(
+ MemoryManager gmm,
+ ISurface surface,
+ uint lumaTopOffset,
+ uint chromaTopOffset,
+ uint lumaBottomOffset,
+ uint chromaBottomOffset)
+ {
+ int lumaSize = GetBlockLinearSize(surface.Width, surface.Height / 2, 1);
+
+ using var lumaTop = gmm.GetWritableRegion(ExtendOffset(lumaTopOffset), lumaSize);
+ using var lumaBottom = gmm.GetWritableRegion(ExtendOffset(lumaBottomOffset), lumaSize);
+
+ WriteLuma(
+ lumaTop.Memory.Span,
+ surface.YPlane.AsSpan(),
+ surface.Stride * 2,
+ surface.Width,
+ surface.Height / 2);
+
+ WriteLuma(
+ lumaBottom.Memory.Span,
+ surface.YPlane.AsSpan().Slice(surface.Stride),
+ surface.Stride * 2,
+ surface.Width,
+ surface.Height / 2);
+
+ int chromaSize = GetBlockLinearSize(surface.UvWidth, surface.UvHeight / 2, 2);
+
+ using var chromaTop = gmm.GetWritableRegion(ExtendOffset(chromaTopOffset), chromaSize);
+ using var chromaBottom = gmm.GetWritableRegion(ExtendOffset(chromaBottomOffset), chromaSize);
+
+ WriteChroma(
+ chromaTop.Memory.Span,
+ surface.UPlane.AsSpan(),
+ surface.VPlane.AsSpan(),
+ surface.UvStride * 2,
+ surface.UvWidth,
+ surface.UvHeight / 2);
+
+ WriteChroma(
+ chromaBottom.Memory.Span,
+ surface.UPlane.AsSpan().Slice(surface.UvStride),
+ surface.VPlane.AsSpan().Slice(surface.UvStride),
+ surface.UvStride * 2,
+ surface.UvWidth,
+ surface.UvHeight / 2);
+ }
+
private static void WriteLuma(Span<byte> dst, ReadOnlySpan<byte> src, int srcStride, int width, int height)
{
LayoutConverter.ConvertLinearToBlockLinear(dst, width, height, srcStride, 1, 2, src);
diff --git a/Ryujinx.Graphics.Nvdec/Types/H264/PictureInfo.cs b/Ryujinx.Graphics.Nvdec/Types/H264/PictureInfo.cs
index 326c40ae..7c779dff 100644
--- a/Ryujinx.Graphics.Nvdec/Types/H264/PictureInfo.cs
+++ b/Ryujinx.Graphics.Nvdec/Types/H264/PictureInfo.cs
@@ -26,10 +26,10 @@ namespace Ryujinx.Graphics.Nvdec.Types.H264
public uint Transform8x8ModeFlag;
public uint LumaPitch;
public uint ChromaPitch;
- public uint LumaTopOffset;
- public uint LumaBottomOffset;
+ public uint LumaTopFieldOffset;
+ public uint LumaBottomFieldOffset;
public uint LumaFrameOffset;
- public uint ChromaTopOffset;
+ public uint ChromaTopFieldOffset;
public uint ChromaBottomFieldOffset;
public uint ChromaFrameOffset;
public uint HistBufferSize;