mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-31 05:40:04 +00:00 
			
		
		
		
	Change Qt to use QOpenGLWidget and support shared context and texture mailbox
This commit is contained in:
		
							parent
							
								
									27d0fc64d0
								
							
						
					
					
						commit
						91255b8802
					
				
					 3 changed files with 85 additions and 118 deletions
				
			
		|  | @ -1,31 +1,33 @@ | ||||||
| #include <QApplication> | #include <QApplication> | ||||||
| #include <QHBoxLayout> | #include <QHBoxLayout> | ||||||
| #include <QKeyEvent> | #include <QKeyEvent> | ||||||
|  | #include <QOffScreenSurface> | ||||||
|  | #include <QOpenGLContext> | ||||||
|  | #include <QOpenGLFunctions> | ||||||
| #include <QScreen> | #include <QScreen> | ||||||
| #include <QWindow> | #include <QWindow> | ||||||
| #include <fmt/format.h> | #include <fmt/format.h> | ||||||
| 
 |  | ||||||
| #include "citra_qt/bootmanager.h" | #include "citra_qt/bootmanager.h" | ||||||
| #include "common/microprofile.h" | #include "common/microprofile.h" | ||||||
| #include "common/scm_rev.h" | #include "common/scm_rev.h" | ||||||
| #include "core/3ds.h" | #include "core/3ds.h" | ||||||
| #include "core/core.h" | #include "core/core.h" | ||||||
|  | #include "core/frontend/scope_acquire_context.h" | ||||||
| #include "core/settings.h" | #include "core/settings.h" | ||||||
| #include "input_common/keyboard.h" | #include "input_common/keyboard.h" | ||||||
| #include "input_common/main.h" | #include "input_common/main.h" | ||||||
| #include "input_common/motion_emu.h" | #include "input_common/motion_emu.h" | ||||||
| #include "network/network.h" | #include "network/network.h" | ||||||
|  | #include "video_core/renderer_base.h" | ||||||
| #include "video_core/video_core.h" | #include "video_core/video_core.h" | ||||||
| 
 | 
 | ||||||
| EmuThread::EmuThread(GRenderWindow* render_window) : render_window(render_window) {} | EmuThread::EmuThread(Frontend::GraphicsContext& core_context) : core_context(core_context) {} | ||||||
| 
 | 
 | ||||||
| EmuThread::~EmuThread() = default; | EmuThread::~EmuThread() = default; | ||||||
| 
 | 
 | ||||||
| void EmuThread::run() { | void EmuThread::run() { | ||||||
|     render_window->MakeCurrent(); |  | ||||||
| 
 |  | ||||||
|     MicroProfileOnThreadCreate("EmuThread"); |     MicroProfileOnThreadCreate("EmuThread"); | ||||||
| 
 |     Frontend::ScopeAcquireContext scope(core_context); | ||||||
|     // Holds whether the cpu was running during the last iteration,
 |     // Holds whether the cpu was running during the last iteration,
 | ||||||
|     // so that the DebugModeLeft signal can be emitted before the
 |     // so that the DebugModeLeft signal can be emitted before the
 | ||||||
|     // next execution step.
 |     // next execution step.
 | ||||||
|  | @ -72,43 +74,10 @@ void EmuThread::run() { | ||||||
| #if MICROPROFILE_ENABLED | #if MICROPROFILE_ENABLED | ||||||
|     MicroProfileOnThreadExit(); |     MicroProfileOnThreadExit(); | ||||||
| #endif | #endif | ||||||
| 
 |  | ||||||
|     render_window->moveContext(); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // This class overrides paintEvent and resizeEvent to prevent the GUI thread from stealing GL
 |  | ||||||
| // context.
 |  | ||||||
| // The corresponding functionality is handled in EmuThread instead
 |  | ||||||
| class GGLWidgetInternal : public QGLWidget { |  | ||||||
| public: |  | ||||||
|     GGLWidgetInternal(QGLFormat fmt, GRenderWindow* parent) |  | ||||||
|         : QGLWidget(fmt, parent), parent(parent) {} |  | ||||||
| 
 |  | ||||||
|     void paintEvent(QPaintEvent* ev) override { |  | ||||||
|         if (do_painting) { |  | ||||||
|             QPainter painter(this); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     void resizeEvent(QResizeEvent* ev) override { |  | ||||||
|         parent->OnClientAreaResized(ev->size().width(), ev->size().height()); |  | ||||||
|         parent->OnFramebufferSizeChanged(); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     void DisablePainting() { |  | ||||||
|         do_painting = false; |  | ||||||
|     } |  | ||||||
|     void EnablePainting() { |  | ||||||
|         do_painting = true; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
| private: |  | ||||||
|     GRenderWindow* parent; |  | ||||||
|     bool do_painting; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| GRenderWindow::GRenderWindow(QWidget* parent, EmuThread* emu_thread) | GRenderWindow::GRenderWindow(QWidget* parent, EmuThread* emu_thread) | ||||||
|     : QWidget(parent), child(nullptr), emu_thread(emu_thread) { |     : QOpenGLWidget(parent), emu_thread(emu_thread) { | ||||||
| 
 | 
 | ||||||
|     setWindowTitle(QStringLiteral("Citra %1 | %2-%3") |     setWindowTitle(QStringLiteral("Citra %1 | %2-%3") | ||||||
|                        .arg(Common::g_build_name, Common::g_scm_branch, Common::g_scm_desc)); |                        .arg(Common::g_build_name, Common::g_scm_branch, Common::g_scm_desc)); | ||||||
|  | @ -121,35 +90,12 @@ GRenderWindow::~GRenderWindow() { | ||||||
|     InputCommon::Shutdown(); |     InputCommon::Shutdown(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void GRenderWindow::moveContext() { |  | ||||||
|     DoneCurrent(); |  | ||||||
| 
 |  | ||||||
|     // If the thread started running, move the GL Context to the new thread. Otherwise, move it
 |  | ||||||
|     // back.
 |  | ||||||
|     auto thread = (QThread::currentThread() == qApp->thread() && emu_thread != nullptr) |  | ||||||
|                       ? emu_thread |  | ||||||
|                       : qApp->thread(); |  | ||||||
|     child->context()->moveToThread(thread); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void GRenderWindow::SwapBuffers() { |  | ||||||
|     // In our multi-threaded QGLWidget use case we shouldn't need to call `makeCurrent`,
 |  | ||||||
|     // since we never call `doneCurrent` in this thread.
 |  | ||||||
|     // However:
 |  | ||||||
|     // - The Qt debug runtime prints a bogus warning on the console if `makeCurrent` wasn't called
 |  | ||||||
|     // since the last time `swapBuffers` was executed;
 |  | ||||||
|     // - On macOS, if `makeCurrent` isn't called explicitely, resizing the buffer breaks.
 |  | ||||||
|     child->makeCurrent(); |  | ||||||
| 
 |  | ||||||
|     child->swapBuffers(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void GRenderWindow::MakeCurrent() { | void GRenderWindow::MakeCurrent() { | ||||||
|     child->makeCurrent(); |     core_context->MakeCurrent(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void GRenderWindow::DoneCurrent() { | void GRenderWindow::DoneCurrent() { | ||||||
|     child->doneCurrent(); |     core_context->DoneCurrent(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void GRenderWindow::PollEvents() {} | void GRenderWindow::PollEvents() {} | ||||||
|  | @ -163,8 +109,8 @@ void GRenderWindow::OnFramebufferSizeChanged() { | ||||||
|     // Screen changes potentially incur a change in screen DPI, hence we should update the
 |     // Screen changes potentially incur a change in screen DPI, hence we should update the
 | ||||||
|     // framebuffer size
 |     // framebuffer size
 | ||||||
|     const qreal pixel_ratio = windowPixelRatio(); |     const qreal pixel_ratio = windowPixelRatio(); | ||||||
|     const u32 width = child->QPaintDevice::width() * pixel_ratio; |     const u32 width = this->width() * pixel_ratio; | ||||||
|     const u32 height = child->QPaintDevice::height() * pixel_ratio; |     const u32 height = this->height() * pixel_ratio; | ||||||
|     UpdateCurrentFramebufferLayout(width, height); |     UpdateCurrentFramebufferLayout(width, height); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -298,42 +244,16 @@ void GRenderWindow::focusOutEvent(QFocusEvent* event) { | ||||||
|     InputCommon::GetKeyboard()->ReleaseAllKeys(); |     InputCommon::GetKeyboard()->ReleaseAllKeys(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void GRenderWindow::OnClientAreaResized(u32 width, u32 height) { | void GRenderWindow::resizeEvent(QResizeEvent* event) { | ||||||
|     NotifyClientAreaSizeChanged(std::make_pair(width, height)); |     QOpenGLWidget::resizeEvent(event); | ||||||
|  |     NotifyClientAreaSizeChanged(std::make_pair(event->size().width(), event->size().height())); | ||||||
|  |     OnFramebufferSizeChanged(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void GRenderWindow::InitRenderTarget() { | void GRenderWindow::InitRenderTarget() { | ||||||
|     if (child) { |  | ||||||
|         delete child; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     if (layout()) { |  | ||||||
|         delete layout(); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     // TODO: One of these flags might be interesting: WA_OpaquePaintEvent, WA_NoBackground,
 |     // TODO: One of these flags might be interesting: WA_OpaquePaintEvent, WA_NoBackground,
 | ||||||
|     // WA_DontShowOnScreen, WA_DeleteOnClose
 |     // WA_DontShowOnScreen, WA_DeleteOnClose
 | ||||||
|     QGLFormat fmt; |     core_context = CreateSharedContext(); | ||||||
|     fmt.setVersion(3, 3); |  | ||||||
|     fmt.setProfile(QGLFormat::CoreProfile); |  | ||||||
|     fmt.setSwapInterval(Settings::values.vsync_enabled); |  | ||||||
| 
 |  | ||||||
|     // Requests a forward-compatible context, which is required to get a 3.2+ context on OS X
 |  | ||||||
|     fmt.setOption(QGL::NoDeprecatedFunctions); |  | ||||||
| 
 |  | ||||||
|     child = new GGLWidgetInternal(fmt, this); |  | ||||||
|     QBoxLayout* layout = new QHBoxLayout(this); |  | ||||||
| 
 |  | ||||||
|     resize(Core::kScreenTopWidth, Core::kScreenTopHeight + Core::kScreenBottomHeight); |  | ||||||
|     layout->addWidget(child); |  | ||||||
|     layout->setMargin(0); |  | ||||||
|     setLayout(layout); |  | ||||||
| 
 |  | ||||||
|     OnMinimalClientAreaChangeRequest(GetActiveConfig().min_client_area_size); |  | ||||||
| 
 |  | ||||||
|     OnFramebufferSizeChanged(); |  | ||||||
|     NotifyClientAreaSizeChanged(std::pair<unsigned, unsigned>(child->width(), child->height())); |  | ||||||
| 
 |  | ||||||
|     BackupGeometry(); |     BackupGeometry(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -361,12 +281,15 @@ void GRenderWindow::OnMinimalClientAreaChangeRequest(std::pair<u32, u32> minimal | ||||||
| 
 | 
 | ||||||
| void GRenderWindow::OnEmulationStarting(EmuThread* emu_thread) { | void GRenderWindow::OnEmulationStarting(EmuThread* emu_thread) { | ||||||
|     this->emu_thread = emu_thread; |     this->emu_thread = emu_thread; | ||||||
|     child->DisablePainting(); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void GRenderWindow::OnEmulationStopping() { | void GRenderWindow::OnEmulationStopping() { | ||||||
|     emu_thread = nullptr; |     emu_thread = nullptr; | ||||||
|     child->EnablePainting(); | } | ||||||
|  | 
 | ||||||
|  | void GRenderWindow::paintGL() { | ||||||
|  |     VideoCore::g_renderer->Present(); | ||||||
|  |     update(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void GRenderWindow::showEvent(QShowEvent* event) { | void GRenderWindow::showEvent(QShowEvent* event) { | ||||||
|  | @ -376,3 +299,24 @@ void GRenderWindow::showEvent(QShowEvent* event) { | ||||||
|     connect(windowHandle(), &QWindow::screenChanged, this, &GRenderWindow::OnFramebufferSizeChanged, |     connect(windowHandle(), &QWindow::screenChanged, this, &GRenderWindow::OnFramebufferSizeChanged, | ||||||
|             Qt::UniqueConnection); |             Qt::UniqueConnection); | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | std::unique_ptr<Frontend::GraphicsContext> GRenderWindow::CreateSharedContext() const { | ||||||
|  |     return std::make_unique<GGLContext>(QOpenGLContext::globalShareContext()); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | GGLContext::GGLContext(QOpenGLContext* shared_context) | ||||||
|  |     : context(new QOpenGLContext(shared_context->parent())), | ||||||
|  |       surface(new QOffscreenSurface(nullptr, shared_context->parent())) { | ||||||
|  |     context->setShareContext(shared_context); | ||||||
|  |     context->create(); | ||||||
|  |     surface->setFormat(shared_context->format()); | ||||||
|  |     surface->create(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void GGLContext::MakeCurrent() { | ||||||
|  |     context->makeCurrent(surface); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void GGLContext::DoneCurrent() { | ||||||
|  |     context->doneCurrent(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | @ -7,8 +7,7 @@ | ||||||
| #include <atomic> | #include <atomic> | ||||||
| #include <condition_variable> | #include <condition_variable> | ||||||
| #include <mutex> | #include <mutex> | ||||||
| #include <QGLWidget> | #include <QOpenGLWidget> | ||||||
| #include <QImage> |  | ||||||
| #include <QThread> | #include <QThread> | ||||||
| #include "common/thread.h" | #include "common/thread.h" | ||||||
| #include "core/core.h" | #include "core/core.h" | ||||||
|  | @ -17,16 +16,30 @@ | ||||||
| class QKeyEvent; | class QKeyEvent; | ||||||
| class QScreen; | class QScreen; | ||||||
| class QTouchEvent; | class QTouchEvent; | ||||||
|  | class QOffscreenSurface; | ||||||
|  | class QOpenGLContext; | ||||||
| 
 | 
 | ||||||
| class GGLWidgetInternal; |  | ||||||
| class GMainWindow; | class GMainWindow; | ||||||
| class GRenderWindow; | class GRenderWindow; | ||||||
| 
 | 
 | ||||||
|  | class GGLContext : public Frontend::GraphicsContext { | ||||||
|  | public: | ||||||
|  |     explicit GGLContext(QOpenGLContext* shared_context); | ||||||
|  | 
 | ||||||
|  |     void MakeCurrent() override; | ||||||
|  | 
 | ||||||
|  |     void DoneCurrent() override; | ||||||
|  | 
 | ||||||
|  | private: | ||||||
|  |     QOpenGLContext* context; | ||||||
|  |     QOffscreenSurface* surface; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| class EmuThread final : public QThread { | class EmuThread final : public QThread { | ||||||
|     Q_OBJECT |     Q_OBJECT | ||||||
| 
 | 
 | ||||||
| public: | public: | ||||||
|     explicit EmuThread(GRenderWindow* render_window); |     explicit EmuThread(Frontend::GraphicsContext& context); | ||||||
|     ~EmuThread() override; |     ~EmuThread() override; | ||||||
| 
 | 
 | ||||||
|     /**
 |     /**
 | ||||||
|  | @ -80,7 +93,7 @@ private: | ||||||
|     std::mutex running_mutex; |     std::mutex running_mutex; | ||||||
|     std::condition_variable running_cv; |     std::condition_variable running_cv; | ||||||
| 
 | 
 | ||||||
|     GRenderWindow* render_window; |     Frontend::GraphicsContext& core_context; | ||||||
| 
 | 
 | ||||||
| signals: | signals: | ||||||
|     /**
 |     /**
 | ||||||
|  | @ -104,18 +117,20 @@ signals: | ||||||
|     void ErrorThrown(Core::System::ResultStatus, std::string); |     void ErrorThrown(Core::System::ResultStatus, std::string); | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| class GRenderWindow : public QWidget, public Frontend::EmuWindow { | class GRenderWindow : public QOpenGLWidget, public Frontend::EmuWindow { | ||||||
|     Q_OBJECT |     Q_OBJECT | ||||||
| 
 | 
 | ||||||
| public: | public: | ||||||
|     GRenderWindow(QWidget* parent, EmuThread* emu_thread); |     GRenderWindow(QWidget* parent, EmuThread* emu_thread); | ||||||
|     ~GRenderWindow() override; |     ~GRenderWindow() override; | ||||||
| 
 | 
 | ||||||
|     // EmuWindow implementation
 |     // EmuWindow implementation.
 | ||||||
|     void SwapBuffers() override; |  | ||||||
|     void MakeCurrent() override; |     void MakeCurrent() override; | ||||||
|     void DoneCurrent() override; |     void DoneCurrent() override; | ||||||
|     void PollEvents() override; |     void PollEvents() override; | ||||||
|  |     std::unique_ptr<Frontend::GraphicsContext> CreateSharedContext() const override; | ||||||
|  | 
 | ||||||
|  |     void paintGL() override; | ||||||
| 
 | 
 | ||||||
|     void BackupGeometry(); |     void BackupGeometry(); | ||||||
|     void RestoreGeometry(); |     void RestoreGeometry(); | ||||||
|  | @ -126,6 +141,8 @@ public: | ||||||
| 
 | 
 | ||||||
|     void closeEvent(QCloseEvent* event) override; |     void closeEvent(QCloseEvent* event) override; | ||||||
| 
 | 
 | ||||||
|  |     void resizeEvent(QResizeEvent* event) override; | ||||||
|  | 
 | ||||||
|     void keyPressEvent(QKeyEvent* event) override; |     void keyPressEvent(QKeyEvent* event) override; | ||||||
|     void keyReleaseEvent(QKeyEvent* event) override; |     void keyReleaseEvent(QKeyEvent* event) override; | ||||||
| 
 | 
 | ||||||
|  | @ -137,14 +154,11 @@ public: | ||||||
| 
 | 
 | ||||||
|     void focusOutEvent(QFocusEvent* event) override; |     void focusOutEvent(QFocusEvent* event) override; | ||||||
| 
 | 
 | ||||||
|     void OnClientAreaResized(u32 width, u32 height); |  | ||||||
| 
 |  | ||||||
|     void InitRenderTarget(); |     void InitRenderTarget(); | ||||||
| 
 | 
 | ||||||
|     void CaptureScreenshot(u32 res_scale, const QString& screenshot_path); |     void CaptureScreenshot(u32 res_scale, const QString& screenshot_path); | ||||||
| 
 | 
 | ||||||
| public slots: | public slots: | ||||||
|     void moveContext(); // overridden
 |  | ||||||
| 
 | 
 | ||||||
|     void OnEmulationStarting(EmuThread* emu_thread); |     void OnEmulationStarting(EmuThread* emu_thread); | ||||||
|     void OnEmulationStopping(); |     void OnEmulationStopping(); | ||||||
|  | @ -162,7 +176,7 @@ private: | ||||||
| 
 | 
 | ||||||
|     void OnMinimalClientAreaChangeRequest(std::pair<u32, u32> minimal_size) override; |     void OnMinimalClientAreaChangeRequest(std::pair<u32, u32> minimal_size) override; | ||||||
| 
 | 
 | ||||||
|     GGLWidgetInternal* child; |     std::unique_ptr<GraphicsContext> core_context; | ||||||
| 
 | 
 | ||||||
|     QByteArray geometry; |     QByteArray geometry; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -5,12 +5,11 @@ | ||||||
| #include <clocale> | #include <clocale> | ||||||
| #include <memory> | #include <memory> | ||||||
| #include <thread> | #include <thread> | ||||||
| #include <glad/glad.h> |  | ||||||
| #define QT_NO_OPENGL |  | ||||||
| #include <QDesktopWidget> | #include <QDesktopWidget> | ||||||
| #include <QFileDialog> | #include <QFileDialog> | ||||||
| #include <QFutureWatcher> | #include <QFutureWatcher> | ||||||
| #include <QMessageBox> | #include <QMessageBox> | ||||||
|  | #include <QOpenGLFunctions_3_3_Core> | ||||||
| #include <QSysInfo> | #include <QSysInfo> | ||||||
| #include <QtConcurrent/QtConcurrentRun> | #include <QtConcurrent/QtConcurrentRun> | ||||||
| #include <QtGui> | #include <QtGui> | ||||||
|  | @ -72,6 +71,7 @@ | ||||||
| #include "core/file_sys/archive_extsavedata.h" | #include "core/file_sys/archive_extsavedata.h" | ||||||
| #include "core/file_sys/archive_source_sd_savedata.h" | #include "core/file_sys/archive_source_sd_savedata.h" | ||||||
| #include "core/frontend/applets/default_applets.h" | #include "core/frontend/applets/default_applets.h" | ||||||
|  | #include "core/frontend/scope_acquire_context.h" | ||||||
| #include "core/gdbstub/gdbstub.h" | #include "core/gdbstub/gdbstub.h" | ||||||
| #include "core/hle/service/fs/archive.h" | #include "core/hle/service/fs/archive.h" | ||||||
| #include "core/hle/service/nfc/nfc.h" | #include "core/hle/service/nfc/nfc.h" | ||||||
|  | @ -768,13 +768,14 @@ bool GMainWindow::LoadROM(const QString& filename) { | ||||||
|         ShutdownGame(); |         ShutdownGame(); | ||||||
| 
 | 
 | ||||||
|     render_window->InitRenderTarget(); |     render_window->InitRenderTarget(); | ||||||
|     render_window->MakeCurrent(); | 
 | ||||||
|  |     Frontend::ScopeAcquireContext scope(*render_window); | ||||||
| 
 | 
 | ||||||
|     const QString below_gl33_title = tr("OpenGL 3.3 Unsupported"); |     const QString below_gl33_title = tr("OpenGL 3.3 Unsupported"); | ||||||
|     const QString below_gl33_message = tr("Your GPU may not support OpenGL 3.3, or you do not " |     const QString below_gl33_message = tr("Your GPU may not support OpenGL 3.3, or you do not " | ||||||
|                                           "have the latest graphics driver."); |                                           "have the latest graphics driver."); | ||||||
| 
 | 
 | ||||||
|     if (!gladLoadGL()) { |     if (!QOpenGLContext::globalShareContext()->versionFunctions<QOpenGLFunctions_3_3_Core>()) { | ||||||
|         QMessageBox::critical(this, below_gl33_title, below_gl33_message); |         QMessageBox::critical(this, below_gl33_title, below_gl33_message); | ||||||
|         return false; |         return false; | ||||||
|     } |     } | ||||||
|  | @ -893,9 +894,8 @@ void GMainWindow::BootGame(const QString& filename) { | ||||||
|         return; |         return; | ||||||
| 
 | 
 | ||||||
|     // Create and start the emulation thread
 |     // Create and start the emulation thread
 | ||||||
|     emu_thread = std::make_unique<EmuThread>(render_window); |     emu_thread = std::make_unique<EmuThread>(*render_window); | ||||||
|     emit EmulationStarting(emu_thread.get()); |     emit EmulationStarting(emu_thread.get()); | ||||||
|     render_window->moveContext(); |  | ||||||
|     emu_thread->start(); |     emu_thread->start(); | ||||||
| 
 | 
 | ||||||
|     connect(render_window, &GRenderWindow::Closed, this, &GMainWindow::OnStopGame); |     connect(render_window, &GRenderWindow::Closed, this, &GMainWindow::OnStopGame); | ||||||
|  | @ -2050,11 +2050,20 @@ int main(int argc, char* argv[]) { | ||||||
|     QCoreApplication::setOrganizationName("Citra team"); |     QCoreApplication::setOrganizationName("Citra team"); | ||||||
|     QCoreApplication::setApplicationName("Citra"); |     QCoreApplication::setApplicationName("Citra"); | ||||||
| 
 | 
 | ||||||
|  |     QSurfaceFormat format; | ||||||
|  |     format.setVersion(3, 3); | ||||||
|  |     format.setProfile(QSurfaceFormat::CoreProfile); | ||||||
|  |     format.setSwapInterval(1); | ||||||
|  |     // TODO: expose a setting for buffer value (ie default/single/double/triple)
 | ||||||
|  |     format.setSwapBehavior(QSurfaceFormat::DefaultSwapBehavior); | ||||||
|  |     QSurfaceFormat::setDefaultFormat(format); | ||||||
|  | 
 | ||||||
| #ifdef __APPLE__ | #ifdef __APPLE__ | ||||||
|     std::string bin_path = FileUtil::GetBundleDirectory() + DIR_SEP + ".."; |     std::string bin_path = FileUtil::GetBundleDirectory() + DIR_SEP + ".."; | ||||||
|     chdir(bin_path.c_str()); |     chdir(bin_path.c_str()); | ||||||
| #endif | #endif | ||||||
| 
 |     QCoreApplication::setAttribute(Qt::AA_DontCheckOpenGLContextThreadAffinity); | ||||||
|  |     QCoreApplication::setAttribute(Qt::AA_ShareOpenGLContexts); | ||||||
|     QApplication app(argc, argv); |     QApplication app(argc, argv); | ||||||
| 
 | 
 | ||||||
|     // Qt changes the locale and causes issues in float conversion using std::to_string() when
 |     // Qt changes the locale and causes issues in float conversion using std::to_string() when
 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue