diff options
Diffstat (limited to 'Ryujinx.Graphics.Vic/VicDevice.cs')
-rw-r--r-- | Ryujinx.Graphics.Vic/VicDevice.cs | 97 |
1 files changed, 97 insertions, 0 deletions
diff --git a/Ryujinx.Graphics.Vic/VicDevice.cs b/Ryujinx.Graphics.Vic/VicDevice.cs new file mode 100644 index 00000000..db4fe513 --- /dev/null +++ b/Ryujinx.Graphics.Vic/VicDevice.cs @@ -0,0 +1,97 @@ +using Ryujinx.Common.Logging; +using Ryujinx.Graphics.Device; +using Ryujinx.Graphics.Gpu.Memory; +using Ryujinx.Graphics.Vic.Image; +using Ryujinx.Graphics.Vic.Types; +using System; +using System.Collections.Generic; + +namespace Ryujinx.Graphics.Vic +{ + public class VicDevice : IDeviceState + { + private readonly MemoryManager _gmm; + private readonly ResourceManager _rm; + private readonly DeviceState<VicRegisters> _state; + + private PlaneOffsets _overrideOffsets; + private bool _hasOverride; + + public VicDevice(MemoryManager gmm) + { + _gmm = gmm; + _rm = new ResourceManager(gmm, new BufferPool<Pixel>(), new BufferPool<byte>()); + _state = new DeviceState<VicRegisters>(new Dictionary<string, RwCallback> + { + { nameof(VicRegisters.Execute), new RwCallback(Execute, null) } + }); + } + + /// <summary> + /// Overrides all input surfaces with a custom surface. + /// </summary> + /// <param name="lumaOffset">Offset of the luma plane or packed data for this surface</param> + /// <param name="chromaUOffset">Offset of the U chroma plane (for planar formats) or both chroma planes (for semiplanar formats)</param> + /// <param name="chromaVOffset">Offset of the V chroma plane for planar formats</param> + public void SetSurfaceOverride(uint lumaOffset, uint chromaUOffset, uint chromaVOffset) + { + _overrideOffsets.LumaOffset = lumaOffset; + _overrideOffsets.ChromaUOffset = chromaUOffset; + _overrideOffsets.ChromaVOffset = chromaVOffset; + _hasOverride = true; + } + + /// <summary> + /// Disables overriding input surfaces. + /// </summary> + /// <remarks> + /// Surface overrides are disabled by default. + /// Call this if you previously called <see cref="SetSurfaceOverride(uint, uint, uint)"/> and which to disable it. + /// </remarks> + public void DisableSurfaceOverride() + { + _hasOverride = false; + } + + public int Read(int offset) => _state.Read(offset); + public void Write(int offset, int data) => _state.Write(offset, data); + + private void Execute(int data) + { + ConfigStruct config = ReadIndirect<ConfigStruct>(_state.State.SetConfigStructOffset); + + using Surface output = new Surface( + _rm.SurfacePool, + config.OutputSurfaceConfig.OutSurfaceWidth + 1, + config.OutputSurfaceConfig.OutSurfaceHeight + 1); + + for (int i = 0; i < config.SlotStruct.Length; i++) + { + ref SlotStruct slot = ref config.SlotStruct[i]; + + if (!slot.SlotConfig.SlotEnable) + { + continue; + } + + var offsets = _state.State.SetSurfacexSlotx[i][0]; + + if (_hasOverride) + { + offsets = _overrideOffsets; + } + + using Surface src = SurfaceReader.Read(_rm, ref slot.SlotSurfaceConfig, ref offsets); + + Blender.BlendOne(output, src, ref slot); + } + + SurfaceWriter.Write(_rm, output, ref config.OutputSurfaceConfig, ref _state.State.SetOutputSurface); + } + + private T ReadIndirect<T>(uint offset) where T : unmanaged + { + return _gmm.Read<T>((ulong)offset << 8); + } + } +} |