mirror of
https://github.com/stenzek/duckstation.git
synced 2025-06-07 12:05:52 +00:00
Host: Expose RunOnUIThread() to core
I hate this, but sadly needed for RAIntegration...
This commit is contained in:
parent
f0d4816de7
commit
c1e01af511
@ -78,6 +78,9 @@ bool ChangeLanguage(const char* new_language);
|
|||||||
/// Safely executes a function on the VM thread.
|
/// Safely executes a function on the VM thread.
|
||||||
void RunOnCPUThread(std::function<void()> function, bool block = false);
|
void RunOnCPUThread(std::function<void()> function, bool block = false);
|
||||||
|
|
||||||
|
/// Safely executes a function on the main/UI thread.
|
||||||
|
void RunOnUIThread(std::function<void()> function, bool block = false);
|
||||||
|
|
||||||
/// Called when the core is creating a render device.
|
/// Called when the core is creating a render device.
|
||||||
/// This could also be fullscreen transition.
|
/// This could also be fullscreen transition.
|
||||||
std::optional<WindowInfo> AcquireRenderWindow(RenderAPI render_api, bool fullscreen, bool exclusive_fullscreen,
|
std::optional<WindowInfo> AcquireRenderWindow(RenderAPI render_api, bool fullscreen, bool exclusive_fullscreen,
|
||||||
|
@ -77,11 +77,9 @@ static bool SetDataDirectory();
|
|||||||
static bool SetCriticalFolders();
|
static bool SetCriticalFolders();
|
||||||
static void SetDefaultSettings(SettingsInterface& si, bool system, bool controller);
|
static void SetDefaultSettings(SettingsInterface& si, bool system, bool controller);
|
||||||
static std::string GetResourcePath(std::string_view name, bool allow_override);
|
static std::string GetResourcePath(std::string_view name, bool allow_override);
|
||||||
static void ProcessCPUThreadEvents(bool block);
|
|
||||||
static bool PerformEarlyHardwareChecks();
|
static bool PerformEarlyHardwareChecks();
|
||||||
static bool EarlyProcessStartup();
|
static bool EarlyProcessStartup();
|
||||||
static void WarnAboutInterface();
|
static void WarnAboutInterface();
|
||||||
static void RunOnUIThread(std::function<void()> func);
|
|
||||||
static void StartCPUThread();
|
static void StartCPUThread();
|
||||||
static void StopCPUThread();
|
static void StopCPUThread();
|
||||||
static void ProcessCPUThreadEvents(bool block);
|
static void ProcessCPUThreadEvents(bool block);
|
||||||
@ -580,7 +578,7 @@ std::optional<WindowInfo> Host::AcquireRenderWindow(RenderAPI render_api, bool f
|
|||||||
|
|
||||||
std::optional<WindowInfo> wi;
|
std::optional<WindowInfo> wi;
|
||||||
|
|
||||||
MiniHost::RunOnUIThread([render_api, fullscreen, error, &wi]() {
|
Host::RunOnUIThread([render_api, fullscreen, error, &wi]() {
|
||||||
const std::string window_title = GetWindowTitle(System::GetGameTitle());
|
const std::string window_title = GetWindowTitle(System::GetGameTitle());
|
||||||
const SDL_PropertiesID props = SDL_CreateProperties();
|
const SDL_PropertiesID props = SDL_CreateProperties();
|
||||||
SDL_SetStringProperty(props, SDL_PROP_WINDOW_CREATE_TITLE_STRING, window_title.c_str());
|
SDL_SetStringProperty(props, SDL_PROP_WINDOW_CREATE_TITLE_STRING, window_title.c_str());
|
||||||
@ -656,7 +654,7 @@ void Host::ReleaseRenderWindow()
|
|||||||
if (!s_state.sdl_window)
|
if (!s_state.sdl_window)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
MiniHost::RunOnUIThread([]() {
|
Host::RunOnUIThread([]() {
|
||||||
if (!s_state.fullscreen.load(std::memory_order_acquire))
|
if (!s_state.fullscreen.load(std::memory_order_acquire))
|
||||||
{
|
{
|
||||||
int window_x = SDL_WINDOWPOS_UNDEFINED, window_y = SDL_WINDOWPOS_UNDEFINED;
|
int window_x = SDL_WINDOWPOS_UNDEFINED, window_y = SDL_WINDOWPOS_UNDEFINED;
|
||||||
@ -909,17 +907,6 @@ void MiniHost::ProcessSDLEvent(const SDL_Event* ev)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MiniHost::RunOnUIThread(std::function<void()> func)
|
|
||||||
{
|
|
||||||
std::function<void()>* pfunc = new std::function<void()>(std::move(func));
|
|
||||||
|
|
||||||
SDL_Event ev;
|
|
||||||
ev.user = {};
|
|
||||||
ev.type = s_state.func_event_id;
|
|
||||||
ev.user.data1 = pfunc;
|
|
||||||
SDL_PushEvent(&ev);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MiniHost::ProcessCPUThreadPlatformMessages()
|
void MiniHost::ProcessCPUThreadPlatformMessages()
|
||||||
{
|
{
|
||||||
// This is lame. On Win32, we need to pump messages, even though *we* don't have any windows
|
// This is lame. On Win32, we need to pump messages, even though *we* don't have any windows
|
||||||
@ -1038,7 +1025,7 @@ void MiniHost::CPUThreadEntryPoint()
|
|||||||
System::CPUThreadShutdown();
|
System::CPUThreadShutdown();
|
||||||
|
|
||||||
// Tell the UI thread to shut down.
|
// Tell the UI thread to shut down.
|
||||||
RunOnUIThread([]() { s_state.ui_thread_running = false; });
|
Host::RunOnUIThread([]() { s_state.ui_thread_running = false; });
|
||||||
}
|
}
|
||||||
|
|
||||||
void MiniHost::CPUThreadMainLoop()
|
void MiniHost::CPUThreadMainLoop()
|
||||||
@ -1211,6 +1198,19 @@ void Host::RunOnCPUThread(std::function<void()> function, bool block /* = false
|
|||||||
s_state.cpu_thread_event_done.wait(lock, []() { return s_state.blocking_cpu_events_pending == 0; });
|
s_state.cpu_thread_event_done.wait(lock, []() { return s_state.blocking_cpu_events_pending == 0; });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Host::RunOnUIThread(std::function<void()> function, bool block /* = false */)
|
||||||
|
{
|
||||||
|
using namespace MiniHost;
|
||||||
|
|
||||||
|
std::function<void()>* pfunc = new std::function<void()>(std::move(function));
|
||||||
|
|
||||||
|
SDL_Event ev;
|
||||||
|
ev.user = {};
|
||||||
|
ev.type = s_state.func_event_id;
|
||||||
|
ev.user.data1 = pfunc;
|
||||||
|
SDL_PushEvent(&ev);
|
||||||
|
}
|
||||||
|
|
||||||
void Host::RefreshGameListAsync(bool invalidate_cache)
|
void Host::RefreshGameListAsync(bool invalidate_cache)
|
||||||
{
|
{
|
||||||
using namespace MiniHost;
|
using namespace MiniHost;
|
||||||
|
@ -661,7 +661,7 @@ void DebuggerWindow::toggleBreakpoint(VirtualMemoryAddress address)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
QtHost::RunOnUIThread([this, address, new_bp_state, bps = CPU::CopyBreakpointList()]() {
|
Host::RunOnUIThread([this, address, new_bp_state, bps = CPU::CopyBreakpointList()]() {
|
||||||
m_code_model->setBreakpointState(address, new_bp_state);
|
m_code_model->setBreakpointState(address, new_bp_state);
|
||||||
refreshBreakpointList(bps);
|
refreshBreakpointList(bps);
|
||||||
});
|
});
|
||||||
@ -715,7 +715,7 @@ bool DebuggerWindow::scrollToMemoryAddress(VirtualMemoryAddress address)
|
|||||||
void DebuggerWindow::refreshBreakpointList()
|
void DebuggerWindow::refreshBreakpointList()
|
||||||
{
|
{
|
||||||
Host::RunOnCPUThread(
|
Host::RunOnCPUThread(
|
||||||
[this]() { QtHost::RunOnUIThread([this, bps = CPU::CopyBreakpointList()]() { refreshBreakpointList(bps); }); });
|
[this]() { Host::RunOnUIThread([this, bps = CPU::CopyBreakpointList()]() { refreshBreakpointList(bps); }); });
|
||||||
}
|
}
|
||||||
|
|
||||||
void DebuggerWindow::refreshBreakpointList(const CPU::BreakpointList& bps)
|
void DebuggerWindow::refreshBreakpointList(const CPU::BreakpointList& bps)
|
||||||
@ -743,7 +743,7 @@ void DebuggerWindow::addBreakpoint(CPU::BreakpointType type, u32 address)
|
|||||||
{
|
{
|
||||||
Host::RunOnCPUThread([this, address, type]() {
|
Host::RunOnCPUThread([this, address, type]() {
|
||||||
const bool result = CPU::AddBreakpoint(type, address);
|
const bool result = CPU::AddBreakpoint(type, address);
|
||||||
QtHost::RunOnUIThread([this, address, type, result, bps = CPU::CopyBreakpointList()]() {
|
Host::RunOnUIThread([this, address, type, result, bps = CPU::CopyBreakpointList()]() {
|
||||||
if (!result)
|
if (!result)
|
||||||
{
|
{
|
||||||
QMessageBox::critical(this, windowTitle(),
|
QMessageBox::critical(this, windowTitle(),
|
||||||
@ -763,7 +763,7 @@ void DebuggerWindow::removeBreakpoint(CPU::BreakpointType type, u32 address)
|
|||||||
{
|
{
|
||||||
Host::RunOnCPUThread([this, address, type]() {
|
Host::RunOnCPUThread([this, address, type]() {
|
||||||
const bool result = CPU::RemoveBreakpoint(type, address);
|
const bool result = CPU::RemoveBreakpoint(type, address);
|
||||||
QtHost::RunOnUIThread([this, address, type, result, bps = CPU::CopyBreakpointList()]() {
|
Host::RunOnUIThread([this, address, type, result, bps = CPU::CopyBreakpointList()]() {
|
||||||
if (!result)
|
if (!result)
|
||||||
{
|
{
|
||||||
QMessageBox::critical(this, windowTitle(), tr("Failed to remove breakpoint. This breakpoint may not exist."));
|
QMessageBox::critical(this, windowTitle(), tr("Failed to remove breakpoint. This breakpoint may not exist."));
|
||||||
|
@ -1037,7 +1037,7 @@ void MainWindow::populateCheatsMenu(QMenu* menu)
|
|||||||
if (Cheats::AreCheatsEnabled() && names.empty())
|
if (Cheats::AreCheatsEnabled() && names.empty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
QtHost::RunOnUIThread([menu, names = std::move(names)]() {
|
Host::RunOnUIThread([menu, names = std::move(names)]() {
|
||||||
if (names.empty())
|
if (names.empty())
|
||||||
{
|
{
|
||||||
QAction* action = menu->addAction(tr("Cheats are not enabled."));
|
QAction* action = menu->addAction(tr("Cheats are not enabled."));
|
||||||
@ -2368,7 +2368,7 @@ void MainWindow::openGamePropertiesForCurrentGame(const char* category /* = null
|
|||||||
if (path.empty() || serial.empty())
|
if (path.empty() || serial.empty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
QtHost::RunOnUIThread([title = std::string(System::GetGameTitle()), path = std::string(path),
|
Host::RunOnUIThread([title = std::string(System::GetGameTitle()), path = std::string(path),
|
||||||
serial = std::string(serial), hash = System::GetGameHash(), region = System::GetDiscRegion(),
|
serial = std::string(serial), hash = System::GetGameHash(), region = System::GetDiscRegion(),
|
||||||
category]() {
|
category]() {
|
||||||
SettingsWindow::openGamePropertiesDialog(path, title, std::move(serial), hash, region, category);
|
SettingsWindow::openGamePropertiesDialog(path, title, std::move(serial), hash, region, category);
|
||||||
|
@ -1149,7 +1149,7 @@ void EmuThread::confirmActionIfMemoryCardBusy(const QString& action, bool cancel
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
QtHost::RunOnUIThread([action, cancel_resume_on_accept, callback = std::move(callback)]() mutable {
|
Host::RunOnUIThread([action, cancel_resume_on_accept, callback = std::move(callback)]() mutable {
|
||||||
auto lock = g_main_window->pauseAndLockSystem();
|
auto lock = g_main_window->pauseAndLockSystem();
|
||||||
|
|
||||||
const bool result =
|
const bool result =
|
||||||
@ -1378,7 +1378,7 @@ void EmuThread::startControllerTest()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
QtHost::RunOnUIThread([path = std::move(path)]() mutable {
|
Host::RunOnUIThread([path = std::move(path)]() mutable {
|
||||||
{
|
{
|
||||||
auto lock = g_main_window->pauseAndLockSystem();
|
auto lock = g_main_window->pauseAndLockSystem();
|
||||||
if (QMessageBox::question(
|
if (QMessageBox::question(
|
||||||
@ -1397,7 +1397,7 @@ void EmuThread::startControllerTest()
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmuThread::runOnEmuThread(std::function<void()> callback)
|
void EmuThread::runOnEmuThread(const std::function<void()>& callback)
|
||||||
{
|
{
|
||||||
callback();
|
callback();
|
||||||
}
|
}
|
||||||
@ -1411,11 +1411,11 @@ void Host::RunOnCPUThread(std::function<void()> function, bool block /* = false
|
|||||||
Q_ARG(std::function<void()>, std::move(function)));
|
Q_ARG(std::function<void()>, std::move(function)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void QtHost::RunOnUIThread(const std::function<void()>& func, bool block /*= false*/)
|
void Host::RunOnUIThread(std::function<void()> function, bool block /* = false*/)
|
||||||
{
|
{
|
||||||
// main window always exists, so it's fine to attach it to that.
|
// main window always exists, so it's fine to attach it to that.
|
||||||
QMetaObject::invokeMethod(g_main_window, "runOnUIThread", block ? Qt::BlockingQueuedConnection : Qt::QueuedConnection,
|
QMetaObject::invokeMethod(g_main_window, "runOnUIThread", block ? Qt::BlockingQueuedConnection : Qt::QueuedConnection,
|
||||||
Q_ARG(const std::function<void()>&, func));
|
Q_ARG(std::function<void()>, std::move(function)));
|
||||||
}
|
}
|
||||||
|
|
||||||
QtAsyncTask::QtAsyncTask(WorkCallback callback)
|
QtAsyncTask::QtAsyncTask(WorkCallback callback)
|
||||||
@ -1432,7 +1432,7 @@ void QtAsyncTask::create(QObject* owner, WorkCallback callback)
|
|||||||
connect(task, &QtAsyncTask::completed, owner, [task]() { std::get<CompletionCallback>(task->m_callback)(); });
|
connect(task, &QtAsyncTask::completed, owner, [task]() { std::get<CompletionCallback>(task->m_callback)(); });
|
||||||
System::QueueAsyncTask([task]() {
|
System::QueueAsyncTask([task]() {
|
||||||
task->m_callback = std::get<WorkCallback>(task->m_callback)();
|
task->m_callback = std::get<WorkCallback>(task->m_callback)();
|
||||||
QtHost::RunOnUIThread([task]() {
|
Host::RunOnUIThread([task]() {
|
||||||
emit task->completed(task);
|
emit task->completed(task);
|
||||||
delete task;
|
delete task;
|
||||||
});
|
});
|
||||||
@ -1710,10 +1710,9 @@ void Host::OpenHostFileSelectorAsync(std::string_view title, bool select_directo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QtHost::RunOnUIThread([title = QtUtils::StringViewToQString(title), select_directory, callback = std::move(callback),
|
Host::RunOnUIThread([title = QtUtils::StringViewToQString(title), select_directory, callback = std::move(callback),
|
||||||
filters_str = std::move(filters_str),
|
filters_str = std::move(filters_str),
|
||||||
initial_directory = QtUtils::StringViewToQString(initial_directory),
|
initial_directory = QtUtils::StringViewToQString(initial_directory), from_cpu_thread]() mutable {
|
||||||
from_cpu_thread]() mutable {
|
|
||||||
auto lock = g_main_window->pauseAndLockSystem();
|
auto lock = g_main_window->pauseAndLockSystem();
|
||||||
|
|
||||||
QString path;
|
QString path;
|
||||||
@ -2103,7 +2102,7 @@ void Host::ConfirmMessageAsync(std::string_view title, std::string_view message,
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Otherwise, use the desktop UI.
|
// Otherwise, use the desktop UI.
|
||||||
QtHost::RunOnUIThread([title = QtUtils::StringViewToQString(title), message = QtUtils::StringViewToQString(message),
|
Host::RunOnUIThread([title = QtUtils::StringViewToQString(title), message = QtUtils::StringViewToQString(message),
|
||||||
callback = std::move(callback), yes_text = QtUtils::StringViewToQString(yes_text),
|
callback = std::move(callback), yes_text = QtUtils::StringViewToQString(yes_text),
|
||||||
no_text = QtUtils::StringViewToQString(no_text), needs_pause]() mutable {
|
no_text = QtUtils::StringViewToQString(no_text), needs_pause]() mutable {
|
||||||
auto lock = g_main_window->pauseAndLockSystem();
|
auto lock = g_main_window->pauseAndLockSystem();
|
||||||
@ -2136,14 +2135,14 @@ void Host::ConfirmMessageAsync(std::string_view title, std::string_view message,
|
|||||||
|
|
||||||
void Host::OpenURL(std::string_view url)
|
void Host::OpenURL(std::string_view url)
|
||||||
{
|
{
|
||||||
QtHost::RunOnUIThread([url = QtUtils::StringViewToQString(url)]() { QtUtils::OpenURL(g_main_window, QUrl(url)); });
|
Host::RunOnUIThread([url = QtUtils::StringViewToQString(url)]() { QtUtils::OpenURL(g_main_window, QUrl(url)); });
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Host::GetClipboardText()
|
std::string Host::GetClipboardText()
|
||||||
{
|
{
|
||||||
// Hope this doesn't deadlock...
|
// Hope this doesn't deadlock...
|
||||||
std::string ret;
|
std::string ret;
|
||||||
QtHost::RunOnUIThread(
|
Host::RunOnUIThread(
|
||||||
[&ret]() {
|
[&ret]() {
|
||||||
QClipboard* clipboard = QGuiApplication::clipboard();
|
QClipboard* clipboard = QGuiApplication::clipboard();
|
||||||
if (clipboard)
|
if (clipboard)
|
||||||
@ -2155,7 +2154,7 @@ std::string Host::GetClipboardText()
|
|||||||
|
|
||||||
bool Host::CopyTextToClipboard(std::string_view text)
|
bool Host::CopyTextToClipboard(std::string_view text)
|
||||||
{
|
{
|
||||||
QtHost::RunOnUIThread([text = QtUtils::StringViewToQString(text)]() {
|
Host::RunOnUIThread([text = QtUtils::StringViewToQString(text)]() {
|
||||||
QClipboard* clipboard = QGuiApplication::clipboard();
|
QClipboard* clipboard = QGuiApplication::clipboard();
|
||||||
if (clipboard)
|
if (clipboard)
|
||||||
clipboard->setText(text);
|
clipboard->setText(text);
|
||||||
@ -2543,7 +2542,7 @@ void QtHost::QueueSettingsSave()
|
|||||||
{
|
{
|
||||||
if (!QThread::isMainThread())
|
if (!QThread::isMainThread())
|
||||||
{
|
{
|
||||||
QtHost::RunOnUIThread(QueueSettingsSave);
|
Host::RunOnUIThread(QueueSettingsSave);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -225,7 +225,7 @@ private Q_SLOTS:
|
|||||||
void onDisplayWindowKeyEvent(int key, bool pressed);
|
void onDisplayWindowKeyEvent(int key, bool pressed);
|
||||||
void onDisplayWindowTextEntered(const QString& text);
|
void onDisplayWindowTextEntered(const QString& text);
|
||||||
void doBackgroundControllerPoll();
|
void doBackgroundControllerPoll();
|
||||||
void runOnEmuThread(std::function<void()> callback);
|
void runOnEmuThread(const std::function<void()>& callback);
|
||||||
void processAuxiliaryRenderWindowInputEvent(void* userdata, quint32 event, quint32 param1, quint32 param2,
|
void processAuxiliaryRenderWindowInputEvent(void* userdata, quint32 event, quint32 param1, quint32 param2,
|
||||||
quint32 param3);
|
quint32 param3);
|
||||||
|
|
||||||
@ -358,9 +358,6 @@ bool IsRunningOnWayland();
|
|||||||
/// Returns true if rendering to the main window should be allowed.
|
/// Returns true if rendering to the main window should be allowed.
|
||||||
bool CanRenderToMainWindow();
|
bool CanRenderToMainWindow();
|
||||||
|
|
||||||
/// Executes a function on the UI thread.
|
|
||||||
void RunOnUIThread(const std::function<void()>& func, bool block = false);
|
|
||||||
|
|
||||||
/// Default language for the platform.
|
/// Default language for the platform.
|
||||||
const char* GetDefaultLanguage();
|
const char* GetDefaultLanguage();
|
||||||
|
|
||||||
|
@ -225,7 +225,7 @@ std::span<const std::pair<const char*, const char*>> Host::GetAvailableLanguageL
|
|||||||
|
|
||||||
bool Host::ChangeLanguage(const char* new_language)
|
bool Host::ChangeLanguage(const char* new_language)
|
||||||
{
|
{
|
||||||
QtHost::RunOnUIThread([new_language = std::string(new_language)]() {
|
Host::RunOnUIThread([new_language = std::string(new_language)]() {
|
||||||
Host::SetBaseStringSettingValue("Main", "Language", new_language.c_str());
|
Host::SetBaseStringSettingValue("Main", "Language", new_language.c_str());
|
||||||
Host::CommitBaseSettingChanges();
|
Host::CommitBaseSettingChanges();
|
||||||
QtHost::UpdateApplicationLanguage(g_main_window);
|
QtHost::UpdateApplicationLanguage(g_main_window);
|
||||||
@ -283,8 +283,7 @@ void QtHost::UpdateGlyphRangesAndClearCache(QWidget* dialog_parent, std::string_
|
|||||||
// If we don't have any specific glyph range, assume Central European, except if English, then keep the size down.
|
// If we don't have any specific glyph range, assume Central European, except if English, then keep the size down.
|
||||||
if ((!gi || !gi->used_glyphs) && language != "en")
|
if ((!gi || !gi->used_glyphs) && language != "en")
|
||||||
{
|
{
|
||||||
glyph_ranges.insert(glyph_ranges.end(), std::begin(s_central_european_ranges),
|
glyph_ranges.insert(glyph_ranges.end(), std::begin(s_central_european_ranges), std::end(s_central_european_ranges));
|
||||||
std::end(s_central_european_ranges));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// List terminator.
|
// List terminator.
|
||||||
|
@ -381,6 +381,11 @@ void RegTestHost::ProcessCPUThreadEvents()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Host::RunOnUIThread(std::function<void()> function, bool block /* = false */)
|
||||||
|
{
|
||||||
|
RunOnCPUThread(std::move(function), block);
|
||||||
|
}
|
||||||
|
|
||||||
void Host::RequestResizeHostDisplay(s32 width, s32 height)
|
void Host::RequestResizeHostDisplay(s32 width, s32 height)
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
|
Loading…
x
Reference in New Issue
Block a user