diff options
Diffstat (limited to '')
-rw-r--r-- | src/core/hle/service/vi/vi.cpp | 127 |
1 files changed, 95 insertions, 32 deletions
diff --git a/src/core/hle/service/vi/vi.cpp b/src/core/hle/service/vi/vi.cpp index fdc62d05b..55e00dd93 100644 --- a/src/core/hle/service/vi/vi.cpp +++ b/src/core/hle/service/vi/vi.cpp @@ -101,8 +101,8 @@ public: } std::u16string ReadInterfaceToken() { - u32 unknown = Read<u32_le>(); - u32 length = Read<u32_le>(); + [[maybe_unused]] const u32 unknown = Read<u32_le>(); + const u32 length = Read<u32_le>(); std::u16string token{}; @@ -159,7 +159,7 @@ public: header.data_size = static_cast<u32_le>(write_index - sizeof(Header)); header.data_offset = sizeof(Header); header.objects_size = 4; - header.objects_offset = sizeof(Header) + header.data_size; + header.objects_offset = static_cast<u32>(sizeof(Header) + header.data_size); std::memcpy(buffer.data(), &header, sizeof(Header)); return buffer; @@ -215,10 +215,9 @@ public: explicit IGBPConnectRequestParcel(std::vector<u8> buffer) : Parcel(std::move(buffer)) { Deserialize(); } - ~IGBPConnectRequestParcel() override = default; void DeserializeData() override { - std::u16string token = ReadInterfaceToken(); + [[maybe_unused]] const std::u16string token = ReadInterfaceToken(); data = Read<Data>(); } @@ -267,7 +266,7 @@ protected: private: struct Data { - u32_le unk_0; + u32_le unk_0{}; }; Data data{}; @@ -279,10 +278,9 @@ public: : Parcel(std::move(buffer)) { Deserialize(); } - ~IGBPSetPreallocatedBufferRequestParcel() override = default; void DeserializeData() override { - std::u16string token = ReadInterfaceToken(); + [[maybe_unused]] const std::u16string token = ReadInterfaceToken(); data = Read<Data>(); buffer = Read<NVFlinger::IGBPBuffer>(); } @@ -306,15 +304,40 @@ protected: } }; +class IGBPCancelBufferRequestParcel : public Parcel { +public: + explicit IGBPCancelBufferRequestParcel(std::vector<u8> buffer) : Parcel(std::move(buffer)) { + Deserialize(); + } + + void DeserializeData() override { + [[maybe_unused]] const std::u16string token = ReadInterfaceToken(); + data = Read<Data>(); + } + + struct Data { + u32_le slot; + Service::Nvidia::MultiFence multi_fence; + }; + + Data data; +}; + +class IGBPCancelBufferResponseParcel : public Parcel { +protected: + void SerializeData() override { + Write<u32>(0); // Success + } +}; + class IGBPDequeueBufferRequestParcel : public Parcel { public: explicit IGBPDequeueBufferRequestParcel(std::vector<u8> buffer) : Parcel(std::move(buffer)) { Deserialize(); } - ~IGBPDequeueBufferRequestParcel() override = default; void DeserializeData() override { - std::u16string token = ReadInterfaceToken(); + [[maybe_unused]] const std::u16string token = ReadInterfaceToken(); data = Read<Data>(); } @@ -333,7 +356,6 @@ class IGBPDequeueBufferResponseParcel : public Parcel { public: explicit IGBPDequeueBufferResponseParcel(u32 slot, Service::Nvidia::MultiFence& multi_fence) : slot(slot), multi_fence(multi_fence) {} - ~IGBPDequeueBufferResponseParcel() override = default; protected: void SerializeData() override { @@ -352,10 +374,9 @@ public: explicit IGBPRequestBufferRequestParcel(std::vector<u8> buffer) : Parcel(std::move(buffer)) { Deserialize(); } - ~IGBPRequestBufferRequestParcel() override = default; void DeserializeData() override { - std::u16string token = ReadInterfaceToken(); + [[maybe_unused]] const std::u16string token = ReadInterfaceToken(); slot = Read<u32_le>(); } @@ -384,10 +405,9 @@ public: explicit IGBPQueueBufferRequestParcel(std::vector<u8> buffer) : Parcel(std::move(buffer)) { Deserialize(); } - ~IGBPQueueBufferRequestParcel() override = default; void DeserializeData() override { - std::u16string token = ReadInterfaceToken(); + [[maybe_unused]] const std::u16string token = ReadInterfaceToken(); data = Read<Data>(); } @@ -447,10 +467,9 @@ public: explicit IGBPQueryRequestParcel(std::vector<u8> buffer) : Parcel(std::move(buffer)) { Deserialize(); } - ~IGBPQueryRequestParcel() override = default; void DeserializeData() override { - std::u16string token = ReadInterfaceToken(); + [[maybe_unused]] const std::u16string token = ReadInterfaceToken(); type = Read<u32_le>(); } @@ -511,6 +530,7 @@ private: LOG_DEBUG(Service_VI, "called. id=0x{:08X} transaction={:X}, flags=0x{:08X}", id, static_cast<u32>(transaction), flags); + const auto guard = nv_flinger->Lock(); auto& buffer_queue = nv_flinger->FindBufferQueue(id); switch (transaction) { @@ -518,9 +538,9 @@ private: IGBPConnectRequestParcel request{ctx.ReadBuffer()}; IGBPConnectResponseParcel response{ static_cast<u32>(static_cast<u32>(DisplayResolution::UndockedWidth) * - Settings::values.resolution_factor), + Settings::values.resolution_factor.GetValue()), static_cast<u32>(static_cast<u32>(DisplayResolution::UndockedHeight) * - Settings::values.resolution_factor)}; + Settings::values.resolution_factor.GetValue())}; ctx.WriteBuffer(response.Serialize()); break; } @@ -547,9 +567,10 @@ private: // Wait the current thread until a buffer becomes available ctx.SleepClientThread( "IHOSBinderDriver::DequeueBuffer", UINT64_MAX, - [=](std::shared_ptr<Kernel::Thread> thread, Kernel::HLERequestContext& ctx, - Kernel::ThreadWakeupReason reason) { + [=, this](std::shared_ptr<Kernel::Thread> thread, + Kernel::HLERequestContext& ctx, Kernel::ThreadWakeupReason reason) { // Repeat TransactParcel DequeueBuffer when a buffer is available + const auto guard = nv_flinger->Lock(); auto& buffer_queue = nv_flinger->FindBufferQueue(id); auto result = buffer_queue.DequeueBuffer(width, height); ASSERT_MSG(result != std::nullopt, "Could not dequeue buffer."); @@ -594,7 +615,12 @@ private: break; } case TransactionId::CancelBuffer: { - LOG_CRITICAL(Service_VI, "(STUBBED) called, transaction=CancelBuffer"); + IGBPCancelBufferRequestParcel request{ctx.ReadBuffer()}; + + buffer_queue.CancelBuffer(request.data.slot, request.data.multi_fence); + + IGBPCancelBufferResponseParcel response{}; + ctx.WriteBuffer(response.Serialize()); break; } case TransactionId::Disconnect: { @@ -614,6 +640,14 @@ private: ctx.WriteBuffer(response.Serialize()); break; } + case TransactionId::SetBufferCount: { + LOG_WARNING(Service_VI, "(STUBBED) called, transaction=SetBufferCount"); + [[maybe_unused]] const auto buffer = ctx.ReadBuffer(); + + IGBPEmptyResponseParcel response{}; + ctx.WriteBuffer(response.Serialize()); + break; + } default: ASSERT_MSG(false, "Unimplemented"); } @@ -690,6 +724,7 @@ public: {3215, nullptr, "SetDisplayGamma"}, {3216, nullptr, "GetDisplayCmuLuma"}, {3217, nullptr, "SetDisplayCmuLuma"}, + {6013, nullptr, "GetLayerPresentationSubmissionTimestamps"}, {8225, nullptr, "GetSharedBufferMemoryHandleId"}, {8250, nullptr, "OpenSharedLayer"}, {8251, nullptr, "CloseSharedLayer"}, @@ -736,16 +771,16 @@ private: IPC::ResponseBuilder rb{ctx, 6}; rb.Push(RESULT_SUCCESS); - if (Settings::values.use_docked_mode) { + if (Settings::values.use_docked_mode.GetValue()) { rb.Push(static_cast<u32>(Service::VI::DisplayResolution::DockedWidth) * - static_cast<u32>(Settings::values.resolution_factor)); + static_cast<u32>(Settings::values.resolution_factor.GetValue())); rb.Push(static_cast<u32>(Service::VI::DisplayResolution::DockedHeight) * - static_cast<u32>(Settings::values.resolution_factor)); + static_cast<u32>(Settings::values.resolution_factor.GetValue())); } else { rb.Push(static_cast<u32>(Service::VI::DisplayResolution::UndockedWidth) * - static_cast<u32>(Settings::values.resolution_factor)); + static_cast<u32>(Settings::values.resolution_factor.GetValue())); rb.Push(static_cast<u32>(Service::VI::DisplayResolution::UndockedHeight) * - static_cast<u32>(Settings::values.resolution_factor)); + static_cast<u32>(Settings::values.resolution_factor.GetValue())); } rb.PushRaw<float>(60.0f); // This wouldn't seem to be correct for 30 fps games. @@ -775,6 +810,7 @@ public: {2300, nullptr, "AcquireLayerTexturePresentingEvent"}, {2301, nullptr, "ReleaseLayerTexturePresentingEvent"}, {2302, nullptr, "GetDisplayHotplugEvent"}, + {2303, nullptr, "GetDisplayModeChangedEvent"}, {2402, nullptr, "GetDisplayHotplugState"}, {2501, nullptr, "GetCompositorErrorInfo"}, {2601, nullptr, "GetDisplayErrorEvent"}, @@ -859,6 +895,7 @@ private: const auto layer_id = nv_flinger->CreateLayer(display); if (!layer_id) { + LOG_ERROR(Service_VI, "Layer not found! display=0x{:016X}", display); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ERR_NOT_FOUND); return; @@ -975,6 +1012,7 @@ private: const auto display_id = nv_flinger->OpenDisplay(name); if (!display_id) { + LOG_ERROR(Service_VI, "Display not found! display_name={}", name); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ERR_NOT_FOUND); return; @@ -1017,9 +1055,9 @@ private: // between docked and undocked dimensions. We take the liberty of applying // the resolution scaling factor here. rb.Push(static_cast<u64>(DisplayResolution::UndockedWidth) * - static_cast<u32>(Settings::values.resolution_factor)); + static_cast<u32>(Settings::values.resolution_factor.GetValue())); rb.Push(static_cast<u64>(DisplayResolution::UndockedHeight) * - static_cast<u32>(Settings::values.resolution_factor)); + static_cast<u32>(Settings::values.resolution_factor.GetValue())); } void SetLayerScalingMode(Kernel::HLERequestContext& ctx) { @@ -1052,8 +1090,8 @@ private: LOG_WARNING(Service_VI, "(STUBBED) called"); DisplayInfo display_info; - display_info.width *= static_cast<u64>(Settings::values.resolution_factor); - display_info.height *= static_cast<u64>(Settings::values.resolution_factor); + display_info.width *= static_cast<u64>(Settings::values.resolution_factor.GetValue()); + display_info.height *= static_cast<u64>(Settings::values.resolution_factor.GetValue()); ctx.WriteBuffer(&display_info, sizeof(DisplayInfo)); IPC::ResponseBuilder rb{ctx, 4}; rb.Push(RESULT_SUCCESS); @@ -1074,6 +1112,7 @@ private: const auto display_id = nv_flinger->OpenDisplay(display_name); if (!display_id) { + LOG_ERROR(Service_VI, "Layer not found! layer_id={}", layer_id); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ERR_NOT_FOUND); return; @@ -1081,6 +1120,7 @@ private: const auto buffer_queue_id = nv_flinger->FindBufferQueueId(*display_id, layer_id); if (!buffer_queue_id) { + LOG_ERROR(Service_VI, "Buffer queue id not found! display_id={}", *display_id); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ERR_NOT_FOUND); return; @@ -1116,6 +1156,7 @@ private: const auto layer_id = nv_flinger->CreateLayer(display_id); if (!layer_id) { + LOG_ERROR(Service_VI, "Layer not found! layer_id={}", *layer_id); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ERR_NOT_FOUND); return; @@ -1123,6 +1164,7 @@ private: const auto buffer_queue_id = nv_flinger->FindBufferQueueId(display_id, *layer_id); if (!buffer_queue_id) { + LOG_ERROR(Service_VI, "Buffer queue id not found! display_id={}", display_id); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ERR_NOT_FOUND); return; @@ -1153,6 +1195,7 @@ private: const auto vsync_event = nv_flinger->FindVsyncEvent(display_id); if (!vsync_event) { + LOG_ERROR(Service_VI, "Vsync event was not found for display_id={}", display_id); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ERR_NOT_FOUND); return; @@ -1180,6 +1223,23 @@ private: } } + void GetIndirectLayerImageRequiredMemoryInfo(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto width = rp.Pop<u64>(); + const auto height = rp.Pop<u64>(); + LOG_DEBUG(Service_VI, "called width={}, height={}", width, height); + + constexpr std::size_t base_size = 0x20000; + constexpr std::size_t alignment = 0x1000; + const auto texture_size = width * height * 4; + const auto out_size = (texture_size + base_size - 1) / base_size * base_size; + + IPC::ResponseBuilder rb{ctx, 6}; + rb.Push(RESULT_SUCCESS); + rb.Push(out_size); + rb.Push(alignment); + } + static ResultVal<ConvertedScaleMode> ConvertScalingModeImpl(NintendoScaleMode mode) { switch (mode) { case NintendoScaleMode::None: @@ -1193,6 +1253,7 @@ private: case NintendoScaleMode::PreserveAspectRatio: return MakeResult(ConvertedScaleMode::PreserveAspectRatio); default: + LOG_ERROR(Service_VI, "Invalid scaling mode specified, mode={}", mode); return ERR_OPERATION_FAILED; } } @@ -1223,7 +1284,8 @@ IApplicationDisplayService::IApplicationDisplayService( {2102, &IApplicationDisplayService::ConvertScalingMode, "ConvertScalingMode"}, {2450, nullptr, "GetIndirectLayerImageMap"}, {2451, nullptr, "GetIndirectLayerImageCropMap"}, - {2460, nullptr, "GetIndirectLayerImageRequiredMemoryInfo"}, + {2460, &IApplicationDisplayService::GetIndirectLayerImageRequiredMemoryInfo, + "GetIndirectLayerImageRequiredMemoryInfo"}, {5202, &IApplicationDisplayService::GetDisplayVsyncEvent, "GetDisplayVsyncEvent"}, {5203, nullptr, "GetDisplayVsyncEventForDebug"}, }; @@ -1249,6 +1311,7 @@ void detail::GetDisplayServiceImpl(Kernel::HLERequestContext& ctx, const auto policy = rp.PopEnum<Policy>(); if (!IsValidServiceAccess(permission, policy)) { + LOG_ERROR(Service_VI, "Permission denied for policy {}", static_cast<u32>(policy)); IPC::ResponseBuilder rb{ctx, 2}; rb.Push(ERR_PERMISSION_DENIED); return; |