From 0885884839c72936f7d47263ca56697fa3146766 Mon Sep 17 00:00:00 2001 From: kd-11 Date: Wed, 1 Feb 2023 23:04:08 +0300 Subject: [PATCH] rsx: Implement notification queue --- rpcs3/Emu/RSX/Overlays/overlay_message.cpp | 113 +++++++++++++++------ rpcs3/Emu/RSX/Overlays/overlay_message.h | 52 ++++++++-- 2 files changed, 122 insertions(+), 43 deletions(-) diff --git a/rpcs3/Emu/RSX/Overlays/overlay_message.cpp b/rpcs3/Emu/RSX/Overlays/overlay_message.cpp index 4c2f98bf02..0738366dc0 100644 --- a/rpcs3/Emu/RSX/Overlays/overlay_message.cpp +++ b/rpcs3/Emu/RSX/Overlays/overlay_message.cpp @@ -6,13 +6,23 @@ namespace rsx { namespace overlays { - template - message_item::message_item(T msg_id, u64 expiration, std::shared_ptr> refs) + static u64 get_expiration_time(u64 duration) { - m_expiration_time = expiration == umax ? expiration : get_system_time() + expiration; + if (duration == umax) + { + return duration; + } + + return rsx::uclock() + duration; + } + + template + message_item::message_item(T msg_id, u64 expiration, std::shared_ptr> refs, std::unique_ptr icon) + { + m_visible_duration = expiration; m_refs = std::move(refs); - m_text.set_font("Arial", 16); + m_text.set_font("Arial", 14); m_text.set_text(msg_id); m_text.auto_resize(); m_text.back_color.a = 0.f; @@ -21,9 +31,15 @@ namespace rsx m_fade_animation.end = color4f(1.0f, 1.0f, 1.0f, 0.f); m_fade_animation.duration = 2.f; m_fade_animation.active = true; + + if (icon) + { + m_icon = std::move(icon); + m_icon->set_pos(m_text.x + m_text.w + 8, m_text.y); + } } - template message_item::message_item(std::string msg_id, u64, std::shared_ptr>); - template message_item::message_item(localized_string_id msg_id, u64, std::shared_ptr>); + template message_item::message_item(std::string msg_id, u64, std::shared_ptr>, std::unique_ptr); + template message_item::message_item(localized_string_id msg_id, u64, std::shared_ptr>, std::unique_ptr); u64 message_item::get_expiration() const { @@ -31,28 +47,41 @@ namespace rsx return m_refs && *m_refs == 0 ? 0 : m_expiration_time; } - compiled_resource message_item::get_compiled() + compiled_resource& message_item::get_compiled() { if (!m_processed) { - return {}; + compiled_resources = {}; + return compiled_resources; } - auto cr = m_text.get_compiled(); - m_fade_animation.apply(cr); + compiled_resources = m_text.get_compiled(); + if (m_icon) + { + compiled_resources.add(m_icon->get_compiled()); + } + m_fade_animation.apply(compiled_resources); - return cr; + return compiled_resources; } - void message_item::update(usz index, u64 time) + void message_item::update(usz index, u64 time, u16 origin, int grow_direction) { if (m_cur_pos != index) { m_cur_pos = index; - m_text.set_pos(10, static_cast(index * 18)); + m_text.set_pos(10, static_cast(origin + (index * 18 * grow_direction))); + if (m_icon) + { + m_icon->set_pos(m_icon->x, m_text.y); + } } - if ((m_expiration_time - time) < 2'000'000) + if (!m_processed) + { + m_expiration_time = get_expiration_time(m_visible_duration); + } + else if ((m_expiration_time - time) < 2'000'000) { m_fade_animation.update(rsx::get_current_renderer()->vblank_count); } @@ -60,6 +89,34 @@ namespace rsx m_processed = true; } + void message::update_queue(std::deque& vis_set, std::deque& ready_set, u16 origin, int grow_direction) + { + const u64 cur_time = rsx::uclock(); + + while (!vis_set.empty() && vis_set.front().get_expiration() < cur_time) + { + vis_set.pop_front(); + } + + while (vis_set.size() < max_visible_items && !ready_set.empty()) + { + vis_set.emplace_back(std::move(ready_set.front())); + ready_set.pop_front(); + } + + if (vis_set.empty() && ready_set.empty()) + { + return; + } + + usz index = 0; + for (auto& item : vis_set) + { + item.update(index, cur_time, origin, grow_direction); + index++; + } + } + void message::update() { if (!visible) @@ -68,26 +125,11 @@ namespace rsx } std::lock_guard lock(m_mutex_queue); - u64 cur_time = get_system_time(); - while (!m_queue.empty() && m_queue.front().get_expiration() < cur_time) - { - m_queue.pop_front(); - } + update_queue(m_vis_items_top, m_ready_queue_top, 0, 1); + update_queue(m_vis_items_bottom, m_ready_queue_bottom, virtual_height - 18, -1); - if (m_queue.empty()) - { - visible = false; - return; - } - - usz index = 0; - - for (auto& item : m_queue) - { - item.update(index, cur_time); - index++; - } + visible = !m_vis_items_top.empty() || !m_vis_items_bottom.empty(); } compiled_resource message::get_compiled() @@ -101,7 +143,12 @@ namespace rsx compiled_resource cr{}; - for (auto& item : m_queue) + for (auto& item : m_vis_items_top) + { + cr.add(item.get_compiled()); + } + + for (auto& item : m_vis_items_bottom) { cr.add(item.get_compiled()); } diff --git a/rpcs3/Emu/RSX/Overlays/overlay_message.h b/rpcs3/Emu/RSX/Overlays/overlay_message.h index 1673ebd718..09348e8111 100644 --- a/rpcs3/Emu/RSX/Overlays/overlay_message.h +++ b/rpcs3/Emu/RSX/Overlays/overlay_message.h @@ -7,21 +7,29 @@ namespace rsx { namespace overlays { - class message_item + enum message_pin_location + { + top, + bottom + }; + + class message_item : public overlay_element { public: template - message_item(T msg_id, u64 expiration, std::shared_ptr> refs); - void update(usz index, u64 time); + message_item(T msg_id, u64 expiration, std::shared_ptr> refs, std::unique_ptr icon = {}); + void update(usz index, u64 time, u16 origin, int grow_direction); u64 get_expiration() const; - compiled_resource get_compiled(); + compiled_resource& get_compiled(); private: label m_text{}; + std::unique_ptr m_icon{}; animation_color_interpolate m_fade_animation; u64 m_expiration_time = 0; + u64 m_visible_duration = 0; std::shared_ptr> m_refs; bool m_processed = false; usz m_cur_pos = umax; @@ -34,32 +42,56 @@ namespace rsx compiled_resource get_compiled() override; template - void queue_message(T msg_id, u64 expiration, std::shared_ptr> refs) + void queue_message( + T msg_id, + u64 expiration, + std::shared_ptr> refs, + message_pin_location location = message_pin_location::top, + std::unique_ptr icon = {}) { std::lock_guard lock(m_mutex_queue); + auto& queue = location == message_pin_location::top + ? m_ready_queue_top + : m_ready_queue_bottom; + if constexpr (std::is_same_v>) { for (auto id : msg_id) { - m_queue.emplace_back(id, expiration, refs); + queue.emplace_back(id, expiration, refs, icon); } } else { - m_queue.emplace_back(msg_id, expiration, std::move(refs)); + queue.emplace_back(msg_id, expiration, std::move(refs), std::move(icon)); } visible = true; } private: + const u32 max_visible_items = 3; shared_mutex m_mutex_queue; - std::deque m_queue; + + // Top and bottom enqueued sets + std::deque m_ready_queue_top; + std::deque m_ready_queue_bottom; + + // Top and bottom visible sets + std::deque m_vis_items_top; + std::deque m_vis_items_bottom; + + void update_queue(std::deque& vis_set, std::deque& ready_set, u16 origin, int grow_direction); }; template - void queue_message(T msg_id, u64 expiration = 5'000'000, std::shared_ptr> refs = {}) + void queue_message( + T msg_id, + u64 expiration = 5'000'000, + std::shared_ptr> refs = {}, + message_pin_location location = message_pin_location::top, + std::unique_ptr icon = {}) { if (auto manager = g_fxo->try_get()) { @@ -69,7 +101,7 @@ namespace rsx msg_overlay = std::make_shared(); msg_overlay = manager->add(msg_overlay); } - msg_overlay->queue_message(msg_id, expiration, std::move(refs)); + msg_overlay->queue_message(msg_id, expiration, std::move(refs), location, std::move(icon)); } }