ThiDevice.cs 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. using Ryujinx.Common;
  2. using Ryujinx.Graphics.Device;
  3. using System;
  4. using System.Collections.Generic;
  5. namespace Ryujinx.Graphics.Host1x
  6. {
  7. class ThiDevice : IDeviceState, IDisposable
  8. {
  9. private readonly ClassId _classId;
  10. private readonly IDeviceState _device;
  11. private readonly SyncptIncrManager _syncptIncrMgr;
  12. private class CommandAction
  13. {
  14. public int Data { get; }
  15. public CommandAction(int data)
  16. {
  17. Data = data;
  18. }
  19. }
  20. private class MethodCallAction : CommandAction
  21. {
  22. public int Method { get; }
  23. public MethodCallAction(int method, int data) : base(data)
  24. {
  25. Method = method;
  26. }
  27. }
  28. private class SyncptIncrAction : CommandAction
  29. {
  30. public SyncptIncrAction(uint syncptIncrHandle) : base((int)syncptIncrHandle)
  31. {
  32. }
  33. }
  34. private readonly AsyncWorkQueue<CommandAction> _commandQueue;
  35. private readonly DeviceState<ThiRegisters> _state;
  36. public ThiDevice(ClassId classId, IDeviceState device, SyncptIncrManager syncptIncrMgr)
  37. {
  38. _classId = classId;
  39. _device = device;
  40. _syncptIncrMgr = syncptIncrMgr;
  41. _commandQueue = new AsyncWorkQueue<CommandAction>(Process, $"Ryujinx.{classId}Processor");
  42. _state = new DeviceState<ThiRegisters>(new Dictionary<string, RwCallback>
  43. {
  44. { nameof(ThiRegisters.IncrSyncpt), new RwCallback(IncrSyncpt, null) },
  45. { nameof(ThiRegisters.Method1), new RwCallback(Method1, null) }
  46. });
  47. }
  48. public int Read(int offset) => _state.Read(offset);
  49. public void Write(int offset, int data) => _state.Write(offset, data);
  50. private void IncrSyncpt(int data)
  51. {
  52. uint syncpointId = (uint)(data & 0xFF);
  53. uint cond = (uint)((data >> 8) & 0xFF); // 0 = Immediate, 1 = Done
  54. if (cond == 0)
  55. {
  56. _syncptIncrMgr.Increment(syncpointId);
  57. }
  58. else
  59. {
  60. _commandQueue.Add(new SyncptIncrAction(_syncptIncrMgr.IncrementWhenDone(_classId, syncpointId)));
  61. }
  62. }
  63. private void Method1(int data)
  64. {
  65. _commandQueue.Add(new MethodCallAction((int)_state.State.Method0 * 4, data));
  66. }
  67. private void Process(CommandAction cmdAction)
  68. {
  69. if (cmdAction is SyncptIncrAction syncptIncrAction)
  70. {
  71. _syncptIncrMgr.SignalDone((uint)syncptIncrAction.Data);
  72. }
  73. else if (cmdAction is MethodCallAction methodCallAction)
  74. {
  75. _device.Write(methodCallAction.Method, methodCallAction.Data);
  76. }
  77. }
  78. public void Dispose() => _commandQueue.Dispose();
  79. }
  80. }