summaryrefslogtreecommitdiffstats
path: root/src/yuzu/bootmanager.cpp
diff options
context:
space:
mode:
authorJames Rowe <jroweboy@gmail.com>2019-01-12 05:06:34 +0100
committerJames Rowe <jroweboy@gmail.com>2019-01-22 00:00:01 +0100
commitc6a0ab9792390fefa816ace846e3a76a85e8b4d5 (patch)
tree5bb2281e4ca19bb6f1a809282047ddb61b0b0d63 /src/yuzu/bootmanager.cpp
parentMerge pull request #2038 from jroweboy/loading-progress-bar (diff)
downloadyuzu-c6a0ab9792390fefa816ace846e3a76a85e8b4d5.tar
yuzu-c6a0ab9792390fefa816ace846e3a76a85e8b4d5.tar.gz
yuzu-c6a0ab9792390fefa816ace846e3a76a85e8b4d5.tar.bz2
yuzu-c6a0ab9792390fefa816ace846e3a76a85e8b4d5.tar.lz
yuzu-c6a0ab9792390fefa816ace846e3a76a85e8b4d5.tar.xz
yuzu-c6a0ab9792390fefa816ace846e3a76a85e8b4d5.tar.zst
yuzu-c6a0ab9792390fefa816ace846e3a76a85e8b4d5.zip
Diffstat (limited to 'src/yuzu/bootmanager.cpp')
-rw-r--r--src/yuzu/bootmanager.cpp91
1 files changed, 72 insertions, 19 deletions
diff --git a/src/yuzu/bootmanager.cpp b/src/yuzu/bootmanager.cpp
index f74cb693a..087ee8f93 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) {