vi.cpp 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814
  1. // Copyright 2018 yuzu emulator team
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. #include <algorithm>
  5. #include <array>
  6. #include "common/alignment.h"
  7. #include "common/scope_exit.h"
  8. #include "core/core_timing.h"
  9. #include "core/hle/ipc_helpers.h"
  10. #include "core/hle/service/nvflinger/buffer_queue.h"
  11. #include "core/hle/service/vi/vi.h"
  12. #include "core/hle/service/vi/vi_m.h"
  13. #include "core/hle/service/vi/vi_s.h"
  14. #include "core/hle/service/vi/vi_u.h"
  15. #include "video_core/renderer_base.h"
  16. #include "video_core/video_core.h"
  17. namespace Service {
  18. namespace VI {
  19. struct DisplayInfo {
  20. char display_name[0x40]{"Default"};
  21. u64 unknown_1{1};
  22. u64 unknown_2{1};
  23. u64 width{1920};
  24. u64 height{1080};
  25. };
  26. static_assert(sizeof(DisplayInfo) == 0x60, "DisplayInfo has wrong size");
  27. class Parcel {
  28. public:
  29. // This default size was chosen arbitrarily.
  30. static constexpr size_t DefaultBufferSize = 0x40;
  31. Parcel() : buffer(DefaultBufferSize) {}
  32. explicit Parcel(std::vector<u8> data) : buffer(std::move(data)) {}
  33. virtual ~Parcel() = default;
  34. template <typename T>
  35. T Read() {
  36. T val;
  37. std::memcpy(&val, buffer.data() + read_index, sizeof(T));
  38. read_index += sizeof(T);
  39. read_index = Common::AlignUp(read_index, 4);
  40. return val;
  41. }
  42. template <typename T>
  43. T ReadUnaligned() {
  44. T val;
  45. std::memcpy(&val, buffer.data() + read_index, sizeof(T));
  46. read_index += sizeof(T);
  47. return val;
  48. }
  49. std::vector<u8> ReadBlock(size_t length) {
  50. const u8* const begin = buffer.data() + read_index;
  51. const u8* const end = begin + length;
  52. std::vector<u8> data(begin, end);
  53. read_index += length;
  54. read_index = Common::AlignUp(read_index, 4);
  55. return data;
  56. }
  57. std::u16string ReadInterfaceToken() {
  58. u32 unknown = Read<u32_le>();
  59. u32 length = Read<u32_le>();
  60. std::u16string token{};
  61. for (u32 ch = 0; ch < length + 1; ++ch) {
  62. token.push_back(ReadUnaligned<u16_le>());
  63. }
  64. read_index = Common::AlignUp(read_index, 4);
  65. return token;
  66. }
  67. template <typename T>
  68. void Write(const T& val) {
  69. if (buffer.size() < write_index + sizeof(T))
  70. buffer.resize(buffer.size() + sizeof(T) + DefaultBufferSize);
  71. std::memcpy(buffer.data() + write_index, &val, sizeof(T));
  72. write_index += sizeof(T);
  73. write_index = Common::AlignUp(write_index, 4);
  74. }
  75. void Deserialize() {
  76. Header header{};
  77. std::memcpy(&header, buffer.data(), sizeof(Header));
  78. read_index = header.data_offset;
  79. DeserializeData();
  80. }
  81. std::vector<u8> Serialize() {
  82. ASSERT(read_index == 0);
  83. write_index = sizeof(Header);
  84. SerializeData();
  85. Header header{};
  86. header.data_size = static_cast<u32_le>(write_index - sizeof(Header));
  87. header.data_offset = sizeof(Header);
  88. header.objects_size = 4;
  89. header.objects_offset = sizeof(Header) + header.data_size;
  90. std::memcpy(buffer.data(), &header, sizeof(Header));
  91. return buffer;
  92. }
  93. protected:
  94. virtual void SerializeData() {}
  95. virtual void DeserializeData() {}
  96. private:
  97. struct Header {
  98. u32_le data_size;
  99. u32_le data_offset;
  100. u32_le objects_size;
  101. u32_le objects_offset;
  102. };
  103. static_assert(sizeof(Header) == 16, "ParcelHeader has wrong size");
  104. std::vector<u8> buffer;
  105. size_t read_index = 0;
  106. size_t write_index = 0;
  107. };
  108. class NativeWindow : public Parcel {
  109. public:
  110. explicit NativeWindow(u32 id) : Parcel() {
  111. data.id = id;
  112. }
  113. ~NativeWindow() override = default;
  114. protected:
  115. void SerializeData() override {
  116. Write(data);
  117. }
  118. private:
  119. struct Data {
  120. u32_le magic = 2;
  121. u32_le process_id = 1;
  122. u32_le id;
  123. INSERT_PADDING_WORDS(3);
  124. std::array<u8, 8> dispdrv = {'d', 'i', 's', 'p', 'd', 'r', 'v', '\0'};
  125. INSERT_PADDING_WORDS(2);
  126. };
  127. static_assert(sizeof(Data) == 0x28, "ParcelData has wrong size");
  128. Data data{};
  129. };
  130. class IGBPConnectRequestParcel : public Parcel {
  131. public:
  132. explicit IGBPConnectRequestParcel(const std::vector<u8>& buffer) : Parcel(buffer) {
  133. Deserialize();
  134. }
  135. ~IGBPConnectRequestParcel() override = default;
  136. void DeserializeData() override {
  137. std::u16string token = ReadInterfaceToken();
  138. data = Read<Data>();
  139. }
  140. struct Data {
  141. u32_le unk;
  142. u32_le api;
  143. u32_le producer_controlled_by_app;
  144. };
  145. Data data;
  146. };
  147. class IGBPConnectResponseParcel : public Parcel {
  148. public:
  149. explicit IGBPConnectResponseParcel(u32 width, u32 height) : Parcel() {
  150. data.width = width;
  151. data.height = height;
  152. }
  153. ~IGBPConnectResponseParcel() override = default;
  154. protected:
  155. void SerializeData() override {
  156. Write(data);
  157. }
  158. private:
  159. struct Data {
  160. u32_le width;
  161. u32_le height;
  162. u32_le transform_hint;
  163. u32_le num_pending_buffers;
  164. u32_le status;
  165. };
  166. static_assert(sizeof(Data) == 20, "ParcelData has wrong size");
  167. Data data{};
  168. };
  169. class IGBPSetPreallocatedBufferRequestParcel : public Parcel {
  170. public:
  171. explicit IGBPSetPreallocatedBufferRequestParcel(const std::vector<u8>& buffer)
  172. : Parcel(buffer) {
  173. Deserialize();
  174. }
  175. ~IGBPSetPreallocatedBufferRequestParcel() override = default;
  176. void DeserializeData() override {
  177. std::u16string token = ReadInterfaceToken();
  178. data = Read<Data>();
  179. buffer = Read<NVFlinger::IGBPBuffer>();
  180. }
  181. struct Data {
  182. u32_le slot;
  183. INSERT_PADDING_WORDS(1);
  184. u32_le graphic_buffer_length;
  185. INSERT_PADDING_WORDS(1);
  186. };
  187. Data data;
  188. NVFlinger::IGBPBuffer buffer;
  189. };
  190. class IGBPSetPreallocatedBufferResponseParcel : public Parcel {
  191. public:
  192. IGBPSetPreallocatedBufferResponseParcel() : Parcel() {}
  193. ~IGBPSetPreallocatedBufferResponseParcel() override = default;
  194. protected:
  195. void SerializeData() override {
  196. // TODO(Subv): Find out what this means
  197. Write<u32>(0);
  198. }
  199. };
  200. class IGBPDequeueBufferRequestParcel : public Parcel {
  201. public:
  202. explicit IGBPDequeueBufferRequestParcel(const std::vector<u8>& buffer) : Parcel(buffer) {
  203. Deserialize();
  204. }
  205. ~IGBPDequeueBufferRequestParcel() override = default;
  206. void DeserializeData() override {
  207. std::u16string token = ReadInterfaceToken();
  208. data = Read<Data>();
  209. }
  210. struct Data {
  211. u32_le pixel_format;
  212. u32_le width;
  213. u32_le height;
  214. u32_le get_frame_timestamps;
  215. u32_le usage;
  216. };
  217. Data data;
  218. };
  219. class IGBPDequeueBufferResponseParcel : public Parcel {
  220. public:
  221. explicit IGBPDequeueBufferResponseParcel(u32 slot) : Parcel(), slot(slot) {}
  222. ~IGBPDequeueBufferResponseParcel() override = default;
  223. protected:
  224. void SerializeData() override {
  225. Write(slot);
  226. // TODO(Subv): Find out how this Fence is used.
  227. std::array<u32_le, 11> fence = {};
  228. Write(fence);
  229. Write<u32_le>(0);
  230. }
  231. u32_le slot;
  232. };
  233. class IGBPRequestBufferRequestParcel : public Parcel {
  234. public:
  235. explicit IGBPRequestBufferRequestParcel(const std::vector<u8>& buffer) : Parcel(buffer) {
  236. Deserialize();
  237. }
  238. ~IGBPRequestBufferRequestParcel() override = default;
  239. void DeserializeData() override {
  240. std::u16string token = ReadInterfaceToken();
  241. slot = Read<u32_le>();
  242. }
  243. u32_le slot;
  244. };
  245. class IGBPRequestBufferResponseParcel : public Parcel {
  246. public:
  247. explicit IGBPRequestBufferResponseParcel(NVFlinger::IGBPBuffer buffer)
  248. : Parcel(), buffer(buffer) {}
  249. ~IGBPRequestBufferResponseParcel() override = default;
  250. protected:
  251. void SerializeData() override {
  252. // TODO(bunnei): Find out what this all means. Writing anything non-zero here breaks libnx.
  253. Write<u32_le>(0);
  254. Write<u32_le>(0);
  255. Write<u32_le>(0);
  256. Write(buffer);
  257. Write<u32_le>(0);
  258. }
  259. NVFlinger::IGBPBuffer buffer;
  260. };
  261. class IGBPQueueBufferRequestParcel : public Parcel {
  262. public:
  263. explicit IGBPQueueBufferRequestParcel(const std::vector<u8>& buffer) : Parcel(buffer) {
  264. Deserialize();
  265. }
  266. ~IGBPQueueBufferRequestParcel() override = default;
  267. void DeserializeData() override {
  268. std::u16string token = ReadInterfaceToken();
  269. data = Read<Data>();
  270. }
  271. struct Fence {
  272. u32_le id;
  273. u32_le value;
  274. };
  275. static_assert(sizeof(Fence) == 8, "Fence has wrong size");
  276. struct Data {
  277. u32_le slot;
  278. INSERT_PADDING_WORDS(3);
  279. u32_le timestamp;
  280. s32_le is_auto_timestamp;
  281. s32_le crop_left;
  282. s32_le crop_top;
  283. s32_le crop_right;
  284. s32_le crop_bottom;
  285. s32_le scaling_mode;
  286. NVFlinger::BufferQueue::BufferTransformFlags transform;
  287. u32_le sticky_transform;
  288. INSERT_PADDING_WORDS(2);
  289. u32_le fence_is_valid;
  290. std::array<Fence, 2> fences;
  291. };
  292. static_assert(sizeof(Data) == 80, "ParcelData has wrong size");
  293. Data data;
  294. };
  295. class IGBPQueueBufferResponseParcel : public Parcel {
  296. public:
  297. explicit IGBPQueueBufferResponseParcel(u32 width, u32 height) : Parcel() {
  298. data.width = width;
  299. data.height = height;
  300. }
  301. ~IGBPQueueBufferResponseParcel() override = default;
  302. protected:
  303. void SerializeData() override {
  304. Write(data);
  305. }
  306. private:
  307. struct Data {
  308. u32_le width;
  309. u32_le height;
  310. u32_le transform_hint;
  311. u32_le num_pending_buffers;
  312. u32_le status;
  313. };
  314. static_assert(sizeof(Data) == 20, "ParcelData has wrong size");
  315. Data data{};
  316. };
  317. class IGBPQueryRequestParcel : public Parcel {
  318. public:
  319. explicit IGBPQueryRequestParcel(const std::vector<u8>& buffer) : Parcel(buffer) {
  320. Deserialize();
  321. }
  322. ~IGBPQueryRequestParcel() override = default;
  323. void DeserializeData() override {
  324. std::u16string token = ReadInterfaceToken();
  325. type = Read<u32_le>();
  326. }
  327. u32 type;
  328. };
  329. class IGBPQueryResponseParcel : public Parcel {
  330. public:
  331. explicit IGBPQueryResponseParcel(u32 value) : Parcel(), value(value) {}
  332. ~IGBPQueryResponseParcel() override = default;
  333. protected:
  334. void SerializeData() override {
  335. Write(value);
  336. }
  337. private:
  338. u32_le value;
  339. };
  340. class IHOSBinderDriver final : public ServiceFramework<IHOSBinderDriver> {
  341. public:
  342. explicit IHOSBinderDriver(std::shared_ptr<NVFlinger::NVFlinger> nv_flinger)
  343. : ServiceFramework("IHOSBinderDriver"), nv_flinger(std::move(nv_flinger)) {
  344. static const FunctionInfo functions[] = {
  345. {0, &IHOSBinderDriver::TransactParcel, "TransactParcel"},
  346. {1, &IHOSBinderDriver::AdjustRefcount, "AdjustRefcount"},
  347. {2, &IHOSBinderDriver::GetNativeHandle, "GetNativeHandle"},
  348. {3, &IHOSBinderDriver::TransactParcelAuto, "TransactParcelAuto"},
  349. };
  350. RegisterHandlers(functions);
  351. }
  352. ~IHOSBinderDriver() = default;
  353. private:
  354. enum class TransactionId {
  355. RequestBuffer = 1,
  356. SetBufferCount = 2,
  357. DequeueBuffer = 3,
  358. DetachBuffer = 4,
  359. DetachNextBuffer = 5,
  360. AttachBuffer = 6,
  361. QueueBuffer = 7,
  362. CancelBuffer = 8,
  363. Query = 9,
  364. Connect = 10,
  365. Disconnect = 11,
  366. AllocateBuffers = 13,
  367. SetPreallocatedBuffer = 14
  368. };
  369. void TransactParcel(u32 id, TransactionId transaction, const std::vector<u8>& input_data,
  370. VAddr output_addr, u64 output_size) {
  371. auto buffer_queue = nv_flinger->GetBufferQueue(id);
  372. std::vector<u8> response_buffer;
  373. if (transaction == TransactionId::Connect) {
  374. IGBPConnectRequestParcel request{input_data};
  375. IGBPConnectResponseParcel response{1280, 720};
  376. response_buffer = response.Serialize();
  377. } else if (transaction == TransactionId::SetPreallocatedBuffer) {
  378. IGBPSetPreallocatedBufferRequestParcel request{input_data};
  379. buffer_queue->SetPreallocatedBuffer(request.data.slot, request.buffer);
  380. IGBPSetPreallocatedBufferResponseParcel response{};
  381. response_buffer = response.Serialize();
  382. } else if (transaction == TransactionId::DequeueBuffer) {
  383. IGBPDequeueBufferRequestParcel request{input_data};
  384. u32 slot = buffer_queue->DequeueBuffer(request.data.pixel_format, request.data.width,
  385. request.data.height);
  386. IGBPDequeueBufferResponseParcel response{slot};
  387. response_buffer = response.Serialize();
  388. } else if (transaction == TransactionId::RequestBuffer) {
  389. IGBPRequestBufferRequestParcel request{input_data};
  390. auto& buffer = buffer_queue->RequestBuffer(request.slot);
  391. IGBPRequestBufferResponseParcel response{buffer};
  392. response_buffer = response.Serialize();
  393. } else if (transaction == TransactionId::QueueBuffer) {
  394. IGBPQueueBufferRequestParcel request{input_data};
  395. buffer_queue->QueueBuffer(request.data.slot, request.data.transform);
  396. IGBPQueueBufferResponseParcel response{1280, 720};
  397. response_buffer = response.Serialize();
  398. } else if (transaction == TransactionId::Query) {
  399. IGBPQueryRequestParcel request{input_data};
  400. u32 value =
  401. buffer_queue->Query(static_cast<NVFlinger::BufferQueue::QueryType>(request.type));
  402. IGBPQueryResponseParcel response{value};
  403. response_buffer = response.Serialize();
  404. } else {
  405. ASSERT_MSG(false, "Unimplemented");
  406. }
  407. Memory::WriteBlock(output_addr, response_buffer.data(), output_size);
  408. }
  409. void TransactParcel(Kernel::HLERequestContext& ctx) {
  410. IPC::RequestParser rp{ctx};
  411. u32 id = rp.Pop<u32>();
  412. auto transaction = static_cast<TransactionId>(rp.Pop<u32>());
  413. u32 flags = rp.Pop<u32>();
  414. LOG_DEBUG(Service_VI, "called, transaction=%x", transaction);
  415. auto& input_buffer = ctx.BufferDescriptorA()[0];
  416. auto& output_buffer = ctx.BufferDescriptorB()[0];
  417. std::vector<u8> input_data(input_buffer.Size());
  418. Memory::ReadBlock(input_buffer.Address(), input_data.data(), input_buffer.Size());
  419. TransactParcel(id, transaction, input_data, output_buffer.Address(), output_buffer.Size());
  420. IPC::ResponseBuilder rb{ctx, 2};
  421. rb.Push(RESULT_SUCCESS);
  422. }
  423. void TransactParcelAuto(Kernel::HLERequestContext& ctx) {
  424. IPC::RequestParser rp{ctx};
  425. u32 id = rp.Pop<u32>();
  426. auto transaction = static_cast<TransactionId>(rp.Pop<u32>());
  427. u32 flags = rp.Pop<u32>();
  428. LOG_DEBUG(Service_VI, "called, transaction=%x", transaction);
  429. auto& input_buffer = ctx.BufferDescriptorX()[0];
  430. auto& output_buffer = ctx.BufferDescriptorC()[0];
  431. std::vector<u8> input_data(input_buffer.size);
  432. Memory::ReadBlock(input_buffer.Address(), input_data.data(), input_buffer.size);
  433. TransactParcel(id, transaction, input_data, output_buffer.Address(), output_buffer.Size());
  434. IPC::ResponseBuilder rb{ctx, 2};
  435. rb.Push(RESULT_SUCCESS);
  436. }
  437. void AdjustRefcount(Kernel::HLERequestContext& ctx) {
  438. IPC::RequestParser rp{ctx};
  439. u32 id = rp.Pop<u32>();
  440. s32 addval = rp.PopRaw<s32>();
  441. u32 type = rp.Pop<u32>();
  442. LOG_WARNING(Service_VI, "(STUBBED) called id=%u, addval=%08X, type=%08X", id, addval, type);
  443. IPC::ResponseBuilder rb{ctx, 2};
  444. rb.Push(RESULT_SUCCESS);
  445. }
  446. void GetNativeHandle(Kernel::HLERequestContext& ctx) {
  447. IPC::RequestParser rp{ctx};
  448. u32 id = rp.Pop<u32>();
  449. u32 unknown = rp.Pop<u32>();
  450. auto buffer_queue = nv_flinger->GetBufferQueue(id);
  451. // TODO(Subv): Find out what this actually is.
  452. LOG_WARNING(Service_VI, "(STUBBED) called id=%u, unknown=%08X", id, unknown);
  453. IPC::ResponseBuilder rb{ctx, 2, 1};
  454. rb.Push(RESULT_SUCCESS);
  455. rb.PushCopyObjects(buffer_queue->GetNativeHandle());
  456. }
  457. std::shared_ptr<NVFlinger::NVFlinger> nv_flinger;
  458. };
  459. class ISystemDisplayService final : public ServiceFramework<ISystemDisplayService> {
  460. public:
  461. ISystemDisplayService() : ServiceFramework("ISystemDisplayService") {
  462. static const FunctionInfo functions[] = {
  463. {1200, nullptr, "GetZOrderCountMin"},
  464. {2205, &ISystemDisplayService::SetLayerZ, "SetLayerZ"},
  465. };
  466. RegisterHandlers(functions);
  467. }
  468. ~ISystemDisplayService() = default;
  469. private:
  470. void SetLayerZ(Kernel::HLERequestContext& ctx) {
  471. LOG_WARNING(Service_VI, "(STUBBED) called");
  472. IPC::RequestParser rp{ctx};
  473. u64 layer_id = rp.Pop<u64>();
  474. u64 z_value = rp.Pop<u64>();
  475. IPC::ResponseBuilder rb = rp.MakeBuilder(2, 0, 0);
  476. rb.Push(RESULT_SUCCESS);
  477. }
  478. };
  479. class IManagerDisplayService final : public ServiceFramework<IManagerDisplayService> {
  480. public:
  481. explicit IManagerDisplayService(std::shared_ptr<NVFlinger::NVFlinger> nv_flinger)
  482. : ServiceFramework("IManagerDisplayService"), nv_flinger(std::move(nv_flinger)) {
  483. static const FunctionInfo functions[] = {
  484. {1020, &IManagerDisplayService::CloseDisplay, "CloseDisplay"},
  485. {1102, nullptr, "GetDisplayResolution"},
  486. {2010, &IManagerDisplayService::CreateManagedLayer, "CreateManagedLayer"},
  487. {6000, &IManagerDisplayService::AddToLayerStack, "AddToLayerStack"},
  488. };
  489. RegisterHandlers(functions);
  490. }
  491. ~IManagerDisplayService() = default;
  492. private:
  493. void CloseDisplay(Kernel::HLERequestContext& ctx) {
  494. LOG_WARNING(Service_VI, "(STUBBED) called");
  495. IPC::RequestParser rp{ctx};
  496. u64 display = rp.Pop<u64>();
  497. IPC::ResponseBuilder rb = rp.MakeBuilder(2, 0, 0);
  498. rb.Push(RESULT_SUCCESS);
  499. }
  500. void CreateManagedLayer(Kernel::HLERequestContext& ctx) {
  501. LOG_WARNING(Service_VI, "(STUBBED) called");
  502. IPC::RequestParser rp{ctx};
  503. u32 unknown = rp.Pop<u32>();
  504. rp.Skip(1, false);
  505. u64 display = rp.Pop<u64>();
  506. u64 aruid = rp.Pop<u64>();
  507. u64 layer_id = nv_flinger->CreateLayer(display);
  508. IPC::ResponseBuilder rb = rp.MakeBuilder(4, 0, 0);
  509. rb.Push(RESULT_SUCCESS);
  510. rb.Push(layer_id);
  511. }
  512. void AddToLayerStack(Kernel::HLERequestContext& ctx) {
  513. LOG_WARNING(Service_VI, "(STUBBED) called");
  514. IPC::RequestParser rp{ctx};
  515. u32 stack = rp.Pop<u32>();
  516. u64 layer_id = rp.Pop<u64>();
  517. IPC::ResponseBuilder rb = rp.MakeBuilder(2, 0, 0);
  518. rb.Push(RESULT_SUCCESS);
  519. }
  520. std::shared_ptr<NVFlinger::NVFlinger> nv_flinger;
  521. };
  522. void IApplicationDisplayService::GetRelayService(Kernel::HLERequestContext& ctx) {
  523. LOG_WARNING(Service_VI, "(STUBBED) called");
  524. IPC::ResponseBuilder rb{ctx, 2, 0, 1};
  525. rb.Push(RESULT_SUCCESS);
  526. rb.PushIpcInterface<IHOSBinderDriver>(nv_flinger);
  527. }
  528. void IApplicationDisplayService::GetSystemDisplayService(Kernel::HLERequestContext& ctx) {
  529. LOG_WARNING(Service_VI, "(STUBBED) called");
  530. IPC::ResponseBuilder rb{ctx, 2, 0, 1};
  531. rb.Push(RESULT_SUCCESS);
  532. rb.PushIpcInterface<ISystemDisplayService>();
  533. }
  534. void IApplicationDisplayService::GetManagerDisplayService(Kernel::HLERequestContext& ctx) {
  535. LOG_WARNING(Service_VI, "(STUBBED) called");
  536. IPC::ResponseBuilder rb{ctx, 2, 0, 1};
  537. rb.Push(RESULT_SUCCESS);
  538. rb.PushIpcInterface<IManagerDisplayService>(nv_flinger);
  539. }
  540. void IApplicationDisplayService::GetIndirectDisplayTransactionService(
  541. Kernel::HLERequestContext& ctx) {
  542. LOG_WARNING(Service_VI, "(STUBBED) called");
  543. IPC::ResponseBuilder rb{ctx, 2, 0, 1};
  544. rb.Push(RESULT_SUCCESS);
  545. rb.PushIpcInterface<IHOSBinderDriver>(nv_flinger);
  546. }
  547. void IApplicationDisplayService::OpenDisplay(Kernel::HLERequestContext& ctx) {
  548. LOG_WARNING(Service_VI, "(STUBBED) called");
  549. IPC::RequestParser rp{ctx};
  550. auto name_buf = rp.PopRaw<std::array<u8, 0x40>>();
  551. auto end = std::find(name_buf.begin(), name_buf.end(), '\0');
  552. std::string name(name_buf.begin(), end);
  553. ASSERT_MSG(name == "Default", "Non-default displays aren't supported yet");
  554. IPC::ResponseBuilder rb = rp.MakeBuilder(4, 0, 0);
  555. rb.Push(RESULT_SUCCESS);
  556. rb.Push<u64>(nv_flinger->OpenDisplay(name));
  557. }
  558. void IApplicationDisplayService::CloseDisplay(Kernel::HLERequestContext& ctx) {
  559. LOG_WARNING(Service_VI, "(STUBBED) called");
  560. IPC::RequestParser rp{ctx};
  561. u64 display_id = rp.Pop<u64>();
  562. IPC::ResponseBuilder rb = rp.MakeBuilder(2, 0, 0);
  563. rb.Push(RESULT_SUCCESS);
  564. }
  565. void IApplicationDisplayService::OpenLayer(Kernel::HLERequestContext& ctx) {
  566. LOG_DEBUG(Service_VI, "called");
  567. IPC::RequestParser rp{ctx};
  568. auto name_buf = rp.PopRaw<std::array<u8, 0x40>>();
  569. auto end = std::find(name_buf.begin(), name_buf.end(), '\0');
  570. std::string display_name(name_buf.begin(), end);
  571. u64 layer_id = rp.Pop<u64>();
  572. u64 aruid = rp.Pop<u64>();
  573. auto& buffer = ctx.BufferDescriptorB()[0];
  574. u64 display_id = nv_flinger->OpenDisplay(display_name);
  575. u32 buffer_queue_id = nv_flinger->GetBufferQueueId(display_id, layer_id);
  576. NativeWindow native_window{buffer_queue_id};
  577. auto data = native_window.Serialize();
  578. Memory::WriteBlock(buffer.Address(), data.data(), data.size());
  579. IPC::ResponseBuilder rb = rp.MakeBuilder(4, 0, 0);
  580. rb.Push(RESULT_SUCCESS);
  581. rb.Push<u64>(data.size());
  582. }
  583. void IApplicationDisplayService::CreateStrayLayer(Kernel::HLERequestContext& ctx) {
  584. LOG_DEBUG(Service_VI, "called");
  585. IPC::RequestParser rp{ctx};
  586. u32 flags = rp.Pop<u32>();
  587. rp.Pop<u32>(); // padding
  588. u64 display_id = rp.Pop<u64>();
  589. auto& buffer = ctx.BufferDescriptorB()[0];
  590. // TODO(Subv): What's the difference between a Stray and a Managed layer?
  591. u64 layer_id = nv_flinger->CreateLayer(display_id);
  592. u32 buffer_queue_id = nv_flinger->GetBufferQueueId(display_id, layer_id);
  593. NativeWindow native_window{buffer_queue_id};
  594. auto data = native_window.Serialize();
  595. Memory::WriteBlock(buffer.Address(), data.data(), data.size());
  596. IPC::ResponseBuilder rb = rp.MakeBuilder(6, 0, 0);
  597. rb.Push(RESULT_SUCCESS);
  598. rb.Push(layer_id);
  599. rb.Push<u64>(data.size());
  600. }
  601. void IApplicationDisplayService::DestroyStrayLayer(Kernel::HLERequestContext& ctx) {
  602. LOG_WARNING(Service_VI, "(STUBBED) called");
  603. IPC::RequestParser rp{ctx};
  604. u64 layer_id = rp.Pop<u64>();
  605. IPC::ResponseBuilder rb = rp.MakeBuilder(2, 0, 0);
  606. rb.Push(RESULT_SUCCESS);
  607. }
  608. void IApplicationDisplayService::SetLayerScalingMode(Kernel::HLERequestContext& ctx) {
  609. LOG_WARNING(Service_VI, "(STUBBED) called");
  610. IPC::RequestParser rp{ctx};
  611. u32 scaling_mode = rp.Pop<u32>();
  612. u64 unknown = rp.Pop<u64>();
  613. IPC::ResponseBuilder rb = rp.MakeBuilder(2, 0, 0);
  614. rb.Push(RESULT_SUCCESS);
  615. }
  616. void IApplicationDisplayService::ListDisplays(Kernel::HLERequestContext& ctx) {
  617. IPC::RequestParser rp{ctx};
  618. DisplayInfo display_info;
  619. auto& buffer = ctx.BufferDescriptorB()[0];
  620. Memory::WriteBlock(buffer.Address(), &display_info, sizeof(DisplayInfo));
  621. IPC::ResponseBuilder rb = rp.MakeBuilder(4, 0, 0);
  622. rb.Push(RESULT_SUCCESS);
  623. rb.Push<u64>(1);
  624. LOG_WARNING(Service_VI, "(STUBBED) called");
  625. }
  626. void IApplicationDisplayService::GetDisplayVsyncEvent(Kernel::HLERequestContext& ctx) {
  627. LOG_WARNING(Service_VI, "(STUBBED) called");
  628. IPC::RequestParser rp{ctx};
  629. u64 display_id = rp.Pop<u64>();
  630. auto vsync_event = nv_flinger->GetVsyncEvent(display_id);
  631. IPC::ResponseBuilder rb = rp.MakeBuilder(2, 1, 0);
  632. rb.Push(RESULT_SUCCESS);
  633. rb.PushCopyObjects(vsync_event);
  634. }
  635. IApplicationDisplayService::IApplicationDisplayService(
  636. std::shared_ptr<NVFlinger::NVFlinger> nv_flinger)
  637. : ServiceFramework("IApplicationDisplayService"), nv_flinger(std::move(nv_flinger)) {
  638. static const FunctionInfo functions[] = {
  639. {100, &IApplicationDisplayService::GetRelayService, "GetRelayService"},
  640. {101, &IApplicationDisplayService::GetSystemDisplayService, "GetSystemDisplayService"},
  641. {102, &IApplicationDisplayService::GetManagerDisplayService, "GetManagerDisplayService"},
  642. {103, &IApplicationDisplayService::GetIndirectDisplayTransactionService,
  643. "GetIndirectDisplayTransactionService"},
  644. {1000, &IApplicationDisplayService::ListDisplays, "ListDisplays"},
  645. {1010, &IApplicationDisplayService::OpenDisplay, "OpenDisplay"},
  646. {1020, &IApplicationDisplayService::CloseDisplay, "CloseDisplay"},
  647. {2101, &IApplicationDisplayService::SetLayerScalingMode, "SetLayerScalingMode"},
  648. {2020, &IApplicationDisplayService::OpenLayer, "OpenLayer"},
  649. {2030, &IApplicationDisplayService::CreateStrayLayer, "CreateStrayLayer"},
  650. {2031, &IApplicationDisplayService::DestroyStrayLayer, "DestroyStrayLayer"},
  651. {5202, &IApplicationDisplayService::GetDisplayVsyncEvent, "GetDisplayVsyncEvent"},
  652. };
  653. RegisterHandlers(functions);
  654. }
  655. void InstallInterfaces(SM::ServiceManager& service_manager,
  656. std::shared_ptr<NVFlinger::NVFlinger> nv_flinger) {
  657. std::make_shared<VI_M>(nv_flinger)->InstallAsService(service_manager);
  658. std::make_shared<VI_S>(nv_flinger)->InstallAsService(service_manager);
  659. std::make_shared<VI_U>(nv_flinger)->InstallAsService(service_manager);
  660. }
  661. } // namespace VI
  662. } // namespace Service