diff options
author | James Rowe <jroweboy@gmail.com> | 2019-01-11 21:06:34 -0700 |
---|---|---|
committer | James Rowe <jroweboy@gmail.com> | 2019-01-21 16:00:01 -0700 |
commit | c6a0ab9792390fefa816ace846e3a76a85e8b4d5 (patch) | |
tree | 5bb2281e4ca19bb6f1a809282047ddb61b0b0d63 /src/yuzu/bootmanager.cpp | |
parent | 125599c2d51fba0bb9466d92382631ed7f34bed9 (diff) |
QT Frontend: Migrate to QOpenGLWindow
Diffstat (limited to 'src/yuzu/bootmanager.cpp')
-rw-r--r-- | src/yuzu/bootmanager.cpp | 91 |
1 files changed, 72 insertions, 19 deletions
diff --git a/src/yuzu/bootmanager.cpp b/src/yuzu/bootmanager.cpp index f74cb693a4..087ee8f93b 100644 --- a/src/yuzu/bootmanager.cpp +++ b/src/yuzu/bootmanager.cpp @@ -1,6 +1,13 @@ +// Copyright 2014 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + #include <QApplication> #include <QHBoxLayout> #include <QKeyEvent> +#include <QOffscreenSurface> +#include <QOpenGLWindow> +#include <QPainter> #include <QScreen> #include <QWindow> #include <fmt/format.h> @@ -73,13 +80,36 @@ void EmuThread::run() { render_window->moveContext(); } +class GGLContext : public Core::Frontend::GraphicsContext { +public: + explicit GGLContext(QOpenGLContext* shared_context) : surface() { + context = std::make_unique<QOpenGLContext>(shared_context); + surface.setFormat(shared_context->format()); + surface.create(); + } + + void MakeCurrent() override { + context->makeCurrent(&surface); + } + + void DoneCurrent() override { + context->doneCurrent(); + } + + void SwapBuffers() override {} + +private: + std::unique_ptr<QOpenGLContext> context; + QOffscreenSurface surface; +}; + // 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 { +class GGLWidgetInternal : public QOpenGLWindow { public: - GGLWidgetInternal(QGLFormat fmt, GRenderWindow* parent) - : QGLWidget(fmt, parent), parent(parent) {} + GGLWidgetInternal(GRenderWindow* parent, QOpenGLContext* shared_context) + : QOpenGLWindow(shared_context), parent(parent) {} void paintEvent(QPaintEvent* ev) override { if (do_painting) { @@ -105,7 +135,7 @@ private: }; GRenderWindow::GRenderWindow(QWidget* parent, EmuThread* emu_thread) - : QWidget(parent), child(nullptr), emu_thread(emu_thread) { + : QWidget(parent), child(nullptr), context(nullptr), emu_thread(emu_thread) { setWindowTitle(QStringLiteral("yuzu %1 | %2-%3") .arg(Common::g_build_name, Common::g_scm_branch, Common::g_scm_desc)); @@ -129,19 +159,19 @@ void GRenderWindow::moveContext() { auto thread = (QThread::currentThread() == qApp->thread() && emu_thread != nullptr) ? emu_thread : qApp->thread(); - child->context()->moveToThread(thread); + context->moveToThread(thread); } void GRenderWindow::SwapBuffers() { - // In our multi-threaded QGLWidget use case we shouldn't need to call `makeCurrent`, + // In our multi-threaded QWidget 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(); + context->makeCurrent(child); - child->swapBuffers(); + context->swapBuffers(child); if (!first_frame) { emit FirstFrameDisplayed(); first_frame = true; @@ -149,11 +179,11 @@ void GRenderWindow::SwapBuffers() { } void GRenderWindow::MakeCurrent() { - child->makeCurrent(); + context->makeCurrent(child); } void GRenderWindow::DoneCurrent() { - child->doneCurrent(); + context->doneCurrent(); } void GRenderWindow::PollEvents() {} @@ -173,7 +203,7 @@ void GRenderWindow::OnFramebufferSizeChanged() { } void GRenderWindow::BackupGeometry() { - geometry = ((QGLWidget*)this)->saveGeometry(); + geometry = ((QWidget*)this)->saveGeometry(); } void GRenderWindow::RestoreGeometry() { @@ -191,7 +221,7 @@ QByteArray GRenderWindow::saveGeometry() { // If we are a top-level widget, store the current geometry // otherwise, store the last backup if (parent() == nullptr) - return ((QGLWidget*)this)->saveGeometry(); + return ((QWidget*)this)->saveGeometry(); else return geometry; } @@ -305,7 +335,19 @@ void GRenderWindow::OnClientAreaResized(unsigned width, unsigned height) { NotifyClientAreaSizeChanged(std::make_pair(width, height)); } +std::unique_ptr<Core::Frontend::GraphicsContext> GRenderWindow::CreateSharedContext() const { + return std::make_unique<GGLContext>(shared_context.get()); +} + void GRenderWindow::InitRenderTarget() { + if (shared_context) { + shared_context.reset(); + } + + if (context) { + context.reset(); + } + if (child) { delete child; } @@ -318,19 +360,28 @@ void GRenderWindow::InitRenderTarget() { // TODO: One of these flags might be interesting: WA_OpaquePaintEvent, WA_NoBackground, // WA_DontShowOnScreen, WA_DeleteOnClose - QGLFormat fmt; + QSurfaceFormat fmt; fmt.setVersion(4, 3); - fmt.setProfile(QGLFormat::CoreProfile); + fmt.setProfile(QSurfaceFormat::CoreProfile); + // TODO: expose a setting for buffer value (ie default/single/double/triple) + fmt.setSwapBehavior(QSurfaceFormat::DefaultSwapBehavior); + shared_context = std::make_unique<QOpenGLContext>(); + shared_context->setFormat(fmt); + shared_context->create(); + context = std::make_unique<QOpenGLContext>(); + context->setShareContext(shared_context.get()); + context->setFormat(fmt); + context->create(); fmt.setSwapInterval(false); - // 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); + child = new GGLWidgetInternal(this, shared_context.get()); + QWidget* container = QWidget::createWindowContainer(child, this); QBoxLayout* layout = new QHBoxLayout(this); resize(Layout::ScreenUndocked::Width, Layout::ScreenUndocked::Height); - layout->addWidget(child); + child->resize(Layout::ScreenUndocked::Width, Layout::ScreenUndocked::Height); + container->resize(Layout::ScreenUndocked::Width, Layout::ScreenUndocked::Height); + layout->addWidget(container); layout->setMargin(0); setLayout(layout); @@ -340,6 +391,8 @@ void GRenderWindow::InitRenderTarget() { NotifyClientAreaSizeChanged(std::pair<unsigned, unsigned>(child->width(), child->height())); BackupGeometry(); + // show causes the window to actually be created and the gl context as well + show(); } void GRenderWindow::CaptureScreenshot(u16 res_scale, const QString& screenshot_path) { |