From e1154fdf0a2076500b3f9e7e8c1307fbea45f7cc Mon Sep 17 00:00:00 2001 From: Andrew Golovashevich Date: Tue, 10 Dec 2024 10:16:40 +0300 Subject: [PATCH] Writing pixels to buffer instead of QImage --- .gitignore | 4 +- .../qt_utilities/owned_qimage.hpp | 39 ++++++++++++++----- .../separate_threaded_renderer.hpp | 27 +++++++++++-- 3 files changed, 57 insertions(+), 13 deletions(-) diff --git a/.gitignore b/.gitignore index b4e9b6f..77e3f2e 100644 --- a/.gitignore +++ b/.gitignore @@ -8,4 +8,6 @@ /.idea/ /*build*/ -/.vs/ \ No newline at end of file +/.vs/ +/out/ +/CMakeSettings.json \ No newline at end of file diff --git a/qt-utilities/include/bgtu/computer_graphics_lab_work/qt_utilities/owned_qimage.hpp b/qt-utilities/include/bgtu/computer_graphics_lab_work/qt_utilities/owned_qimage.hpp index 9f5718d..2136d30 100644 --- a/qt-utilities/include/bgtu/computer_graphics_lab_work/qt_utilities/owned_qimage.hpp +++ b/qt-utilities/include/bgtu/computer_graphics_lab_work/qt_utilities/owned_qimage.hpp @@ -15,10 +15,11 @@ namespace BGTU::ComputerGraphicsLabWork::QtUtilities { class OwnedQImage : public QImage, public RendererApi::VoxelDrawer::Exporter { private: RendererApi::SpriteMetadata const **owners; + std::uint_least8_t *pixels_buffer; + bool owns_buffers; public: - OwnedQImage(unsigned width, unsigned height) : - QImage(width, height, QImage::Format_ARGB32) { + OwnedQImage(unsigned width, unsigned height) : QImage(width, height, QImage::Format_ARGB32), pixels_buffer{nullptr}, owns_buffers{true} { if (width == 0 || height == 0) { this->owners = nullptr; } else { @@ -29,8 +30,22 @@ namespace BGTU::ComputerGraphicsLabWork::QtUtilities { } } - OwnedQImage() : QImage(), owners{nullptr} {} + OwnedQImage() : QImage(), owners{nullptr}, pixels_buffer{nullptr} {} + OwnedQImage(std::uint_least8_t *data, unsigned width, unsigned height, QImage::Format f, RendererApi::SpriteMetadata const **owners, QImageCleanupFunction destructor, void *destructor_closure) : + QImage(data, width, height, f, destructor, destructor_closure), pixels_buffer{data}, owners{owners}, owns_buffers{false} {} + + OwnedQImage(std::uint_least8_t *data, unsigned width, unsigned height, QImage::Format f, RendererApi::SpriteMetadata const **owners) : + QImage(data, width, height, f), pixels_buffer{data}, owners{owners}, owns_buffers{false} {} + + enum _DelegateBuffers { + DelegateBuffers + }; + + OwnedQImage(std::uint_least8_t *data, unsigned width, unsigned height, QImage::Format f, RendererApi::SpriteMetadata const **owners, _DelegateBuffers) : + QImage(data, width, height, f), pixels_buffer{data}, owners{owners}, owns_buffers{true} {} + +#if 0 OwnedQImage &operator=(OwnedQImage const ©) { if (this == ©) return *this; @@ -49,13 +64,13 @@ namespace BGTU::ComputerGraphicsLabWork::QtUtilities { *this = copy; } - OwnedQImage(OwnedQImage &&move) noexcept : QImage{std::move(move)} { + OwnedQImage(OwnedQImage &&move) noexcept: QImage{std::move(move)} { if (this->owners != nullptr) delete[] this->owners; this->owners = move.owners; move.owners = nullptr; } - +#endif void setPixelOwner(unsigned x, unsigned y, RendererApi::SpriteMetadata const *o) { assert(x < this->width()); @@ -64,7 +79,7 @@ namespace BGTU::ComputerGraphicsLabWork::QtUtilities { this->owners[y * this->width() + x] = o; } - RendererApi::SpriteMetadata const *getPixelOwner(unsigned x, unsigned y) const { + [[nodiscard]] RendererApi::SpriteMetadata const *getPixelOwner(unsigned x, unsigned y) const { assert(x < this->width()); assert(y < this->height()); @@ -77,9 +92,15 @@ namespace BGTU::ComputerGraphicsLabWork::QtUtilities { } ~OwnedQImage() override { - if (this->owners != nullptr) { - delete[] this->owners; - this->owners = nullptr; + if (this->owns_buffers) { + if (this->owners != nullptr) { + delete[] this->owners; + this->owners = nullptr; + } + if (this->pixels_buffer != nullptr) { + delete[] this->pixels_buffer; + this->pixels_buffer = nullptr; + } } } }; diff --git a/qt-utilities/include/bgtu/computer_graphics_lab_work/qt_utilities/separate_threaded_renderer.hpp b/qt-utilities/include/bgtu/computer_graphics_lab_work/qt_utilities/separate_threaded_renderer.hpp index 4692b12..e916450 100644 --- a/qt-utilities/include/bgtu/computer_graphics_lab_work/qt_utilities/separate_threaded_renderer.hpp +++ b/qt-utilities/include/bgtu/computer_graphics_lab_work/qt_utilities/separate_threaded_renderer.hpp @@ -169,16 +169,37 @@ namespace BGTU::ComputerGraphicsLabWork::QtUtilities { data_t cached = *const_cast(&this->owner->next_data); this->owner->sync.unlock(); - auto img = new OwnedQImage{cached.width, cached.height}; + struct VoxelDrawerExporterImpl : public RendererApi::VoxelDrawer::Exporter { + public: + RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t const w; + RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t const h; + std::uint_least8_t *const pixels_argb;; + RendererApi::SpriteMetadata const **const owners; + + VoxelDrawerExporterImpl(RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t w, RendererApi::VoxelDrawer::visible_pixel_coordinate_fast_t h) : + w{w}, h{h}, + pixels_argb{new std::uint_least8_t[w * h * 4]}, + owners{new RendererApi::SpriteMetadata const *[w * h]} {} + + void set_pixel(long long x, long long y, BGTU::ComputerGraphicsLabWork::RendererApi::Color c, const BGTU::ComputerGraphicsLabWork::RendererApi::SpriteMetadata *owner) final { + if (x < 0 || this->w <= x) return; + if (y < 0 || this->h <= y) return; + this->pixels_argb[(y * this->w + x) * 4] = c.red; + this->pixels_argb[(y * this->w + x) * 4 + 1] = c.green; + this->pixels_argb[(y * this->w + x) * 4 + 2] = c.blue; + this->owners[y * this->w + x] = owner; + } + } img{cached.width, cached.height}; + (this->owner->renderer_context->*renderer_procedure)( cached.width, cached.height, - img, + &img, cached.bg, cached.projection, cached.sprites, cached.sprites_count, cached.sprite_data ); - emit this->owner->frame_rendered(img); + emit this->owner->frame_rendered(new OwnedQImage{img.pixels_argb, img.w, img.h, QImage::Format_RGB32, img.owners, OwnedQImage::DelegateBuffers}); auto elapsed = timer.elapsed(); qCritical() << elapsed << "ms"; this->sleepms(std::max(static_cast(cached.ms_per_frame) - elapsed, 0));