VicDevice.cs 3.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. using Ryujinx.Common.Logging;
  2. using Ryujinx.Graphics.Device;
  3. using Ryujinx.Graphics.Gpu.Memory;
  4. using Ryujinx.Graphics.Vic.Image;
  5. using Ryujinx.Graphics.Vic.Types;
  6. using System;
  7. using System.Collections.Generic;
  8. namespace Ryujinx.Graphics.Vic
  9. {
  10. public class VicDevice : IDeviceState
  11. {
  12. private readonly MemoryManager _gmm;
  13. private readonly ResourceManager _rm;
  14. private readonly DeviceState<VicRegisters> _state;
  15. private PlaneOffsets _overrideOffsets;
  16. private bool _hasOverride;
  17. public VicDevice(MemoryManager gmm)
  18. {
  19. _gmm = gmm;
  20. _rm = new ResourceManager(gmm, new BufferPool<Pixel>(), new BufferPool<byte>());
  21. _state = new DeviceState<VicRegisters>(new Dictionary<string, RwCallback>
  22. {
  23. { nameof(VicRegisters.Execute), new RwCallback(Execute, null) }
  24. });
  25. }
  26. /// <summary>
  27. /// Overrides all input surfaces with a custom surface.
  28. /// </summary>
  29. /// <param name="lumaOffset">Offset of the luma plane or packed data for this surface</param>
  30. /// <param name="chromaUOffset">Offset of the U chroma plane (for planar formats) or both chroma planes (for semiplanar formats)</param>
  31. /// <param name="chromaVOffset">Offset of the V chroma plane for planar formats</param>
  32. public void SetSurfaceOverride(uint lumaOffset, uint chromaUOffset, uint chromaVOffset)
  33. {
  34. _overrideOffsets.LumaOffset = lumaOffset;
  35. _overrideOffsets.ChromaUOffset = chromaUOffset;
  36. _overrideOffsets.ChromaVOffset = chromaVOffset;
  37. _hasOverride = true;
  38. }
  39. /// <summary>
  40. /// Disables overriding input surfaces.
  41. /// </summary>
  42. /// <remarks>
  43. /// Surface overrides are disabled by default.
  44. /// Call this if you previously called <see cref="SetSurfaceOverride(uint, uint, uint)"/> and which to disable it.
  45. /// </remarks>
  46. public void DisableSurfaceOverride()
  47. {
  48. _hasOverride = false;
  49. }
  50. public int Read(int offset) => _state.Read(offset);
  51. public void Write(int offset, int data) => _state.Write(offset, data);
  52. private void Execute(int data)
  53. {
  54. ConfigStruct config = ReadIndirect<ConfigStruct>(_state.State.SetConfigStructOffset);
  55. using Surface output = new Surface(
  56. _rm.SurfacePool,
  57. config.OutputSurfaceConfig.OutSurfaceWidth + 1,
  58. config.OutputSurfaceConfig.OutSurfaceHeight + 1);
  59. for (int i = 0; i < config.SlotStruct.Length; i++)
  60. {
  61. ref SlotStruct slot = ref config.SlotStruct[i];
  62. if (!slot.SlotConfig.SlotEnable)
  63. {
  64. continue;
  65. }
  66. var offsets = _state.State.SetSurfacexSlotx[i][0];
  67. if (_hasOverride)
  68. {
  69. offsets = _overrideOffsets;
  70. }
  71. using Surface src = SurfaceReader.Read(_rm, ref slot.SlotSurfaceConfig, ref offsets);
  72. Blender.BlendOne(output, src, ref slot);
  73. }
  74. SurfaceWriter.Write(_rm, output, ref config.OutputSurfaceConfig, ref _state.State.SetOutputSurface);
  75. }
  76. private T ReadIndirect<T>(uint offset) where T : unmanaged
  77. {
  78. return _gmm.Read<T>((ulong)offset << 8);
  79. }
  80. }
  81. }