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:
@@ -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) {
|
||||||
|
@@ -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;
|
||||||
|
@@ -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)
|
||||||
|
@@ -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) {
|
||||||
|
@@ -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;
|
||||||
};
|
};
|
||||||
|
@@ -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;
|
||||||
}
|
}
|
||||||
|
@@ -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;
|
||||||
|
|
||||||
|
@@ -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) {
|
||||||
|
@@ -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;
|
||||||
|
Reference in New Issue
Block a user