diff --git a/src/core/hle/service/nvnflinger/hos_binder_driver.cpp b/src/core/hle/service/nvnflinger/hos_binder_driver.cpp index 8629a2e89b..1ca64769fa 100644 --- a/src/core/hle/service/nvnflinger/hos_binder_driver.cpp +++ b/src/core/hle/service/nvnflinger/hos_binder_driver.cpp @@ -41,12 +41,14 @@ Result IHOSBinderDriver::TransactParcel(s32 binder_id, u32 transaction_id, Result IHOSBinderDriver::AdjustRefcount(s32 binder_id, s32 addval, s32 type) { LOG_WARNING(Service_VI, "(STUBBED) called id={}, addval={}, type={}", binder_id, addval, type); + R_UNLESS(type == 0 || type == 1, ResultUnknown); + m_server->AdjustRefcount(binder_id, addval, type == 1); R_SUCCEED(); } Result IHOSBinderDriver::GetNativeHandle(s32 binder_id, u32 type_id, OutCopyHandle out_handle) { - LOG_WARNING(Service_VI, "(STUBBED) called id={}, type_id={}", binder_id, type_id); + LOG_DEBUG(Service_VI, "called id={}, type_id={}", binder_id, type_id); const auto binder = m_server->TryGetBinder(binder_id); R_UNLESS(binder != nullptr, ResultUnknown); diff --git a/src/core/hle/service/nvnflinger/hos_binder_driver_server.cpp b/src/core/hle/service/nvnflinger/hos_binder_driver_server.cpp index 29addda44d..b85f1a4fa4 100644 --- a/src/core/hle/service/nvnflinger/hos_binder_driver_server.cpp +++ b/src/core/hle/service/nvnflinger/hos_binder_driver_server.cpp @@ -17,6 +17,7 @@ s32 HosBinderDriverServer::RegisterBinder(std::shared_ptr&& bi last_id++; binders[last_id] = std::move(binder); + refcounts[last_id] = {}; // strong = 1, weak = 0 return last_id; } @@ -25,6 +26,29 @@ void HosBinderDriverServer::UnregisterBinder(s32 binder_id) { std::scoped_lock lk{lock}; binders.erase(binder_id); + refcounts.erase(binder_id); +} + +void HosBinderDriverServer::AdjustRefcount(s32 binder_id, s32 delta, bool is_weak) { + std::scoped_lock lk{lock}; + + auto search_rc = refcounts.find(binder_id); + if (search_rc == refcounts.end()) { + LOG_WARNING(Service_VI, "AdjustRefcount called for unknown binder id {}", binder_id); + return; + } + + auto& rc = search_rc->second; + s32& counter = is_weak ? rc.weak : rc.strong; + counter += delta; + + if (counter < 0) + counter = 0; + + if (rc.strong == 0 && rc.weak == 0) { + binders.erase(binder_id); + refcounts.erase(search_rc); + } } std::shared_ptr HosBinderDriverServer::TryGetBinder(s32 id) const { diff --git a/src/core/hle/service/nvnflinger/hos_binder_driver_server.h b/src/core/hle/service/nvnflinger/hos_binder_driver_server.h index d72b50833d..f4b4060115 100644 --- a/src/core/hle/service/nvnflinger/hos_binder_driver_server.h +++ b/src/core/hle/service/nvnflinger/hos_binder_driver_server.h @@ -26,10 +26,18 @@ public: std::shared_ptr TryGetBinder(s32 id) const; + void AdjustRefcount(s32 binder_id, s32 delta, bool is_weak); + private: - std::unordered_map> binders; + struct RefCounts { + s32 strong{1}; + s32 weak{0}; + }; + mutable std::mutex lock; - s32 last_id{}; + s32 last_id = 0; + std::unordered_map> binders; + std::unordered_map refcounts; }; } // namespace Service::Nvnflinger