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
{
template <typename T>
message_item::message_item(T msg_id, u64 expiration, std::shared_ptr<atomic_t<u32>> 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 <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_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<atomic_t<u32>>);
template message_item::message_item(localized_string_id 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>>, std::unique_ptr<overlay_element>);
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<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);
}
@ -60,6 +89,34 @@ namespace rsx
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()
{
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());
}

View file

@ -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 <typename T>
message_item(T msg_id, u64 expiration, std::shared_ptr<atomic_t<u32>> refs);
void update(usz index, u64 time);
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, u16 origin, int grow_direction);
u64 get_expiration() const;
compiled_resource get_compiled();
compiled_resource& get_compiled();
private:
label m_text{};
std::unique_ptr<overlay_element> m_icon{};
animation_color_interpolate m_fade_animation;
u64 m_expiration_time = 0;
u64 m_visible_duration = 0;
std::shared_ptr<atomic_t<u32>> m_refs;
bool m_processed = false;
usz m_cur_pos = umax;
@ -34,32 +42,56 @@ namespace rsx
compiled_resource get_compiled() override;
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);
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>>)
{
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<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>
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>())
{
@ -69,7 +101,7 @@ namespace rsx
msg_overlay = std::make_shared<rsx::overlays::message>();
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));
}
}