VicDevice.cs
1 using Ryujinx.Graphics.Device; 2 using Ryujinx.Graphics.Vic.Image; 3 using Ryujinx.Graphics.Vic.Types; 4 using System; 5 using System.Collections.Generic; 6 7 namespace Ryujinx.Graphics.Vic 8 { 9 public class VicDevice : IDeviceState 10 { 11 private readonly DeviceMemoryManager _mm; 12 private readonly ResourceManager _rm; 13 private readonly DeviceState<VicRegisters> _state; 14 15 public VicDevice(DeviceMemoryManager mm) 16 { 17 _mm = mm; 18 _rm = new ResourceManager(mm, new BufferPool<Pixel>(), new BufferPool<byte>()); 19 _state = new DeviceState<VicRegisters>(new Dictionary<string, RwCallback> 20 { 21 { nameof(VicRegisters.Execute), new RwCallback(Execute, null) }, 22 }); 23 } 24 25 public int Read(int offset) => _state.Read(offset); 26 public void Write(int offset, int data) => _state.Write(offset, data); 27 28 private void Execute(int data) 29 { 30 ConfigStruct config = ReadIndirect<ConfigStruct>(_state.State.SetConfigStructOffset); 31 32 using Surface output = new( 33 _rm.SurfacePool, 34 config.OutputSurfaceConfig.OutSurfaceWidth + 1, 35 config.OutputSurfaceConfig.OutSurfaceHeight + 1); 36 37 for (int i = 0; i < config.SlotStruct.Length; i++) 38 { 39 ref SlotStruct slot = ref config.SlotStruct[i]; 40 41 if (!slot.SlotConfig.SlotEnable) 42 { 43 continue; 44 } 45 46 ref var offsets = ref _state.State.SetSurfacexSlotx[i]; 47 48 using Surface src = SurfaceReader.Read(_rm, ref slot.SlotConfig, ref slot.SlotSurfaceConfig, ref offsets); 49 50 int x1 = config.OutputConfig.TargetRectLeft; 51 int y1 = config.OutputConfig.TargetRectTop; 52 int x2 = config.OutputConfig.TargetRectRight + 1; 53 int y2 = config.OutputConfig.TargetRectBottom + 1; 54 55 int targetX = Math.Min(x1, x2); 56 int targetY = Math.Min(y1, y2); 57 int targetW = Math.Min(output.Width - targetX, Math.Abs(x2 - x1)); 58 int targetH = Math.Min(output.Height - targetY, Math.Abs(y2 - y1)); 59 60 Rectangle targetRect = new(targetX, targetY, targetW, targetH); 61 62 Blender.BlendOne(output, src, ref slot, targetRect); 63 } 64 65 SurfaceWriter.Write(_rm, output, ref config.OutputSurfaceConfig, ref _state.State.SetOutputSurface); 66 } 67 68 private T ReadIndirect<T>(uint offset) where T : unmanaged 69 { 70 return _mm.Read<T>((ulong)offset << 8); 71 } 72 } 73 }