NvdecDevice.cs 2.5 KB

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