diff --git a/external/glslang b/external/glslang index 9c7fd1a3..3ebb72cc 160000 --- a/external/glslang +++ b/external/glslang @@ -1 +1 @@ -Subproject commit 9c7fd1a33e5cecbe465e1cd70170167d5e40d398 +Subproject commit 3ebb72cc7429f0ab8218104dc3687c659c0f364d diff --git a/qt/src/EmuApplication.cpp b/qt/src/EmuApplication.cpp index 2db05c1a..71520562 100644 --- a/qt/src/EmuApplication.cpp +++ b/qt/src/EmuApplication.cpp @@ -2,6 +2,7 @@ #include "common/audio/s9x_sound_driver_sdl.hpp" #include "common/audio/s9x_sound_driver_cubeb.hpp" #include +#include #ifdef USE_PULSEAUDIO #include "common/audio/s9x_sound_driver_pulse.hpp" #endif @@ -169,9 +170,7 @@ void EmuApplication::suspendThread() if (suspend_count > 0) { - printf("Suspend %d\n", suspend_count); - emu_thread->runOnThread([&] { emu_thread->setStatusBits(EmuThread::eSuspended); }); - emu_thread->waitForStatusBit(EmuThread::eSuspended); + emu_thread->runOnThread([&] { emu_thread->setStatusBits(EmuThread::eSuspended); }, true); } } @@ -183,12 +182,9 @@ void EmuApplication::unsuspendThread() if (!emu_thread) return; - printf("Un Suspend %d\n", suspend_count); - if (suspend_count == 0) { - emu_thread->runOnThread([&] { emu_thread->unsetStatusBits(EmuThread::eSuspended); }); - emu_thread->waitForStatusBitCleared(EmuThread::eSuspended); + emu_thread->runOnThread([&] { emu_thread->unsetStatusBits(EmuThread::eSuspended); }, true); } } @@ -260,7 +256,6 @@ void EmuApplication::mainLoop() return; } - printf("Here\n"); core->mainLoop(); } @@ -522,11 +517,15 @@ bool EmuApplication::isCoreActive() return core->active; } -void EmuThread::runOnThread(std::function func) +void EmuThread::runOnThread(std::function func, bool blocking) { if (QThread::currentThread() != this) { - QMetaObject::invokeMethod(this, "runOnThread", Q_ARG(std::function, func)); + QMetaObject::invokeMethod(this, + "runOnThread", + blocking ? Qt::BlockingQueuedConnection : Qt::QueuedConnection, + Q_ARG(std::function, func), + Q_ARG(bool, blocking)); return; } @@ -541,20 +540,12 @@ EmuThread::EmuThread(QThread *main_thread_) void EmuThread::setStatusBits(int new_status) { - std::unique_lock lock(status_mutex); status |= new_status; - lock.unlock(); - status_cond.notify_all(); } void EmuThread::unsetStatusBits(int new_status) { - printf("Old: %08x, new: %08x\n", status, new_status); - std::unique_lock lock(status_mutex); status &= ~new_status; - printf("Final: %08x\n", status); - lock.unlock(); - status_cond.notify_all(); } void EmuThread::waitForStatusBit(int new_status) @@ -564,8 +555,7 @@ void EmuThread::waitForStatusBit(int new_status) while (1) { - std::unique_lock lock(status_mutex); - status_cond.wait_for(lock, std::chrono::milliseconds(500)); + QThread::yieldCurrentThread(); if (status & new_status) break; } @@ -578,8 +568,7 @@ void EmuThread::waitForStatusBitCleared(int new_status) while (1) { - std::unique_lock lock(status_mutex); - status_cond.wait_for(lock, std::chrono::milliseconds(500)); + QThread::yieldCurrentThread(); if (!(status & new_status)) break; } @@ -587,14 +576,12 @@ void EmuThread::waitForStatusBitCleared(int new_status) void EmuThread::pause() { - runOnThread([&] { setStatusBits(ePaused); }); - waitForStatusBit(ePaused); + runOnThread([&] { setStatusBits(ePaused); }, true); } void EmuThread::unpause() { - runOnThread([&] { unsetStatusBits(ePaused); }); - waitForStatusBitCleared(ePaused); + runOnThread([&] { unsetStatusBits(ePaused); }, true); } void EmuThread::run() @@ -612,12 +599,10 @@ void EmuThread::run() if (status & (ePaused | eSuspended)) { - std::this_thread::sleep_for(2ms); - printf("Paused: %08x\n", status); + QThread::usleep(2000); continue; } - printf("Loop\n"); if (main_loop) main_loop(); } diff --git a/qt/src/EmuApplication.hpp b/qt/src/EmuApplication.hpp index 0b30777a..fe5c990a 100644 --- a/qt/src/EmuApplication.hpp +++ b/qt/src/EmuApplication.hpp @@ -36,11 +36,9 @@ Q_OBJECT }; int status = eDead; - std::mutex status_mutex; - std::condition_variable status_cond; - + public slots: - void runOnThread(std::function func); + void runOnThread(std::function func, bool blocking = false); }; struct EmuApplication diff --git a/qt/src/EmuCanvas.hpp b/qt/src/EmuCanvas.hpp index 6cceda44..c3d8515f 100644 --- a/qt/src/EmuCanvas.hpp +++ b/qt/src/EmuCanvas.hpp @@ -12,6 +12,8 @@ class EmuCanvas : public QWidget virtual void deinit() = 0; virtual void draw() = 0; + void paintEvent(QPaintEvent *) override = 0; + virtual void createContext() {} void output(uint8_t *buffer, int width, int height, QImage::Format format, int bytes_per_line, double frame_rate); void throttle(); void resizeEvent(QResizeEvent *event) override = 0; diff --git a/qt/src/EmuCanvasOpenGL.cpp b/qt/src/EmuCanvasOpenGL.cpp index 7e790aae..93ae4057 100644 --- a/qt/src/EmuCanvasOpenGL.cpp +++ b/qt/src/EmuCanvasOpenGL.cpp @@ -57,11 +57,6 @@ EmuCanvasOpenGL::EmuCanvasOpenGL(EmuConfig *config, QWidget *parent, QWidget *ma setAttribute(Qt::WA_OpaquePaintEvent); createWinId(); - - auto timer = new QTimer(this); - timer->setSingleShot(true); - timer->callOnTimeout([&]{ createContext(); }); - timer->start(); } EmuCanvasOpenGL::~EmuCanvasOpenGL() @@ -251,6 +246,7 @@ void EmuCanvasOpenGL::draw() return; context->make_current(); + gladLoaderLoadGL(); uploadTexture(); glActiveTexture(GL_TEXTURE0); @@ -298,7 +294,8 @@ void EmuCanvasOpenGL::resizeEvent(QResizeEvent *event) { QWidget::resizeEvent(event); - if (!context) return; + if (!context) + return; auto g = parent->geometry(); int s = devicePixelRatio(); @@ -308,6 +305,8 @@ void EmuCanvasOpenGL::resizeEvent(QResizeEvent *event) ((WaylandEGLContext *)context.get())->resize({ g.x(), g.y(), g.width(), g.height(), s }); else if (platform == "xcb") ((GTKGLXContext *)context.get())->resize(); +#else + ((WGLContext *)context.get())->resize(); #endif } @@ -324,6 +323,9 @@ void EmuCanvasOpenGL::paintEvent(QPaintEvent *event) return; } +#ifdef _WIN32 + ((WGLContext *)context.get())->resize(); +#endif glClearColor(0.0f, 0.0f, 0.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); context->swap_buffers(); diff --git a/qt/src/EmuCanvasOpenGL.hpp b/qt/src/EmuCanvasOpenGL.hpp index 8ab4b71f..ac3f2440 100644 --- a/qt/src/EmuCanvasOpenGL.hpp +++ b/qt/src/EmuCanvasOpenGL.hpp @@ -14,6 +14,7 @@ class EmuCanvasOpenGL : public EmuCanvas EmuCanvasOpenGL(EmuConfig *config, QWidget *parent, QWidget *main_window); ~EmuCanvasOpenGL(); + void createContext() override; void deinit() override; void paintEvent(QPaintEvent *event) override; void resizeEvent(QResizeEvent *event) override; @@ -26,7 +27,6 @@ class EmuCanvasOpenGL : public EmuCanvas private: void resizeTexture(int width, int height); - void createContext(); void createStockShaders(); void stockShaderDraw(); void customShaderDraw(); diff --git a/qt/src/EmuCanvasVulkan.cpp b/qt/src/EmuCanvasVulkan.cpp index 5283d682..d598755e 100644 --- a/qt/src/EmuCanvasVulkan.cpp +++ b/qt/src/EmuCanvasVulkan.cpp @@ -25,11 +25,6 @@ EmuCanvasVulkan::EmuCanvasVulkan(EmuConfig *config, QWidget *parent, QWidget *ma createWinId(); window = windowHandle(); - - auto timer = new QTimer(this); - timer->setSingleShot(true); - timer->callOnTimeout([&]{ createContext(); }); - timer->start(); } EmuCanvasVulkan::~EmuCanvasVulkan() diff --git a/qt/src/EmuCanvasVulkan.hpp b/qt/src/EmuCanvasVulkan.hpp index 97fa3989..2a31961b 100644 --- a/qt/src/EmuCanvasVulkan.hpp +++ b/qt/src/EmuCanvasVulkan.hpp @@ -16,6 +16,7 @@ class EmuCanvasVulkan : public EmuCanvas EmuCanvasVulkan(EmuConfig *config, QWidget *parent, QWidget *main_window); ~EmuCanvasVulkan(); + void createContext(); void deinit() override; void paintEvent(QPaintEvent *event) override; void resizeEvent(QResizeEvent *event) override; @@ -37,7 +38,6 @@ class EmuCanvasVulkan : public EmuCanvas std::unique_ptr shader_chain; private: - void createContext(); void tryLoadShader(); std::string current_shader; QWindow *window = nullptr; diff --git a/qt/src/EmuMainWindow.cpp b/qt/src/EmuMainWindow.cpp index cb75c4f4..3cf80471 100644 --- a/qt/src/EmuMainWindow.cpp +++ b/qt/src/EmuMainWindow.cpp @@ -84,22 +84,40 @@ void EmuMainWindow::createCanvas() auto central_widget = new QStackedWidget(); if (app->config->display_driver == "vulkan") + { canvas = new EmuCanvasVulkan(app->config.get(), central_widget, this); + QGuiApplication::processEvents(); + canvas->createContext(); + } else if (app->config->display_driver == "opengl") + { canvas = new EmuCanvasOpenGL(app->config.get(), central_widget, this); + QGuiApplication::processEvents(); + app->emu_thread->runOnThread([&] { canvas->createContext(); }, true); + } central_widget->addWidget(canvas); central_widget->setCurrentWidget(canvas); setCentralWidget(central_widget); using_stacked_widget = true; + QGuiApplication::processEvents(); + return; } #endif if (app->config->display_driver == "vulkan") + { canvas = new EmuCanvasVulkan(app->config.get(), this, this); + QGuiApplication::processEvents(); + canvas->createContext(); + } else if (app->config->display_driver == "opengl") + { canvas = new EmuCanvasOpenGL(app->config.get(), this, this); + QGuiApplication::processEvents(); + app->emu_thread->runOnThread([&] { canvas->createContext(); }, true); + } else canvas = new EmuCanvasQt(app->config.get(), this, this); @@ -447,6 +465,7 @@ bool EmuMainWindow::event(QEvent *event) { toggleFullscreen(); } + app->stopThread(); if (canvas) canvas->deinit(); QGuiApplication::sync(); @@ -530,13 +549,24 @@ void EmuMainWindow::toggleFullscreen() bool EmuMainWindow::eventFilter(QObject *watched, QEvent *event) { - if (watched == canvas && event->type() == QEvent::Resize) + if (watched == canvas) { - app->suspendThread(); - canvas->resizeEvent((QResizeEvent *)event); - event->accept(); - app->unsuspendThread(); - return true; + if (event->type() == QEvent::Resize) + { + app->suspendThread(); + canvas->resizeEvent((QResizeEvent *)event); + event->accept(); + app->unsuspendThread(); + return true; + } + else if (event->type() == QEvent::Paint) + { + app->emu_thread->runOnThread([&] { + canvas->paintEvent((QPaintEvent *)event); + }, true); + event->accept(); + return true; + } } if (event->type() != QEvent::KeyPress && event->type() != QEvent::KeyRelease) diff --git a/qt/src/main.cpp b/qt/src/main.cpp index 76101103..00fa71a5 100644 --- a/qt/src/main.cpp +++ b/qt/src/main.cpp @@ -17,6 +17,8 @@ int main(int argc, char *argv[]) signal(s, quit_handler); #endif + emu.startThread(); + emu.config = std::make_unique(); emu.config->setDefaults(); emu.config->loadFile(EmuConfig::findConfigFile()); @@ -27,7 +29,6 @@ int main(int argc, char *argv[]) emu.updateBindings(); emu.startInputTimer(); - emu.startThread(); emu.qtapp->exec(); emu.stopThread();