VicDevice.cs 2.7 KB

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