IApplicationDisplayService.cs 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287
  1. using ARMeilleure.Memory;
  2. using Ryujinx.HLE.HOS.Ipc;
  3. using Ryujinx.HLE.HOS.Kernel.Common;
  4. using System;
  5. using System.IO;
  6. using System.Text;
  7. using static Ryujinx.HLE.HOS.Services.Android.Parcel;
  8. namespace Ryujinx.HLE.HOS.Services.Vi
  9. {
  10. class IApplicationDisplayService : IpcService
  11. {
  12. private IdDictionary _displays;
  13. public IApplicationDisplayService()
  14. {
  15. _displays = new IdDictionary();
  16. }
  17. [Command(100)]
  18. // GetRelayService() -> object<nns::hosbinder::IHOSBinderDriver>
  19. public ResultCode GetRelayService(ServiceCtx context)
  20. {
  21. MakeObject(context, new IHOSBinderDriver(
  22. context.Device.System,
  23. context.Device.Gpu.Renderer));
  24. return ResultCode.Success;
  25. }
  26. [Command(101)]
  27. // GetSystemDisplayService() -> object<nn::visrv::sf::ISystemDisplayService>
  28. public ResultCode GetSystemDisplayService(ServiceCtx context)
  29. {
  30. MakeObject(context, new ISystemDisplayService(this));
  31. return ResultCode.Success;
  32. }
  33. [Command(102)]
  34. // GetManagerDisplayService() -> object<nn::visrv::sf::IManagerDisplayService>
  35. public ResultCode GetManagerDisplayService(ServiceCtx context)
  36. {
  37. MakeObject(context, new IManagerDisplayService(this));
  38. return ResultCode.Success;
  39. }
  40. [Command(103)] // 2.0.0+
  41. // GetIndirectDisplayTransactionService() -> object<nns::hosbinder::IHOSBinderDriver>
  42. public ResultCode GetIndirectDisplayTransactionService(ServiceCtx context)
  43. {
  44. MakeObject(context, new IHOSBinderDriver(
  45. context.Device.System,
  46. context.Device.Gpu.Renderer));
  47. return ResultCode.Success;
  48. }
  49. [Command(1000)]
  50. // ListDisplays() -> (u64, buffer<nn::vi::DisplayInfo, 6>)
  51. public ResultCode ListDisplays(ServiceCtx context)
  52. {
  53. long recBuffPtr = context.Request.ReceiveBuff[0].Position;
  54. MemoryHelper.FillWithZeros(context.Memory, recBuffPtr, 0x60);
  55. // Add only the default display to buffer
  56. context.Memory.WriteBytes(recBuffPtr, Encoding.ASCII.GetBytes("Default"));
  57. context.Memory.WriteInt64(recBuffPtr + 0x40, 0x1L);
  58. context.Memory.WriteInt64(recBuffPtr + 0x48, 0x1L);
  59. context.Memory.WriteInt64(recBuffPtr + 0x50, 1920L);
  60. context.Memory.WriteInt64(recBuffPtr + 0x58, 1080L);
  61. context.ResponseData.Write(1L);
  62. return ResultCode.Success;
  63. }
  64. [Command(1010)]
  65. // OpenDisplay(nn::vi::DisplayName) -> u64
  66. public ResultCode OpenDisplay(ServiceCtx context)
  67. {
  68. string name = GetDisplayName(context);
  69. long displayId = _displays.Add(new Display(name));
  70. context.ResponseData.Write(displayId);
  71. return ResultCode.Success;
  72. }
  73. [Command(1020)]
  74. // CloseDisplay(u64)
  75. public ResultCode CloseDisplay(ServiceCtx context)
  76. {
  77. int displayId = context.RequestData.ReadInt32();
  78. _displays.Delete(displayId);
  79. return ResultCode.Success;
  80. }
  81. [Command(1102)]
  82. // GetDisplayResolution(u64) -> (u64, u64)
  83. public ResultCode GetDisplayResolution(ServiceCtx context)
  84. {
  85. long displayId = context.RequestData.ReadInt32();
  86. context.ResponseData.Write(1280);
  87. context.ResponseData.Write(720);
  88. return ResultCode.Success;
  89. }
  90. [Command(2020)]
  91. // OpenLayer(nn::vi::DisplayName, u64, nn::applet::AppletResourceUserId, pid) -> (u64, buffer<bytes, 6>)
  92. public ResultCode OpenLayer(ServiceCtx context)
  93. {
  94. long layerId = context.RequestData.ReadInt64();
  95. long userId = context.RequestData.ReadInt64();
  96. long parcelPtr = context.Request.ReceiveBuff[0].Position;
  97. byte[] parcel = MakeIGraphicsBufferProducer(parcelPtr);
  98. context.Memory.WriteBytes(parcelPtr, parcel);
  99. context.ResponseData.Write((long)parcel.Length);
  100. return ResultCode.Success;
  101. }
  102. [Command(2021)]
  103. // CloseLayer(u64)
  104. public ResultCode CloseLayer(ServiceCtx context)
  105. {
  106. long layerId = context.RequestData.ReadInt64();
  107. return ResultCode.Success;
  108. }
  109. [Command(2030)]
  110. // CreateStrayLayer(u32, u64) -> (u64, u64, buffer<bytes, 6>)
  111. public ResultCode CreateStrayLayer(ServiceCtx context)
  112. {
  113. long layerFlags = context.RequestData.ReadInt64();
  114. long displayId = context.RequestData.ReadInt64();
  115. long parcelPtr = context.Request.ReceiveBuff[0].Position;
  116. Display disp = _displays.GetData<Display>((int)displayId);
  117. byte[] parcel = MakeIGraphicsBufferProducer(parcelPtr);
  118. context.Memory.WriteBytes(parcelPtr, parcel);
  119. context.ResponseData.Write(0L);
  120. context.ResponseData.Write((long)parcel.Length);
  121. return ResultCode.Success;
  122. }
  123. [Command(2031)]
  124. // DestroyStrayLayer(u64)
  125. public ResultCode DestroyStrayLayer(ServiceCtx context)
  126. {
  127. return ResultCode.Success;
  128. }
  129. [Command(2101)]
  130. // SetLayerScalingMode(u32, u64)
  131. public ResultCode SetLayerScalingMode(ServiceCtx context)
  132. {
  133. int scalingMode = context.RequestData.ReadInt32();
  134. long unknown = context.RequestData.ReadInt64();
  135. return ResultCode.Success;
  136. }
  137. [Command(2102)] // 5.0.0+
  138. // ConvertScalingMode(unknown) -> unknown
  139. public ResultCode ConvertScalingMode(ServiceCtx context)
  140. {
  141. SrcScalingMode scalingMode = (SrcScalingMode)context.RequestData.ReadInt32();
  142. DstScalingMode? convertedScalingMode = ConvertScalingMode(scalingMode);
  143. if (!convertedScalingMode.HasValue)
  144. {
  145. // Scaling mode out of the range of valid values.
  146. return ResultCode.InvalidArguments;
  147. }
  148. if (scalingMode != SrcScalingMode.ScaleToWindow &&
  149. scalingMode != SrcScalingMode.PreserveAspectRatio)
  150. {
  151. // Invalid scaling mode specified.
  152. return ResultCode.InvalidScalingMode;
  153. }
  154. context.ResponseData.Write((ulong)convertedScalingMode);
  155. return ResultCode.Success;
  156. }
  157. private DstScalingMode? ConvertScalingMode(SrcScalingMode source)
  158. {
  159. switch (source)
  160. {
  161. case SrcScalingMode.None: return DstScalingMode.None;
  162. case SrcScalingMode.Freeze: return DstScalingMode.Freeze;
  163. case SrcScalingMode.ScaleAndCrop: return DstScalingMode.ScaleAndCrop;
  164. case SrcScalingMode.ScaleToWindow: return DstScalingMode.ScaleToWindow;
  165. case SrcScalingMode.PreserveAspectRatio: return DstScalingMode.PreserveAspectRatio;
  166. }
  167. return null;
  168. }
  169. [Command(5202)]
  170. // GetDisplayVsyncEvent(u64) -> handle<copy>
  171. public ResultCode GetDisplayVSyncEvent(ServiceCtx context)
  172. {
  173. string name = GetDisplayName(context);
  174. if (context.Process.HandleTable.GenerateHandle(context.Device.System.VsyncEvent.ReadableEvent, out int handle) != KernelResult.Success)
  175. {
  176. throw new InvalidOperationException("Out of handles!");
  177. }
  178. context.Response.HandleDesc = IpcHandleDesc.MakeCopy(handle);
  179. return ResultCode.Success;
  180. }
  181. private byte[] MakeIGraphicsBufferProducer(long basePtr)
  182. {
  183. long id = 0x20;
  184. long cookiePtr = 0L;
  185. using (MemoryStream ms = new MemoryStream())
  186. {
  187. BinaryWriter writer = new BinaryWriter(ms);
  188. // flat_binder_object (size is 0x28)
  189. writer.Write(2); //Type (BINDER_TYPE_WEAK_BINDER)
  190. writer.Write(0); //Flags
  191. writer.Write((int)(id >> 0));
  192. writer.Write((int)(id >> 32));
  193. writer.Write((int)(cookiePtr >> 0));
  194. writer.Write((int)(cookiePtr >> 32));
  195. writer.Write((byte)'d');
  196. writer.Write((byte)'i');
  197. writer.Write((byte)'s');
  198. writer.Write((byte)'p');
  199. writer.Write((byte)'d');
  200. writer.Write((byte)'r');
  201. writer.Write((byte)'v');
  202. writer.Write((byte)'\0');
  203. writer.Write(0L); //Pad
  204. return MakeParcel(ms.ToArray(), new byte[] { 0, 0, 0, 0 });
  205. }
  206. }
  207. private string GetDisplayName(ServiceCtx context)
  208. {
  209. string name = string.Empty;
  210. for (int index = 0; index < 8 &&
  211. context.RequestData.BaseStream.Position <
  212. context.RequestData.BaseStream.Length; index++)
  213. {
  214. byte chr = context.RequestData.ReadByte();
  215. if (chr >= 0x20 && chr < 0x7f)
  216. {
  217. name += (char)chr;
  218. }
  219. }
  220. return name;
  221. }
  222. }
  223. }