Qt: Simplify Window drawing (fixes #2190)

This commit is contained in:
Vicki Pfau 2022-06-06 17:21:02 -07:00
parent 97cb18d3fd
commit ae0c5e91aa
7 changed files with 59 additions and 70 deletions

View File

@ -57,6 +57,7 @@ Other fixes:
- Qt: Fix some hangs when using the debugger console
- Qt: Fix crash when clicking past last tile in viewer
- Qt: Fix preloading for ROM replacing
- Qt: Fix screen not displaying on Wayland (fixes mgba.io/i/2190)
- VFS: Failed file mapping should return NULL on POSIX
Misc:
- Core: Suspend runloop when a core crashes

View File

@ -56,10 +56,13 @@ uint qHash(const QSurfaceFormat& format, uint seed) {
}
void mGLWidget::initializeGL() {
m_vao.create();
m_program.create();
m_vao = std::make_unique<QOpenGLVertexArrayObject>();
m_vao->create();
m_program.addShaderFromSourceCode(QOpenGLShader::Vertex, R"(#version 150 core
m_program = std::make_unique<QOpenGLShaderProgram>();
m_program->create();
m_program->addShaderFromSourceCode(QOpenGLShader::Vertex, R"(#version 150 core
in vec4 position;
out vec2 texCoord;
void main() {
@ -67,7 +70,7 @@ void mGLWidget::initializeGL() {
texCoord = (position.st + 1.0) * 0.5;
})");
m_program.addShaderFromSourceCode(QOpenGLShader::Fragment, R"(#version 150 core
m_program->addShaderFromSourceCode(QOpenGLShader::Fragment, R"(#version 150 core
in vec2 texCoord;
out vec4 color;
uniform sampler2D tex;
@ -75,9 +78,9 @@ void mGLWidget::initializeGL() {
color = vec4(texture(tex, texCoord).rgb, 1.0);
})");
m_program.link();
m_program.setUniformValue("tex", 0);
m_positionLocation = m_program.attributeLocation("position");
m_program->link();
m_program->setUniformValue("tex", 0);
m_positionLocation = m_program->attributeLocation("position");
connect(&m_refresh, &QTimer::timeout, this, static_cast<void (QWidget::*)()>(&QWidget::update));
}
@ -85,11 +88,11 @@ void mGLWidget::initializeGL() {
void mGLWidget::finalizeVAO() {
QOpenGLFunctions_Baseline* fn = context()->versionFunctions<QOpenGLFunctions_Baseline>();
fn->glGetError(); // Clear the error
m_vao.bind();
m_vao->bind();
fn->glBindBuffer(GL_ARRAY_BUFFER, m_vbo);
fn->glEnableVertexAttribArray(m_positionLocation);
fn->glVertexAttribPointer(m_positionLocation, 2, GL_FLOAT, GL_FALSE, 0, NULL);
m_vao.release();
m_vao->release();
if (fn->glGetError() == GL_NO_ERROR) {
m_vaoDone = true;
}
@ -100,13 +103,13 @@ void mGLWidget::paintGL() {
finalizeVAO();
}
QOpenGLFunctions_Baseline* fn = context()->versionFunctions<QOpenGLFunctions_Baseline>();
m_program.bind();
m_vao.bind();
m_program->bind();
m_vao->bind();
fn->glBindTexture(GL_TEXTURE_2D, m_tex);
fn->glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
fn->glBindTexture(GL_TEXTURE_2D, 0);
m_vao.release();
m_program.release();
m_vao->release();
m_program->release();
// TODO: Better timing
++m_refreshResidue;

View File

@ -32,6 +32,7 @@
#include <QTimer>
#include <array>
#include <memory>
#include "CoreController.h"
#include "VideoProxy.h"
@ -62,8 +63,8 @@ private:
GLuint m_vbo;
bool m_vaoDone = false;
QOpenGLVertexArrayObject m_vao;
QOpenGLShaderProgram m_program;
std::unique_ptr<QOpenGLVertexArrayObject> m_vao;
std::unique_ptr<QOpenGLShaderProgram> m_program;
GLuint m_positionLocation;
QTimer m_refresh;

View File

@ -9,6 +9,7 @@
#include "GamepadAxisEvent.h"
#include "GamepadButtonEvent.h"
#include "VFileDevice.h"
#include "utils.h"
#include <QAction>
#include <QDateTime>
@ -251,6 +252,10 @@ void LoadSaveState::focusInEvent(QFocusEvent*) {
void LoadSaveState::paintEvent(QPaintEvent*) {
QPainter painter(this);
painter.setRenderHint(QPainter::SmoothPixmapTransform, true);
QRect full(QPoint(), size());
painter.fillRect(full, Qt::black);
painter.drawPixmap(clampSize(m_dims, size(), m_lockAspectRatio, m_lockIntegerScaling), m_background);
painter.fillRect(full, QColor(0, 0, 0, 128));
}

View File

@ -32,6 +32,10 @@ public:
void setInputController(InputController* controller);
void setMode(LoadSave mode);
void setBackground(const QPixmap& pixmap) { m_background = pixmap; }
void setDimensions(const QSize& dims) { m_dims = dims; }
void setLockIntegerScaling(bool lockIntegerScaling) { m_lockIntegerScaling = lockIntegerScaling; }
void setLockAspectRatio(bool lockApsectRatio) { m_lockAspectRatio = lockApsectRatio; }
signals:
void closed();
@ -54,6 +58,11 @@ private:
int m_currentFocus;
QPixmap m_currentImage;
QPixmap m_background;
QSize m_dims;
bool m_lockAspectRatio;
bool m_lockIntegerScaling;
};
}

View File

@ -12,7 +12,6 @@
#include <QMimeData>
#include <QPainter>
#include <QScreen>
#include <QStackedLayout>
#include <QWindow>
#ifdef USE_SQLITE3
@ -58,7 +57,6 @@
#include "TileView.h"
#include "VideoProxy.h"
#include "VideoView.h"
#include "utils.h"
#ifdef USE_DISCORD_RPC
#include "DiscordCoordinator.h"
@ -113,14 +111,12 @@ Window::Window(CoreManager* manager, ConfigController* config, int playerId, QWi
m_libraryView = new LibraryController(nullptr, ConfigController::configDir() + "/library.sqlite3", m_config);
ConfigOption* showLibrary = m_config->addOption("showLibrary");
showLibrary->connect([this](const QVariant& value) {
if (value.toBool()) {
if (m_controller) {
m_screenWidget->layout()->addWidget(m_libraryView);
} else {
if (!m_controller) {
if (value.toBool()) {
attachWidget(m_libraryView);
} else {
attachWidget(m_screenWidget);
}
} else {
detachWidget(m_libraryView);
}
}, this);
m_config->updateOption("showLibrary");
@ -150,7 +146,6 @@ Window::Window(CoreManager* manager, ConfigController* config, int playerId, QWi
resizeFrame(QSize(GB_VIDEO_HORIZONTAL_PIXELS * i, GB_VIDEO_VERTICAL_PIXELS * i));
#endif
setLogo();
setCentralWidget(m_screenWidget);
connect(this, &Window::shutdown, m_logView, &QWidget::hide);
connect(&m_fpsTimer, &QTimer::timeout, this, &Window::showFPS);
@ -883,7 +878,6 @@ void Window::gameStarted() {
action.value()->setEnabled(m_controller->platform() == action.key());
}
QSize size = m_controller->screenDimensions();
m_screenWidget->setDimensions(size.width(), size.height());
m_config->updateOption("lockIntegerScaling");
m_config->updateOption("lockAspectRatio");
m_config->updateOption("interframeBlending");
@ -977,7 +971,6 @@ void Window::gameStopped() {
m_audioProcessor.reset();
}
m_display->stopDrawing();
detachWidget(m_display.get());
setLogo();
if (m_display) {
#ifdef M_CORE_GB
@ -988,6 +981,7 @@ void Window::gameStopped() {
}
m_controller.reset();
detachWidget();
updateTitle();
if (m_pendingClose) {
@ -1039,7 +1033,7 @@ void Window::unimplementedBiosCall(int) {
void Window::reloadDisplayDriver() {
if (m_controller) {
m_display->stopDrawing();
detachWidget(m_display.get());
detachWidget();
}
m_display = std::unique_ptr<QGBA::Display>(Display::create(this));
if (!m_display) {
@ -1054,7 +1048,7 @@ void Window::reloadDisplayDriver() {
#endif
connect(m_display.get(), &QGBA::Display::hideCursor, [this]() {
if (static_cast<QStackedLayout*>(m_screenWidget->layout())->currentWidget() == m_display.get()) {
if (centralWidget() == m_display.get()) {
m_screenWidget->setCursor(Qt::BlankCursor);
}
});
@ -1215,15 +1209,13 @@ void Window::openStateWindow(LoadSave ls) {
m_stateWindow = new LoadSaveState(m_controller);
connect(this, &Window::shutdown, m_stateWindow, &QWidget::close);
connect(m_stateWindow, &LoadSaveState::closed, [this]() {
detachWidget(m_stateWindow);
static_cast<QStackedLayout*>(m_screenWidget->layout())->setCurrentWidget(m_display.get());
attachWidget(m_display.get());
m_stateWindow = nullptr;
QMetaObject::invokeMethod(this, "setFocus", Qt::QueuedConnection);
});
if (!wasPaused) {
m_controller->setPaused(true);
connect(m_stateWindow, &LoadSaveState::closed, [this]() {
m_screenWidget->filter(m_config->getOption("resampleVideo").toInt());
if (m_controller) {
m_controller->setPaused(false);
}
@ -1232,6 +1224,10 @@ void Window::openStateWindow(LoadSave ls) {
m_stateWindow->setAttribute(Qt::WA_DeleteOnClose);
m_stateWindow->setMode(ls);
m_stateWindow->setDimensions(m_controller->screenDimensions());
m_config->updateOption("lockAspectRatio");
m_config->updateOption("lockIntegerScaling");
QImage still(m_controller->getPixels());
if (still.format() != QImage::Format_RGB888) {
still = still.convertToFormat(QImage::Format_RGB888);
@ -1249,8 +1245,7 @@ void Window::openStateWindow(LoadSave ls) {
QPixmap pixmap;
pixmap.convertFromImage(output);
m_screenWidget->setPixmap(pixmap);
m_screenWidget->filter(true);
m_stateWindow->setBackground(pixmap);
#ifndef Q_OS_MAC
menuBar()->show();
@ -1536,8 +1531,8 @@ void Window::setupMenu(QMenuBar* menubar) {
if (m_display) {
m_display->lockAspectRatio(value.toBool());
}
if (m_controller) {
m_screenWidget->setLockAspectRatio(value.toBool());
if (m_stateWindow) {
m_stateWindow->setLockAspectRatio(value.toBool());
}
}, this);
m_config->updateOption("lockAspectRatio");
@ -1548,8 +1543,8 @@ void Window::setupMenu(QMenuBar* menubar) {
if (m_display) {
m_display->lockIntegerScaling(value.toBool());
}
if (m_controller) {
m_screenWidget->setLockIntegerScaling(value.toBool());
if (m_stateWindow) {
m_stateWindow->setLockIntegerScaling(value.toBool());
}
}, this);
m_config->updateOption("lockIntegerScaling");
@ -1569,9 +1564,6 @@ void Window::setupMenu(QMenuBar* menubar) {
if (m_display) {
m_display->filter(value.toBool());
}
if (m_controller) {
m_screenWidget->filter(value.toBool());
}
}, this);
m_config->updateOption("resampleVideo");
@ -1894,13 +1886,12 @@ void Window::setupOptions() {
}
void Window::attachWidget(QWidget* widget) {
m_screenWidget->layout()->addWidget(widget);
m_screenWidget->unsetCursor();
static_cast<QStackedLayout*>(m_screenWidget->layout())->setCurrentWidget(widget);
takeCentralWidget();
setCentralWidget(widget);
}
void Window::detachWidget(QWidget* widget) {
m_screenWidget->layout()->removeWidget(widget);
void Window::detachWidget() {
m_config->updateOption("showLibrary");
}
void Window::appendMRU(const QString& fname) {
@ -1996,7 +1987,7 @@ void Window::focusCheck() {
}
void Window::updateFrame() {
if (static_cast<QStackedLayout*>(m_screenWidget->layout())->currentWidget() != m_display.get()) {
if (!m_controller) {
return;
}
QPixmap pixmap;
@ -2171,17 +2162,12 @@ void Window::updateMute() {
void Window::setLogo() {
m_screenWidget->setPixmap(m_logo);
m_screenWidget->setDimensions(m_logo.width(), m_logo.height());
m_screenWidget->setLockIntegerScaling(false);
m_screenWidget->setLockAspectRatio(true);
m_screenWidget->filter(true);
m_screenWidget->unsetCursor();
}
WindowBackground::WindowBackground(QWidget* parent)
: QWidget(parent)
{
setLayout(new QStackedLayout());
layout()->setContentsMargins(0, 0, 0, 0);
}
void WindowBackground::setPixmap(const QPixmap& pmap) {
@ -2202,24 +2188,12 @@ void WindowBackground::setDimensions(int width, int height) {
m_aspectHeight = height;
}
void WindowBackground::setLockIntegerScaling(bool lock) {
m_lockIntegerScaling = lock;
}
void WindowBackground::setLockAspectRatio(bool lock) {
m_lockAspectRatio = lock;
}
void WindowBackground::filter(bool filter) {
m_filter = filter;
}
void WindowBackground::paintEvent(QPaintEvent* event) {
QWidget::paintEvent(event);
const QPixmap& logo = pixmap();
QPainter painter(this);
painter.setRenderHint(QPainter::SmoothPixmapTransform, m_filter);
painter.setRenderHint(QPainter::SmoothPixmapTransform, true);
painter.fillRect(QRect(QPoint(), size()), Qt::black);
QRect full(clampSize(QSize(m_aspectWidth, m_aspectHeight), size(), m_lockAspectRatio, m_lockIntegerScaling));
QRect full(clampSize(QSize(m_aspectWidth, m_aspectHeight), size(), true, false));
painter.drawPixmap(full, logo);
}

View File

@ -167,7 +167,7 @@ private:
void openStateWindow(LoadSave);
void attachWidget(QWidget* widget);
void detachWidget(QWidget* widget);
void detachWidget();
void appendMRU(const QString& fname);
void clearMRU();
@ -277,7 +277,6 @@ public:
void setDimensions(int width, int height);
void setLockIntegerScaling(bool lock);
void setLockAspectRatio(bool lock);
void filter(bool filter);
const QPixmap& pixmap() const { return m_pixmap; }
@ -289,9 +288,6 @@ private:
QSize m_sizeHint;
int m_aspectWidth;
int m_aspectHeight;
bool m_lockAspectRatio;
bool m_lockIntegerScaling;
bool m_filter;
};
}