rsx: Implement notification queue

This commit is contained in:
kd-11 2023-02-01 23:04:08 +03:00 committed by kd-11
parent c471120a80
commit 0885884839
2 changed files with 122 additions and 43 deletions

View file

@ -6,13 +6,23 @@ namespace rsx
{ {
namespace overlays namespace overlays
{ {
template <typename T> static u64 get_expiration_time(u64 duration)
message_item::message_item(T msg_id, u64 expiration, std::shared_ptr<atomic_t<u32>> refs)
{ {
m_expiration_time = expiration == umax ? expiration : get_system_time() + expiration; if (duration == umax)
{
return duration;
}
return rsx::uclock() + duration;
}
template <typename T>
message_item::message_item(T msg_id, u64 expiration, std::shared_ptr<atomic_t<u32>> refs, std::unique_ptr<overlay_element> icon)
{
m_visible_duration = expiration;
m_refs = std::move(refs); 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.set_text(msg_id);
m_text.auto_resize(); m_text.auto_resize();
m_text.back_color.a = 0.f; 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.end = color4f(1.0f, 1.0f, 1.0f, 0.f);
m_fade_animation.duration = 2.f; m_fade_animation.duration = 2.f;
m_fade_animation.active = true; 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<atomic_t<u32>>); template message_item::message_item(std::string msg_id, u64, std::shared_ptr<atomic_t<u32>>, std::unique_ptr<overlay_element>);
template message_item::message_item(localized_string_id msg_id, u64, std::shared_ptr<atomic_t<u32>>); template message_item::message_item(localized_string_id msg_id, u64, std::shared_ptr<atomic_t<u32>>, std::unique_ptr<overlay_element>);
u64 message_item::get_expiration() const u64 message_item::get_expiration() const
{ {
@ -31,28 +47,41 @@ namespace rsx
return m_refs && *m_refs == 0 ? 0 : m_expiration_time; 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) if (!m_processed)
{ {
return {}; compiled_resources = {};
return compiled_resources;
} }
auto cr = m_text.get_compiled(); compiled_resources = m_text.get_compiled();
m_fade_animation.apply(cr); 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) if (m_cur_pos != index)
{ {
m_cur_pos = index; m_cur_pos = index;
m_text.set_pos(10, static_cast<u16>(index * 18)); m_text.set_pos(10, static_cast<u16>(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); m_fade_animation.update(rsx::get_current_renderer()->vblank_count);
} }
@ -60,6 +89,34 @@ namespace rsx
m_processed = true; m_processed = true;
} }
void message::update_queue(std::deque<message_item>& vis_set, std::deque<message_item>& 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() void message::update()
{ {
if (!visible) if (!visible)
@ -68,26 +125,11 @@ namespace rsx
} }
std::lock_guard lock(m_mutex_queue); std::lock_guard lock(m_mutex_queue);
u64 cur_time = get_system_time();
while (!m_queue.empty() && m_queue.front().get_expiration() < cur_time) 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);
m_queue.pop_front();
}
if (m_queue.empty()) visible = !m_vis_items_top.empty() || !m_vis_items_bottom.empty();
{
visible = false;
return;
}
usz index = 0;
for (auto& item : m_queue)
{
item.update(index, cur_time);
index++;
}
} }
compiled_resource message::get_compiled() compiled_resource message::get_compiled()
@ -101,7 +143,12 @@ namespace rsx
compiled_resource cr{}; 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()); cr.add(item.get_compiled());
} }

View file

@ -7,21 +7,29 @@ namespace rsx
{ {
namespace overlays namespace overlays
{ {
class message_item enum message_pin_location
{
top,
bottom
};
class message_item : public overlay_element
{ {
public: public:
template <typename T> template <typename T>
message_item(T msg_id, u64 expiration, std::shared_ptr<atomic_t<u32>> refs); message_item(T msg_id, u64 expiration, std::shared_ptr<atomic_t<u32>> refs, std::unique_ptr<overlay_element> icon = {});
void update(usz index, u64 time); void update(usz index, u64 time, u16 origin, int grow_direction);
u64 get_expiration() const; u64 get_expiration() const;
compiled_resource get_compiled(); compiled_resource& get_compiled();
private: private:
label m_text{}; label m_text{};
std::unique_ptr<overlay_element> m_icon{};
animation_color_interpolate m_fade_animation; animation_color_interpolate m_fade_animation;
u64 m_expiration_time = 0; u64 m_expiration_time = 0;
u64 m_visible_duration = 0;
std::shared_ptr<atomic_t<u32>> m_refs; std::shared_ptr<atomic_t<u32>> m_refs;
bool m_processed = false; bool m_processed = false;
usz m_cur_pos = umax; usz m_cur_pos = umax;
@ -34,32 +42,56 @@ namespace rsx
compiled_resource get_compiled() override; compiled_resource get_compiled() override;
template <typename T> template <typename T>
void queue_message(T msg_id, u64 expiration, std::shared_ptr<atomic_t<u32>> refs) void queue_message(
T msg_id,
u64 expiration,
std::shared_ptr<atomic_t<u32>> refs,
message_pin_location location = message_pin_location::top,
std::unique_ptr<overlay_element> icon = {})
{ {
std::lock_guard lock(m_mutex_queue); 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<T, std::initializer_list<localized_string_id>>) if constexpr (std::is_same_v<T, std::initializer_list<localized_string_id>>)
{ {
for (auto id : msg_id) for (auto id : msg_id)
{ {
m_queue.emplace_back(id, expiration, refs); queue.emplace_back(id, expiration, refs, icon);
} }
} }
else 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; visible = true;
} }
private: private:
const u32 max_visible_items = 3;
shared_mutex m_mutex_queue; shared_mutex m_mutex_queue;
std::deque<message_item> m_queue;
// Top and bottom enqueued sets
std::deque<message_item> m_ready_queue_top;
std::deque<message_item> m_ready_queue_bottom;
// Top and bottom visible sets
std::deque<message_item> m_vis_items_top;
std::deque<message_item> m_vis_items_bottom;
void update_queue(std::deque<message_item>& vis_set, std::deque<message_item>& ready_set, u16 origin, int grow_direction);
}; };
template <typename T> template <typename T>
void queue_message(T msg_id, u64 expiration = 5'000'000, std::shared_ptr<atomic_t<u32>> refs = {}) void queue_message(
T msg_id,
u64 expiration = 5'000'000,
std::shared_ptr<atomic_t<u32>> refs = {},
message_pin_location location = message_pin_location::top,
std::unique_ptr<overlay_element> icon = {})
{ {
if (auto manager = g_fxo->try_get<rsx::overlays::display_manager>()) if (auto manager = g_fxo->try_get<rsx::overlays::display_manager>())
{ {
@ -69,7 +101,7 @@ namespace rsx
msg_overlay = std::make_shared<rsx::overlays::message>(); msg_overlay = std::make_shared<rsx::overlays::message>();
msg_overlay = manager->add(msg_overlay); 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));
} }
} }