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