vi.cpp 46 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329
  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 <cstring>
  7. #include <memory>
  8. #include <optional>
  9. #include <type_traits>
  10. #include <utility>
  11. #include "common/alignment.h"
  12. #include "common/assert.h"
  13. #include "common/common_funcs.h"
  14. #include "common/logging/log.h"
  15. #include "common/math_util.h"
  16. #include "common/swap.h"
  17. #include "core/core_timing.h"
  18. #include "core/hle/ipc_helpers.h"
  19. #include "core/hle/kernel/readable_event.h"
  20. #include "core/hle/kernel/thread.h"
  21. #include "core/hle/kernel/writable_event.h"
  22. #include "core/hle/service/nvdrv/nvdata.h"
  23. #include "core/hle/service/nvdrv/nvdrv.h"
  24. #include "core/hle/service/nvflinger/buffer_queue.h"
  25. #include "core/hle/service/nvflinger/nvflinger.h"
  26. #include "core/hle/service/service.h"
  27. #include "core/hle/service/vi/vi.h"
  28. #include "core/hle/service/vi/vi_m.h"
  29. #include "core/hle/service/vi/vi_s.h"
  30. #include "core/hle/service/vi/vi_u.h"
  31. #include "core/settings.h"
  32. namespace Service::VI {
  33. constexpr ResultCode ERR_OPERATION_FAILED{ErrorModule::VI, 1};
  34. constexpr ResultCode ERR_PERMISSION_DENIED{ErrorModule::VI, 5};
  35. constexpr ResultCode ERR_UNSUPPORTED{ErrorModule::VI, 6};
  36. constexpr ResultCode ERR_NOT_FOUND{ErrorModule::VI, 7};
  37. struct DisplayInfo {
  38. /// The name of this particular display.
  39. char display_name[0x40]{"Default"};
  40. /// Whether or not the display has a limited number of layers.
  41. u8 has_limited_layers{1};
  42. INSERT_PADDING_BYTES(7);
  43. /// Indicates the total amount of layers supported by the display.
  44. /// @note This is only valid if has_limited_layers is set.
  45. u64 max_layers{1};
  46. /// Maximum width in pixels.
  47. u64 width{1920};
  48. /// Maximum height in pixels.
  49. u64 height{1080};
  50. };
  51. static_assert(sizeof(DisplayInfo) == 0x60, "DisplayInfo has wrong size");
  52. class Parcel {
  53. public:
  54. // This default size was chosen arbitrarily.
  55. static constexpr std::size_t DefaultBufferSize = 0x40;
  56. Parcel() : buffer(DefaultBufferSize) {}
  57. explicit Parcel(std::vector<u8> data) : buffer(std::move(data)) {}
  58. virtual ~Parcel() = default;
  59. template <typename T>
  60. T Read() {
  61. static_assert(std::is_trivially_copyable_v<T>, "T must be trivially copyable.");
  62. ASSERT(read_index + sizeof(T) <= buffer.size());
  63. T val;
  64. std::memcpy(&val, buffer.data() + read_index, sizeof(T));
  65. read_index += sizeof(T);
  66. read_index = Common::AlignUp(read_index, 4);
  67. return val;
  68. }
  69. template <typename T>
  70. T ReadUnaligned() {
  71. static_assert(std::is_trivially_copyable_v<T>, "T must be trivially copyable.");
  72. ASSERT(read_index + sizeof(T) <= buffer.size());
  73. T val;
  74. std::memcpy(&val, buffer.data() + read_index, sizeof(T));
  75. read_index += sizeof(T);
  76. return val;
  77. }
  78. std::vector<u8> ReadBlock(std::size_t length) {
  79. ASSERT(read_index + length <= buffer.size());
  80. const u8* const begin = buffer.data() + read_index;
  81. const u8* const end = begin + length;
  82. std::vector<u8> data(begin, end);
  83. read_index += length;
  84. read_index = Common::AlignUp(read_index, 4);
  85. return data;
  86. }
  87. std::u16string ReadInterfaceToken() {
  88. [[maybe_unused]] const u32 unknown = Read<u32_le>();
  89. const u32 length = Read<u32_le>();
  90. std::u16string token{};
  91. for (u32 ch = 0; ch < length + 1; ++ch) {
  92. token.push_back(ReadUnaligned<u16_le>());
  93. }
  94. read_index = Common::AlignUp(read_index, 4);
  95. return token;
  96. }
  97. template <typename T>
  98. void Write(const T& val) {
  99. static_assert(std::is_trivially_copyable_v<T>, "T must be trivially copyable.");
  100. if (buffer.size() < write_index + sizeof(T)) {
  101. buffer.resize(buffer.size() + sizeof(T) + DefaultBufferSize);
  102. }
  103. std::memcpy(buffer.data() + write_index, &val, sizeof(T));
  104. write_index += sizeof(T);
  105. write_index = Common::AlignUp(write_index, 4);
  106. }
  107. template <typename T>
  108. void WriteObject(const T& val) {
  109. static_assert(std::is_trivially_copyable_v<T>, "T must be trivially copyable.");
  110. const u32_le size = static_cast<u32>(sizeof(val));
  111. Write(size);
  112. // TODO(Subv): Support file descriptors.
  113. Write<u32_le>(0); // Fd count.
  114. Write(val);
  115. }
  116. void Deserialize() {
  117. ASSERT(buffer.size() > sizeof(Header));
  118. Header header{};
  119. std::memcpy(&header, buffer.data(), sizeof(Header));
  120. read_index = header.data_offset;
  121. DeserializeData();
  122. }
  123. std::vector<u8> Serialize() {
  124. ASSERT(read_index == 0);
  125. write_index = sizeof(Header);
  126. SerializeData();
  127. Header header{};
  128. header.data_size = static_cast<u32_le>(write_index - sizeof(Header));
  129. header.data_offset = sizeof(Header);
  130. header.objects_size = 4;
  131. header.objects_offset = static_cast<u32>(sizeof(Header) + header.data_size);
  132. std::memcpy(buffer.data(), &header, sizeof(Header));
  133. return buffer;
  134. }
  135. protected:
  136. virtual void SerializeData() {}
  137. virtual void DeserializeData() {}
  138. private:
  139. struct Header {
  140. u32_le data_size;
  141. u32_le data_offset;
  142. u32_le objects_size;
  143. u32_le objects_offset;
  144. };
  145. static_assert(sizeof(Header) == 16, "ParcelHeader has wrong size");
  146. std::vector<u8> buffer;
  147. std::size_t read_index = 0;
  148. std::size_t write_index = 0;
  149. };
  150. class NativeWindow : public Parcel {
  151. public:
  152. explicit NativeWindow(u32 id) {
  153. data.id = id;
  154. }
  155. ~NativeWindow() override = default;
  156. protected:
  157. void SerializeData() override {
  158. Write(data);
  159. }
  160. private:
  161. struct Data {
  162. u32_le magic = 2;
  163. u32_le process_id = 1;
  164. u32_le id;
  165. INSERT_PADDING_WORDS(3);
  166. std::array<u8, 8> dispdrv = {'d', 'i', 's', 'p', 'd', 'r', 'v', '\0'};
  167. INSERT_PADDING_WORDS(2);
  168. };
  169. static_assert(sizeof(Data) == 0x28, "ParcelData has wrong size");
  170. Data data{};
  171. };
  172. class IGBPConnectRequestParcel : public Parcel {
  173. public:
  174. explicit IGBPConnectRequestParcel(std::vector<u8> buffer) : Parcel(std::move(buffer)) {
  175. Deserialize();
  176. }
  177. void DeserializeData() override {
  178. [[maybe_unused]] const std::u16string token = ReadInterfaceToken();
  179. data = Read<Data>();
  180. }
  181. struct Data {
  182. u32_le unk;
  183. u32_le api;
  184. u32_le producer_controlled_by_app;
  185. };
  186. Data data;
  187. };
  188. class IGBPConnectResponseParcel : public Parcel {
  189. public:
  190. explicit IGBPConnectResponseParcel(u32 width, u32 height) {
  191. data.width = width;
  192. data.height = height;
  193. }
  194. ~IGBPConnectResponseParcel() override = default;
  195. protected:
  196. void SerializeData() override {
  197. Write(data);
  198. }
  199. private:
  200. struct Data {
  201. u32_le width;
  202. u32_le height;
  203. u32_le transform_hint;
  204. u32_le num_pending_buffers;
  205. u32_le status;
  206. };
  207. static_assert(sizeof(Data) == 20, "ParcelData has wrong size");
  208. Data data{};
  209. };
  210. /// Represents a parcel containing one int '0' as its data
  211. /// Used by DetachBuffer and Disconnect
  212. class IGBPEmptyResponseParcel : public Parcel {
  213. protected:
  214. void SerializeData() override {
  215. Write(data);
  216. }
  217. private:
  218. struct Data {
  219. u32_le unk_0{};
  220. };
  221. Data data{};
  222. };
  223. class IGBPSetPreallocatedBufferRequestParcel : public Parcel {
  224. public:
  225. explicit IGBPSetPreallocatedBufferRequestParcel(std::vector<u8> buffer)
  226. : Parcel(std::move(buffer)) {
  227. Deserialize();
  228. }
  229. void DeserializeData() override {
  230. [[maybe_unused]] const std::u16string token = ReadInterfaceToken();
  231. data = Read<Data>();
  232. buffer = Read<NVFlinger::IGBPBuffer>();
  233. }
  234. struct Data {
  235. u32_le slot;
  236. INSERT_PADDING_WORDS(1);
  237. u32_le graphic_buffer_length;
  238. INSERT_PADDING_WORDS(1);
  239. };
  240. Data data;
  241. NVFlinger::IGBPBuffer buffer;
  242. };
  243. class IGBPSetPreallocatedBufferResponseParcel : public Parcel {
  244. protected:
  245. void SerializeData() override {
  246. // TODO(Subv): Find out what this means
  247. Write<u32>(0);
  248. }
  249. };
  250. class IGBPCancelBufferRequestParcel : public Parcel {
  251. public:
  252. explicit IGBPCancelBufferRequestParcel(std::vector<u8> buffer) : Parcel(std::move(buffer)) {
  253. Deserialize();
  254. }
  255. void DeserializeData() override {
  256. [[maybe_unused]] const std::u16string token = ReadInterfaceToken();
  257. data = Read<Data>();
  258. }
  259. struct Data {
  260. u32_le slot;
  261. Service::Nvidia::MultiFence multi_fence;
  262. };
  263. Data data;
  264. };
  265. class IGBPCancelBufferResponseParcel : public Parcel {
  266. protected:
  267. void SerializeData() override {
  268. Write<u32>(0); // Success
  269. }
  270. };
  271. class IGBPDequeueBufferRequestParcel : public Parcel {
  272. public:
  273. explicit IGBPDequeueBufferRequestParcel(std::vector<u8> buffer) : Parcel(std::move(buffer)) {
  274. Deserialize();
  275. }
  276. void DeserializeData() override {
  277. [[maybe_unused]] const std::u16string token = ReadInterfaceToken();
  278. data = Read<Data>();
  279. }
  280. struct Data {
  281. u32_le pixel_format;
  282. u32_le width;
  283. u32_le height;
  284. u32_le get_frame_timestamps;
  285. u32_le usage;
  286. };
  287. Data data;
  288. };
  289. class IGBPDequeueBufferResponseParcel : public Parcel {
  290. public:
  291. explicit IGBPDequeueBufferResponseParcel(u32 slot, Service::Nvidia::MultiFence& multi_fence)
  292. : slot(slot), multi_fence(multi_fence) {}
  293. protected:
  294. void SerializeData() override {
  295. Write(slot);
  296. Write<u32_le>(1);
  297. WriteObject(multi_fence);
  298. Write<u32_le>(0);
  299. }
  300. u32_le slot;
  301. Service::Nvidia::MultiFence multi_fence;
  302. };
  303. class IGBPRequestBufferRequestParcel : public Parcel {
  304. public:
  305. explicit IGBPRequestBufferRequestParcel(std::vector<u8> buffer) : Parcel(std::move(buffer)) {
  306. Deserialize();
  307. }
  308. void DeserializeData() override {
  309. [[maybe_unused]] const std::u16string token = ReadInterfaceToken();
  310. slot = Read<u32_le>();
  311. }
  312. u32_le slot;
  313. };
  314. class IGBPRequestBufferResponseParcel : public Parcel {
  315. public:
  316. explicit IGBPRequestBufferResponseParcel(NVFlinger::IGBPBuffer buffer) : buffer(buffer) {}
  317. ~IGBPRequestBufferResponseParcel() override = default;
  318. protected:
  319. void SerializeData() override {
  320. // TODO(Subv): Figure out what this value means, writing non-zero here will make libnx
  321. // try to read an IGBPBuffer object from the parcel.
  322. Write<u32_le>(1);
  323. WriteObject(buffer);
  324. Write<u32_le>(0);
  325. }
  326. NVFlinger::IGBPBuffer buffer;
  327. };
  328. class IGBPQueueBufferRequestParcel : public Parcel {
  329. public:
  330. explicit IGBPQueueBufferRequestParcel(std::vector<u8> buffer) : Parcel(std::move(buffer)) {
  331. Deserialize();
  332. }
  333. void DeserializeData() override {
  334. [[maybe_unused]] const std::u16string token = ReadInterfaceToken();
  335. data = Read<Data>();
  336. }
  337. struct Data {
  338. u32_le slot;
  339. INSERT_PADDING_WORDS(3);
  340. u32_le timestamp;
  341. s32_le is_auto_timestamp;
  342. s32_le crop_top;
  343. s32_le crop_left;
  344. s32_le crop_right;
  345. s32_le crop_bottom;
  346. s32_le scaling_mode;
  347. NVFlinger::BufferQueue::BufferTransformFlags transform;
  348. u32_le sticky_transform;
  349. INSERT_PADDING_WORDS(1);
  350. u32_le swap_interval;
  351. Service::Nvidia::MultiFence multi_fence;
  352. Common::Rectangle<int> GetCropRect() const {
  353. return {crop_left, crop_top, crop_right, crop_bottom};
  354. }
  355. };
  356. static_assert(sizeof(Data) == 96, "ParcelData has wrong size");
  357. Data data;
  358. };
  359. class IGBPQueueBufferResponseParcel : public Parcel {
  360. public:
  361. explicit IGBPQueueBufferResponseParcel(u32 width, u32 height) {
  362. data.width = width;
  363. data.height = height;
  364. }
  365. ~IGBPQueueBufferResponseParcel() override = default;
  366. protected:
  367. void SerializeData() override {
  368. Write(data);
  369. }
  370. private:
  371. struct Data {
  372. u32_le width;
  373. u32_le height;
  374. u32_le transform_hint;
  375. u32_le num_pending_buffers;
  376. u32_le status;
  377. };
  378. static_assert(sizeof(Data) == 20, "ParcelData has wrong size");
  379. Data data{};
  380. };
  381. class IGBPQueryRequestParcel : public Parcel {
  382. public:
  383. explicit IGBPQueryRequestParcel(std::vector<u8> buffer) : Parcel(std::move(buffer)) {
  384. Deserialize();
  385. }
  386. void DeserializeData() override {
  387. [[maybe_unused]] const std::u16string token = ReadInterfaceToken();
  388. type = Read<u32_le>();
  389. }
  390. u32 type;
  391. };
  392. class IGBPQueryResponseParcel : public Parcel {
  393. public:
  394. explicit IGBPQueryResponseParcel(u32 value) : value(value) {}
  395. ~IGBPQueryResponseParcel() override = default;
  396. protected:
  397. void SerializeData() override {
  398. Write(value);
  399. }
  400. private:
  401. u32_le value;
  402. };
  403. class IHOSBinderDriver final : public ServiceFramework<IHOSBinderDriver> {
  404. public:
  405. explicit IHOSBinderDriver(NVFlinger::NVFlinger& nv_flinger)
  406. : ServiceFramework("IHOSBinderDriver"), nv_flinger(nv_flinger) {
  407. static const FunctionInfo functions[] = {
  408. {0, &IHOSBinderDriver::TransactParcel, "TransactParcel"},
  409. {1, &IHOSBinderDriver::AdjustRefcount, "AdjustRefcount"},
  410. {2, &IHOSBinderDriver::GetNativeHandle, "GetNativeHandle"},
  411. {3, &IHOSBinderDriver::TransactParcel, "TransactParcelAuto"},
  412. };
  413. RegisterHandlers(functions);
  414. }
  415. private:
  416. enum class TransactionId {
  417. RequestBuffer = 1,
  418. SetBufferCount = 2,
  419. DequeueBuffer = 3,
  420. DetachBuffer = 4,
  421. DetachNextBuffer = 5,
  422. AttachBuffer = 6,
  423. QueueBuffer = 7,
  424. CancelBuffer = 8,
  425. Query = 9,
  426. Connect = 10,
  427. Disconnect = 11,
  428. AllocateBuffers = 13,
  429. SetPreallocatedBuffer = 14
  430. };
  431. void TransactParcel(Kernel::HLERequestContext& ctx) {
  432. IPC::RequestParser rp{ctx};
  433. const u32 id = rp.Pop<u32>();
  434. const auto transaction = static_cast<TransactionId>(rp.Pop<u32>());
  435. const u32 flags = rp.Pop<u32>();
  436. LOG_DEBUG(Service_VI, "called. id=0x{:08X} transaction={:X}, flags=0x{:08X}", id,
  437. static_cast<u32>(transaction), flags);
  438. const auto guard = nv_flinger.Lock();
  439. auto& buffer_queue = nv_flinger.FindBufferQueue(id);
  440. switch (transaction) {
  441. case TransactionId::Connect: {
  442. IGBPConnectRequestParcel request{ctx.ReadBuffer()};
  443. IGBPConnectResponseParcel response{
  444. static_cast<u32>(static_cast<u32>(DisplayResolution::UndockedWidth) *
  445. Settings::values.resolution_factor.GetValue()),
  446. static_cast<u32>(static_cast<u32>(DisplayResolution::UndockedHeight) *
  447. Settings::values.resolution_factor.GetValue())};
  448. ctx.WriteBuffer(response.Serialize());
  449. break;
  450. }
  451. case TransactionId::SetPreallocatedBuffer: {
  452. IGBPSetPreallocatedBufferRequestParcel request{ctx.ReadBuffer()};
  453. buffer_queue.SetPreallocatedBuffer(request.data.slot, request.buffer);
  454. IGBPSetPreallocatedBufferResponseParcel response{};
  455. ctx.WriteBuffer(response.Serialize());
  456. break;
  457. }
  458. case TransactionId::DequeueBuffer: {
  459. IGBPDequeueBufferRequestParcel request{ctx.ReadBuffer()};
  460. const u32 width{request.data.width};
  461. const u32 height{request.data.height};
  462. auto result = buffer_queue.DequeueBuffer(width, height);
  463. if (result) {
  464. // Buffer is available
  465. IGBPDequeueBufferResponseParcel response{result->first, *result->second};
  466. ctx.WriteBuffer(response.Serialize());
  467. } else {
  468. // Wait the current thread until a buffer becomes available
  469. ctx.SleepClientThread(
  470. "IHOSBinderDriver::DequeueBuffer", UINT64_MAX,
  471. [=, this](std::shared_ptr<Kernel::Thread> thread,
  472. Kernel::HLERequestContext& ctx, Kernel::ThreadWakeupReason reason) {
  473. // Repeat TransactParcel DequeueBuffer when a buffer is available
  474. const auto guard = nv_flinger.Lock();
  475. auto& buffer_queue = nv_flinger.FindBufferQueue(id);
  476. auto result = buffer_queue.DequeueBuffer(width, height);
  477. ASSERT_MSG(result != std::nullopt, "Could not dequeue buffer.");
  478. IGBPDequeueBufferResponseParcel response{result->first, *result->second};
  479. ctx.WriteBuffer(response.Serialize());
  480. IPC::ResponseBuilder rb{ctx, 2};
  481. rb.Push(RESULT_SUCCESS);
  482. },
  483. buffer_queue.GetWritableBufferWaitEvent());
  484. }
  485. break;
  486. }
  487. case TransactionId::RequestBuffer: {
  488. IGBPRequestBufferRequestParcel request{ctx.ReadBuffer()};
  489. auto& buffer = buffer_queue.RequestBuffer(request.slot);
  490. IGBPRequestBufferResponseParcel response{buffer};
  491. ctx.WriteBuffer(response.Serialize());
  492. break;
  493. }
  494. case TransactionId::QueueBuffer: {
  495. IGBPQueueBufferRequestParcel request{ctx.ReadBuffer()};
  496. buffer_queue.QueueBuffer(request.data.slot, request.data.transform,
  497. request.data.GetCropRect(), request.data.swap_interval,
  498. request.data.multi_fence);
  499. IGBPQueueBufferResponseParcel response{1280, 720};
  500. ctx.WriteBuffer(response.Serialize());
  501. break;
  502. }
  503. case TransactionId::Query: {
  504. IGBPQueryRequestParcel request{ctx.ReadBuffer()};
  505. const u32 value =
  506. buffer_queue.Query(static_cast<NVFlinger::BufferQueue::QueryType>(request.type));
  507. IGBPQueryResponseParcel response{value};
  508. ctx.WriteBuffer(response.Serialize());
  509. break;
  510. }
  511. case TransactionId::CancelBuffer: {
  512. IGBPCancelBufferRequestParcel request{ctx.ReadBuffer()};
  513. buffer_queue.CancelBuffer(request.data.slot, request.data.multi_fence);
  514. IGBPCancelBufferResponseParcel response{};
  515. ctx.WriteBuffer(response.Serialize());
  516. break;
  517. }
  518. case TransactionId::Disconnect: {
  519. LOG_WARNING(Service_VI, "(STUBBED) called, transaction=Disconnect");
  520. const auto buffer = ctx.ReadBuffer();
  521. buffer_queue.Disconnect();
  522. IGBPEmptyResponseParcel response{};
  523. ctx.WriteBuffer(response.Serialize());
  524. break;
  525. }
  526. case TransactionId::DetachBuffer: {
  527. const auto buffer = ctx.ReadBuffer();
  528. IGBPEmptyResponseParcel response{};
  529. ctx.WriteBuffer(response.Serialize());
  530. break;
  531. }
  532. case TransactionId::SetBufferCount: {
  533. LOG_WARNING(Service_VI, "(STUBBED) called, transaction=SetBufferCount");
  534. [[maybe_unused]] const auto buffer = ctx.ReadBuffer();
  535. IGBPEmptyResponseParcel response{};
  536. ctx.WriteBuffer(response.Serialize());
  537. break;
  538. }
  539. default:
  540. ASSERT_MSG(false, "Unimplemented");
  541. }
  542. IPC::ResponseBuilder rb{ctx, 2};
  543. rb.Push(RESULT_SUCCESS);
  544. }
  545. void AdjustRefcount(Kernel::HLERequestContext& ctx) {
  546. IPC::RequestParser rp{ctx};
  547. const u32 id = rp.Pop<u32>();
  548. const s32 addval = rp.PopRaw<s32>();
  549. const u32 type = rp.Pop<u32>();
  550. LOG_WARNING(Service_VI, "(STUBBED) called id={}, addval={:08X}, type={:08X}", id, addval,
  551. type);
  552. IPC::ResponseBuilder rb{ctx, 2};
  553. rb.Push(RESULT_SUCCESS);
  554. }
  555. void GetNativeHandle(Kernel::HLERequestContext& ctx) {
  556. IPC::RequestParser rp{ctx};
  557. const u32 id = rp.Pop<u32>();
  558. const u32 unknown = rp.Pop<u32>();
  559. LOG_WARNING(Service_VI, "(STUBBED) called id={}, unknown={:08X}", id, unknown);
  560. const auto& buffer_queue = nv_flinger.FindBufferQueue(id);
  561. // TODO(Subv): Find out what this actually is.
  562. IPC::ResponseBuilder rb{ctx, 2, 1};
  563. rb.Push(RESULT_SUCCESS);
  564. rb.PushCopyObjects(buffer_queue.GetBufferWaitEvent());
  565. }
  566. NVFlinger::NVFlinger& nv_flinger;
  567. };
  568. class ISystemDisplayService final : public ServiceFramework<ISystemDisplayService> {
  569. public:
  570. explicit ISystemDisplayService() : ServiceFramework("ISystemDisplayService") {
  571. static const FunctionInfo functions[] = {
  572. {1200, nullptr, "GetZOrderCountMin"},
  573. {1202, nullptr, "GetZOrderCountMax"},
  574. {1203, nullptr, "GetDisplayLogicalResolution"},
  575. {1204, nullptr, "SetDisplayMagnification"},
  576. {2201, nullptr, "SetLayerPosition"},
  577. {2203, nullptr, "SetLayerSize"},
  578. {2204, nullptr, "GetLayerZ"},
  579. {2205, &ISystemDisplayService::SetLayerZ, "SetLayerZ"},
  580. {2207, &ISystemDisplayService::SetLayerVisibility, "SetLayerVisibility"},
  581. {2209, nullptr, "SetLayerAlpha"},
  582. {2312, nullptr, "CreateStrayLayer"},
  583. {2400, nullptr, "OpenIndirectLayer"},
  584. {2401, nullptr, "CloseIndirectLayer"},
  585. {2402, nullptr, "FlipIndirectLayer"},
  586. {3000, nullptr, "ListDisplayModes"},
  587. {3001, nullptr, "ListDisplayRgbRanges"},
  588. {3002, nullptr, "ListDisplayContentTypes"},
  589. {3200, &ISystemDisplayService::GetDisplayMode, "GetDisplayMode"},
  590. {3201, nullptr, "SetDisplayMode"},
  591. {3202, nullptr, "GetDisplayUnderscan"},
  592. {3203, nullptr, "SetDisplayUnderscan"},
  593. {3204, nullptr, "GetDisplayContentType"},
  594. {3205, nullptr, "SetDisplayContentType"},
  595. {3206, nullptr, "GetDisplayRgbRange"},
  596. {3207, nullptr, "SetDisplayRgbRange"},
  597. {3208, nullptr, "GetDisplayCmuMode"},
  598. {3209, nullptr, "SetDisplayCmuMode"},
  599. {3210, nullptr, "GetDisplayContrastRatio"},
  600. {3211, nullptr, "SetDisplayContrastRatio"},
  601. {3214, nullptr, "GetDisplayGamma"},
  602. {3215, nullptr, "SetDisplayGamma"},
  603. {3216, nullptr, "GetDisplayCmuLuma"},
  604. {3217, nullptr, "SetDisplayCmuLuma"},
  605. {6013, nullptr, "GetLayerPresentationSubmissionTimestamps"},
  606. {8225, nullptr, "GetSharedBufferMemoryHandleId"},
  607. {8250, nullptr, "OpenSharedLayer"},
  608. {8251, nullptr, "CloseSharedLayer"},
  609. {8252, nullptr, "ConnectSharedLayer"},
  610. {8253, nullptr, "DisconnectSharedLayer"},
  611. {8254, nullptr, "AcquireSharedFrameBuffer"},
  612. {8255, nullptr, "PresentSharedFrameBuffer"},
  613. {8256, nullptr, "GetSharedFrameBufferAcquirableEvent"},
  614. {8257, nullptr, "FillSharedFrameBufferColor"},
  615. {8258, nullptr, "CancelSharedFrameBuffer"},
  616. };
  617. RegisterHandlers(functions);
  618. }
  619. private:
  620. void SetLayerZ(Kernel::HLERequestContext& ctx) {
  621. IPC::RequestParser rp{ctx};
  622. const u64 layer_id = rp.Pop<u64>();
  623. const u64 z_value = rp.Pop<u64>();
  624. LOG_WARNING(Service_VI, "(STUBBED) called. layer_id=0x{:016X}, z_value=0x{:016X}", layer_id,
  625. z_value);
  626. IPC::ResponseBuilder rb{ctx, 2};
  627. rb.Push(RESULT_SUCCESS);
  628. }
  629. // This function currently does nothing but return a success error code in
  630. // the vi library itself, so do the same thing, but log out the passed in values.
  631. void SetLayerVisibility(Kernel::HLERequestContext& ctx) {
  632. IPC::RequestParser rp{ctx};
  633. const u64 layer_id = rp.Pop<u64>();
  634. const bool visibility = rp.Pop<bool>();
  635. LOG_DEBUG(Service_VI, "called, layer_id=0x{:08X}, visibility={}", layer_id, visibility);
  636. IPC::ResponseBuilder rb{ctx, 2};
  637. rb.Push(RESULT_SUCCESS);
  638. }
  639. void GetDisplayMode(Kernel::HLERequestContext& ctx) {
  640. LOG_WARNING(Service_VI, "(STUBBED) called");
  641. IPC::ResponseBuilder rb{ctx, 6};
  642. rb.Push(RESULT_SUCCESS);
  643. if (Settings::values.use_docked_mode.GetValue()) {
  644. rb.Push(static_cast<u32>(Service::VI::DisplayResolution::DockedWidth) *
  645. static_cast<u32>(Settings::values.resolution_factor.GetValue()));
  646. rb.Push(static_cast<u32>(Service::VI::DisplayResolution::DockedHeight) *
  647. static_cast<u32>(Settings::values.resolution_factor.GetValue()));
  648. } else {
  649. rb.Push(static_cast<u32>(Service::VI::DisplayResolution::UndockedWidth) *
  650. static_cast<u32>(Settings::values.resolution_factor.GetValue()));
  651. rb.Push(static_cast<u32>(Service::VI::DisplayResolution::UndockedHeight) *
  652. static_cast<u32>(Settings::values.resolution_factor.GetValue()));
  653. }
  654. rb.PushRaw<float>(60.0f); // This wouldn't seem to be correct for 30 fps games.
  655. rb.Push<u32>(0);
  656. }
  657. };
  658. class IManagerDisplayService final : public ServiceFramework<IManagerDisplayService> {
  659. public:
  660. explicit IManagerDisplayService(NVFlinger::NVFlinger& nv_flinger)
  661. : ServiceFramework("IManagerDisplayService"), nv_flinger(nv_flinger) {
  662. // clang-format off
  663. static const FunctionInfo functions[] = {
  664. {200, nullptr, "AllocateProcessHeapBlock"},
  665. {201, nullptr, "FreeProcessHeapBlock"},
  666. {1020, &IManagerDisplayService::CloseDisplay, "CloseDisplay"},
  667. {1102, nullptr, "GetDisplayResolution"},
  668. {2010, &IManagerDisplayService::CreateManagedLayer, "CreateManagedLayer"},
  669. {2011, nullptr, "DestroyManagedLayer"},
  670. {2012, nullptr, "CreateStrayLayer"},
  671. {2050, nullptr, "CreateIndirectLayer"},
  672. {2051, nullptr, "DestroyIndirectLayer"},
  673. {2052, nullptr, "CreateIndirectProducerEndPoint"},
  674. {2053, nullptr, "DestroyIndirectProducerEndPoint"},
  675. {2054, nullptr, "CreateIndirectConsumerEndPoint"},
  676. {2055, nullptr, "DestroyIndirectConsumerEndPoint"},
  677. {2300, nullptr, "AcquireLayerTexturePresentingEvent"},
  678. {2301, nullptr, "ReleaseLayerTexturePresentingEvent"},
  679. {2302, nullptr, "GetDisplayHotplugEvent"},
  680. {2303, nullptr, "GetDisplayModeChangedEvent"},
  681. {2402, nullptr, "GetDisplayHotplugState"},
  682. {2501, nullptr, "GetCompositorErrorInfo"},
  683. {2601, nullptr, "GetDisplayErrorEvent"},
  684. {4201, nullptr, "SetDisplayAlpha"},
  685. {4203, nullptr, "SetDisplayLayerStack"},
  686. {4205, nullptr, "SetDisplayPowerState"},
  687. {4206, nullptr, "SetDefaultDisplay"},
  688. {6000, &IManagerDisplayService::AddToLayerStack, "AddToLayerStack"},
  689. {6001, nullptr, "RemoveFromLayerStack"},
  690. {6002, &IManagerDisplayService::SetLayerVisibility, "SetLayerVisibility"},
  691. {6003, nullptr, "SetLayerConfig"},
  692. {6004, nullptr, "AttachLayerPresentationTracer"},
  693. {6005, nullptr, "DetachLayerPresentationTracer"},
  694. {6006, nullptr, "StartLayerPresentationRecording"},
  695. {6007, nullptr, "StopLayerPresentationRecording"},
  696. {6008, nullptr, "StartLayerPresentationFenceWait"},
  697. {6009, nullptr, "StopLayerPresentationFenceWait"},
  698. {6010, nullptr, "GetLayerPresentationAllFencesExpiredEvent"},
  699. {6011, nullptr, "EnableLayerAutoClearTransitionBuffer"},
  700. {6012, nullptr, "DisableLayerAutoClearTransitionBuffer"},
  701. {7000, nullptr, "SetContentVisibility"},
  702. {8000, nullptr, "SetConductorLayer"},
  703. {8001, nullptr, "SetTimestampTracking"},
  704. {8100, nullptr, "SetIndirectProducerFlipOffset"},
  705. {8200, nullptr, "CreateSharedBufferStaticStorage"},
  706. {8201, nullptr, "CreateSharedBufferTransferMemory"},
  707. {8202, nullptr, "DestroySharedBuffer"},
  708. {8203, nullptr, "BindSharedLowLevelLayerToManagedLayer"},
  709. {8204, nullptr, "BindSharedLowLevelLayerToIndirectLayer"},
  710. {8207, nullptr, "UnbindSharedLowLevelLayer"},
  711. {8208, nullptr, "ConnectSharedLowLevelLayerToSharedBuffer"},
  712. {8209, nullptr, "DisconnectSharedLowLevelLayerFromSharedBuffer"},
  713. {8210, nullptr, "CreateSharedLayer"},
  714. {8211, nullptr, "DestroySharedLayer"},
  715. {8216, nullptr, "AttachSharedLayerToLowLevelLayer"},
  716. {8217, nullptr, "ForceDetachSharedLayerFromLowLevelLayer"},
  717. {8218, nullptr, "StartDetachSharedLayerFromLowLevelLayer"},
  718. {8219, nullptr, "FinishDetachSharedLayerFromLowLevelLayer"},
  719. {8220, nullptr, "GetSharedLayerDetachReadyEvent"},
  720. {8221, nullptr, "GetSharedLowLevelLayerSynchronizedEvent"},
  721. {8222, nullptr, "CheckSharedLowLevelLayerSynchronized"},
  722. {8223, nullptr, "RegisterSharedBufferImporterAruid"},
  723. {8224, nullptr, "UnregisterSharedBufferImporterAruid"},
  724. {8227, nullptr, "CreateSharedBufferProcessHeap"},
  725. {8228, nullptr, "GetSharedLayerLayerStacks"},
  726. {8229, nullptr, "SetSharedLayerLayerStacks"},
  727. {8291, nullptr, "PresentDetachedSharedFrameBufferToLowLevelLayer"},
  728. {8292, nullptr, "FillDetachedSharedFrameBufferColor"},
  729. {8293, nullptr, "GetDetachedSharedFrameBufferImage"},
  730. {8294, nullptr, "SetDetachedSharedFrameBufferImage"},
  731. {8295, nullptr, "CopyDetachedSharedFrameBufferImage"},
  732. {8296, nullptr, "SetDetachedSharedFrameBufferSubImage"},
  733. {8297, nullptr, "GetSharedFrameBufferContentParameter"},
  734. {8298, nullptr, "ExpandStartupLogoOnSharedFrameBuffer"},
  735. };
  736. // clang-format on
  737. RegisterHandlers(functions);
  738. }
  739. private:
  740. void CloseDisplay(Kernel::HLERequestContext& ctx) {
  741. IPC::RequestParser rp{ctx};
  742. const u64 display = rp.Pop<u64>();
  743. LOG_WARNING(Service_VI, "(STUBBED) called. display=0x{:016X}", display);
  744. IPC::ResponseBuilder rb{ctx, 2};
  745. rb.Push(RESULT_SUCCESS);
  746. }
  747. void CreateManagedLayer(Kernel::HLERequestContext& ctx) {
  748. IPC::RequestParser rp{ctx};
  749. const u32 unknown = rp.Pop<u32>();
  750. rp.Skip(1, false);
  751. const u64 display = rp.Pop<u64>();
  752. const u64 aruid = rp.Pop<u64>();
  753. LOG_WARNING(Service_VI,
  754. "(STUBBED) called. unknown=0x{:08X}, display=0x{:016X}, aruid=0x{:016X}",
  755. unknown, display, aruid);
  756. const auto layer_id = nv_flinger.CreateLayer(display);
  757. if (!layer_id) {
  758. LOG_ERROR(Service_VI, "Layer not found! display=0x{:016X}", display);
  759. IPC::ResponseBuilder rb{ctx, 2};
  760. rb.Push(ERR_NOT_FOUND);
  761. return;
  762. }
  763. IPC::ResponseBuilder rb{ctx, 4};
  764. rb.Push(RESULT_SUCCESS);
  765. rb.Push(*layer_id);
  766. }
  767. void AddToLayerStack(Kernel::HLERequestContext& ctx) {
  768. IPC::RequestParser rp{ctx};
  769. const u32 stack = rp.Pop<u32>();
  770. const u64 layer_id = rp.Pop<u64>();
  771. LOG_WARNING(Service_VI, "(STUBBED) called. stack=0x{:08X}, layer_id=0x{:016X}", stack,
  772. layer_id);
  773. IPC::ResponseBuilder rb{ctx, 2};
  774. rb.Push(RESULT_SUCCESS);
  775. }
  776. void SetLayerVisibility(Kernel::HLERequestContext& ctx) {
  777. IPC::RequestParser rp{ctx};
  778. const u64 layer_id = rp.Pop<u64>();
  779. const bool visibility = rp.Pop<bool>();
  780. LOG_WARNING(Service_VI, "(STUBBED) called, layer_id=0x{:X}, visibility={}", layer_id,
  781. visibility);
  782. IPC::ResponseBuilder rb{ctx, 2};
  783. rb.Push(RESULT_SUCCESS);
  784. }
  785. NVFlinger::NVFlinger& nv_flinger;
  786. };
  787. class IApplicationDisplayService final : public ServiceFramework<IApplicationDisplayService> {
  788. public:
  789. explicit IApplicationDisplayService(NVFlinger::NVFlinger& nv_flinger);
  790. private:
  791. enum class ConvertedScaleMode : u64 {
  792. Freeze = 0,
  793. ScaleToWindow = 1,
  794. ScaleAndCrop = 2,
  795. None = 3,
  796. PreserveAspectRatio = 4,
  797. };
  798. enum class NintendoScaleMode : u32 {
  799. None = 0,
  800. Freeze = 1,
  801. ScaleToWindow = 2,
  802. ScaleAndCrop = 3,
  803. PreserveAspectRatio = 4,
  804. };
  805. void GetRelayService(Kernel::HLERequestContext& ctx) {
  806. LOG_WARNING(Service_VI, "(STUBBED) called");
  807. IPC::ResponseBuilder rb{ctx, 2, 0, 1};
  808. rb.Push(RESULT_SUCCESS);
  809. rb.PushIpcInterface<IHOSBinderDriver>(nv_flinger);
  810. }
  811. void GetSystemDisplayService(Kernel::HLERequestContext& ctx) {
  812. LOG_WARNING(Service_VI, "(STUBBED) called");
  813. IPC::ResponseBuilder rb{ctx, 2, 0, 1};
  814. rb.Push(RESULT_SUCCESS);
  815. rb.PushIpcInterface<ISystemDisplayService>();
  816. }
  817. void GetManagerDisplayService(Kernel::HLERequestContext& ctx) {
  818. LOG_WARNING(Service_VI, "(STUBBED) called");
  819. IPC::ResponseBuilder rb{ctx, 2, 0, 1};
  820. rb.Push(RESULT_SUCCESS);
  821. rb.PushIpcInterface<IManagerDisplayService>(nv_flinger);
  822. }
  823. void GetIndirectDisplayTransactionService(Kernel::HLERequestContext& ctx) {
  824. LOG_WARNING(Service_VI, "(STUBBED) called");
  825. IPC::ResponseBuilder rb{ctx, 2, 0, 1};
  826. rb.Push(RESULT_SUCCESS);
  827. rb.PushIpcInterface<IHOSBinderDriver>(nv_flinger);
  828. }
  829. void OpenDisplay(Kernel::HLERequestContext& ctx) {
  830. LOG_WARNING(Service_VI, "(STUBBED) called");
  831. IPC::RequestParser rp{ctx};
  832. const auto name_buf = rp.PopRaw<std::array<char, 0x40>>();
  833. OpenDisplayImpl(ctx, std::string_view{name_buf.data(), name_buf.size()});
  834. }
  835. void OpenDefaultDisplay(Kernel::HLERequestContext& ctx) {
  836. LOG_DEBUG(Service_VI, "called");
  837. OpenDisplayImpl(ctx, "Default");
  838. }
  839. void OpenDisplayImpl(Kernel::HLERequestContext& ctx, std::string_view name) {
  840. const auto trim_pos = name.find('\0');
  841. if (trim_pos != std::string_view::npos) {
  842. name.remove_suffix(name.size() - trim_pos);
  843. }
  844. ASSERT_MSG(name == "Default", "Non-default displays aren't supported yet");
  845. const auto display_id = nv_flinger.OpenDisplay(name);
  846. if (!display_id) {
  847. LOG_ERROR(Service_VI, "Display not found! display_name={}", name);
  848. IPC::ResponseBuilder rb{ctx, 2};
  849. rb.Push(ERR_NOT_FOUND);
  850. return;
  851. }
  852. IPC::ResponseBuilder rb{ctx, 4};
  853. rb.Push(RESULT_SUCCESS);
  854. rb.Push<u64>(*display_id);
  855. }
  856. void CloseDisplay(Kernel::HLERequestContext& ctx) {
  857. IPC::RequestParser rp{ctx};
  858. const u64 display_id = rp.Pop<u64>();
  859. LOG_WARNING(Service_VI, "(STUBBED) called. display_id=0x{:016X}", display_id);
  860. IPC::ResponseBuilder rb{ctx, 2};
  861. rb.Push(RESULT_SUCCESS);
  862. }
  863. // This literally does nothing internally in the actual service itself,
  864. // and just returns a successful result code regardless of the input.
  865. void SetDisplayEnabled(Kernel::HLERequestContext& ctx) {
  866. LOG_DEBUG(Service_VI, "called.");
  867. IPC::ResponseBuilder rb{ctx, 2};
  868. rb.Push(RESULT_SUCCESS);
  869. }
  870. void GetDisplayResolution(Kernel::HLERequestContext& ctx) {
  871. IPC::RequestParser rp{ctx};
  872. const u64 display_id = rp.Pop<u64>();
  873. LOG_DEBUG(Service_VI, "called. display_id=0x{:016X}", display_id);
  874. IPC::ResponseBuilder rb{ctx, 6};
  875. rb.Push(RESULT_SUCCESS);
  876. // This only returns the fixed values of 1280x720 and makes no distinguishing
  877. // between docked and undocked dimensions. We take the liberty of applying
  878. // the resolution scaling factor here.
  879. rb.Push(static_cast<u64>(DisplayResolution::UndockedWidth) *
  880. static_cast<u32>(Settings::values.resolution_factor.GetValue()));
  881. rb.Push(static_cast<u64>(DisplayResolution::UndockedHeight) *
  882. static_cast<u32>(Settings::values.resolution_factor.GetValue()));
  883. }
  884. void SetLayerScalingMode(Kernel::HLERequestContext& ctx) {
  885. IPC::RequestParser rp{ctx};
  886. const auto scaling_mode = rp.PopEnum<NintendoScaleMode>();
  887. const u64 unknown = rp.Pop<u64>();
  888. LOG_DEBUG(Service_VI, "called. scaling_mode=0x{:08X}, unknown=0x{:016X}",
  889. static_cast<u32>(scaling_mode), unknown);
  890. IPC::ResponseBuilder rb{ctx, 2};
  891. if (scaling_mode > NintendoScaleMode::PreserveAspectRatio) {
  892. LOG_ERROR(Service_VI, "Invalid scaling mode provided.");
  893. rb.Push(ERR_OPERATION_FAILED);
  894. return;
  895. }
  896. if (scaling_mode != NintendoScaleMode::ScaleToWindow &&
  897. scaling_mode != NintendoScaleMode::PreserveAspectRatio) {
  898. LOG_ERROR(Service_VI, "Unsupported scaling mode supplied.");
  899. rb.Push(ERR_UNSUPPORTED);
  900. return;
  901. }
  902. rb.Push(RESULT_SUCCESS);
  903. }
  904. void ListDisplays(Kernel::HLERequestContext& ctx) {
  905. LOG_WARNING(Service_VI, "(STUBBED) called");
  906. DisplayInfo display_info;
  907. display_info.width *= static_cast<u64>(Settings::values.resolution_factor.GetValue());
  908. display_info.height *= static_cast<u64>(Settings::values.resolution_factor.GetValue());
  909. ctx.WriteBuffer(&display_info, sizeof(DisplayInfo));
  910. IPC::ResponseBuilder rb{ctx, 4};
  911. rb.Push(RESULT_SUCCESS);
  912. rb.Push<u64>(1);
  913. }
  914. void OpenLayer(Kernel::HLERequestContext& ctx) {
  915. IPC::RequestParser rp{ctx};
  916. const auto name_buf = rp.PopRaw<std::array<u8, 0x40>>();
  917. const auto end = std::find(name_buf.begin(), name_buf.end(), '\0');
  918. const std::string display_name(name_buf.begin(), end);
  919. const u64 layer_id = rp.Pop<u64>();
  920. const u64 aruid = rp.Pop<u64>();
  921. LOG_DEBUG(Service_VI, "called. layer_id=0x{:016X}, aruid=0x{:016X}", layer_id, aruid);
  922. const auto display_id = nv_flinger.OpenDisplay(display_name);
  923. if (!display_id) {
  924. LOG_ERROR(Service_VI, "Layer not found! layer_id={}", layer_id);
  925. IPC::ResponseBuilder rb{ctx, 2};
  926. rb.Push(ERR_NOT_FOUND);
  927. return;
  928. }
  929. const auto buffer_queue_id = nv_flinger.FindBufferQueueId(*display_id, layer_id);
  930. if (!buffer_queue_id) {
  931. LOG_ERROR(Service_VI, "Buffer queue id not found! display_id={}", *display_id);
  932. IPC::ResponseBuilder rb{ctx, 2};
  933. rb.Push(ERR_NOT_FOUND);
  934. return;
  935. }
  936. NativeWindow native_window{*buffer_queue_id};
  937. IPC::ResponseBuilder rb{ctx, 4};
  938. rb.Push(RESULT_SUCCESS);
  939. rb.Push<u64>(ctx.WriteBuffer(native_window.Serialize()));
  940. }
  941. void CloseLayer(Kernel::HLERequestContext& ctx) {
  942. IPC::RequestParser rp{ctx};
  943. const auto layer_id{rp.Pop<u64>()};
  944. LOG_DEBUG(Service_VI, "called. layer_id=0x{:016X}", layer_id);
  945. nv_flinger.CloseLayer(layer_id);
  946. IPC::ResponseBuilder rb{ctx, 2};
  947. rb.Push(RESULT_SUCCESS);
  948. }
  949. void CreateStrayLayer(Kernel::HLERequestContext& ctx) {
  950. IPC::RequestParser rp{ctx};
  951. const u32 flags = rp.Pop<u32>();
  952. rp.Pop<u32>(); // padding
  953. const u64 display_id = rp.Pop<u64>();
  954. LOG_DEBUG(Service_VI, "called. flags=0x{:08X}, display_id=0x{:016X}", flags, display_id);
  955. // TODO(Subv): What's the difference between a Stray and a Managed layer?
  956. const auto layer_id = nv_flinger.CreateLayer(display_id);
  957. if (!layer_id) {
  958. LOG_ERROR(Service_VI, "Layer not found! layer_id={}", *layer_id);
  959. IPC::ResponseBuilder rb{ctx, 2};
  960. rb.Push(ERR_NOT_FOUND);
  961. return;
  962. }
  963. const auto buffer_queue_id = nv_flinger.FindBufferQueueId(display_id, *layer_id);
  964. if (!buffer_queue_id) {
  965. LOG_ERROR(Service_VI, "Buffer queue id not found! display_id={}", display_id);
  966. IPC::ResponseBuilder rb{ctx, 2};
  967. rb.Push(ERR_NOT_FOUND);
  968. return;
  969. }
  970. NativeWindow native_window{*buffer_queue_id};
  971. IPC::ResponseBuilder rb{ctx, 6};
  972. rb.Push(RESULT_SUCCESS);
  973. rb.Push(*layer_id);
  974. rb.Push<u64>(ctx.WriteBuffer(native_window.Serialize()));
  975. }
  976. void DestroyStrayLayer(Kernel::HLERequestContext& ctx) {
  977. IPC::RequestParser rp{ctx};
  978. const u64 layer_id = rp.Pop<u64>();
  979. LOG_WARNING(Service_VI, "(STUBBED) called. layer_id=0x{:016X}", layer_id);
  980. IPC::ResponseBuilder rb{ctx, 2};
  981. rb.Push(RESULT_SUCCESS);
  982. }
  983. void GetDisplayVsyncEvent(Kernel::HLERequestContext& ctx) {
  984. IPC::RequestParser rp{ctx};
  985. const u64 display_id = rp.Pop<u64>();
  986. LOG_WARNING(Service_VI, "(STUBBED) called. display_id=0x{:016X}", display_id);
  987. const auto vsync_event = nv_flinger.FindVsyncEvent(display_id);
  988. if (!vsync_event) {
  989. LOG_ERROR(Service_VI, "Vsync event was not found for display_id={}", display_id);
  990. IPC::ResponseBuilder rb{ctx, 2};
  991. rb.Push(ERR_NOT_FOUND);
  992. return;
  993. }
  994. IPC::ResponseBuilder rb{ctx, 2, 1};
  995. rb.Push(RESULT_SUCCESS);
  996. rb.PushCopyObjects(vsync_event);
  997. }
  998. void ConvertScalingMode(Kernel::HLERequestContext& ctx) {
  999. IPC::RequestParser rp{ctx};
  1000. const auto mode = rp.PopEnum<NintendoScaleMode>();
  1001. LOG_DEBUG(Service_VI, "called mode={}", static_cast<u32>(mode));
  1002. const auto converted_mode = ConvertScalingModeImpl(mode);
  1003. if (converted_mode.Succeeded()) {
  1004. IPC::ResponseBuilder rb{ctx, 4};
  1005. rb.Push(RESULT_SUCCESS);
  1006. rb.PushEnum(*converted_mode);
  1007. } else {
  1008. IPC::ResponseBuilder rb{ctx, 2};
  1009. rb.Push(converted_mode.Code());
  1010. }
  1011. }
  1012. void GetIndirectLayerImageRequiredMemoryInfo(Kernel::HLERequestContext& ctx) {
  1013. IPC::RequestParser rp{ctx};
  1014. const auto width = rp.Pop<u64>();
  1015. const auto height = rp.Pop<u64>();
  1016. LOG_DEBUG(Service_VI, "called width={}, height={}", width, height);
  1017. constexpr std::size_t base_size = 0x20000;
  1018. constexpr std::size_t alignment = 0x1000;
  1019. const auto texture_size = width * height * 4;
  1020. const auto out_size = (texture_size + base_size - 1) / base_size * base_size;
  1021. IPC::ResponseBuilder rb{ctx, 6};
  1022. rb.Push(RESULT_SUCCESS);
  1023. rb.Push(out_size);
  1024. rb.Push(alignment);
  1025. }
  1026. static ResultVal<ConvertedScaleMode> ConvertScalingModeImpl(NintendoScaleMode mode) {
  1027. switch (mode) {
  1028. case NintendoScaleMode::None:
  1029. return MakeResult(ConvertedScaleMode::None);
  1030. case NintendoScaleMode::Freeze:
  1031. return MakeResult(ConvertedScaleMode::Freeze);
  1032. case NintendoScaleMode::ScaleToWindow:
  1033. return MakeResult(ConvertedScaleMode::ScaleToWindow);
  1034. case NintendoScaleMode::ScaleAndCrop:
  1035. return MakeResult(ConvertedScaleMode::ScaleAndCrop);
  1036. case NintendoScaleMode::PreserveAspectRatio:
  1037. return MakeResult(ConvertedScaleMode::PreserveAspectRatio);
  1038. default:
  1039. LOG_ERROR(Service_VI, "Invalid scaling mode specified, mode={}", mode);
  1040. return ERR_OPERATION_FAILED;
  1041. }
  1042. }
  1043. NVFlinger::NVFlinger& nv_flinger;
  1044. };
  1045. IApplicationDisplayService::IApplicationDisplayService(NVFlinger::NVFlinger& nv_flinger)
  1046. : ServiceFramework("IApplicationDisplayService"), nv_flinger(nv_flinger) {
  1047. static const FunctionInfo functions[] = {
  1048. {100, &IApplicationDisplayService::GetRelayService, "GetRelayService"},
  1049. {101, &IApplicationDisplayService::GetSystemDisplayService, "GetSystemDisplayService"},
  1050. {102, &IApplicationDisplayService::GetManagerDisplayService, "GetManagerDisplayService"},
  1051. {103, &IApplicationDisplayService::GetIndirectDisplayTransactionService,
  1052. "GetIndirectDisplayTransactionService"},
  1053. {1000, &IApplicationDisplayService::ListDisplays, "ListDisplays"},
  1054. {1010, &IApplicationDisplayService::OpenDisplay, "OpenDisplay"},
  1055. {1011, &IApplicationDisplayService::OpenDefaultDisplay, "OpenDefaultDisplay"},
  1056. {1020, &IApplicationDisplayService::CloseDisplay, "CloseDisplay"},
  1057. {1101, &IApplicationDisplayService::SetDisplayEnabled, "SetDisplayEnabled"},
  1058. {1102, &IApplicationDisplayService::GetDisplayResolution, "GetDisplayResolution"},
  1059. {2020, &IApplicationDisplayService::OpenLayer, "OpenLayer"},
  1060. {2021, &IApplicationDisplayService::CloseLayer, "CloseLayer"},
  1061. {2030, &IApplicationDisplayService::CreateStrayLayer, "CreateStrayLayer"},
  1062. {2031, &IApplicationDisplayService::DestroyStrayLayer, "DestroyStrayLayer"},
  1063. {2101, &IApplicationDisplayService::SetLayerScalingMode, "SetLayerScalingMode"},
  1064. {2102, &IApplicationDisplayService::ConvertScalingMode, "ConvertScalingMode"},
  1065. {2450, nullptr, "GetIndirectLayerImageMap"},
  1066. {2451, nullptr, "GetIndirectLayerImageCropMap"},
  1067. {2460, &IApplicationDisplayService::GetIndirectLayerImageRequiredMemoryInfo,
  1068. "GetIndirectLayerImageRequiredMemoryInfo"},
  1069. {5202, &IApplicationDisplayService::GetDisplayVsyncEvent, "GetDisplayVsyncEvent"},
  1070. {5203, nullptr, "GetDisplayVsyncEventForDebug"},
  1071. };
  1072. RegisterHandlers(functions);
  1073. }
  1074. static bool IsValidServiceAccess(Permission permission, Policy policy) {
  1075. if (permission == Permission::User) {
  1076. return policy == Policy::User;
  1077. }
  1078. if (permission == Permission::System || permission == Permission::Manager) {
  1079. return policy == Policy::User || policy == Policy::Compositor;
  1080. }
  1081. return false;
  1082. }
  1083. void detail::GetDisplayServiceImpl(Kernel::HLERequestContext& ctx, NVFlinger::NVFlinger& nv_flinger,
  1084. Permission permission) {
  1085. IPC::RequestParser rp{ctx};
  1086. const auto policy = rp.PopEnum<Policy>();
  1087. if (!IsValidServiceAccess(permission, policy)) {
  1088. LOG_ERROR(Service_VI, "Permission denied for policy {}", static_cast<u32>(policy));
  1089. IPC::ResponseBuilder rb{ctx, 2};
  1090. rb.Push(ERR_PERMISSION_DENIED);
  1091. return;
  1092. }
  1093. IPC::ResponseBuilder rb{ctx, 2, 0, 1};
  1094. rb.Push(RESULT_SUCCESS);
  1095. rb.PushIpcInterface<IApplicationDisplayService>(nv_flinger);
  1096. }
  1097. void InstallInterfaces(SM::ServiceManager& service_manager, NVFlinger::NVFlinger& nv_flinger) {
  1098. std::make_shared<VI_M>(nv_flinger)->InstallAsService(service_manager);
  1099. std::make_shared<VI_S>(nv_flinger)->InstallAsService(service_manager);
  1100. std::make_shared<VI_U>(nv_flinger)->InstallAsService(service_manager);
  1101. }
  1102. } // namespace Service::VI