From 67a0f7a85fb434415c18a60afbe0e7e776e3b117 Mon Sep 17 00:00:00 2001 From: Cacodemon345 Date: Tue, 21 Dec 2021 16:38:13 +0600 Subject: [PATCH] Blitting improvements * Use a single QImage copy for actual drawing * Use std::array and std::unique_ptr for image buffers * Signal immediately after copying the buffer to internal image --- src/qt/qt_hardwarerenderer.cpp | 6 +++--- src/qt/qt_hardwarerenderer.hpp | 2 +- src/qt/qt_mainwindow.cpp | 4 +--- src/qt/qt_renderercomon.cpp | 3 --- src/qt/qt_renderercomon.hpp | 2 +- src/qt/qt_rendererstack.cpp | 9 ++++----- src/qt/qt_rendererstack.hpp | 8 +++----- src/qt/qt_softwarerenderer.cpp | 6 +++--- src/qt/qt_softwarerenderer.hpp | 2 +- 9 files changed, 17 insertions(+), 25 deletions(-) diff --git a/src/qt/qt_hardwarerenderer.cpp b/src/qt/qt_hardwarerenderer.cpp index 077021a24..4c491495f 100644 --- a/src/qt/qt_hardwarerenderer.cpp +++ b/src/qt/qt_hardwarerenderer.cpp @@ -35,11 +35,11 @@ void HardwareRenderer::setRenderType(RenderType type) { setFormat(format); } -void HardwareRenderer::onBlit(const QImage& img, int x, int y, int w, int h, std::atomic_flag* in_use) { - image = img; +void HardwareRenderer::onBlit(const std::unique_ptr* img, int x, int y, int w, int h, std::atomic_flag* in_use) { + memcpy(image.bits(), img->get(), 2048 * 2048 * 4); + in_use->clear(); source.setRect(x, y, w, h); update(); - in_use->clear(); } void HardwareRenderer::resizeEvent(QResizeEvent *event) { diff --git a/src/qt/qt_hardwarerenderer.hpp b/src/qt/qt_hardwarerenderer.hpp index 0068eb7dc..3c8fb3110 100644 --- a/src/qt/qt_hardwarerenderer.hpp +++ b/src/qt/qt_hardwarerenderer.hpp @@ -47,7 +47,7 @@ public: void setRenderType(RenderType type); public slots: - void onBlit(const QImage& img, int, int, int, int, std::atomic_flag* in_use); + void onBlit(const std::unique_ptr* img, int, int, int, int, std::atomic_flag* in_use); protected: void resizeEvent(QResizeEvent *event) override; diff --git a/src/qt/qt_mainwindow.cpp b/src/qt/qt_mainwindow.cpp index a02ed77d6..8e4dcc1de 100644 --- a/src/qt/qt_mainwindow.cpp +++ b/src/qt/qt_mainwindow.cpp @@ -901,9 +901,7 @@ void MainWindow::on_actionFullscreen_triggered() { video_fullscreen = 1; } - auto widget = ui->stackedWidget->currentWidget(); - auto rc = dynamic_cast(widget); - rc->onResize(widget->width(), widget->height()); + ui->stackedWidget->switchRenderer((RendererStack::Renderer)vid_api); } void MainWindow::getTitle_(wchar_t *title) diff --git a/src/qt/qt_renderercomon.cpp b/src/qt/qt_renderercomon.cpp index 8c1b89aeb..144bb88af 100644 --- a/src/qt/qt_renderercomon.cpp +++ b/src/qt/qt_renderercomon.cpp @@ -18,9 +18,6 @@ void RendererCommon::onPaint(QPaintDevice* device) { painter.fillRect(0, 0, device->width(), device->height(), QColorConstants::Black); painter.setCompositionMode(QPainter::CompositionMode_Plus); painter.drawImage(destination, image, source); - // "release" image, reducing it's refcount, so renderstack::blit() - // won't have to reallocate - image = QImage(); } static void integer_scale(double *d, double *g) { diff --git a/src/qt/qt_renderercomon.hpp b/src/qt/qt_renderercomon.hpp index 6eed9c9b2..8cad5f92c 100644 --- a/src/qt/qt_renderercomon.hpp +++ b/src/qt/qt_renderercomon.hpp @@ -14,6 +14,6 @@ public: protected: void onPaint(QPaintDevice* device); - QImage image; + QImage image{QSize(2048, 2048), QImage::Format_RGB32}; QRect source, destination; }; diff --git a/src/qt/qt_rendererstack.cpp b/src/qt/qt_rendererstack.cpp index 72d79fae6..15ab840d1 100644 --- a/src/qt/qt_rendererstack.cpp +++ b/src/qt/qt_rendererstack.cpp @@ -24,9 +24,8 @@ RendererStack::RendererStack(QWidget *parent) : ui(new Ui::RendererStack) { ui->setupUi(this); - imagebufs = QVector(2); - imagebufs[0] = QImage{QSize(2048, 2048), QImage::Format_RGB32}; - imagebufs[1] = QImage{QSize(2048, 2048), QImage::Format_RGB32}; + imagebufs[0].reset(new uint8_t[2048 * 2048 * 4]); + imagebufs[1].reset(new uint8_t[2048 * 2048 * 4]); buffers_in_use = std::vector(2); buffers_in_use[0].clear(); @@ -222,7 +221,7 @@ void RendererStack::blit(int x, int y, int w, int h) sy = y; sw = this->w = w; sh = this->h = h; - auto imagebits = imagebufs[currentBuf].bits(); + auto imagebits = imagebufs[currentBuf].get(); video_copy(imagebits + y * (2048 * 4) + x * 4, &(buffer32->line[y][x]), h * 2048 * sizeof(uint32_t)); if (screenshots) @@ -230,6 +229,6 @@ void RendererStack::blit(int x, int y, int w, int h) video_screenshot((uint32_t *)imagebits, 0, 0, 2048); } video_blit_complete(); - blitToRenderer(imagebufs[currentBuf], sx, sy, sw, sh, &buffers_in_use[currentBuf]); + blitToRenderer(&imagebufs[currentBuf], sx, sy, sw, sh, &buffers_in_use[currentBuf]); currentBuf = (currentBuf + 1) % 2; } diff --git a/src/qt/qt_rendererstack.hpp b/src/qt/qt_rendererstack.hpp index 2d987aa1e..a512fb7e1 100644 --- a/src/qt/qt_rendererstack.hpp +++ b/src/qt/qt_rendererstack.hpp @@ -7,6 +7,7 @@ #include #include #include +#include namespace Ui { class RendererStack; @@ -42,7 +43,7 @@ public: void switchRenderer(Renderer renderer); signals: - void blitToRenderer(const QImage& img, int, int, int, int, std::atomic_flag* in_use); + void blitToRenderer(const std::unique_ptr* img, int, int, int, int, std::atomic_flag* in_use); public slots: void blit(int x, int y, int w, int h); @@ -59,11 +60,8 @@ private: int x, y, w, h, sx, sy, sw, sh; - // always have a qimage available for writing, which is _probably_ unused - // worst case - it will just get reallocated because it's refcounter is > 1 - // when calling bits(); int currentBuf = 0; - QVector imagebufs; + std::array, 2> imagebufs; std::unique_ptr current; diff --git a/src/qt/qt_softwarerenderer.cpp b/src/qt/qt_softwarerenderer.cpp index b424c8bad..9a64fe043 100644 --- a/src/qt/qt_softwarerenderer.cpp +++ b/src/qt/qt_softwarerenderer.cpp @@ -7,11 +7,11 @@ void SoftwareRenderer::paintEvent(QPaintEvent *event) { onPaint(this); } -void SoftwareRenderer::onBlit(const QImage& img, int x, int y, int w, int h, std::atomic_flag* in_use) { - image = img; +void SoftwareRenderer::onBlit(const std::unique_ptr* img, int x, int y, int w, int h, std::atomic_flag* in_use) { + memcpy(image.bits(), img->get(), 2048 * 2048 * 4); + in_use->clear(); source.setRect(x, y, w, h); update(); - in_use->clear(); } void SoftwareRenderer::resizeEvent(QResizeEvent *event) { diff --git a/src/qt/qt_softwarerenderer.hpp b/src/qt/qt_softwarerenderer.hpp index 1e37f65d4..c30303cc5 100644 --- a/src/qt/qt_softwarerenderer.hpp +++ b/src/qt/qt_softwarerenderer.hpp @@ -13,7 +13,7 @@ public: void paintEvent(QPaintEvent *event) override; public slots: - void onBlit(const QImage& img, int, int, int, int, std::atomic_flag* in_use); + void onBlit(const std::unique_ptr* img, int, int, int, int, std::atomic_flag* in_use); protected: void resizeEvent(QResizeEvent *event) override;