mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-03-29 22:20:48 +00:00
rsx/overlays: Putting it all together
- Migrate dialogs with input-only threads to use the unified input system
This commit is contained in:
parent
12690de9de
commit
ddc9e74aa8
@ -5,6 +5,8 @@
|
|||||||
#include "Emu/Cell/lv2/sys_sync.h"
|
#include "Emu/Cell/lv2/sys_sync.h"
|
||||||
#include "Emu/Cell/timers.hpp"
|
#include "Emu/Cell/timers.hpp"
|
||||||
#include "Emu/Io/interception.h"
|
#include "Emu/Io/interception.h"
|
||||||
|
|
||||||
|
#include "Emu/RSX/Overlays/overlay_manager.h"
|
||||||
#include "Emu/RSX/Overlays/overlay_message_dialog.h"
|
#include "Emu/RSX/Overlays/overlay_message_dialog.h"
|
||||||
|
|
||||||
#include "cellSysutil.h"
|
#include "cellSysutil.h"
|
||||||
|
@ -4,9 +4,11 @@
|
|||||||
#include "Emu/Cell/PPUModule.h"
|
#include "Emu/Cell/PPUModule.h"
|
||||||
#include "Emu/Io/interception.h"
|
#include "Emu/Io/interception.h"
|
||||||
#include "Emu/Io/Keyboard.h"
|
#include "Emu/Io/Keyboard.h"
|
||||||
#include "Emu/RSX/Overlays/overlay_osk.h"
|
|
||||||
#include "Emu/IdManager.h"
|
#include "Emu/IdManager.h"
|
||||||
|
|
||||||
|
#include "Emu/RSX/Overlays/overlay_manager.h"
|
||||||
|
#include "Emu/RSX/Overlays/overlay_osk.h"
|
||||||
|
|
||||||
#include "cellSysutil.h"
|
#include "cellSysutil.h"
|
||||||
#include "cellOskDialog.h"
|
#include "cellOskDialog.h"
|
||||||
#include "cellMsgDialog.h"
|
#include "cellMsgDialog.h"
|
||||||
|
@ -4,6 +4,8 @@
|
|||||||
#include "Emu/VFS.h"
|
#include "Emu/VFS.h"
|
||||||
#include "Emu/IdManager.h"
|
#include "Emu/IdManager.h"
|
||||||
#include "Emu/Cell/PPUModule.h"
|
#include "Emu/Cell/PPUModule.h"
|
||||||
|
|
||||||
|
#include "Emu/RSX/Overlays/overlay_manager.h"
|
||||||
#include "Emu/RSX/Overlays/overlay_user_list_dialog.h"
|
#include "Emu/RSX/Overlays/overlay_user_list_dialog.h"
|
||||||
|
|
||||||
#include "cellUserInfo.h"
|
#include "cellUserInfo.h"
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
#include "GLGSRender.h"
|
#include "GLGSRender.h"
|
||||||
#include "Emu/Cell/Modules/cellVideoOut.h"
|
#include "Emu/Cell/Modules/cellVideoOut.h"
|
||||||
|
#include "Emu/RSX/Overlays/overlay_manager.h"
|
||||||
#include "util/video_provider.h"
|
#include "util/video_provider.h"
|
||||||
|
|
||||||
LOG_CHANNEL(screenshot_log, "SCREENSHOT");
|
LOG_CHANNEL(screenshot_log, "SCREENSHOT");
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
#include "overlay_home_menu.h"
|
#include "overlay_home_menu.h"
|
||||||
|
#include "../overlay_manager.h"
|
||||||
#include "Emu/RSX/RSXThread.h"
|
#include "Emu/RSX/RSXThread.h"
|
||||||
#include "Utilities/date_time.h"
|
#include "Utilities/date_time.h"
|
||||||
|
|
||||||
@ -165,31 +166,24 @@ namespace rsx
|
|||||||
this->on_close = std::move(on_close);
|
this->on_close = std::move(on_close);
|
||||||
visible = true;
|
visible = true;
|
||||||
|
|
||||||
auto& list_thread = g_fxo->get<named_thread<home_menu_dialog_thread>>();
|
|
||||||
|
|
||||||
const auto notify = std::make_shared<atomic_t<bool>>(false);
|
const auto notify = std::make_shared<atomic_t<bool>>(false);
|
||||||
|
auto& overlayman = g_fxo->get<display_manager>();
|
||||||
|
|
||||||
list_thread([&, notify]()
|
overlayman.attach_thread_input(
|
||||||
{
|
uid, // Target
|
||||||
const u64 tbit = alloc_thread_bit();
|
[](s32 error) // What to do with the result
|
||||||
g_thread_bit = tbit;
|
|
||||||
|
|
||||||
*notify = true;
|
|
||||||
notify->notify_one();
|
|
||||||
|
|
||||||
auto ref = g_fxo->get<display_manager>().get(uid);
|
|
||||||
|
|
||||||
if (const auto error = run_input_loop())
|
|
||||||
{
|
{
|
||||||
if (error != selection_code::canceled)
|
if (error && error != selection_code::canceled)
|
||||||
{
|
{
|
||||||
rsx_log.error("Home menu dialog input loop exited with error code=%d", error);
|
rsx_log.error("Home menu dialog input loop exited with error code=%d", error);
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
[¬ify]() // What to do before starting the loop
|
||||||
|
{
|
||||||
|
*notify = true;
|
||||||
|
notify->notify_one();
|
||||||
}
|
}
|
||||||
|
);
|
||||||
thread_bits &= ~tbit;
|
|
||||||
thread_bits.notify_all();
|
|
||||||
});
|
|
||||||
|
|
||||||
if (g_cfg.misc.pause_during_home_menu)
|
if (g_cfg.misc.pause_during_home_menu)
|
||||||
{
|
{
|
||||||
@ -199,7 +193,7 @@ namespace rsx
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
while (list_thread < thread_state::errored && !*notify)
|
while (!Emu.IsStopped() && !*notify)
|
||||||
{
|
{
|
||||||
notify->wait(false, atomic_wait_timeout{1'000'000});
|
notify->wait(false, atomic_wait_timeout{1'000'000});
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
#include "shader_loading_dialog_native.h"
|
#include "shader_loading_dialog_native.h"
|
||||||
|
#include "../overlay_manager.h"
|
||||||
#include "../overlay_message_dialog.h"
|
#include "../overlay_message_dialog.h"
|
||||||
#include "../../GSRender.h"
|
#include "../../GSRender.h"
|
||||||
#include "Emu/Cell/ErrorCodes.h"
|
#include "Emu/Cell/ErrorCodes.h"
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
#include "overlay_cursor.h"
|
#include "overlay_cursor.h"
|
||||||
|
#include "overlay_manager.h"
|
||||||
|
|
||||||
#include "Emu/RSX/RSXThread.h"
|
#include "Emu/RSX/RSXThread.h"
|
||||||
|
|
||||||
namespace rsx
|
namespace rsx
|
||||||
|
@ -1,10 +1,23 @@
|
|||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
#include "overlay_manager.h"
|
#include "overlay_manager.h"
|
||||||
|
#include "Emu/System.h"
|
||||||
|
|
||||||
namespace rsx
|
namespace rsx
|
||||||
{
|
{
|
||||||
namespace overlays
|
namespace overlays
|
||||||
{
|
{
|
||||||
|
display_manager::~display_manager()
|
||||||
|
{
|
||||||
|
if (m_input_thread)
|
||||||
|
{
|
||||||
|
m_input_thread_abort.store(true);
|
||||||
|
while (*m_input_thread <= thread_state::aborting)
|
||||||
|
{
|
||||||
|
_mm_pause();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void display_manager::lock()
|
void display_manager::lock()
|
||||||
{
|
{
|
||||||
m_list_mutex.lock_shared();
|
m_list_mutex.lock_shared();
|
||||||
@ -123,8 +136,29 @@ namespace rsx
|
|||||||
{
|
{
|
||||||
if (auto iface = std::dynamic_pointer_cast<user_interface>(item))
|
if (auto iface = std::dynamic_pointer_cast<user_interface>(item))
|
||||||
{
|
{
|
||||||
|
// Kick input thread if not enabled. Expect the interface to attach shortly
|
||||||
std::lock_guard lock(m_input_thread_lock);
|
std::lock_guard lock(m_input_thread_lock);
|
||||||
m_input_token_stack.emplace_front(std::move(iface));
|
|
||||||
|
if (!m_input_thread)
|
||||||
|
{
|
||||||
|
m_input_thread = std::make_shared<named_thread<overlay_input_thread>>();
|
||||||
|
(*m_input_thread)([this]()
|
||||||
|
{
|
||||||
|
input_thread_loop();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void display_manager::attach_thread_input(
|
||||||
|
u32 uid,
|
||||||
|
std::function<void(s32)> on_input_loop_exit,
|
||||||
|
std::function<void()> on_input_loop_enter)
|
||||||
|
{
|
||||||
|
if (auto iface = std::dynamic_pointer_cast<user_interface>(get(uid)))
|
||||||
|
{
|
||||||
|
std::lock_guard lock(m_input_thread_lock);
|
||||||
|
m_input_token_stack.emplace_front(std::move(iface), on_input_loop_enter, on_input_loop_exit);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -153,5 +187,40 @@ namespace rsx
|
|||||||
m_input_token_stack.pop_front();
|
m_input_token_stack.pop_front();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void display_manager::input_thread_loop()
|
||||||
|
{
|
||||||
|
while (!m_input_thread_abort)
|
||||||
|
{
|
||||||
|
input_thread_context_t input_context;
|
||||||
|
{
|
||||||
|
reader_lock lock(m_input_thread_lock);
|
||||||
|
if (!m_input_token_stack.empty())
|
||||||
|
{
|
||||||
|
input_context = m_input_token_stack.front();
|
||||||
|
m_input_token_stack.pop_front();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (input_context.target)
|
||||||
|
{
|
||||||
|
if (input_context.input_loop_prologue)
|
||||||
|
{
|
||||||
|
input_context.input_loop_prologue();
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto result = input_context.target->run_input_loop();
|
||||||
|
|
||||||
|
if (input_context.input_loop_epilogue)
|
||||||
|
{
|
||||||
|
input_context.input_loop_epilogue(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
thread_ctrl::wait_for(1000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
#include "Emu/IdManager.h"
|
#include "Emu/IdManager.h"
|
||||||
#include "Utilities/mutex.h"
|
#include "Utilities/mutex.h"
|
||||||
|
#include "Utilities/Thread.h"
|
||||||
#include "Utilities/Timer.h"
|
#include "Utilities/Timer.h"
|
||||||
|
|
||||||
#include <deque>
|
#include <deque>
|
||||||
@ -41,6 +42,8 @@ namespace rsx
|
|||||||
explicit display_manager(int) noexcept
|
explicit display_manager(int) noexcept
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
~display_manager();
|
||||||
|
|
||||||
// Adds an object to the internal list. Optionally removes other objects of the same type.
|
// 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
|
// Original handle loses ownership but a usable pointer is returned
|
||||||
template <typename T>
|
template <typename T>
|
||||||
@ -152,19 +155,31 @@ namespace rsx
|
|||||||
// Release read-only lock (BasicLockable). May perform internal cleanup before returning
|
// Release read-only lock (BasicLockable). May perform internal cleanup before returning
|
||||||
void unlock();
|
void unlock();
|
||||||
|
|
||||||
|
// Enable input thread attach to the specified interface
|
||||||
|
void attach_thread_input(
|
||||||
|
u32 uid, // The input target
|
||||||
|
std::function<void(s32)> on_input_loop_exit = nullptr, // [optional] What to do with the result if any
|
||||||
|
std::function<void()> on_input_loop_enter = nullptr); // [optional] What to do before running the input routine
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct overlay_input_thread
|
struct overlay_input_thread
|
||||||
{
|
{
|
||||||
static constexpr auto thread_name = "Overlay Input Thread"sv;
|
static constexpr auto thread_name = "Overlay Input Thread"sv;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct input_thread_access_token
|
struct input_thread_context_t
|
||||||
{
|
{
|
||||||
std::shared_ptr<user_interface> target;
|
std::shared_ptr<user_interface> target;
|
||||||
|
std::function<void()> input_loop_prologue = nullptr;
|
||||||
|
std::function<void(s32)> input_loop_epilogue = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
std::deque<input_thread_access_token> m_input_token_stack;
|
std::deque<input_thread_context_t> m_input_token_stack;
|
||||||
shared_mutex m_input_thread_lock;
|
shared_mutex m_input_thread_lock;
|
||||||
|
atomic_t<bool> m_input_thread_abort = false;
|
||||||
|
|
||||||
|
std::shared_ptr<named_thread<overlay_input_thread>> m_input_thread;
|
||||||
|
void input_thread_loop();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
|
#include "overlays.h"
|
||||||
|
#include "overlay_manager.h"
|
||||||
#include "overlay_media_list_dialog.h"
|
#include "overlay_media_list_dialog.h"
|
||||||
|
|
||||||
|
#include "Emu/Cell/Modules/cellMusic.h"
|
||||||
|
#include "Emu/VFS.h"
|
||||||
#include "Utilities/StrUtil.h"
|
#include "Utilities/StrUtil.h"
|
||||||
#include "Utilities/Thread.h"
|
#include "Utilities/Thread.h"
|
||||||
#include "overlays.h"
|
|
||||||
#include "Emu/VFS.h"
|
|
||||||
#include "Emu/Cell/Modules/cellMusic.h"
|
|
||||||
|
|
||||||
namespace rsx
|
namespace rsx
|
||||||
{
|
{
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "overlays.h"
|
#include "overlays.h"
|
||||||
|
#include "overlay_manager.h"
|
||||||
|
|
||||||
#include <deque>
|
#include <deque>
|
||||||
|
|
||||||
namespace rsx
|
namespace rsx
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
|
#include "overlay_manager.h"
|
||||||
#include "overlay_message_dialog.h"
|
#include "overlay_message_dialog.h"
|
||||||
#include "Emu/System.h"
|
#include "Emu/System.h"
|
||||||
#include "Emu/system_config.h"
|
#include "Emu/system_config.h"
|
||||||
@ -299,52 +300,42 @@ namespace rsx
|
|||||||
{
|
{
|
||||||
if (!m_stop_input_loop)
|
if (!m_stop_input_loop)
|
||||||
{
|
{
|
||||||
auto& dlg_thread = g_fxo->get<named_thread<msg_dialog_thread>>();
|
|
||||||
|
|
||||||
const auto notify = std::make_shared<atomic_t<bool>>(false);
|
const auto notify = std::make_shared<atomic_t<bool>>(false);
|
||||||
|
auto& overlayman = g_fxo->get<display_manager>();
|
||||||
|
|
||||||
dlg_thread([&, notify]()
|
overlayman.attach_thread_input(
|
||||||
|
uid,
|
||||||
|
[](s32 error)
|
||||||
|
{
|
||||||
|
if (error && error != selection_code::canceled)
|
||||||
|
{
|
||||||
|
rsx_log.error("Message dialog input loop exited with error code=%d", error);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[¬ify]()
|
||||||
|
{
|
||||||
|
*notify = true;
|
||||||
|
notify->notify_one();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
while (!m_stop_input_loop && thread_ctrl::state() != thread_state::aborting)
|
||||||
{
|
{
|
||||||
const u64 tbit = alloc_thread_bit();
|
refresh();
|
||||||
g_thread_bit = tbit;
|
|
||||||
|
|
||||||
*notify = true;
|
// Only update the screen at about 60fps since updating it everytime slows down the process
|
||||||
notify->notify_one();
|
std::this_thread::sleep_for(16ms);
|
||||||
|
|
||||||
if (interactive)
|
if (!g_fxo->is_init<display_manager>())
|
||||||
{
|
{
|
||||||
auto ref = g_fxo->get<display_manager>().get(uid);
|
rsx_log.fatal("display_manager was improperly destroyed");
|
||||||
|
break;
|
||||||
if (const auto error = run_input_loop())
|
|
||||||
{
|
|
||||||
if (error != selection_code::canceled)
|
|
||||||
{
|
|
||||||
rsx_log.error("Message dialog input loop exited with error code=%d", error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
}
|
||||||
{
|
#endif
|
||||||
while (!m_stop_input_loop && thread_ctrl::state() != thread_state::aborting)
|
|
||||||
{
|
|
||||||
refresh();
|
|
||||||
|
|
||||||
// Only update the screen at about 60fps since updating it everytime slows down the process
|
while (!Emu.IsStopped() && !*notify)
|
||||||
std::this_thread::sleep_for(16ms);
|
|
||||||
|
|
||||||
if (!g_fxo->is_init<display_manager>())
|
|
||||||
{
|
|
||||||
rsx_log.fatal("display_manager was improperly destroyed");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
thread_bits &= ~tbit;
|
|
||||||
thread_bits.notify_all();
|
|
||||||
});
|
|
||||||
|
|
||||||
while (dlg_thread < thread_state::errored && !*notify)
|
|
||||||
{
|
{
|
||||||
notify->wait(false, atomic_wait_timeout{1'000'000});
|
notify->wait(false, atomic_wait_timeout{1'000'000});
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
|
#include "overlay_manager.h"
|
||||||
#include "overlay_osk.h"
|
#include "overlay_osk.h"
|
||||||
#include "Emu/RSX/RSXThread.h"
|
#include "Emu/RSX/RSXThread.h"
|
||||||
#include "Emu/Cell/Modules/cellSysutil.h"
|
#include "Emu/Cell/Modules/cellSysutil.h"
|
||||||
@ -1624,31 +1625,26 @@ namespace rsx
|
|||||||
|
|
||||||
update_panel();
|
update_panel();
|
||||||
|
|
||||||
auto& osk_thread = g_fxo->get<named_thread<osk_dialog_thread>>();
|
|
||||||
|
|
||||||
const auto notify = std::make_shared<atomic_t<bool>>(false);
|
const auto notify = std::make_shared<atomic_t<bool>>(false);
|
||||||
|
auto& overlayman = g_fxo->get<display_manager>();
|
||||||
|
|
||||||
osk_thread([&, notify]()
|
overlayman.attach_thread_input(
|
||||||
{
|
uid,
|
||||||
const u64 tbit = alloc_thread_bit();
|
[](s32 error)
|
||||||
g_thread_bit = tbit;
|
|
||||||
|
|
||||||
*notify = true;
|
|
||||||
notify->notify_one();
|
|
||||||
|
|
||||||
if (const auto error = run_input_loop())
|
|
||||||
{
|
{
|
||||||
if (error != selection_code::canceled)
|
if (error && error != selection_code::canceled)
|
||||||
{
|
{
|
||||||
rsx_log.error("Osk input loop exited with error code=%d", error);
|
rsx_log.error("Osk input loop exited with error code=%d", error);
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
[¬ify]()
|
||||||
|
{
|
||||||
|
*notify = true;
|
||||||
|
notify->notify_one();
|
||||||
}
|
}
|
||||||
|
);
|
||||||
|
|
||||||
thread_bits &= ~tbit;
|
while (!Emu.IsStopped() && !*notify)
|
||||||
thread_bits.notify_all();
|
|
||||||
});
|
|
||||||
|
|
||||||
while (osk_thread < thread_state::errored && !*notify)
|
|
||||||
{
|
{
|
||||||
notify->wait(false, atomic_wait_timeout{1'000'000});
|
notify->wait(false, atomic_wait_timeout{1'000'000});
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
|
#include "overlay_manager.h"
|
||||||
#include "overlay_perf_metrics.h"
|
#include "overlay_perf_metrics.h"
|
||||||
#include "Emu/RSX/RSXThread.h"
|
#include "Emu/RSX/RSXThread.h"
|
||||||
#include "Emu/Cell/SPUThread.h"
|
#include "Emu/Cell/SPUThread.h"
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
|
#include "overlay_manager.h"
|
||||||
#include "overlay_user_list_dialog.h"
|
#include "overlay_user_list_dialog.h"
|
||||||
#include "Emu/vfs_config.h"
|
#include "Emu/vfs_config.h"
|
||||||
#include "Emu/system_utils.hpp"
|
#include "Emu/system_utils.hpp"
|
||||||
@ -243,33 +244,26 @@ namespace rsx
|
|||||||
this->on_close = std::move(on_close);
|
this->on_close = std::move(on_close);
|
||||||
visible = true;
|
visible = true;
|
||||||
|
|
||||||
auto& list_thread = g_fxo->get<named_thread<user_list_dialog_thread>>();
|
|
||||||
|
|
||||||
const auto notify = std::make_shared<atomic_t<bool>>(false);
|
const auto notify = std::make_shared<atomic_t<bool>>(false);
|
||||||
|
auto& overlayman = g_fxo->get<display_manager>();
|
||||||
|
|
||||||
list_thread([&, notify]()
|
overlayman.attach_thread_input(
|
||||||
{
|
uid,
|
||||||
const u64 tbit = alloc_thread_bit();
|
[](s32 error)
|
||||||
g_thread_bit = tbit;
|
|
||||||
|
|
||||||
*notify = true;
|
|
||||||
notify->notify_one();
|
|
||||||
|
|
||||||
auto ref = g_fxo->get<display_manager>().get(uid);
|
|
||||||
|
|
||||||
if (const auto error = run_input_loop())
|
|
||||||
{
|
{
|
||||||
if (error != selection_code::canceled)
|
if (error && error != selection_code::canceled)
|
||||||
{
|
{
|
||||||
rsx_log.error("User list dialog input loop exited with error code=%d", error);
|
rsx_log.error("User list dialog input loop exited with error code=%d", error);
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
[¬ify]()
|
||||||
|
{
|
||||||
|
*notify = true;
|
||||||
|
notify->notify_one();
|
||||||
}
|
}
|
||||||
|
);
|
||||||
|
|
||||||
thread_bits &= ~tbit;
|
while (!Emu.IsStopped() && !*notify)
|
||||||
thread_bits.notify_all();
|
|
||||||
});
|
|
||||||
|
|
||||||
while (list_thread < thread_state::errored && !*notify)
|
|
||||||
{
|
{
|
||||||
notify->wait(false, atomic_wait_timeout{1'000'000});
|
notify->wait(false, atomic_wait_timeout{1'000'000});
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
#include "overlays.h"
|
#include "overlays.h"
|
||||||
|
#include "overlay_manager.h"
|
||||||
#include "overlay_message_dialog.h"
|
#include "overlay_message_dialog.h"
|
||||||
#include "Input/pad_thread.h"
|
#include "Input/pad_thread.h"
|
||||||
#include "Emu/Io/interception.h"
|
#include "Emu/Io/interception.h"
|
||||||
@ -47,6 +48,8 @@ namespace rsx
|
|||||||
|
|
||||||
s32 user_interface::run_input_loop()
|
s32 user_interface::run_input_loop()
|
||||||
{
|
{
|
||||||
|
user_interface::thread_bits_allocator thread_bits_alloc(this);
|
||||||
|
|
||||||
m_interactive = true;
|
m_interactive = true;
|
||||||
|
|
||||||
std::array<steady_clock::time_point, CELL_PAD_MAX_PORT_NUM> timestamp;
|
std::array<steady_clock::time_point, CELL_PAD_MAX_PORT_NUM> timestamp;
|
||||||
|
@ -123,6 +123,26 @@ namespace rsx
|
|||||||
|
|
||||||
std::function<void(s32 status)> on_close = nullptr;
|
std::function<void(s32 status)> on_close = nullptr;
|
||||||
|
|
||||||
|
class thread_bits_allocator
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
thread_bits_allocator(user_interface* parent)
|
||||||
|
: m_parent(parent)
|
||||||
|
{
|
||||||
|
m_thread_bit = m_parent->alloc_thread_bit();
|
||||||
|
g_thread_bit = m_thread_bit;
|
||||||
|
}
|
||||||
|
|
||||||
|
~thread_bits_allocator()
|
||||||
|
{
|
||||||
|
m_parent->thread_bits &= ~m_thread_bit;
|
||||||
|
m_parent->thread_bits.notify_all();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
user_interface* m_parent;
|
||||||
|
u64 m_thread_bit;
|
||||||
|
};
|
||||||
public:
|
public:
|
||||||
s32 return_code = 0; // CELL_OK
|
s32 return_code = 0; // CELL_OK
|
||||||
|
|
||||||
@ -137,236 +157,5 @@ namespace rsx
|
|||||||
|
|
||||||
s32 run_input_loop();
|
s32 run_input_loop();
|
||||||
};
|
};
|
||||||
|
|
||||||
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 found = false;
|
|
||||||
for (auto It = m_iface_list.begin(); It != m_iface_list.end();)
|
|
||||||
{
|
|
||||||
if (It->get()->type_index == type_id)
|
|
||||||
{
|
|
||||||
m_dirty_list.push_back(std::move(*It));
|
|
||||||
It = m_iface_list.erase(It);
|
|
||||||
found = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
++It;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return found;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool 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)
|
|
||||||
{
|
|
||||||
m_dirty_list.push_back(std::move(*It));
|
|
||||||
m_iface_list.erase(It);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void 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();
|
|
||||||
}
|
|
||||||
|
|
||||||
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));
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
if (m_list_mutex.try_lock())
|
|
||||||
{
|
|
||||||
remove_uid(uid);
|
|
||||||
m_list_mutex.unlock();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
m_uids_to_remove.push_back(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)
|
|
||||||
{
|
|
||||||
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()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns pointer to the object matching the given uid
|
|
||||||
std::shared_ptr<overlay> get(u32 uid)
|
|
||||||
{
|
|
||||||
reader_lock lock(m_list_mutex);
|
|
||||||
|
|
||||||
for (const auto& iface : m_iface_list)
|
|
||||||
{
|
|
||||||
if (iface->uid == uid)
|
|
||||||
return iface;
|
|
||||||
}
|
|
||||||
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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()
|
|
||||||
{
|
|
||||||
m_list_mutex.lock_shared();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Release read-only lock (BasicLockable). May perform internal cleanup before returning
|
|
||||||
void 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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,7 @@
|
|||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
|
#include "../Overlays/overlay_animated_icon.h"
|
||||||
|
#include "../Overlays/overlay_dock.h"
|
||||||
|
#include "../Overlays/overlay_manager.h"
|
||||||
#include "../Overlays/overlay_shader_compile_notification.h"
|
#include "../Overlays/overlay_shader_compile_notification.h"
|
||||||
#include "../Overlays/Shaders/shader_loading_dialog_native.h"
|
#include "../Overlays/Shaders/shader_loading_dialog_native.h"
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
#include "VKGSRender.h"
|
#include "VKGSRender.h"
|
||||||
#include "vkutils/buffer_object.h"
|
#include "vkutils/buffer_object.h"
|
||||||
|
#include "Emu/RSX/Overlays/overlay_manager.h"
|
||||||
#include "Emu/RSX/Overlays/overlays.h"
|
#include "Emu/RSX/Overlays/overlays.h"
|
||||||
#include "Emu/Cell/Modules/cellVideoOut.h"
|
#include "Emu/Cell/Modules/cellVideoOut.h"
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#include "system_progress.hpp"
|
#include "system_progress.hpp"
|
||||||
#include "Emu/Cell/Modules/cellMsgDialog.h"
|
#include "Emu/Cell/Modules/cellMsgDialog.h"
|
||||||
#include "Emu/RSX/RSXThread.h"
|
#include "Emu/RSX/RSXThread.h"
|
||||||
|
#include "Emu/RSX/Overlays/overlay_manager.h"
|
||||||
#include "Emu/RSX/Overlays/overlay_message_dialog.h"
|
#include "Emu/RSX/Overlays/overlay_message_dialog.h"
|
||||||
#include "Emu/System.h"
|
#include "Emu/System.h"
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#include "Emu/System.h"
|
#include "Emu/System.h"
|
||||||
#include "Emu/IdManager.h"
|
#include "Emu/IdManager.h"
|
||||||
#include "Emu/Io/interception.h"
|
#include "Emu/Io/interception.h"
|
||||||
|
#include "../Emu/RSX/Overlays/overlay_manager.h"
|
||||||
#include "Emu/RSX/Overlays/overlay_save_dialog.h"
|
#include "Emu/RSX/Overlays/overlay_save_dialog.h"
|
||||||
#include "Emu/Cell/Modules/cellSysutil.h"
|
#include "Emu/Cell/Modules/cellSysutil.h"
|
||||||
|
|
||||||
|
@ -3,6 +3,8 @@
|
|||||||
|
|
||||||
#include "../Emu/IdManager.h"
|
#include "../Emu/IdManager.h"
|
||||||
#include "../Emu/System.h"
|
#include "../Emu/System.h"
|
||||||
|
|
||||||
|
#include "../Emu/RSX/Overlays/overlay_manager.h"
|
||||||
#include "../Emu/RSX/Overlays/overlay_trophy_notification.h"
|
#include "../Emu/RSX/Overlays/overlay_trophy_notification.h"
|
||||||
|
|
||||||
#include "Utilities/File.h"
|
#include "Utilities/File.h"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user