mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-10 00:41:26 +12:00
rsx/overlays: Refactor and implement callbacks for input token
This commit is contained in:
parent
6b30cdac09
commit
12690de9de
5 changed files with 336 additions and 0 deletions
|
@ -456,6 +456,7 @@ target_sources(rpcs3_emu PRIVATE
|
||||||
RSX/Overlays/overlay_edit_text.cpp
|
RSX/Overlays/overlay_edit_text.cpp
|
||||||
RSX/Overlays/overlay_fonts.cpp
|
RSX/Overlays/overlay_fonts.cpp
|
||||||
RSX/Overlays/overlay_list_view.cpp
|
RSX/Overlays/overlay_list_view.cpp
|
||||||
|
RSX/Overlays/overlay_manager.cpp
|
||||||
RSX/Overlays/overlay_media_list_dialog.cpp
|
RSX/Overlays/overlay_media_list_dialog.cpp
|
||||||
RSX/Overlays/overlay_message.cpp
|
RSX/Overlays/overlay_message.cpp
|
||||||
RSX/Overlays/overlay_message_dialog.cpp
|
RSX/Overlays/overlay_message_dialog.cpp
|
||||||
|
|
157
rpcs3/Emu/RSX/Overlays/overlay_manager.cpp
Normal file
157
rpcs3/Emu/RSX/Overlays/overlay_manager.cpp
Normal file
|
@ -0,0 +1,157 @@
|
||||||
|
#include "stdafx.h"
|
||||||
|
#include "overlay_manager.h"
|
||||||
|
|
||||||
|
namespace rsx
|
||||||
|
{
|
||||||
|
namespace overlays
|
||||||
|
{
|
||||||
|
void display_manager::lock()
|
||||||
|
{
|
||||||
|
m_list_mutex.lock_shared();
|
||||||
|
}
|
||||||
|
|
||||||
|
void display_manager::unlock()
|
||||||
|
{
|
||||||
|
m_list_mutex.unlock_shared();
|
||||||
|
|
||||||
|
if (!m_uids_to_remove.empty() || !m_type_ids_to_remove.empty())
|
||||||
|
{
|
||||||
|
std::lock_guard lock(m_list_mutex);
|
||||||
|
cleanup_internal();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<overlay> display_manager::get(u32 uid)
|
||||||
|
{
|
||||||
|
reader_lock lock(m_list_mutex);
|
||||||
|
|
||||||
|
for (const auto& iface : m_iface_list)
|
||||||
|
{
|
||||||
|
if (iface->uid == uid)
|
||||||
|
return iface;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
void display_manager::remove(u32 uid)
|
||||||
|
{
|
||||||
|
if (m_list_mutex.try_lock())
|
||||||
|
{
|
||||||
|
remove_uid(uid);
|
||||||
|
m_list_mutex.unlock();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_uids_to_remove.push_back(uid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void display_manager::dispose(const std::vector<u32>& uids)
|
||||||
|
{
|
||||||
|
std::lock_guard lock(m_list_mutex);
|
||||||
|
|
||||||
|
if (!m_uids_to_remove.empty() || !m_type_ids_to_remove.empty())
|
||||||
|
{
|
||||||
|
cleanup_internal();
|
||||||
|
}
|
||||||
|
|
||||||
|
m_dirty_list.erase
|
||||||
|
(
|
||||||
|
std::remove_if(m_dirty_list.begin(), m_dirty_list.end(), [&uids](std::shared_ptr<overlay>& e)
|
||||||
|
{
|
||||||
|
return std::find(uids.begin(), uids.end(), e->uid) != uids.end();
|
||||||
|
}),
|
||||||
|
m_dirty_list.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool display_manager::remove_type(u32 type_id)
|
||||||
|
{
|
||||||
|
bool found = false;
|
||||||
|
for (auto It = m_iface_list.begin(); It != m_iface_list.end();)
|
||||||
|
{
|
||||||
|
if (It->get()->type_index == type_id)
|
||||||
|
{
|
||||||
|
on_overlay_removed(*It);
|
||||||
|
m_dirty_list.push_back(std::move(*It));
|
||||||
|
It = m_iface_list.erase(It);
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
++It;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool display_manager::remove_uid(u32 uid)
|
||||||
|
{
|
||||||
|
for (auto It = m_iface_list.begin(); It != m_iface_list.end(); It++)
|
||||||
|
{
|
||||||
|
const auto e = It->get();
|
||||||
|
if (e->uid == uid)
|
||||||
|
{
|
||||||
|
on_overlay_removed(*It);
|
||||||
|
m_dirty_list.push_back(std::move(*It));
|
||||||
|
m_iface_list.erase(It);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void display_manager::cleanup_internal()
|
||||||
|
{
|
||||||
|
for (const auto& uid : m_uids_to_remove)
|
||||||
|
{
|
||||||
|
remove_uid(uid);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto& type_id : m_type_ids_to_remove)
|
||||||
|
{
|
||||||
|
remove_type(type_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_uids_to_remove.clear();
|
||||||
|
m_type_ids_to_remove.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void display_manager::on_overlay_activated(const std::shared_ptr<overlay>& item)
|
||||||
|
{
|
||||||
|
if (auto iface = std::dynamic_pointer_cast<user_interface>(item))
|
||||||
|
{
|
||||||
|
std::lock_guard lock(m_input_thread_lock);
|
||||||
|
m_input_token_stack.emplace_front(std::move(iface));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void display_manager::on_overlay_removed(const std::shared_ptr<overlay>& item)
|
||||||
|
{
|
||||||
|
if (!dynamic_cast<user_interface*>(item.get()))
|
||||||
|
{
|
||||||
|
// Not instance of UI, ignore
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::lock_guard lock(m_input_thread_lock);
|
||||||
|
for (auto& entry : m_input_token_stack)
|
||||||
|
{
|
||||||
|
if (entry.target->uid == item->uid)
|
||||||
|
{
|
||||||
|
// Release
|
||||||
|
entry.target = {};
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// The top must never be an empty ref. Pop all empties.
|
||||||
|
while (!m_input_token_stack.front().target && m_input_token_stack.size())
|
||||||
|
{
|
||||||
|
m_input_token_stack.pop_front();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
170
rpcs3/Emu/RSX/Overlays/overlay_manager.h
Normal file
170
rpcs3/Emu/RSX/Overlays/overlay_manager.h
Normal file
|
@ -0,0 +1,170 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "overlays.h"
|
||||||
|
|
||||||
|
#include "Emu/IdManager.h"
|
||||||
|
#include "Utilities/mutex.h"
|
||||||
|
#include "Utilities/Timer.h"
|
||||||
|
|
||||||
|
#include <deque>
|
||||||
|
#include <set>
|
||||||
|
|
||||||
|
namespace rsx
|
||||||
|
{
|
||||||
|
namespace overlays
|
||||||
|
{
|
||||||
|
struct overlay;
|
||||||
|
|
||||||
|
class display_manager
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
atomic_t<u32> m_uid_ctr = 0;
|
||||||
|
std::vector<std::shared_ptr<overlay>> m_iface_list;
|
||||||
|
std::vector<std::shared_ptr<overlay>> m_dirty_list;
|
||||||
|
|
||||||
|
shared_mutex m_list_mutex;
|
||||||
|
std::vector<u32> m_uids_to_remove;
|
||||||
|
std::vector<u32> m_type_ids_to_remove;
|
||||||
|
|
||||||
|
bool remove_type(u32 type_id);
|
||||||
|
|
||||||
|
bool remove_uid(u32 uid);
|
||||||
|
|
||||||
|
void cleanup_internal();
|
||||||
|
|
||||||
|
void on_overlay_activated(const std::shared_ptr<overlay>& item);
|
||||||
|
|
||||||
|
void on_overlay_removed(const std::shared_ptr<overlay>& item);
|
||||||
|
|
||||||
|
public:
|
||||||
|
// Disable default construction to make it conditionally available in g_fxo
|
||||||
|
explicit display_manager(int) noexcept
|
||||||
|
{}
|
||||||
|
|
||||||
|
// Adds an object to the internal list. Optionally removes other objects of the same type.
|
||||||
|
// Original handle loses ownership but a usable pointer is returned
|
||||||
|
template <typename T>
|
||||||
|
std::shared_ptr<T> add(std::shared_ptr<T>& entry, bool remove_existing = true)
|
||||||
|
{
|
||||||
|
std::lock_guard lock(m_list_mutex);
|
||||||
|
|
||||||
|
entry->uid = m_uid_ctr.fetch_add(1);
|
||||||
|
entry->type_index = id_manager::typeinfo::get_index<T>();
|
||||||
|
|
||||||
|
if (remove_existing)
|
||||||
|
{
|
||||||
|
for (auto It = m_iface_list.begin(); It != m_iface_list.end(); It++)
|
||||||
|
{
|
||||||
|
if (It->get()->type_index == entry->type_index)
|
||||||
|
{
|
||||||
|
// Replace
|
||||||
|
m_dirty_list.push_back(std::move(*It));
|
||||||
|
*It = std::move(entry);
|
||||||
|
return std::static_pointer_cast<T>(*It);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_iface_list.push_back(std::move(entry));
|
||||||
|
on_overlay_activated(m_iface_list.back());
|
||||||
|
return std::static_pointer_cast<T>(m_iface_list.back());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allocates object and adds to internal list. Returns pointer to created object
|
||||||
|
template <typename T, typename ...Args>
|
||||||
|
std::shared_ptr<T> create(Args&&... args)
|
||||||
|
{
|
||||||
|
auto object = std::make_shared<T>(std::forward<Args>(args)...);
|
||||||
|
return add(object);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Removes item from list if it matches the uid
|
||||||
|
void remove(u32 uid);
|
||||||
|
|
||||||
|
// Removes all objects of this type from the list
|
||||||
|
template <typename T>
|
||||||
|
void remove()
|
||||||
|
{
|
||||||
|
const auto type_id = id_manager::typeinfo::get_index<T>();
|
||||||
|
if (m_list_mutex.try_lock())
|
||||||
|
{
|
||||||
|
remove_type(type_id);
|
||||||
|
m_list_mutex.unlock();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_type_ids_to_remove.push_back(type_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// True if any visible elements to draw exist
|
||||||
|
bool has_visible() const
|
||||||
|
{
|
||||||
|
return !m_iface_list.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
// True if any elements have been deleted but their resources may not have been cleaned up
|
||||||
|
bool has_dirty() const
|
||||||
|
{
|
||||||
|
return !m_dirty_list.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns current list for reading. Caller must ensure synchronization by first locking the list
|
||||||
|
const std::vector<std::shared_ptr<overlay>>& get_views() const
|
||||||
|
{
|
||||||
|
return m_iface_list;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns current list of removed objects not yet deallocated for reading.
|
||||||
|
// Caller must ensure synchronization by first locking the list
|
||||||
|
const std::vector<std::shared_ptr<overlay>>& get_dirty() const
|
||||||
|
{
|
||||||
|
return m_dirty_list;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deallocate object. Object must first be removed via the remove() functions
|
||||||
|
void dispose(const std::vector<u32>& uids);
|
||||||
|
|
||||||
|
// Returns pointer to the object matching the given uid
|
||||||
|
std::shared_ptr<overlay> get(u32 uid);
|
||||||
|
|
||||||
|
// Returns pointer to the first object matching the given type
|
||||||
|
template <typename T>
|
||||||
|
std::shared_ptr<T> get()
|
||||||
|
{
|
||||||
|
reader_lock lock(m_list_mutex);
|
||||||
|
|
||||||
|
const auto type_id = id_manager::typeinfo::get_index<T>();
|
||||||
|
for (const auto& iface : m_iface_list)
|
||||||
|
{
|
||||||
|
if (iface->type_index == type_id)
|
||||||
|
{
|
||||||
|
return std::static_pointer_cast<T>(iface);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lock for read-only access (BasicLockable)
|
||||||
|
void lock();
|
||||||
|
|
||||||
|
// Release read-only lock (BasicLockable). May perform internal cleanup before returning
|
||||||
|
void unlock();
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct overlay_input_thread
|
||||||
|
{
|
||||||
|
static constexpr auto thread_name = "Overlay Input Thread"sv;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct input_thread_access_token
|
||||||
|
{
|
||||||
|
std::shared_ptr<user_interface> target;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::deque<input_thread_access_token> m_input_token_stack;
|
||||||
|
shared_mutex m_input_thread_lock;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
|
@ -95,6 +95,7 @@
|
||||||
<ClCompile Include="Emu\RSX\Overlays\overlay_animated_icon.cpp" />
|
<ClCompile Include="Emu\RSX\Overlays\overlay_animated_icon.cpp" />
|
||||||
<ClCompile Include="Emu\RSX\Overlays\overlay_controls.cpp" />
|
<ClCompile Include="Emu\RSX\Overlays\overlay_controls.cpp" />
|
||||||
<ClCompile Include="Emu\RSX\Overlays\overlay_cursor.cpp" />
|
<ClCompile Include="Emu\RSX\Overlays\overlay_cursor.cpp" />
|
||||||
|
<ClCompile Include="Emu\RSX\Overlays\overlay_manager.cpp" />
|
||||||
<ClCompile Include="Emu\RSX\Overlays\overlay_media_list_dialog.cpp" />
|
<ClCompile Include="Emu\RSX\Overlays\overlay_media_list_dialog.cpp" />
|
||||||
<ClCompile Include="Emu\RSX\Overlays\overlay_osk_panel.cpp" />
|
<ClCompile Include="Emu\RSX\Overlays\overlay_osk_panel.cpp" />
|
||||||
<ClCompile Include="Emu\RSX\Overlays\overlay_shader_compile_notification.cpp" />
|
<ClCompile Include="Emu\RSX\Overlays\overlay_shader_compile_notification.cpp" />
|
||||||
|
@ -555,6 +556,7 @@
|
||||||
<ClInclude Include="Emu\RSX\Overlays\overlay_edit_text.hpp" />
|
<ClInclude Include="Emu\RSX\Overlays\overlay_edit_text.hpp" />
|
||||||
<ClInclude Include="Emu\RSX\Overlays\overlay_list_view.hpp" />
|
<ClInclude Include="Emu\RSX\Overlays\overlay_list_view.hpp" />
|
||||||
<ClInclude Include="Emu\RSX\Overlays\overlay_loading_icon.hpp" />
|
<ClInclude Include="Emu\RSX\Overlays\overlay_loading_icon.hpp" />
|
||||||
|
<ClInclude Include="Emu\RSX\Overlays\overlay_manager.h" />
|
||||||
<ClInclude Include="Emu\RSX\Overlays\overlay_media_list_dialog.h" />
|
<ClInclude Include="Emu\RSX\Overlays\overlay_media_list_dialog.h" />
|
||||||
<ClInclude Include="Emu\RSX\Overlays\overlay_progress_bar.hpp" />
|
<ClInclude Include="Emu\RSX\Overlays\overlay_progress_bar.hpp" />
|
||||||
<ClInclude Include="Emu\RSX\Program\GLSLTypes.h" />
|
<ClInclude Include="Emu\RSX\Program\GLSLTypes.h" />
|
||||||
|
|
|
@ -1144,6 +1144,9 @@
|
||||||
<ClCompile Include="Emu\NP\upnp_config.cpp">
|
<ClCompile Include="Emu\NP\upnp_config.cpp">
|
||||||
<Filter>Emu\NP</Filter>
|
<Filter>Emu\NP</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="Emu\RSX\Overlays\overlay_manager.cpp">
|
||||||
|
<Filter>Emu\GPU\RSX\Overlays</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="Crypto\aes.h">
|
<ClInclude Include="Crypto\aes.h">
|
||||||
|
@ -2296,6 +2299,9 @@
|
||||||
<ClInclude Include="Emu\RSX\Overlays\HomeMenu\overlay_home_menu_message_box.h">
|
<ClInclude Include="Emu\RSX\Overlays\HomeMenu\overlay_home_menu_message_box.h">
|
||||||
<Filter>Emu\GPU\RSX\Overlays\HomeMenu</Filter>
|
<Filter>Emu\GPU\RSX\Overlays\HomeMenu</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="Emu\RSX\Overlays\overlay_manager.h">
|
||||||
|
<Filter>Emu\GPU\RSX\Overlays</Filter>
|
||||||
|
</ClInclude>
|
||||||
<ClInclude Include="Emu\NP\upnp_handler.h">
|
<ClInclude Include="Emu\NP\upnp_handler.h">
|
||||||
<Filter>Emu\NP</Filter>
|
<Filter>Emu\NP</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue