From 884a7c745bfae2d461dc507df8742d4e6b626b94 Mon Sep 17 00:00:00 2001 From: lisyarus Date: Fri, 11 Mar 2022 14:51:49 +0300 Subject: [PATCH] Optimize ui painter to not draw elements not in the current bbox --- libs/ui/include/psemek/ui/painter_impl.hpp | 2 ++ libs/ui/source/controller.cpp | 9 +++++++-- libs/ui/source/painter_impl.cpp | 20 ++++++++++++++++++-- 3 files changed, 27 insertions(+), 4 deletions(-) diff --git a/libs/ui/include/psemek/ui/painter_impl.hpp b/libs/ui/include/psemek/ui/painter_impl.hpp index 6b66f55e..2664f9b8 100644 --- a/libs/ui/include/psemek/ui/painter_impl.hpp +++ b/libs/ui/include/psemek/ui/painter_impl.hpp @@ -26,7 +26,9 @@ namespace psemek::ui void commit_stencil() override; void end_stencil() override; + void start_frame(geom::box const & bbox); void render(geom::matrix const & transform); + geom::box current_bbox() const; private: psemek_declare_pimpl diff --git a/libs/ui/source/controller.cpp b/libs/ui/source/controller.cpp index 57abd2bc..fa274538 100644 --- a/libs/ui/source/controller.cpp +++ b/libs/ui/source/controller.cpp @@ -173,12 +173,17 @@ namespace psemek::ui void controller::render(gfx::render_target const & rt) { + impl().painter.start_frame(geom::cast(rt.viewport)); + auto visitor = util::recursive([&](auto && self, element * elem) -> void { if (elem->hidden()) return; - elem->draw(impl().painter); + bool const visible = !(impl().painter.current_bbox() & elem->shape().bbox()).empty(); + if (visible) + elem->draw(impl().painter); for (auto c : elem->children()) if (c) self(c); - elem->post_draw(impl().painter); + if (visible) + elem->post_draw(impl().painter); }); visitor(impl().root.get()); diff --git a/libs/ui/source/painter_impl.cpp b/libs/ui/source/painter_impl.cpp index 17896fba..17b91771 100644 --- a/libs/ui/source/painter_impl.cpp +++ b/libs/ui/source/painter_impl.cpp @@ -219,6 +219,7 @@ void main() int stencil_level = 0; static constexpr int max_stencil_level = 8; + std::vector> stencil_bbox; geom::box draw_bbox; @@ -405,6 +406,7 @@ void main() batch.dpass = gl::REPLACE; ++impl().stencil_level; + impl().draw_bbox = {}; } void painter_impl::commit_stencil() @@ -420,6 +422,8 @@ void main() batch.sfail = gl::KEEP; batch.dfail = gl::KEEP; batch.dpass = gl::KEEP; + + impl().stencil_bbox.push_back(impl().draw_bbox); } void painter_impl::end_stencil() @@ -438,7 +442,7 @@ void main() clear_batch.dpass = gl::REPLACE; } - draw_rect(impl().draw_bbox, {0, 0, 0, 255}); + draw_rect(impl().stencil_bbox.back(), {0, 0, 0, 255}); { auto & batch = impl().batch({}); @@ -457,6 +461,13 @@ void main() } --impl().stencil_level; + + impl().stencil_bbox.pop_back(); + } + + void painter_impl::start_frame(geom::box const & bbox) + { + impl().stencil_bbox.push_back(bbox); } void painter_impl::render(geom::matrix const & transform) @@ -524,13 +535,18 @@ void main() for (auto const & b : impl().batches) std::visit(batch_visitor, b); - impl().max_batch_count = std::max(impl().max_batch_count, impl().batches.size()); impl().depth = 0; impl().batches.clear(); impl().stencil_level = 0; + impl().stencil_bbox.clear(); impl().draw_bbox = {}; } + geom::box painter_impl::current_bbox() const + { + return impl().stencil_bbox.back(); + } + }