IGraphicBufferProducer.cs 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  1. using Ryujinx.Common.Logging;
  2. using Ryujinx.HLE.HOS.Kernel.Threading;
  3. using Ryujinx.HLE.HOS.Services.SurfaceFlinger.Types;
  4. using System;
  5. using System.Runtime.CompilerServices;
  6. using System.Runtime.InteropServices;
  7. namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
  8. {
  9. abstract class IGraphicBufferProducer : IBinder
  10. {
  11. public string InterfaceToken => "android.gui.IGraphicBufferProducer";
  12. enum TransactionCode : uint
  13. {
  14. RequestBuffer = 1,
  15. SetBufferCount,
  16. DequeueBuffer,
  17. DetachBuffer,
  18. DetachNextBuffer,
  19. AttachBuffer,
  20. QueueBuffer,
  21. CancelBuffer,
  22. Query,
  23. Connect,
  24. Disconnect,
  25. SetSidebandStream,
  26. AllocateBuffers,
  27. SetPreallocatedBuffer,
  28. Reserved15,
  29. GetBufferInfo,
  30. GetBufferHistory
  31. }
  32. [StructLayout(LayoutKind.Sequential, Pack = 1, Size = 0x54)]
  33. public struct QueueBufferInput : IFlattenable
  34. {
  35. public long Timestamp;
  36. public int IsAutoTimestamp;
  37. public Rect Crop;
  38. public NativeWindowScalingMode ScalingMode;
  39. public NativeWindowTransform Transform;
  40. public uint StickyTransform;
  41. public int Async;
  42. public int SwapInterval;
  43. public AndroidFence Fence;
  44. public void Flatten(Parcel parcel)
  45. {
  46. parcel.WriteUnmanagedType(ref this);
  47. }
  48. public uint GetFdCount()
  49. {
  50. return 0;
  51. }
  52. public uint GetFlattenedSize()
  53. {
  54. return (uint)Unsafe.SizeOf<QueueBufferInput>();
  55. }
  56. public void Unflatten(Parcel parcel)
  57. {
  58. this = parcel.ReadUnmanagedType<QueueBufferInput>();
  59. }
  60. }
  61. public struct QueueBufferOutput
  62. {
  63. public uint Width;
  64. public uint Height;
  65. public NativeWindowTransform TransformHint;
  66. public uint NumPendingBuffers;
  67. }
  68. public ResultCode AdjustRefcount(int addVal, int type)
  69. {
  70. // TODO?
  71. return ResultCode.Success;
  72. }
  73. public void GetNativeHandle(uint typeId, out KReadableEvent readableEvent)
  74. {
  75. if (typeId == 0xF)
  76. {
  77. readableEvent = GetWaitBufferFreeEvent();
  78. }
  79. else
  80. {
  81. throw new NotImplementedException($"Unimplemented native event type {typeId}!");
  82. }
  83. }
  84. public void OnTransact(uint code, uint flags, Parcel inputParcel, Parcel outputParcel)
  85. {
  86. Status status = Status.Success;
  87. int slot;
  88. AndroidFence fence;
  89. QueueBufferInput queueInput;
  90. QueueBufferOutput queueOutput;
  91. NativeWindowApi api;
  92. AndroidStrongPointer<GraphicBuffer> graphicBuffer;
  93. AndroidStrongPointer<AndroidFence> strongFence;
  94. switch ((TransactionCode)code)
  95. {
  96. case TransactionCode.RequestBuffer:
  97. slot = inputParcel.ReadInt32();
  98. status = RequestBuffer(slot, out graphicBuffer);
  99. outputParcel.WriteStrongPointer(ref graphicBuffer);
  100. outputParcel.WriteStatus(status);
  101. break;
  102. case TransactionCode.SetBufferCount:
  103. int bufferCount = inputParcel.ReadInt32();
  104. status = SetBufferCount(bufferCount);
  105. outputParcel.WriteStatus(status);
  106. break;
  107. case TransactionCode.DequeueBuffer:
  108. bool async = inputParcel.ReadBoolean();
  109. uint width = inputParcel.ReadUInt32();
  110. uint height = inputParcel.ReadUInt32();
  111. PixelFormat format = inputParcel.ReadUnmanagedType<PixelFormat>();
  112. uint usage = inputParcel.ReadUInt32();
  113. status = DequeueBuffer(out int dequeueSlot, out fence, async, width, height, format, usage);
  114. strongFence = new AndroidStrongPointer<AndroidFence>(fence);
  115. outputParcel.WriteInt32(dequeueSlot);
  116. outputParcel.WriteStrongPointer(ref strongFence);
  117. outputParcel.WriteStatus(status);
  118. break;
  119. case TransactionCode.DetachBuffer:
  120. slot = inputParcel.ReadInt32();
  121. status = DetachBuffer(slot);
  122. outputParcel.WriteStatus(status);
  123. break;
  124. case TransactionCode.DetachNextBuffer:
  125. status = DetachNextBuffer(out graphicBuffer, out fence);
  126. strongFence = new AndroidStrongPointer<AndroidFence>(fence);
  127. outputParcel.WriteStrongPointer(ref graphicBuffer);
  128. outputParcel.WriteStrongPointer(ref strongFence);
  129. outputParcel.WriteStatus(status);
  130. break;
  131. case TransactionCode.AttachBuffer:
  132. graphicBuffer = inputParcel.ReadStrongPointer<GraphicBuffer>();
  133. status = AttachBuffer(out slot, graphicBuffer);
  134. outputParcel.WriteInt32(slot);
  135. outputParcel.WriteStatus(status);
  136. break;
  137. case TransactionCode.QueueBuffer:
  138. slot = inputParcel.ReadInt32();
  139. queueInput = inputParcel.ReadFlattenable<QueueBufferInput>();
  140. status = QueueBuffer(slot, ref queueInput, out queueOutput);
  141. outputParcel.WriteUnmanagedType(ref queueOutput);
  142. outputParcel.WriteStatus(status);
  143. break;
  144. case TransactionCode.CancelBuffer:
  145. slot = inputParcel.ReadInt32();
  146. fence = inputParcel.ReadFlattenable<AndroidFence>();
  147. CancelBuffer(slot, ref fence);
  148. outputParcel.WriteStatus(Status.Success);
  149. break;
  150. case TransactionCode.Query:
  151. NativeWindowAttribute what = inputParcel.ReadUnmanagedType<NativeWindowAttribute>();
  152. status = Query(what, out int outValue);
  153. outputParcel.WriteInt32(outValue);
  154. outputParcel.WriteStatus(status);
  155. break;
  156. case TransactionCode.Connect:
  157. bool hasListener = inputParcel.ReadBoolean();
  158. IProducerListener listener = null;
  159. if (hasListener)
  160. {
  161. throw new NotImplementedException("Connect with a strong binder listener isn't implemented");
  162. }
  163. api = inputParcel.ReadUnmanagedType<NativeWindowApi>();
  164. bool producerControlledByApp = inputParcel.ReadBoolean();
  165. status = Connect(listener, api, producerControlledByApp, out queueOutput);
  166. outputParcel.WriteUnmanagedType(ref queueOutput);
  167. outputParcel.WriteStatus(status);
  168. break;
  169. case TransactionCode.Disconnect:
  170. api = inputParcel.ReadUnmanagedType<NativeWindowApi>();
  171. status = Disconnect(api);
  172. outputParcel.WriteStatus(status);
  173. break;
  174. case TransactionCode.SetPreallocatedBuffer:
  175. slot = inputParcel.ReadInt32();
  176. graphicBuffer = inputParcel.ReadStrongPointer<GraphicBuffer>();
  177. status = SetPreallocatedBuffer(slot, graphicBuffer);
  178. outputParcel.WriteStatus(status);
  179. break;
  180. default:
  181. throw new NotImplementedException($"Transaction {(TransactionCode)code} not implemented");
  182. }
  183. if (status != Status.Success)
  184. {
  185. Logger.PrintError(LogClass.SurfaceFlinger, $"Error returned by transaction {(TransactionCode)code}: {status}");
  186. }
  187. }
  188. protected abstract KReadableEvent GetWaitBufferFreeEvent();
  189. public abstract Status RequestBuffer(int slot, out AndroidStrongPointer<GraphicBuffer> graphicBuffer);
  190. public abstract Status SetBufferCount(int bufferCount);
  191. public abstract Status DequeueBuffer(out int slot, out AndroidFence fence, bool async, uint width, uint height, PixelFormat format, uint usage);
  192. public abstract Status DetachBuffer(int slot);
  193. public abstract Status DetachNextBuffer(out AndroidStrongPointer<GraphicBuffer> graphicBuffer, out AndroidFence fence);
  194. public abstract Status AttachBuffer(out int slot, AndroidStrongPointer<GraphicBuffer> graphicBuffer);
  195. public abstract Status QueueBuffer(int slot, ref QueueBufferInput input, out QueueBufferOutput output);
  196. public abstract void CancelBuffer(int slot, ref AndroidFence fence);
  197. public abstract Status Query(NativeWindowAttribute what, out int outValue);
  198. public abstract Status Connect(IProducerListener listener, NativeWindowApi api, bool producerControlledByApp, out QueueBufferOutput output);
  199. public abstract Status Disconnect(NativeWindowApi api);
  200. public abstract Status SetPreallocatedBuffer(int slot, AndroidStrongPointer<GraphicBuffer> graphicBuffer);
  201. }
  202. }