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
This commit is contained in:
Cacodemon345
2021-12-21 16:38:13 +06:00
parent bbb0b38d31
commit 67a0f7a85f
9 changed files with 17 additions and 25 deletions

View File

@@ -35,11 +35,11 @@ void HardwareRenderer::setRenderType(RenderType type) {
setFormat(format); setFormat(format);
} }
void HardwareRenderer::onBlit(const QImage& img, int x, int y, int w, int h, std::atomic_flag* in_use) { void HardwareRenderer::onBlit(const std::unique_ptr<uint8_t>* img, int x, int y, int w, int h, std::atomic_flag* in_use) {
image = img; memcpy(image.bits(), img->get(), 2048 * 2048 * 4);
in_use->clear();
source.setRect(x, y, w, h); source.setRect(x, y, w, h);
update(); update();
in_use->clear();
} }
void HardwareRenderer::resizeEvent(QResizeEvent *event) { void HardwareRenderer::resizeEvent(QResizeEvent *event) {

View File

@@ -47,7 +47,7 @@ public:
void setRenderType(RenderType type); void setRenderType(RenderType type);
public slots: public slots:
void onBlit(const QImage& img, int, int, int, int, std::atomic_flag* in_use); void onBlit(const std::unique_ptr<uint8_t>* img, int, int, int, int, std::atomic_flag* in_use);
protected: protected:
void resizeEvent(QResizeEvent *event) override; void resizeEvent(QResizeEvent *event) override;

View File

@@ -901,9 +901,7 @@ void MainWindow::on_actionFullscreen_triggered() {
video_fullscreen = 1; video_fullscreen = 1;
} }
auto widget = ui->stackedWidget->currentWidget(); ui->stackedWidget->switchRenderer((RendererStack::Renderer)vid_api);
auto rc = dynamic_cast<RendererCommon*>(widget);
rc->onResize(widget->width(), widget->height());
} }
void MainWindow::getTitle_(wchar_t *title) void MainWindow::getTitle_(wchar_t *title)

View File

@@ -18,9 +18,6 @@ void RendererCommon::onPaint(QPaintDevice* device) {
painter.fillRect(0, 0, device->width(), device->height(), QColorConstants::Black); painter.fillRect(0, 0, device->width(), device->height(), QColorConstants::Black);
painter.setCompositionMode(QPainter::CompositionMode_Plus); painter.setCompositionMode(QPainter::CompositionMode_Plus);
painter.drawImage(destination, image, source); 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) { static void integer_scale(double *d, double *g) {

View File

@@ -14,6 +14,6 @@ public:
protected: protected:
void onPaint(QPaintDevice* device); void onPaint(QPaintDevice* device);
QImage image; QImage image{QSize(2048, 2048), QImage::Format_RGB32};
QRect source, destination; QRect source, destination;
}; };

View File

@@ -24,9 +24,8 @@ RendererStack::RendererStack(QWidget *parent) :
ui(new Ui::RendererStack) ui(new Ui::RendererStack)
{ {
ui->setupUi(this); ui->setupUi(this);
imagebufs = QVector<QImage>(2); imagebufs[0].reset(new uint8_t[2048 * 2048 * 4]);
imagebufs[0] = QImage{QSize(2048, 2048), QImage::Format_RGB32}; imagebufs[1].reset(new uint8_t[2048 * 2048 * 4]);
imagebufs[1] = QImage{QSize(2048, 2048), QImage::Format_RGB32};
buffers_in_use = std::vector<std::atomic_flag>(2); buffers_in_use = std::vector<std::atomic_flag>(2);
buffers_in_use[0].clear(); buffers_in_use[0].clear();
@@ -222,7 +221,7 @@ void RendererStack::blit(int x, int y, int w, int h)
sy = y; sy = y;
sw = this->w = w; sw = this->w = w;
sh = this->h = h; 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)); video_copy(imagebits + y * (2048 * 4) + x * 4, &(buffer32->line[y][x]), h * 2048 * sizeof(uint32_t));
if (screenshots) 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_screenshot((uint32_t *)imagebits, 0, 0, 2048);
} }
video_blit_complete(); 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; currentBuf = (currentBuf + 1) % 2;
} }

View File

@@ -7,6 +7,7 @@
#include <memory> #include <memory>
#include <vector> #include <vector>
#include <atomic> #include <atomic>
#include <array>
namespace Ui { namespace Ui {
class RendererStack; class RendererStack;
@@ -42,7 +43,7 @@ public:
void switchRenderer(Renderer renderer); void switchRenderer(Renderer renderer);
signals: signals:
void blitToRenderer(const QImage& img, int, int, int, int, std::atomic_flag* in_use); void blitToRenderer(const std::unique_ptr<uint8_t>* img, int, int, int, int, std::atomic_flag* in_use);
public slots: public slots:
void blit(int x, int y, int w, int h); void blit(int x, int y, int w, int h);
@@ -59,11 +60,8 @@ private:
int x, y, w, h, sx, sy, sw, sh; 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; int currentBuf = 0;
QVector<QImage> imagebufs; std::array<std::unique_ptr<uint8_t>, 2> imagebufs;
std::unique_ptr<QWidget> current; std::unique_ptr<QWidget> current;

View File

@@ -7,11 +7,11 @@ void SoftwareRenderer::paintEvent(QPaintEvent *event) {
onPaint(this); onPaint(this);
} }
void SoftwareRenderer::onBlit(const QImage& img, int x, int y, int w, int h, std::atomic_flag* in_use) { void SoftwareRenderer::onBlit(const std::unique_ptr<uint8_t>* img, int x, int y, int w, int h, std::atomic_flag* in_use) {
image = img; memcpy(image.bits(), img->get(), 2048 * 2048 * 4);
in_use->clear();
source.setRect(x, y, w, h); source.setRect(x, y, w, h);
update(); update();
in_use->clear();
} }
void SoftwareRenderer::resizeEvent(QResizeEvent *event) { void SoftwareRenderer::resizeEvent(QResizeEvent *event) {

View File

@@ -13,7 +13,7 @@ public:
void paintEvent(QPaintEvent *event) override; void paintEvent(QPaintEvent *event) override;
public slots: public slots:
void onBlit(const QImage& img, int, int, int, int, std::atomic_flag* in_use); void onBlit(const std::unique_ptr<uint8_t>* img, int, int, int, int, std::atomic_flag* in_use);
protected: protected:
void resizeEvent(QResizeEvent *event) override; void resizeEvent(QResizeEvent *event) override;