Qt: Pre-render messages for improved speed

This commit is contained in:
Jeffrey Pfau 2015-07-02 23:19:29 -07:00
parent 7395d47a5a
commit 5b3fd879b4
4 changed files with 53 additions and 20 deletions

View File

@ -52,12 +52,12 @@ Display::Display(QWidget* parent)
} }
void Display::resizeEvent(QResizeEvent*) { void Display::resizeEvent(QResizeEvent*) {
m_messagePainter.resize(size(), m_lockAspectRatio); m_messagePainter.resize(size(), m_lockAspectRatio, devicePixelRatio());
} }
void Display::lockAspectRatio(bool lock) { void Display::lockAspectRatio(bool lock) {
m_lockAspectRatio = lock; m_lockAspectRatio = lock;
m_messagePainter.resize(size(), m_lockAspectRatio); m_messagePainter.resize(size(), m_lockAspectRatio, devicePixelRatio());
} }
void Display::filter(bool filter) { void Display::filter(bool filter) {

View File

@ -47,6 +47,7 @@ void DisplayGL::startDrawing(GBAThread* thread) {
lockAspectRatio(isAspectRatioLocked()); lockAspectRatio(isAspectRatioLocked());
filter(isFiltered()); filter(isFiltered());
messagePainter()->resize(size(), isAspectRatioLocked(), devicePixelRatio());
resizePainter(); resizePainter();
} }

View File

@ -7,6 +7,8 @@
#include <QPainter> #include <QPainter>
#include <QDebug>
extern "C" { extern "C" {
#include "gba/video.h" #include "gba/video.h"
} }
@ -16,6 +18,7 @@ using namespace QGBA;
MessagePainter::MessagePainter(QObject* parent) MessagePainter::MessagePainter(QObject* parent)
: QObject(parent) : QObject(parent)
, m_messageTimer(this) , m_messageTimer(this)
, m_scaleFactor(1)
{ {
m_messageFont.setFamily("Source Code Pro"); m_messageFont.setFamily("Source Code Pro");
m_messageFont.setStyleHint(QFont::Monospace); m_messageFont.setStyleHint(QFont::Monospace);
@ -27,7 +30,7 @@ MessagePainter::MessagePainter(QObject* parent)
clearMessage(); clearMessage();
} }
void MessagePainter::resize(const QSize& size, bool lockAspectRatio) { void MessagePainter::resize(const QSize& size, bool lockAspectRatio, qreal scaleFactor) {
int w = size.width(); int w = size.width();
int h = size.height(); int h = size.height();
int drawW = w; int drawW = w;
@ -40,42 +43,63 @@ void MessagePainter::resize(const QSize& size, bool lockAspectRatio) {
} }
} }
m_world.reset(); m_world.reset();
m_world.translate((w - drawW) / 2, (h - drawH) / 2);
m_world.scale(qreal(drawW) / VIDEO_HORIZONTAL_PIXELS, qreal(drawH) / VIDEO_VERTICAL_PIXELS); m_world.scale(qreal(drawW) / VIDEO_HORIZONTAL_PIXELS, qreal(drawH) / VIDEO_VERTICAL_PIXELS);
m_scaleFactor = scaleFactor;
m_local = QPoint(1, VIDEO_VERTICAL_PIXELS - m_messageFont.pixelSize() - 1);
m_local = m_world.map(m_local);
m_local += QPoint((w - drawW) / 2, (h - drawH) / 2);
m_pixmapBuffer = QPixmap(drawW * m_scaleFactor,
(m_messageFont.pixelSize() + 2) * m_world.m22() * m_scaleFactor);
m_pixmapBuffer.setDevicePixelRatio(m_scaleFactor);
m_mutex.lock(); m_mutex.lock();
m_message.prepare(m_world, m_messageFont); m_message.prepare(m_world, m_messageFont);
redraw();
m_mutex.unlock(); m_mutex.unlock();
} }
void MessagePainter::paint(QPainter* painter) { void MessagePainter::redraw() {
painter->setWorldTransform(m_world); m_pixmapBuffer.fill(Qt::transparent);
painter->setRenderHint(QPainter::Antialiasing); if (m_message.text().isEmpty()) {
painter->setFont(m_messageFont); m_pixmap = m_pixmapBuffer;
painter->setPen(Qt::black); m_pixmap.setDevicePixelRatio(m_scaleFactor);
painter->translate(1, VIDEO_VERTICAL_PIXELS - m_messageFont.pixelSize() - 1); return;
m_mutex.lock(); }
QPainter painter(&m_pixmapBuffer);
painter.setWorldTransform(m_world);
painter.setRenderHint(QPainter::Antialiasing);
painter.setFont(m_messageFont);
painter.setPen(Qt::black);
const static int ITERATIONS = 11; const static int ITERATIONS = 11;
for (int i = 0; i < ITERATIONS; ++i) { for (int i = 0; i < ITERATIONS; ++i) {
painter->save(); painter.save();
painter->translate(cos(i * 2.0 * M_PI / ITERATIONS) * 0.8, sin(i * 2.0 * M_PI / ITERATIONS) * 0.8); painter.translate(cos(i * 2.0 * M_PI / ITERATIONS) * 0.8, sin(i * 2.0 * M_PI / ITERATIONS) * 0.8);
painter->drawStaticText(0, 0, m_message); painter.drawStaticText(0, 0, m_message);
painter->restore(); painter.restore();
} }
painter->setPen(Qt::white); painter.setPen(Qt::white);
painter->drawStaticText(0, 0, m_message); painter.drawStaticText(0, 0, m_message);
m_mutex.unlock(); m_pixmap = m_pixmapBuffer;
m_pixmap.setDevicePixelRatio(m_scaleFactor);
} }
void MessagePainter::paint(QPainter* painter) {
painter->drawPixmap(m_local, m_pixmap);
}
void MessagePainter::showMessage(const QString& message) { void MessagePainter::showMessage(const QString& message) {
m_mutex.lock(); m_mutex.lock();
m_message.setText(message); m_message.setText(message);
m_message.prepare(m_world, m_messageFont); redraw();
m_mutex.unlock(); m_mutex.unlock();
m_messageTimer.stop(); m_messageTimer.stop();
m_messageTimer.start(); m_messageTimer.start();
} }
void MessagePainter::clearMessage() { void MessagePainter::clearMessage() {
m_mutex.lock();
m_message.setText(QString()); m_message.setText(QString());
redraw();
m_mutex.unlock();
m_messageTimer.stop(); m_messageTimer.stop();
} }

View File

@ -8,6 +8,7 @@
#include <QMutex> #include <QMutex>
#include <QObject> #include <QObject>
#include <QPixmap>
#include <QStaticText> #include <QStaticText>
#include <QTimer> #include <QTimer>
@ -19,19 +20,26 @@ Q_OBJECT
public: public:
MessagePainter(QObject* parent = nullptr); MessagePainter(QObject* parent = nullptr);
void resize(const QSize& size, bool lockAspectRatio); void resize(const QSize& size, bool lockAspectRatio, qreal scaleFactor);
void paint(QPainter* painter); void paint(QPainter* painter);
void setScaleFactor(qreal factor);
public slots: public slots:
void showMessage(const QString& message); void showMessage(const QString& message);
void clearMessage(); void clearMessage();
private: private:
void redraw();
QMutex m_mutex; QMutex m_mutex;
QStaticText m_message; QStaticText m_message;
QPixmap m_pixmap;
QPixmap m_pixmapBuffer;
QTimer m_messageTimer; QTimer m_messageTimer;
QPoint m_local;
QTransform m_world; QTransform m_world;
QFont m_messageFont; QFont m_messageFont;
qreal m_scaleFactor;
}; };
} }