BufferQueueConsumer.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372
  1. using Ryujinx.Common.Logging;
  2. using Ryujinx.HLE.HOS.Services.SurfaceFlinger.Types;
  3. using System;
  4. namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
  5. {
  6. class BufferQueueConsumer
  7. {
  8. public BufferQueueCore Core { get; }
  9. public BufferQueueConsumer(BufferQueueCore core)
  10. {
  11. Core = core;
  12. }
  13. public Status AcquireBuffer(out BufferItem bufferItem, ulong expectedPresent)
  14. {
  15. lock (Core.Lock)
  16. {
  17. int numAcquiredBuffers = 0;
  18. for (int i = 0; i < Core.Slots.Length; i++)
  19. {
  20. if (Core.Slots[i].BufferState == BufferState.Acquired)
  21. {
  22. numAcquiredBuffers++;
  23. }
  24. }
  25. if (numAcquiredBuffers >= Core.MaxAcquiredBufferCount + 1)
  26. {
  27. bufferItem = null;
  28. Logger.PrintDebug(LogClass.SurfaceFlinger, $"Max acquired buffer count reached: {numAcquiredBuffers} (max: {Core.MaxAcquiredBufferCount})");
  29. return Status.InvalidOperation;
  30. }
  31. if (Core.Queue.Count == 0)
  32. {
  33. bufferItem = null;
  34. return Status.NoBufferAvailaible;
  35. }
  36. if (expectedPresent != 0)
  37. {
  38. // TODO: support this for advanced presenting.
  39. throw new NotImplementedException();
  40. }
  41. bufferItem = Core.Queue[0];
  42. if (Core.StillTracking(ref bufferItem))
  43. {
  44. Core.Slots[bufferItem.Slot].AcquireCalled = true;
  45. Core.Slots[bufferItem.Slot].NeedsCleanupOnRelease = true;
  46. Core.Slots[bufferItem.Slot].BufferState = BufferState.Acquired;
  47. Core.Slots[bufferItem.Slot].Fence = AndroidFence.NoFence;
  48. }
  49. if (bufferItem.AcquireCalled)
  50. {
  51. bufferItem.GraphicBuffer.Reset();
  52. }
  53. Core.Queue.RemoveAt(0);
  54. Core.CheckSystemEventsLocked(Core.GetMaxBufferCountLocked(true));
  55. Core.SignalDequeueEvent();
  56. }
  57. return Status.Success;
  58. }
  59. public Status DetachBuffer(int slot)
  60. {
  61. lock (Core.Lock)
  62. {
  63. if (Core.IsAbandoned)
  64. {
  65. return Status.NoInit;
  66. }
  67. if (slot < 0 || slot >= Core.Slots.Length || !Core.IsOwnedByConsumerLocked(slot))
  68. {
  69. return Status.BadValue;
  70. }
  71. if (!Core.Slots[slot].RequestBufferCalled)
  72. {
  73. Logger.PrintError(LogClass.SurfaceFlinger, $"Slot {slot} was detached without requesting a buffer");
  74. return Status.BadValue;
  75. }
  76. Core.FreeBufferLocked(slot);
  77. Core.SignalDequeueEvent();
  78. return Status.Success;
  79. }
  80. }
  81. public Status AttachBuffer(out int slot, ref AndroidStrongPointer<GraphicBuffer> graphicBuffer)
  82. {
  83. lock (Core.Lock)
  84. {
  85. int numAcquiredBuffers = 0;
  86. int freeSlot = BufferSlotArray.InvalidBufferSlot;
  87. for (int i = 0; i < Core.Slots.Length; i++)
  88. {
  89. if (Core.Slots[i].BufferState == BufferState.Acquired)
  90. {
  91. numAcquiredBuffers++;
  92. }
  93. else if (Core.Slots[i].BufferState == BufferState.Free)
  94. {
  95. if (freeSlot == BufferSlotArray.InvalidBufferSlot || Core.Slots[i].FrameNumber < Core.Slots[freeSlot].FrameNumber)
  96. {
  97. freeSlot = i;
  98. }
  99. }
  100. }
  101. if (numAcquiredBuffers > Core.MaxAcquiredBufferCount + 1)
  102. {
  103. slot = BufferSlotArray.InvalidBufferSlot;
  104. Logger.PrintError(LogClass.SurfaceFlinger, $"Max acquired buffer count reached: {numAcquiredBuffers} (max: {Core.MaxAcquiredBufferCount})");
  105. return Status.InvalidOperation;
  106. }
  107. if (freeSlot == BufferSlotArray.InvalidBufferSlot)
  108. {
  109. slot = BufferSlotArray.InvalidBufferSlot;
  110. return Status.NoMemory;
  111. }
  112. slot = freeSlot;
  113. Core.Slots[slot].GraphicBuffer.Set(graphicBuffer);
  114. Core.Slots[slot].BufferState = BufferState.Acquired;
  115. Core.Slots[slot].AttachedByConsumer = true;
  116. Core.Slots[slot].NeedsCleanupOnRelease = false;
  117. Core.Slots[slot].Fence = AndroidFence.NoFence;
  118. Core.Slots[slot].FrameNumber = 0;
  119. Core.Slots[slot].AcquireCalled = false;
  120. }
  121. return Status.Success;
  122. }
  123. public Status ReleaseBuffer(int slot, ulong frameNumber, ref AndroidFence fence)
  124. {
  125. if (slot < 0 || slot >= Core.Slots.Length)
  126. {
  127. return Status.BadValue;
  128. }
  129. IProducerListener listener = null;
  130. lock (Core.Lock)
  131. {
  132. if (Core.Slots[slot].FrameNumber != frameNumber)
  133. {
  134. return Status.StaleBufferSlot;
  135. }
  136. foreach (BufferItem item in Core.Queue)
  137. {
  138. if (item.Slot == slot)
  139. {
  140. return Status.BadValue;
  141. }
  142. }
  143. if (Core.Slots[slot].BufferState == BufferState.Acquired)
  144. {
  145. Core.Slots[slot].BufferState = BufferState.Free;
  146. Core.Slots[slot].Fence = fence;
  147. listener = Core.ProducerListener;
  148. }
  149. else if (Core.Slots[slot].NeedsCleanupOnRelease)
  150. {
  151. Core.Slots[slot].NeedsCleanupOnRelease = false;
  152. return Status.StaleBufferSlot;
  153. }
  154. else
  155. {
  156. return Status.BadValue;
  157. }
  158. Core.Slots[slot].GraphicBuffer.Object.DecrementNvMapHandleRefCount(Core.Owner);
  159. Core.CheckSystemEventsLocked(Core.GetMaxBufferCountLocked(true));
  160. Core.SignalDequeueEvent();
  161. }
  162. listener?.OnBufferReleased();
  163. return Status.Success;
  164. }
  165. public Status Connect(IConsumerListener consumerListener, bool controlledByApp)
  166. {
  167. if (consumerListener == null)
  168. {
  169. return Status.BadValue;
  170. }
  171. lock (Core.Lock)
  172. {
  173. if (Core.IsAbandoned)
  174. {
  175. return Status.NoInit;
  176. }
  177. Core.ConsumerListener = consumerListener;
  178. Core.ConsumerControlledByApp = controlledByApp;
  179. }
  180. return Status.Success;
  181. }
  182. public Status Disconnect()
  183. {
  184. lock (Core.Lock)
  185. {
  186. if (!Core.IsConsumerConnectedLocked())
  187. {
  188. return Status.BadValue;
  189. }
  190. Core.IsAbandoned = true;
  191. Core.ConsumerListener = null;
  192. Core.Queue.Clear();
  193. Core.FreeAllBuffersLocked();
  194. Core.SignalDequeueEvent();
  195. }
  196. return Status.Success;
  197. }
  198. public Status GetReleasedBuffers(out ulong slotMask)
  199. {
  200. slotMask = 0;
  201. lock (Core.Lock)
  202. {
  203. if (Core.IsAbandoned)
  204. {
  205. return Status.BadValue;
  206. }
  207. for (int slot = 0; slot < Core.Slots.Length; slot++)
  208. {
  209. if (!Core.Slots[slot].AcquireCalled)
  210. {
  211. slotMask |= 1UL << slot;
  212. }
  213. }
  214. for (int i = 0; i < Core.Queue.Count; i++)
  215. {
  216. if (Core.Queue[i].AcquireCalled)
  217. {
  218. slotMask &= ~(1UL << i);
  219. }
  220. }
  221. }
  222. return Status.Success;
  223. }
  224. public Status SetDefaultBufferSize(uint width, uint height)
  225. {
  226. if (width == 0 || height == 0)
  227. {
  228. return Status.BadValue;
  229. }
  230. lock (Core.Lock)
  231. {
  232. Core.DefaultWidth = (int)width;
  233. Core.DefaultHeight = (int)height;
  234. }
  235. return Status.Success;
  236. }
  237. public Status SetDefaultMaxBufferCount(int bufferMaxCount)
  238. {
  239. lock (Core.Lock)
  240. {
  241. return Core.SetDefaultMaxBufferCountLocked(bufferMaxCount);
  242. }
  243. }
  244. public Status DisableAsyncBuffer()
  245. {
  246. lock (Core.Lock)
  247. {
  248. if (Core.IsConsumerConnectedLocked())
  249. {
  250. return Status.InvalidOperation;
  251. }
  252. Core.UseAsyncBuffer = false;
  253. }
  254. return Status.Success;
  255. }
  256. public Status SetMaxAcquiredBufferCount(int maxAcquiredBufferCount)
  257. {
  258. if (maxAcquiredBufferCount < 0 || maxAcquiredBufferCount > BufferSlotArray.MaxAcquiredBuffers)
  259. {
  260. return Status.BadValue;
  261. }
  262. lock (Core.Lock)
  263. {
  264. if (Core.IsProducerConnectedLocked())
  265. {
  266. return Status.InvalidOperation;
  267. }
  268. Core.MaxAcquiredBufferCount = maxAcquiredBufferCount;
  269. }
  270. return Status.Success;
  271. }
  272. public Status SetDefaultBufferFormat(PixelFormat defaultFormat)
  273. {
  274. lock (Core.Lock)
  275. {
  276. Core.DefaultBufferFormat = defaultFormat;
  277. }
  278. return Status.Success;
  279. }
  280. public Status SetConsumerUsageBits(uint usage)
  281. {
  282. lock (Core.Lock)
  283. {
  284. Core.ConsumerUsageBits = usage;
  285. }
  286. return Status.Success;
  287. }
  288. public Status SetTransformHint(NativeWindowTransform transformHint)
  289. {
  290. lock (Core.Lock)
  291. {
  292. Core.TransformHint = transformHint;
  293. }
  294. return Status.Success;
  295. }
  296. }
  297. }