mirror of
https://github.com/WinampDesktop/winamp.git
synced 2025-06-18 09:05:47 -04:00
Move more logic from frontend to base HostInterface
This commit is contained in:
@ -169,6 +169,11 @@ void D3D11DisplayWindow::onWindowResized(int width, int height)
|
||||
Panic("Failed to recreate swap chain RTV after resize");
|
||||
}
|
||||
|
||||
bool D3D11DisplayWindow::hasDeviceContext() const
|
||||
{
|
||||
return static_cast<bool>(m_device);
|
||||
}
|
||||
|
||||
bool D3D11DisplayWindow::createDeviceContext(QThread* worker_thread, bool debug_device)
|
||||
{
|
||||
ComPtr<IDXGIFactory> dxgi_factory;
|
||||
|
@ -21,6 +21,7 @@ public:
|
||||
|
||||
HostDisplay* getHostDisplayInterface() override;
|
||||
|
||||
bool hasDeviceContext() const override;
|
||||
bool createDeviceContext(QThread* worker_thread, bool debug_device) override;
|
||||
bool initializeDeviceContext(bool debug_device) override;
|
||||
void destroyDeviceContext() override;
|
||||
|
@ -1,8 +1,10 @@
|
||||
#include "mainwindow.h"
|
||||
#include "common/assert.h"
|
||||
#include "core/game_list.h"
|
||||
#include "core/settings.h"
|
||||
#include "gamelistsettingswidget.h"
|
||||
#include "gamelistwidget.h"
|
||||
#include "qtdisplaywindow.h"
|
||||
#include "qthostinterface.h"
|
||||
#include "qtsettingsinterface.h"
|
||||
#include "settingsdialog.h"
|
||||
@ -28,8 +30,7 @@ MainWindow::MainWindow(QtHostInterface* host_interface) : QMainWindow(nullptr),
|
||||
|
||||
MainWindow::~MainWindow()
|
||||
{
|
||||
delete m_display_widget;
|
||||
m_host_interface->displayWidgetDestroyed();
|
||||
Assert(!m_display_widget);
|
||||
}
|
||||
|
||||
void MainWindow::reportError(QString message)
|
||||
@ -42,31 +43,40 @@ void MainWindow::reportMessage(QString message)
|
||||
m_ui.statusBar->showMessage(message, 2000);
|
||||
}
|
||||
|
||||
void MainWindow::onEmulationStarting()
|
||||
void MainWindow::createDisplayWindow(QThread* worker_thread, bool use_debug_device)
|
||||
{
|
||||
DebugAssert(!m_display_widget);
|
||||
|
||||
QtDisplayWindow* display_window = m_host_interface->createDisplayWindow();
|
||||
DebugAssert(display_window);
|
||||
|
||||
m_display_widget = QWidget::createWindowContainer(display_window, m_ui.mainContainer);
|
||||
DebugAssert(m_display_widget);
|
||||
|
||||
m_display_widget->setFocusPolicy(Qt::StrongFocus);
|
||||
m_ui.mainContainer->insertWidget(1, m_display_widget);
|
||||
|
||||
// we need the surface visible.. this might be able to be replaced with something else
|
||||
switchToEmulationView();
|
||||
updateEmulationActions(true, false);
|
||||
|
||||
// we need the surface visible..
|
||||
QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
|
||||
|
||||
display_window->createDeviceContext(worker_thread, use_debug_device);
|
||||
}
|
||||
|
||||
void MainWindow::onEmulationStarted()
|
||||
void MainWindow::destroyDisplayWindow()
|
||||
{
|
||||
m_emulation_running = true;
|
||||
updateEmulationActions(false, true);
|
||||
}
|
||||
DebugAssert(m_display_widget);
|
||||
|
||||
const bool was_fullscreen = m_display_widget->isFullScreen();
|
||||
if (was_fullscreen)
|
||||
toggleFullscreen();
|
||||
|
||||
void MainWindow::onEmulationStopped()
|
||||
{
|
||||
m_emulation_running = false;
|
||||
updateEmulationActions(false, false);
|
||||
switchToGameListView();
|
||||
}
|
||||
|
||||
void MainWindow::onEmulationPaused(bool paused)
|
||||
{
|
||||
m_ui.actionPause->setChecked(paused);
|
||||
// recreate the display widget using the potentially-new renderer
|
||||
m_ui.mainContainer->removeWidget(m_display_widget);
|
||||
delete m_display_widget;
|
||||
m_display_widget = nullptr;
|
||||
}
|
||||
|
||||
void MainWindow::toggleFullscreen()
|
||||
@ -91,36 +101,22 @@ void MainWindow::toggleFullscreen()
|
||||
m_ui.actionFullscreen->setChecked(fullscreen);
|
||||
}
|
||||
|
||||
void MainWindow::recreateDisplayWidget(bool create_device_context)
|
||||
void MainWindow::onEmulationStarted()
|
||||
{
|
||||
const bool was_fullscreen = m_display_widget->isFullScreen();
|
||||
if (was_fullscreen)
|
||||
toggleFullscreen();
|
||||
m_emulation_running = true;
|
||||
updateEmulationActions(false, true);
|
||||
}
|
||||
|
||||
void MainWindow::onEmulationStopped()
|
||||
{
|
||||
m_emulation_running = false;
|
||||
updateEmulationActions(false, false);
|
||||
switchToGameListView();
|
||||
}
|
||||
|
||||
// recreate the display widget using the potentially-new renderer
|
||||
m_ui.mainContainer->removeWidget(m_display_widget);
|
||||
m_host_interface->displayWidgetDestroyed();
|
||||
delete m_display_widget;
|
||||
m_display_widget = m_host_interface->createDisplayWidget(m_ui.mainContainer);
|
||||
m_ui.mainContainer->insertWidget(1, m_display_widget);
|
||||
|
||||
if (create_device_context)
|
||||
switchToEmulationView();
|
||||
|
||||
// we need the surface visible..
|
||||
QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
|
||||
|
||||
if (create_device_context && !m_host_interface->createDisplayDeviceContext())
|
||||
{
|
||||
QMessageBox::critical(this, tr("DuckStation Error"),
|
||||
tr("Failed to create new device context on renderer switch. Cannot continue."));
|
||||
QCoreApplication::exit();
|
||||
return;
|
||||
}
|
||||
|
||||
updateDebugMenuGPURenderer();
|
||||
void MainWindow::onEmulationPaused(bool paused)
|
||||
{
|
||||
m_ui.actionPause->setChecked(paused);
|
||||
}
|
||||
|
||||
void MainWindow::onSystemPerformanceCountersUpdated(float speed, float fps, float vps, float average_frame_time,
|
||||
@ -149,7 +145,7 @@ void MainWindow::onStartDiscActionTriggered()
|
||||
if (filename.isEmpty())
|
||||
return;
|
||||
|
||||
m_host_interface->bootSystem(std::move(filename), QString());
|
||||
m_host_interface->bootSystemFromFile(std::move(filename));
|
||||
}
|
||||
|
||||
void MainWindow::onChangeDiscFromFileActionTriggered()
|
||||
@ -168,11 +164,6 @@ void MainWindow::onChangeDiscFromGameListActionTriggered()
|
||||
switchToGameListView();
|
||||
}
|
||||
|
||||
void MainWindow::onStartBiosActionTriggered()
|
||||
{
|
||||
m_host_interface->bootSystem(QString(), QString());
|
||||
}
|
||||
|
||||
static void OpenURL(QWidget* parent, const char* url)
|
||||
{
|
||||
const QUrl qurl(QUrl::fromEncoded(QByteArray(url, static_cast<int>(std::strlen(url)))));
|
||||
@ -200,10 +191,6 @@ void MainWindow::setupAdditionalUi()
|
||||
m_game_list_widget = new GameListWidget(m_ui.mainContainer);
|
||||
m_game_list_widget->initialize(m_host_interface);
|
||||
m_ui.mainContainer->insertWidget(0, m_game_list_widget);
|
||||
|
||||
m_display_widget = m_host_interface->createDisplayWidget(m_ui.mainContainer);
|
||||
m_ui.mainContainer->insertWidget(1, m_display_widget);
|
||||
|
||||
m_ui.mainContainer->setCurrentIndex(0);
|
||||
|
||||
m_status_speed_widget = new QLabel(m_ui.statusBar);
|
||||
@ -304,14 +291,14 @@ void MainWindow::connectSignals()
|
||||
onEmulationPaused(false);
|
||||
|
||||
connect(m_ui.actionStartDisc, &QAction::triggered, this, &MainWindow::onStartDiscActionTriggered);
|
||||
connect(m_ui.actionStartBios, &QAction::triggered, this, &MainWindow::onStartBiosActionTriggered);
|
||||
connect(m_ui.actionStartBios, &QAction::triggered, m_host_interface, &QtHostInterface::bootSystemFromBIOS);
|
||||
connect(m_ui.actionChangeDisc, &QAction::triggered, [this] { m_ui.menuChangeDisc->exec(QCursor::pos()); });
|
||||
connect(m_ui.actionChangeDiscFromFile, &QAction::triggered, this, &MainWindow::onChangeDiscFromFileActionTriggered);
|
||||
connect(m_ui.actionChangeDiscFromGameList, &QAction::triggered, this,
|
||||
&MainWindow::onChangeDiscFromGameListActionTriggered);
|
||||
connect(m_ui.actionAddGameDirectory, &QAction::triggered,
|
||||
[this]() { getSettingsDialog()->getGameListSettingsWidget()->addSearchDirectory(this); });
|
||||
connect(m_ui.actionPowerOff, &QAction::triggered, [this]() { m_host_interface->powerOffSystem(true, false); });
|
||||
connect(m_ui.actionPowerOff, &QAction::triggered, [this]() { m_host_interface->destroySystem(true, false); });
|
||||
connect(m_ui.actionReset, &QAction::triggered, m_host_interface, &QtHostInterface::resetSystem);
|
||||
connect(m_ui.actionPause, &QAction::toggled, m_host_interface, &QtHostInterface::pauseSystem);
|
||||
connect(m_ui.actionLoadState, &QAction::triggered, this, [this]() { m_ui.menuLoadState->exec(QCursor::pos()); });
|
||||
@ -336,14 +323,14 @@ void MainWindow::connectSignals()
|
||||
|
||||
connect(m_host_interface, &QtHostInterface::errorReported, this, &MainWindow::reportError,
|
||||
Qt::BlockingQueuedConnection);
|
||||
connect(m_host_interface, &QtHostInterface::createDisplayWindowRequested, this, &MainWindow::createDisplayWindow,
|
||||
Qt::BlockingQueuedConnection);
|
||||
connect(m_host_interface, &QtHostInterface::destroyDisplayWindowRequested, this, &MainWindow::destroyDisplayWindow);
|
||||
connect(m_host_interface, &QtHostInterface::toggleFullscreenRequested, this, &MainWindow::toggleFullscreen);
|
||||
connect(m_host_interface, &QtHostInterface::messageReported, this, &MainWindow::reportMessage);
|
||||
connect(m_host_interface, &QtHostInterface::emulationStarting, this, &MainWindow::onEmulationStarting);
|
||||
connect(m_host_interface, &QtHostInterface::emulationStarted, this, &MainWindow::onEmulationStarted);
|
||||
connect(m_host_interface, &QtHostInterface::emulationStopped, this, &MainWindow::onEmulationStopped);
|
||||
connect(m_host_interface, &QtHostInterface::emulationPaused, this, &MainWindow::onEmulationPaused);
|
||||
connect(m_host_interface, &QtHostInterface::toggleFullscreenRequested, this, &MainWindow::toggleFullscreen);
|
||||
connect(m_host_interface, &QtHostInterface::recreateDisplayWidgetRequested, this, &MainWindow::recreateDisplayWidget,
|
||||
Qt::BlockingQueuedConnection);
|
||||
connect(m_host_interface, &QtHostInterface::systemPerformanceCountersUpdated, this,
|
||||
&MainWindow::onSystemPerformanceCountersUpdated);
|
||||
connect(m_host_interface, &QtHostInterface::runningGameChanged, this, &MainWindow::onRunningGameChanged);
|
||||
@ -353,7 +340,7 @@ void MainWindow::connectSignals()
|
||||
QString path = QString::fromStdString(entry->path);
|
||||
if (!m_emulation_running)
|
||||
{
|
||||
m_host_interface->bootSystem(path, QString());
|
||||
m_host_interface->bootSystemFromFile(path);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -446,6 +433,6 @@ void MainWindow::updateDebugMenuGPURenderer()
|
||||
|
||||
void MainWindow::closeEvent(QCloseEvent* event)
|
||||
{
|
||||
m_host_interface->powerOffSystem(true, true);
|
||||
m_host_interface->destroySystem(true, true);
|
||||
QMainWindow::closeEvent(event);
|
||||
}
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include "ui_mainwindow.h"
|
||||
|
||||
class QLabel;
|
||||
class QThread;
|
||||
|
||||
class GameListWidget;
|
||||
class QtHostInterface;
|
||||
@ -23,12 +24,12 @@ public:
|
||||
private Q_SLOTS:
|
||||
void reportError(QString message);
|
||||
void reportMessage(QString message);
|
||||
void onEmulationStarting();
|
||||
void createDisplayWindow(QThread* worker_thread, bool use_debug_device);
|
||||
void destroyDisplayWindow();
|
||||
void toggleFullscreen();
|
||||
void onEmulationStarted();
|
||||
void onEmulationStopped();
|
||||
void onEmulationPaused(bool paused);
|
||||
void toggleFullscreen();
|
||||
void recreateDisplayWidget(bool create_device_context);
|
||||
void onSystemPerformanceCountersUpdated(float speed, float fps, float vps, float average_frame_time,
|
||||
float worst_frame_time);
|
||||
void onRunningGameChanged(QString filename, QString game_code, QString game_title);
|
||||
@ -36,7 +37,6 @@ private Q_SLOTS:
|
||||
void onStartDiscActionTriggered();
|
||||
void onChangeDiscFromFileActionTriggered();
|
||||
void onChangeDiscFromGameListActionTriggered();
|
||||
void onStartBiosActionTriggered();
|
||||
void onGitHubRepositoryActionTriggered();
|
||||
void onIssueTrackerActionTriggered();
|
||||
void onAboutActionTriggered();
|
||||
|
@ -223,6 +223,11 @@ static void APIENTRY GLDebugCallback(GLenum source, GLenum type, GLuint id, GLen
|
||||
}
|
||||
}
|
||||
|
||||
bool OpenGLDisplayWindow::hasDeviceContext() const
|
||||
{
|
||||
return static_cast<bool>(m_gl_context);
|
||||
}
|
||||
|
||||
bool OpenGLDisplayWindow::createDeviceContext(QThread* worker_thread, bool debug_device)
|
||||
{
|
||||
m_gl_context = std::make_unique<QOpenGLContext>();
|
||||
|
@ -27,6 +27,7 @@ public:
|
||||
|
||||
HostDisplay* getHostDisplayInterface() override;
|
||||
|
||||
bool hasDeviceContext() const override;
|
||||
bool createDeviceContext(QThread* worker_thread, bool debug_device) override;
|
||||
bool initializeDeviceContext(bool debug_device) override;
|
||||
void destroyDeviceContext() override;
|
||||
|
@ -18,6 +18,11 @@ HostDisplay* QtDisplayWindow::getHostDisplayInterface()
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool QtDisplayWindow::hasDeviceContext() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QtDisplayWindow::createDeviceContext(QThread* worker_thread, bool debug_device)
|
||||
{
|
||||
return true;
|
||||
|
@ -18,6 +18,7 @@ public:
|
||||
|
||||
virtual HostDisplay* getHostDisplayInterface();
|
||||
|
||||
virtual bool hasDeviceContext() const;
|
||||
virtual bool createDeviceContext(QThread* worker_thread, bool debug_device);
|
||||
virtual bool initializeDeviceContext(bool debug_device);
|
||||
virtual void destroyDeviceContext();
|
||||
|
@ -151,8 +151,10 @@ void QtHostInterface::refreshGameList(bool invalidate_cache /* = false */, bool
|
||||
emit gameListRefreshed();
|
||||
}
|
||||
|
||||
QWidget* QtHostInterface::createDisplayWidget(QWidget* parent)
|
||||
QtDisplayWindow* QtHostInterface::createDisplayWindow()
|
||||
{
|
||||
Assert(!m_display_window);
|
||||
|
||||
#ifdef WIN32
|
||||
if (m_settings.gpu_renderer == GPURenderer::HardwareOpenGL)
|
||||
m_display_window = new OpenGLDisplayWindow(this, nullptr);
|
||||
@ -162,40 +164,29 @@ QWidget* QtHostInterface::createDisplayWidget(QWidget* parent)
|
||||
m_display_window = new OpenGLDisplayWindow(this, nullptr);
|
||||
#endif
|
||||
connect(m_display_window, &QtDisplayWindow::windowResizedEvent, this, &QtHostInterface::onDisplayWindowResized);
|
||||
|
||||
m_display.release();
|
||||
m_display = std::unique_ptr<HostDisplay>(m_display_window->getHostDisplayInterface());
|
||||
m_display->SetDisplayLinearFiltering(m_settings.display_linear_filtering);
|
||||
|
||||
QWidget* widget = QWidget::createWindowContainer(m_display_window, parent);
|
||||
widget->setFocusPolicy(Qt::StrongFocus);
|
||||
return widget;
|
||||
return m_display_window;
|
||||
}
|
||||
|
||||
bool QtHostInterface::createDisplayDeviceContext()
|
||||
void QtHostInterface::bootSystemFromFile(QString filename)
|
||||
{
|
||||
return m_display_window->createDeviceContext(m_worker_thread, m_settings.gpu_use_debug_device);
|
||||
}
|
||||
|
||||
void QtHostInterface::displayWidgetDestroyed()
|
||||
{
|
||||
m_display.release();
|
||||
m_display_window = nullptr;
|
||||
}
|
||||
|
||||
void QtHostInterface::bootSystem(QString initial_filename, QString initial_save_state_filename)
|
||||
{
|
||||
Assert(!isOnWorkerThread());
|
||||
emit emulationStarting();
|
||||
|
||||
if (!createDisplayDeviceContext())
|
||||
if (!isOnWorkerThread())
|
||||
{
|
||||
emit emulationStopped();
|
||||
QMetaObject::invokeMethod(this, "bootSystemFromFile", Qt::QueuedConnection, Q_ARG(QString, filename));
|
||||
return;
|
||||
}
|
||||
|
||||
QMetaObject::invokeMethod(this, "doBootSystem", Qt::QueuedConnection, Q_ARG(QString, initial_filename),
|
||||
Q_ARG(QString, initial_save_state_filename));
|
||||
HostInterface::BootSystemFromFile(filename.toStdString().c_str());
|
||||
}
|
||||
|
||||
void QtHostInterface::bootSystemFromBIOS()
|
||||
{
|
||||
if (!isOnWorkerThread())
|
||||
{
|
||||
QMetaObject::invokeMethod(this, "bootSystemFromBIOS", Qt::QueuedConnection);
|
||||
return;
|
||||
}
|
||||
|
||||
HostInterface::BootSystemFromBIOS();
|
||||
}
|
||||
|
||||
void QtHostInterface::handleKeyEvent(int key, bool pressed)
|
||||
@ -223,51 +214,82 @@ void QtHostInterface::onDisplayWindowResized(int width, int height)
|
||||
m_display_window->onWindowResized(width, height);
|
||||
}
|
||||
|
||||
void QtHostInterface::SwitchGPURenderer()
|
||||
bool QtHostInterface::AcquireHostDisplay()
|
||||
{
|
||||
// Due to the GPU class owning textures, we have to shut the system down.
|
||||
std::unique_ptr<ByteStream> stream;
|
||||
if (m_system)
|
||||
{
|
||||
stream = ByteStream_CreateGrowableMemoryStream(nullptr, 8 * 1024);
|
||||
if (!m_system->SaveState(stream.get()) || !stream->SeekAbsolute(0))
|
||||
ReportError("Failed to save state before GPU renderer switch");
|
||||
DebugAssert(!m_display_window);
|
||||
|
||||
DestroySystem();
|
||||
m_audio_stream->PauseOutput(true);
|
||||
emit createDisplayWindowRequested(m_worker_thread, m_settings.gpu_use_debug_device);
|
||||
if (!m_display_window->hasDeviceContext())
|
||||
{
|
||||
m_display_window = nullptr;
|
||||
emit destroyDisplayWindowRequested();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!m_display_window->initializeDeviceContext(m_settings.gpu_use_debug_device))
|
||||
{
|
||||
m_display_window->destroyDeviceContext();
|
||||
m_display_window = nullptr;
|
||||
emit destroyDisplayWindowRequested();
|
||||
return false;
|
||||
}
|
||||
|
||||
const bool restore_state = static_cast<bool>(stream);
|
||||
emit recreateDisplayWidgetRequested(restore_state);
|
||||
Assert(m_display_window != nullptr);
|
||||
m_display = m_display_window->getHostDisplayInterface();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (restore_state)
|
||||
void QtHostInterface::ReleaseHostDisplay()
|
||||
{
|
||||
DebugAssert(m_display_window && m_display == m_display_window->getHostDisplayInterface());
|
||||
m_display = nullptr;
|
||||
m_display_window->disconnect(this);
|
||||
m_display_window->destroyDeviceContext();
|
||||
m_display_window = nullptr;
|
||||
emit destroyDisplayWindowRequested();
|
||||
}
|
||||
|
||||
std::unique_ptr<AudioStream> QtHostInterface::CreateAudioStream(AudioBackend backend)
|
||||
{
|
||||
switch (backend)
|
||||
{
|
||||
if (!m_display_window->initializeDeviceContext(m_settings.gpu_use_debug_device))
|
||||
{
|
||||
emit runningGameChanged(QString(), QString(), QString());
|
||||
emit emulationStopped();
|
||||
return;
|
||||
}
|
||||
case AudioBackend::Default:
|
||||
case AudioBackend::Cubeb:
|
||||
return AudioStream::CreateCubebAudioStream();
|
||||
|
||||
CreateSystem();
|
||||
if (!BootSystem(nullptr, nullptr) || !m_system->LoadState(stream.get()))
|
||||
{
|
||||
ReportError("Failed to load state after GPU renderer switch, resetting");
|
||||
m_system->Reset();
|
||||
}
|
||||
case AudioBackend::Null:
|
||||
return AudioStream::CreateNullAudioStream();
|
||||
|
||||
if (!m_paused)
|
||||
{
|
||||
m_audio_stream->PauseOutput(false);
|
||||
UpdateSpeedLimiterState();
|
||||
}
|
||||
|
||||
m_system->ResetPerformanceCounters();
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void QtHostInterface::OnSystemCreated()
|
||||
{
|
||||
HostInterface::OnSystemCreated();
|
||||
|
||||
wakeThread();
|
||||
|
||||
emit emulationStarted();
|
||||
}
|
||||
|
||||
void QtHostInterface::OnSystemPaused(bool paused)
|
||||
{
|
||||
HostInterface::OnSystemPaused(paused);
|
||||
|
||||
if (!paused)
|
||||
wakeThread();
|
||||
|
||||
emit emulationPaused(paused);
|
||||
}
|
||||
|
||||
void QtHostInterface::OnSystemDestroyed()
|
||||
{
|
||||
HostInterface::OnSystemDestroyed();
|
||||
|
||||
emit emulationStopped();
|
||||
}
|
||||
|
||||
void QtHostInterface::OnSystemPerformanceCountersUpdated()
|
||||
{
|
||||
HostInterface::OnSystemPerformanceCountersUpdated();
|
||||
@ -457,11 +479,11 @@ void QtHostInterface::addButtonToInputMap(const QString& binding, InputButtonHan
|
||||
}
|
||||
}
|
||||
|
||||
void QtHostInterface::powerOffSystem(bool save_resume_state /* = false */, bool block_until_done /* = false */)
|
||||
void QtHostInterface::destroySystem(bool save_resume_state /* = false */, bool block_until_done /* = false */)
|
||||
{
|
||||
if (!isOnWorkerThread())
|
||||
{
|
||||
QMetaObject::invokeMethod(this, "powerOffSystem",
|
||||
QMetaObject::invokeMethod(this, "destroySystem",
|
||||
block_until_done ? Qt::BlockingQueuedConnection : Qt::QueuedConnection,
|
||||
Q_ARG(bool, save_resume_state), Q_ARG(bool, block_until_done));
|
||||
return;
|
||||
@ -470,15 +492,7 @@ void QtHostInterface::powerOffSystem(bool save_resume_state /* = false */, bool
|
||||
if (!m_system)
|
||||
return;
|
||||
|
||||
if (save_resume_state)
|
||||
Log_InfoPrintf("TODO: Save resume state");
|
||||
|
||||
DestroySystem();
|
||||
m_audio_stream->PauseOutput(true);
|
||||
m_display_window->destroyDeviceContext();
|
||||
|
||||
emit runningGameChanged(QString(), QString(), QString());
|
||||
emit emulationStopped();
|
||||
}
|
||||
|
||||
void QtHostInterface::resetSystem()
|
||||
@ -515,59 +529,6 @@ void QtHostInterface::pauseSystem(bool paused)
|
||||
|
||||
void QtHostInterface::changeDisc(QString new_disc_filename) {}
|
||||
|
||||
void QtHostInterface::doBootSystem(QString initial_filename, QString initial_save_state_filename)
|
||||
{
|
||||
if (!m_display_window->initializeDeviceContext(m_settings.gpu_use_debug_device))
|
||||
{
|
||||
emit emulationStopped();
|
||||
return;
|
||||
}
|
||||
|
||||
std::string initial_filename_str = initial_filename.toStdString();
|
||||
std::string initial_save_state_filename_str = initial_save_state_filename.toStdString();
|
||||
std::lock_guard<std::mutex> lock(m_qsettings_mutex);
|
||||
if (!CreateSystem() ||
|
||||
!BootSystem(initial_filename_str.empty() ? nullptr : initial_filename_str.c_str(),
|
||||
initial_save_state_filename_str.empty() ? nullptr : initial_save_state_filename_str.c_str()))
|
||||
{
|
||||
DestroySystem();
|
||||
m_display_window->destroyDeviceContext();
|
||||
emit emulationStopped();
|
||||
return;
|
||||
}
|
||||
|
||||
wakeThread();
|
||||
m_audio_stream->PauseOutput(false);
|
||||
UpdateSpeedLimiterState();
|
||||
emit emulationStarted();
|
||||
}
|
||||
|
||||
void QtHostInterface::createAudioStream()
|
||||
{
|
||||
switch (m_settings.audio_backend)
|
||||
{
|
||||
case AudioBackend::Default:
|
||||
case AudioBackend::Cubeb:
|
||||
m_audio_stream = AudioStream::CreateCubebAudioStream();
|
||||
break;
|
||||
|
||||
case AudioBackend::Null:
|
||||
default:
|
||||
m_audio_stream = AudioStream::CreateNullAudioStream();
|
||||
break;
|
||||
}
|
||||
|
||||
if (!m_audio_stream->Reconfigure(AUDIO_SAMPLE_RATE, AUDIO_CHANNELS, AUDIO_BUFFER_SIZE, 4))
|
||||
{
|
||||
qWarning() << "Failed to configure audio stream, falling back to null output";
|
||||
|
||||
// fall back to null output
|
||||
m_audio_stream.reset();
|
||||
m_audio_stream = AudioStream::CreateNullAudioStream();
|
||||
m_audio_stream->Reconfigure(AUDIO_SAMPLE_RATE, AUDIO_CHANNELS, AUDIO_BUFFER_SIZE, 4);
|
||||
}
|
||||
}
|
||||
|
||||
void QtHostInterface::populateSaveStateMenus(const char* game_code, QMenu* load_menu, QMenu* save_menu)
|
||||
{
|
||||
const std::vector<SaveStateInfo> available_states(GetAvailableSaveStates(game_code));
|
||||
@ -626,10 +587,7 @@ void QtHostInterface::loadState(QString filename)
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_system)
|
||||
LoadState(filename.toStdString().c_str());
|
||||
else
|
||||
doBootSystem(QString(), filename);
|
||||
LoadState(filename.toStdString().c_str());
|
||||
}
|
||||
|
||||
void QtHostInterface::loadState(bool global, qint32 slot)
|
||||
@ -640,19 +598,7 @@ void QtHostInterface::loadState(bool global, qint32 slot)
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_system)
|
||||
{
|
||||
LoadState(slot, global);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!global)
|
||||
{
|
||||
// can't load a non-global system without a game code
|
||||
return;
|
||||
}
|
||||
|
||||
loadState(QString::fromStdString(GetGlobalSaveStateFileName(slot)));
|
||||
LoadState(global, slot);
|
||||
}
|
||||
|
||||
void QtHostInterface::saveState(bool global, qint32 slot, bool block_until_done /* = false */)
|
||||
@ -694,8 +640,6 @@ void QtHostInterface::threadEntryPoint()
|
||||
{
|
||||
m_worker_thread_event_loop = new QEventLoop();
|
||||
|
||||
createAudioStream();
|
||||
|
||||
// TODO: Event which flags the thread as ready
|
||||
while (!m_shutdown_flag.load())
|
||||
{
|
||||
|
@ -45,11 +45,7 @@ public:
|
||||
|
||||
bool isOnWorkerThread() const { return QThread::currentThread() == m_worker_thread; }
|
||||
|
||||
QWidget* createDisplayWidget(QWidget* parent);
|
||||
bool createDisplayDeviceContext();
|
||||
void displayWidgetDestroyed();
|
||||
|
||||
void bootSystem(QString initial_filename, QString initial_save_state_filename);
|
||||
QtDisplayWindow* createDisplayWindow();
|
||||
|
||||
void updateInputMap();
|
||||
void handleKeyEvent(int key, bool pressed);
|
||||
@ -67,20 +63,22 @@ public:
|
||||
Q_SIGNALS:
|
||||
void errorReported(QString message);
|
||||
void messageReported(QString message);
|
||||
void emulationStarting();
|
||||
void emulationStarted();
|
||||
void emulationStopped();
|
||||
void emulationPaused(bool paused);
|
||||
void gameListRefreshed();
|
||||
void createDisplayWindowRequested(QThread* worker_thread, bool use_debug_device);
|
||||
void destroyDisplayWindowRequested();
|
||||
void toggleFullscreenRequested();
|
||||
void recreateDisplayWidgetRequested(bool create_device_context);
|
||||
void systemPerformanceCountersUpdated(float speed, float fps, float vps, float avg_frame_time,
|
||||
float worst_frame_time);
|
||||
void runningGameChanged(QString filename, QString game_code, QString game_title);
|
||||
|
||||
public Q_SLOTS:
|
||||
void applySettings();
|
||||
void powerOffSystem(bool save_resume_state = false, bool block_until_done = false);
|
||||
void bootSystemFromFile(QString filename);
|
||||
void bootSystemFromBIOS();
|
||||
void destroySystem(bool save_resume_state = false, bool block_until_done = false);
|
||||
void resetSystem();
|
||||
void pauseSystem(bool paused);
|
||||
void changeDisc(QString new_disc_filename);
|
||||
@ -90,13 +88,18 @@ public Q_SLOTS:
|
||||
|
||||
private Q_SLOTS:
|
||||
void doStopThread();
|
||||
void doBootSystem(QString initial_filename, QString initial_save_state_filename);
|
||||
void doUpdateInputMap();
|
||||
void doHandleKeyEvent(int key, bool pressed);
|
||||
void onDisplayWindowResized(int width, int height);
|
||||
|
||||
protected:
|
||||
void SwitchGPURenderer() override;
|
||||
bool AcquireHostDisplay() override;
|
||||
void ReleaseHostDisplay() override;
|
||||
std::unique_ptr<AudioStream> CreateAudioStream(AudioBackend backend) override;
|
||||
|
||||
void OnSystemCreated() override;
|
||||
void OnSystemPaused(bool paused) override;
|
||||
void OnSystemDestroyed() override;
|
||||
void OnSystemPerformanceCountersUpdated() override;
|
||||
void OnRunningGameChanged() override;
|
||||
|
||||
@ -122,7 +125,6 @@ private:
|
||||
void updateControllerInputMap();
|
||||
void updateHotkeyInputMap();
|
||||
void addButtonToInputMap(const QString& binding, InputButtonHandler handler);
|
||||
void createAudioStream();
|
||||
void createThread();
|
||||
void stopThread();
|
||||
void threadEntryPoint();
|
||||
|
Reference in New Issue
Block a user