LibWeb: Refresh clip and scroll state only when needed

Although refreshing is cheap, it was performed before each hit-testing
and was 2-4% in profiles on Discord and Twitter.

Now clip and scroll states are refreshed only if scroll offset has
changed.
This commit is contained in:
Aliaksandr Kalenik 2024-05-28 13:47:00 +02:00 committed by Andreas Kling
parent d6297ec074
commit e806136116
5 changed files with 32 additions and 0 deletions

View file

@ -5056,4 +5056,16 @@ void Document::process_top_layer_removals()
}
}
void Document::set_needs_to_refresh_clip_state(bool b)
{
if (auto* paintable = this->paintable())
paintable->set_needs_to_refresh_clip_state(b);
}
void Document::set_needs_to_refresh_scroll_state(bool b)
{
if (auto* paintable = this->paintable())
paintable->set_needs_to_refresh_scroll_state(b);
}
}

View file

@ -474,6 +474,9 @@ public:
bool needs_full_style_update() const { return m_needs_full_style_update; }
void set_needs_full_style_update(bool b) { m_needs_full_style_update = b; }
void set_needs_to_refresh_clip_state(bool b);
void set_needs_to_refresh_scroll_state(bool b);
bool has_active_favicon() const { return m_active_favicon; }
void check_favicon_after_loading_link_resource();

View file

@ -71,6 +71,9 @@ void PaintableBox::set_scroll_offset(CSSPixelPoint offset)
if (!scrollable_overflow_rect.has_value())
return;
document().set_needs_to_refresh_clip_state(true);
document().set_needs_to_refresh_scroll_state(true);
auto max_x_offset = scrollable_overflow_rect->width() - content_size().width();
auto max_y_offset = scrollable_overflow_rect->height() - content_size().height();
offset.set_x(clamp(offset.x(), 0, max_x_offset));

View file

@ -128,6 +128,10 @@ void ViewportPaintable::assign_clip_frames()
void ViewportPaintable::refresh_scroll_state()
{
if (!m_needs_to_refresh_scroll_state)
return;
m_needs_to_refresh_scroll_state = false;
for (auto& it : scroll_state) {
auto const& paintable_box = *it.key;
auto& scroll_frame = *it.value;
@ -142,6 +146,10 @@ void ViewportPaintable::refresh_scroll_state()
void ViewportPaintable::refresh_clip_state()
{
if (!m_needs_to_refresh_clip_state)
return;
m_needs_to_refresh_clip_state = false;
for (auto& it : clip_state) {
auto const& paintable_box = *it.key;
auto& clip_frame = *it.value;

View file

@ -36,12 +36,18 @@ public:
bool handle_mousewheel(Badge<EventHandler>, CSSPixelPoint, unsigned, unsigned, int wheel_delta_x, int wheel_delta_y) override;
void set_needs_to_refresh_clip_state(bool value) { m_needs_to_refresh_clip_state = value; }
void set_needs_to_refresh_scroll_state(bool value) { m_needs_to_refresh_scroll_state = value; }
private:
void build_stacking_context_tree();
explicit ViewportPaintable(Layout::Viewport const&);
virtual void visit_edges(Visitor&) override;
bool m_needs_to_refresh_clip_state { true };
bool m_needs_to_refresh_scroll_state { true };
};
}