From d9d7188ad7b22e8991a9ef685840ac0e88566b39 Mon Sep 17 00:00:00 2001 From: Bent Bisballe Nyeng Date: Sat, 7 Mar 2020 14:22:56 +0100 Subject: Use vector for PixelBuffer memory allocation. Use optimized render routines in some more painter algorithms. Fix capitalization of Canvas::getPixelBuffer method. --- .gitignore | 23 ++++++--------- plugin/drumgizmo_plugin.cc | 2 +- plugingui/canvas.h | 4 +-- plugingui/layout.cc | 26 +++++++++------- plugingui/painter.cc | 35 +++++++++++----------- plugingui/pixelbuffer.cc | 69 +++++++++++++++++++++++-------------------- plugingui/pixelbuffer.h | 4 ++- plugingui/widget.cc | 2 +- plugingui/widget.h | 2 +- test/paintertest.cc | 2 +- test/uitests/benchmarktest.cc | 34 ++++++++++++++++++++- 11 files changed, 121 insertions(+), 82 deletions(-) diff --git a/.gitignore b/.gitignore index 37d5603..00d9b7d 100644 --- a/.gitignore +++ b/.gitignore @@ -24,6 +24,8 @@ compile config.h.in~ test-driver INSTALL +*.mo +*.pot *.o *.a *.la @@ -50,19 +52,7 @@ test/audiocachefile test/audiocacheidmanager test/configfile test/memchecker -test/randomtest -test/atomictest -test/syncedsettingstest -test/imagecachetest -test/semaphoretest -test/enginetest -test/paintertest -test/drumkitcreatortest -test/dgxmlparsertest -test/bytesizeparsertest -test/notifiertest -test/drumkitparsertest -test/instrumentparsertest +test/*test test/dgreftest/dgreftest test/dgreftest/*.mid test/dgreftest/*.wav @@ -70,6 +60,8 @@ test/uitests/filebrowsertest test/uitests/framewidgettest test/uitests/resizetest test/uitests/tabwidgettest +test/uitests/benchmarktest +test/uitests/benchmarktest_resource_data.cc drumgizmo-*.tar.gz tst vst/Makefile.mingw32 @@ -93,4 +85,7 @@ plugin/vst/public.sdk/ *.log *.pch *.gch -cov-int/ \ No newline at end of file +cov-int/ +ttlgen +manifest.ttl +dgvalidator \ No newline at end of file diff --git a/plugin/drumgizmo_plugin.cc b/plugin/drumgizmo_plugin.cc index 494be4e..0e1021d 100644 --- a/plugin/drumgizmo_plugin.cc +++ b/plugin/drumgizmo_plugin.cc @@ -199,7 +199,7 @@ public: } // From Canvas: - GUI::PixelBufferAlpha& GetPixelBuffer() override + GUI::PixelBufferAlpha& getPixelBuffer() override { return pixbuf; } diff --git a/plugingui/canvas.h b/plugingui/canvas.h index 2326f0e..d6e8f99 100644 --- a/plugingui/canvas.h +++ b/plugingui/canvas.h @@ -31,14 +31,14 @@ namespace GUI { -//! Abstract class that can be used by the Paiter to draw on. +//! Abstract class that can be used by the Painter to draw on. class Canvas { public: virtual ~Canvas() = default; //! @returns a reference to the pixel buffer. - virtual PixelBufferAlpha& GetPixelBuffer() = 0; + virtual PixelBufferAlpha& getPixelBuffer() = 0; }; } // GUI:: diff --git a/plugingui/layout.cc b/plugingui/layout.cc index f38bc20..61e4f77 100644 --- a/plugingui/layout.cc +++ b/plugingui/layout.cc @@ -33,7 +33,8 @@ namespace GUI { -LayoutItem::LayoutItem() : parent(nullptr) +LayoutItem::LayoutItem() + : parent(nullptr) { } @@ -170,7 +171,8 @@ void VBoxLayout::setHAlignment(HAlignment alignment) // HBoxLayout::HBoxLayout(LayoutItem* parent) - : BoxLayout(parent), align(VAlignment::center) + : BoxLayout(parent) + , align(VAlignment::center) { } @@ -242,10 +244,10 @@ void HBoxLayout::setVAlignment(VAlignment alignment) // GridLayout::GridLayout(LayoutItem* parent, std::size_t number_of_columns, - std::size_t number_of_rows) - : BoxLayout(parent) - , number_of_columns(number_of_columns) - , number_of_rows(number_of_rows) + std::size_t number_of_rows) + : BoxLayout(parent) + , number_of_columns(number_of_columns) + , number_of_rows(number_of_rows) { } @@ -297,9 +299,11 @@ int GridLayout::lastUsedRow(int column) const { int last_row = -1; - for (auto const& grid_range : grid_ranges) { + for (auto const& grid_range : grid_ranges) + { auto const& range = grid_range.second; - if (column >= range.column_begin && column < range.column_end) { + if (column >= range.column_begin && column < range.column_end) + { last_row = std::max(last_row, range.row_end - 1); } } @@ -311,9 +315,11 @@ int GridLayout::lastUsedColumn(int row) const { int last_column = -1; - for (auto const& grid_range : grid_ranges) { + for (auto const& grid_range : grid_ranges) + { auto const& range = grid_range.second; - if (row >= range.row_begin && row < range.row_end) { + if (row >= range.row_begin && row < range.row_end) + { last_column = std::max(last_column, range.column_end - 1); } } diff --git a/plugingui/painter.cc b/plugingui/painter.cc index 7f8acba..d3f28ff 100644 --- a/plugingui/painter.cc +++ b/plugingui/painter.cc @@ -39,7 +39,7 @@ namespace GUI { Painter::Painter(Canvas& canvas) - : pixbuf(canvas.GetPixelBuffer()) + : pixbuf(canvas.getPixelBuffer()) { colour = Colour(0.0f, 0.0f, 0.0f, 0.5f); } @@ -111,11 +111,11 @@ void Painter::drawLine(int x0, int y0, int x1, int y1) if(steep) { - plot(pixbuf, colour, ypxl1, xpxl1, 1); + pixbuf.addPixel(ypxl1, xpxl1, colour); } else { - plot(pixbuf, colour, xpxl1, ypxl1, 1); + pixbuf.addPixel(xpxl1, ypxl1, colour); } double intery = yend + gradient; // first y-intersection for the main loop @@ -129,11 +129,11 @@ void Painter::drawLine(int x0, int y0, int x1, int y1) if(steep) { - plot(pixbuf, colour, ypxl2, xpxl2, 1); + pixbuf.addPixel(ypxl2, xpxl2, colour); } else { - plot(pixbuf, colour, xpxl2, ypxl2, 1); + pixbuf.addPixel(xpxl2, ypxl2, colour); } // main loop @@ -205,22 +205,21 @@ void Painter::drawText(int x0, int y0, const Font& font, { for(int y = -1 * std::min(0, y0); y < renderHeight; ++y) { - for(int x = -1 * std::min(0, x0); x < renderWidth; ++x) - { - assert(x >= 0); - assert(y >= 0); - assert(x < (int)textbuf->width); - assert(y < (int)textbuf->height); + int x = -1 * std::min(0, x0); - auto c = textbuf->pixel(x, y); + assert(x >= 0); + assert(y >= 0); + assert(x < (int)textbuf->width); + assert(y < (int)textbuf->height); - assert(x + x0 >= 0); - assert(y + y0 >= 0); - assert(x + x0 < (int)pixbuf.width); - assert(y + y0 < (int)pixbuf.height); + auto c = textbuf->getLine(x, y); - pixbuf.addPixel(x + x0, y + y0, c); - } + assert(x + x0 >= 0); + assert(y + y0 >= 0); + assert(x + x0 < (int)pixbuf.width); + assert(y + y0 < (int)pixbuf.height); + + pixbuf.blendLine(x + x0, y + y0, c, renderWidth - x); } } else diff --git a/plugingui/pixelbuffer.cc b/plugingui/pixelbuffer.cc index 918298b..c73e663 100644 --- a/plugingui/pixelbuffer.cc +++ b/plugingui/pixelbuffer.cc @@ -35,20 +35,18 @@ namespace GUI { PixelBuffer::PixelBuffer(std::size_t width, std::size_t height) - : buf(nullptr) { realloc(width, height); } PixelBuffer::~PixelBuffer() { - free(buf); } void PixelBuffer::realloc(std::size_t width, std::size_t height) { - free(buf); - buf = (std::uint8_t *)calloc(width * height, 3); + buf_data.resize(width * height * 3); + buf = buf_data.data(); this->width = width; this->height = height; } @@ -61,7 +59,7 @@ void PixelBuffer::blendLine(std::size_t x, std::size_t y, { if(line[3] == 0xff) { - memcpy(target, line, 3); + std::memcpy(target, line, 3); } else { @@ -219,53 +217,50 @@ Rect PixelBuffer::updateBuffer(std::vector& pixel_buffers) return dirty_rect; } - PixelBufferAlpha::PixelBufferAlpha(std::size_t width, std::size_t height) - : managed(true) - , buf(nullptr) - , x(0) - , y(0) { realloc(width, height); } PixelBufferAlpha::~PixelBufferAlpha() { - if(managed) - { - free(buf); - } } void PixelBufferAlpha::realloc(std::size_t width, std::size_t height) { - free(buf); - buf = (std::uint8_t *)calloc(width * height, 4); + buf_data.resize(width * height * 4); + buf = buf_data.data(); this->width = width; this->height = height; + clear(); } void PixelBufferAlpha::clear() { - memset(buf, 0, width * height * 4); + std::memset(buf, 0, width * height * 4); } -#undef PX -#define PX(k) ((x + y * width) * 4 + k) void PixelBufferAlpha::setPixel(std::size_t x, std::size_t y, const Colour& c) { - std::uint8_t* pixel = &buf[PX(0)]; - memcpy(pixel, c.data(), 4); + std::uint8_t* pixel = buf + (x + y * width) * 4; + std::memcpy(pixel, c.data(), 4); } void PixelBufferAlpha::writeLine(std::size_t x, std::size_t y, const std::uint8_t* line, std::size_t len) { - auto offset = &buf[PX(0)]; - if(x + y * width + len > width * height) + if(x >= width || y >= height) { - return; // out of bounds + return; } + + if(x + len > width) + { + len = width - x; + } + + auto offset = buf + (x + y * width) * 4; + std::memcpy(offset, line, len * 4); } @@ -276,13 +271,18 @@ void PixelBufferAlpha::writeLine(std::size_t x, std::size_t y, void PixelBufferAlpha::blendLine(std::size_t x, std::size_t y, const std::uint8_t* line, std::size_t len) { - if(x + y * width + len > width * height) + if(x >= width || y >= height) { - return; // out of bounds + return; + } + + if(x + len > width) + { + len = width - x; } int a, b; - std::uint8_t* target = &buf[PX(0)]; + std::uint8_t* target = buf + (x + y * width) * 4; while(len) { if(line[3] == 0xff) @@ -293,7 +293,7 @@ void PixelBufferAlpha::blendLine(std::size_t x, std::size_t y, end += 4; } auto chunk_len = end - line; - memcpy(target, line, chunk_len); + std::memcpy(target, line, chunk_len); line += chunk_len; target += chunk_len; len -= chunk_len / 4; @@ -322,6 +322,11 @@ void PixelBufferAlpha::blendLine(std::size_t x, std::size_t y, void PixelBufferAlpha::addPixel(std::size_t x, std::size_t y, const Colour& c) { + if(x >= width || y >= height) + { + return; // out of bounds + } + const std::uint8_t* colour = c.data(); if(colour[3] == 0) @@ -330,11 +335,11 @@ void PixelBufferAlpha::addPixel(std::size_t x, std::size_t y, const Colour& c) } int a, b; - std::uint8_t* target = &buf[PX(0)]; + std::uint8_t* target = buf + (x + y * width) * 4; if(colour[3] == 0xff) { - memcpy(target, colour, 4); + std::memcpy(target, colour, 4); } else { @@ -351,13 +356,13 @@ void PixelBufferAlpha::addPixel(std::size_t x, std::size_t y, const Colour& c) const Colour& PixelBufferAlpha::pixel(std::size_t x, std::size_t y) const { static Colour c; - memcpy(c.data(), &buf[PX(0)], 4); + std::memcpy(c.data(), buf + (x + y * width) * 4, 4); return c; } const std::uint8_t* PixelBufferAlpha::getLine(std::size_t x, std::size_t y) const { - return &buf[PX(0)]; + return buf + (x + y * width) * 4; } } // GUI:: diff --git a/plugingui/pixelbuffer.h b/plugingui/pixelbuffer.h index 5078ed6..5c11d14 100644 --- a/plugingui/pixelbuffer.h +++ b/plugingui/pixelbuffer.h @@ -29,6 +29,7 @@ #include "colour.h" #include +#include #include #include "guievent.h" @@ -49,6 +50,7 @@ public: Rect updateBuffer(std::vector& pixel_buffers); + std::vector buf_data; std::uint8_t* buf{nullptr}; std::size_t width{0}; std::size_t height{0}; @@ -78,7 +80,7 @@ public: const std::uint8_t* getLine(std::size_t x, std::size_t y) const; - bool managed{false}; + std::vector buf_data; std::uint8_t* buf{nullptr}; std::size_t width{0}; std::size_t height{0}; diff --git a/plugingui/widget.cc b/plugingui/widget.cc index 5a76af9..da6b1e2 100644 --- a/plugingui/widget.cc +++ b/plugingui/widget.cc @@ -201,7 +201,7 @@ Point Widget::position() const return { _x, _y }; } -PixelBufferAlpha& Widget::GetPixelBuffer() +PixelBufferAlpha& Widget::getPixelBuffer() { return pixbuf; } diff --git a/plugingui/widget.h b/plugingui/widget.h index fbf3f5b..b9436b7 100644 --- a/plugingui/widget.h +++ b/plugingui/widget.h @@ -81,7 +81,7 @@ public: Point position() const; // From Canvas - PixelBufferAlpha& GetPixelBuffer() override; + PixelBufferAlpha& getPixelBuffer() override; virtual bool isFocusable() { return false; } virtual bool catchMouse() { return false; } diff --git a/test/paintertest.cc b/test/paintertest.cc index c6e8615..518a5ac 100644 --- a/test/paintertest.cc +++ b/test/paintertest.cc @@ -39,7 +39,7 @@ public: : pixbuf(width, height) {} - GUI::PixelBufferAlpha& GetPixelBuffer() override + GUI::PixelBufferAlpha& getPixelBuffer() override { return pixbuf; } diff --git a/test/uitests/benchmarktest.cc b/test/uitests/benchmarktest.cc index 33defc6..aaf3946 100644 --- a/test/uitests/benchmarktest.cc +++ b/test/uitests/benchmarktest.cc @@ -37,11 +37,16 @@ class TimedCanvas : public GUI::Canvas { public: - GUI::PixelBufferAlpha& GetPixelBuffer() override + GUI::PixelBufferAlpha& getPixelBuffer() override { return pixbuf; } + void resize(std::size_t width, std::size_t height) + { + pixbuf.realloc(width, height); + } + private: GUI::PixelBufferAlpha pixbuf{800, 600}; }; @@ -83,6 +88,33 @@ int main() GUI::Image image_edge_alpha(":benchmarktest_resources/image_edge_alpha.png"); GUI::Image image_inner_alpha(":benchmarktest_resources/image_inner_alpha.png"); + { + TimedCanvas canvas; + TimedScope timed("Pixelbuffer resize", 100000); + painter.setColour(GUI::Colour(1.f, 1.f, 1.f, 1.f)); + for(int i = 0; i < 100000; ++i) + { + canvas.resize(i % 1000 + 100, i % 1000 + 100); + } + } + + { + TimedScope timed("Filled rect, no alpha", 100000); + for(int i = 0; i < 100000; ++i) + { + painter.drawRectangle(0, 0, 800, 600); + } + } + + { + TimedScope timed("Filled rect, with alpha", 100000); + painter.setColour(GUI::Colour(1.f, 1.f, 1.f, 0.5f)); + for(int i = 0; i < 100000; ++i) + { + painter.drawRectangle(0, 0, 800, 600); + } + } + { TimedScope timed("No scale, no alpha", 100000); for(int i = 0; i < 100000; ++i) -- cgit v1.2.3