Optimize ui painter to not draw elements not in the current bbox

This commit is contained in:
Nikita Lisitsa 2022-03-11 14:51:49 +03:00
parent e237959894
commit 884a7c745b
3 changed files with 27 additions and 4 deletions

View file

@ -26,7 +26,9 @@ namespace psemek::ui
void commit_stencil() override;
void end_stencil() override;
void start_frame(geom::box<float, 2> const & bbox);
void render(geom::matrix<float, 4, 4> const & transform);
geom::box<float, 2> current_bbox() const;
private:
psemek_declare_pimpl

View file

@ -173,12 +173,17 @@ namespace psemek::ui
void controller::render(gfx::render_target const & rt)
{
impl().painter.start_frame(geom::cast<float>(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());

View file

@ -219,6 +219,7 @@ void main()
int stencil_level = 0;
static constexpr int max_stencil_level = 8;
std::vector<geom::box<float, 2>> stencil_bbox;
geom::box<float, 2> 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<stencil_batch>({});
@ -457,6 +461,13 @@ void main()
}
--impl().stencil_level;
impl().stencil_bbox.pop_back();
}
void painter_impl::start_frame(geom::box<float, 2> const & bbox)
{
impl().stencil_bbox.push_back(bbox);
}
void painter_impl::render(geom::matrix<float, 4, 4> 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<float, 2> painter_impl::current_bbox() const
{
return impl().stencil_bbox.back();
}
}