NvGpuEngine2d.cs 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. using ChocolArm64.Memory;
  2. using Ryujinx.Graphics.Gal;
  3. using System.Collections.Generic;
  4. namespace Ryujinx.Graphics.Gpu
  5. {
  6. public class NvGpuEngine2d : INvGpuEngine
  7. {
  8. private enum CopyOperation
  9. {
  10. SrcCopyAnd,
  11. RopAnd,
  12. Blend,
  13. SrcCopy,
  14. Rop,
  15. SrcCopyPremult,
  16. BlendPremult
  17. }
  18. public int[] Registers { get; private set; }
  19. private NsGpu Gpu;
  20. private Dictionary<int, NvGpuMethod> Methods;
  21. public NvGpuEngine2d(NsGpu Gpu)
  22. {
  23. this.Gpu = Gpu;
  24. Registers = new int[0xe00];
  25. Methods = new Dictionary<int, NvGpuMethod>();
  26. void AddMethod(int Meth, int Count, int Stride, NvGpuMethod Method)
  27. {
  28. while (Count-- > 0)
  29. {
  30. Methods.Add(Meth, Method);
  31. Meth += Stride;
  32. }
  33. }
  34. AddMethod(0xb5, 1, 1, TextureCopy);
  35. }
  36. public void CallMethod(AMemory Memory, NsGpuPBEntry PBEntry)
  37. {
  38. if (Methods.TryGetValue(PBEntry.Method, out NvGpuMethod Method))
  39. {
  40. Method(Memory, PBEntry);
  41. }
  42. else
  43. {
  44. WriteRegister(PBEntry);
  45. }
  46. }
  47. private void TextureCopy(AMemory Memory, NsGpuPBEntry PBEntry)
  48. {
  49. CopyOperation Operation = (CopyOperation)ReadRegister(NvGpuEngine2dReg.CopyOperation);
  50. bool SrcLinear = ReadRegister(NvGpuEngine2dReg.SrcLinear) != 0;
  51. int SrcWidth = ReadRegister(NvGpuEngine2dReg.SrcWidth);
  52. int SrcHeight = ReadRegister(NvGpuEngine2dReg.SrcHeight);
  53. bool DstLinear = ReadRegister(NvGpuEngine2dReg.DstLinear) != 0;
  54. int DstWidth = ReadRegister(NvGpuEngine2dReg.DstWidth);
  55. int DstHeight = ReadRegister(NvGpuEngine2dReg.DstHeight);
  56. int DstPitch = ReadRegister(NvGpuEngine2dReg.DstPitch);
  57. int DstBlkDim = ReadRegister(NvGpuEngine2dReg.DstBlockDimensions);
  58. TextureSwizzle DstSwizzle = DstLinear
  59. ? TextureSwizzle.Pitch
  60. : TextureSwizzle.BlockLinear;
  61. int DstBlockHeight = 1 << ((DstBlkDim >> 4) & 0xf);
  62. long Tag = MakeInt64From2xInt32(NvGpuEngine2dReg.SrcAddress);
  63. TryGetCpuAddr(NvGpuEngine2dReg.SrcAddress, out long SrcAddress);
  64. TryGetCpuAddr(NvGpuEngine2dReg.DstAddress, out long DstAddress);
  65. bool IsFbTexture = Gpu.Engine3d.IsFrameBufferPosition(Tag);
  66. if (IsFbTexture && DstLinear)
  67. {
  68. DstSwizzle = TextureSwizzle.BlockLinear;
  69. }
  70. Texture DstTexture = new Texture(
  71. DstAddress,
  72. DstWidth,
  73. DstHeight,
  74. DstBlockHeight,
  75. DstBlockHeight,
  76. DstSwizzle,
  77. GalTextureFormat.A8B8G8R8);
  78. if (IsFbTexture)
  79. {
  80. Gpu.Renderer.GetFrameBufferData(Tag, (byte[] Buffer) =>
  81. {
  82. CopyTexture(Memory, DstTexture, Buffer);
  83. });
  84. }
  85. else
  86. {
  87. long Size = SrcWidth * SrcHeight * 4;
  88. byte[] Buffer = AMemoryHelper.ReadBytes(Memory, SrcAddress, Size);
  89. CopyTexture(Memory, DstTexture, Buffer);
  90. }
  91. }
  92. private void CopyTexture(AMemory Memory, Texture Texture, byte[] Buffer)
  93. {
  94. TextureWriter.Write(Memory, Texture, Buffer);
  95. }
  96. private bool TryGetCpuAddr(NvGpuEngine2dReg Reg, out long Position)
  97. {
  98. Position = MakeInt64From2xInt32(Reg);
  99. Position = Gpu.GetCpuAddr(Position);
  100. return Position != -1;
  101. }
  102. private long MakeInt64From2xInt32(NvGpuEngine2dReg Reg)
  103. {
  104. return
  105. (long)Registers[(int)Reg + 0] << 32 |
  106. (uint)Registers[(int)Reg + 1];
  107. }
  108. private void WriteRegister(NsGpuPBEntry PBEntry)
  109. {
  110. int ArgsCount = PBEntry.Arguments.Count;
  111. if (ArgsCount > 0)
  112. {
  113. Registers[PBEntry.Method] = PBEntry.Arguments[ArgsCount - 1];
  114. }
  115. }
  116. private int ReadRegister(NvGpuEngine2dReg Reg)
  117. {
  118. return Registers[(int)Reg];
  119. }
  120. private void WriteRegister(NvGpuEngine2dReg Reg, int Value)
  121. {
  122. Registers[(int)Reg] = Value;
  123. }
  124. }
  125. }