NvdecDevice.cs 2.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. using Ryujinx.Common.Logging;
  2. using Ryujinx.Graphics.Device;
  3. using Ryujinx.Graphics.Gpu.Memory;
  4. using Ryujinx.Graphics.Nvdec.Image;
  5. using System.Collections.Concurrent;
  6. using System.Collections.Generic;
  7. using System.Threading;
  8. namespace Ryujinx.Graphics.Nvdec
  9. {
  10. public class NvdecDevice : IDeviceStateWithContext
  11. {
  12. private readonly ResourceManager _rm;
  13. private readonly DeviceState<NvdecRegisters> _state;
  14. private long _currentId;
  15. private ConcurrentDictionary<long, NvdecDecoderContext> _contexts;
  16. private NvdecDecoderContext _currentContext;
  17. public NvdecDevice(MemoryManager gmm)
  18. {
  19. _rm = new ResourceManager(gmm, new SurfaceCache(gmm));
  20. _state = new DeviceState<NvdecRegisters>(new Dictionary<string, RwCallback>
  21. {
  22. { nameof(NvdecRegisters.Execute), new RwCallback(Execute, null) }
  23. });
  24. _contexts = new ConcurrentDictionary<long, NvdecDecoderContext>();
  25. }
  26. public long CreateContext()
  27. {
  28. long id = Interlocked.Increment(ref _currentId);
  29. _contexts.TryAdd(id, new NvdecDecoderContext());
  30. return id;
  31. }
  32. public void DestroyContext(long id)
  33. {
  34. if (_contexts.TryRemove(id, out var context))
  35. {
  36. context.Dispose();
  37. }
  38. _rm.Cache.Trim();
  39. }
  40. public void BindContext(long id)
  41. {
  42. if (_contexts.TryGetValue(id, out var context))
  43. {
  44. _currentContext = context;
  45. }
  46. }
  47. public int Read(int offset) => _state.Read(offset);
  48. public void Write(int offset, int data) => _state.Write(offset, data);
  49. private void Execute(int data)
  50. {
  51. Decode((CodecId)_state.State.SetCodecID);
  52. }
  53. private void Decode(CodecId codecId)
  54. {
  55. switch (codecId)
  56. {
  57. case CodecId.H264:
  58. H264Decoder.Decode(_currentContext, _rm, ref _state.State);
  59. break;
  60. case CodecId.Vp8:
  61. Vp8Decoder.Decode(_currentContext, _rm, ref _state.State);
  62. break;
  63. case CodecId.Vp9:
  64. Vp9Decoder.Decode(_rm, ref _state.State);
  65. break;
  66. default:
  67. Logger.Error?.Print(LogClass.Nvdec, $"Unsupported codec \"{codecId}\".");
  68. break;
  69. }
  70. }
  71. }
  72. }