diff --git a/rpcs3/Emu/RSX/Overlays/overlay_trophy_notification.cpp b/rpcs3/Emu/RSX/Overlays/overlay_trophy_notification.cpp index 654644d370..dbf5d63895 100644 --- a/rpcs3/Emu/RSX/Overlays/overlay_trophy_notification.cpp +++ b/rpcs3/Emu/RSX/Overlays/overlay_trophy_notification.cpp @@ -5,6 +5,31 @@ namespace rsx { namespace overlays { + // TODO: Move somewhere in rsx_utils or general utils if needed anywhere else + class ticket_semaphore_t + { + atomic_t acquired{0}; + atomic_t released{0}; + + public: + u64 enqueue() + { + return acquired.fetch_add(1); + } + + bool try_acquire(u64 queue_id) const + { + return (queue_id == released.load()); + } + + void release() + { + released++; + } + }; + + static ticket_semaphore_t s_trophy_semaphore; + trophy_notification::trophy_notification() { frame.set_pos(0, 0); @@ -27,9 +52,23 @@ namespace rsx sliding_animation.progress_limit = { 0, 0, 0}; sliding_animation.active = true; } + void trophy_notification::update() { - u64 t = get_system_time(); + if (!s_trophy_semaphore.try_acquire(display_sched_id)) + { + // Not scheduled to run just yet + return; + } + + const u64 t = get_system_time(); + if (!creation_time) + { + // First tick + creation_time = t; + return; + } + if (((t - creation_time) / 1000) > 7500) { if (!sliding_animation.active) @@ -38,6 +77,7 @@ namespace rsx sliding_animation.progress_limit = { -int(frame.w), 0, 0 }; sliding_animation.on_finish = [this] { + s_trophy_semaphore.release(); close(); }; @@ -53,6 +93,11 @@ namespace rsx compiled_resource trophy_notification::get_compiled() { + if (!creation_time) + { + return {}; + } + auto result = frame.get_compiled(); result.add(image.get_compiled()); result.add(text_view.get_compiled()); @@ -63,6 +108,9 @@ namespace rsx s32 trophy_notification::show(const SceNpTrophyDetails& trophy, const std::vector& trophy_icon_buffer) { + // Schedule to display this trophy + display_sched_id = s_trophy_semaphore.enqueue(); + if (!trophy_icon_buffer.empty()) { icon_info = std::make_unique(trophy_icon_buffer); @@ -87,7 +135,6 @@ namespace rsx u16 margin_sz = text_view.x - image.w - image.x; frame.w = text_view.x + text_view.w + margin_sz; - creation_time = get_system_time(); return CELL_OK; } } // namespace overlays diff --git a/rpcs3/Emu/RSX/Overlays/overlays.h b/rpcs3/Emu/RSX/Overlays/overlays.h index 77dd9f14a3..f3d3f061b4 100644 --- a/rpcs3/Emu/RSX/Overlays/overlays.h +++ b/rpcs3/Emu/RSX/Overlays/overlays.h @@ -503,6 +503,7 @@ namespace rsx image_view image; label text_view; + u64 display_sched_id = 0; u64 creation_time = 0; std::unique_ptr icon_info; diff --git a/rpcs3/rpcs3qt/trophy_notification_helper.cpp b/rpcs3/rpcs3qt/trophy_notification_helper.cpp index bd0d636dcb..ad202736a9 100644 --- a/rpcs3/rpcs3qt/trophy_notification_helper.cpp +++ b/rpcs3/rpcs3qt/trophy_notification_helper.cpp @@ -9,7 +9,9 @@ s32 trophy_notification_helper::ShowTrophyNotification(const SceNpTrophyDetails& { if (auto manager = g_fxo->get()) { - return manager->create()->show(trophy, trophy_icon_buffer); + // Allow adding more than one trophy notification. The notification class manages scheduling + auto popup = std::make_shared(); + return manager->add(popup, false)->show(trophy, trophy_icon_buffer); } if (!Emu.HasGui())