LibWeb: Fix infinite repaint loop when cached display list is used

Before this change, `m_needs_repaint` was reset in
`Document::record_display_list()` only when the cached display list was
absent. This meant that if the last triggered repaint used the cached
display list, we would keep repainting indefinitely until the display
list was invalidated (We schedule a task that checks if repainting is
required 60/s).

This change also moves `m_needs_repaint` from Document to
TraversableNavigable as we only ever need to repaint a document that
belongs to traversable.
This commit is contained in:
Aliaksandr Kalenik 2025-02-01 19:33:18 +01:00 committed by Andreas Kling
commit 0c5b61b7e1
Notes: github-actions[bot] 2025-02-01 22:32:14 +00:00
9 changed files with 17 additions and 25 deletions

View file

@ -411,13 +411,13 @@ void EventLoop::update_the_rendering()
for (auto& document : docs) {
document->page().client().process_screenshot_requests();
auto navigable = document->navigable();
if (navigable && document->needs_repaint()) {
auto* browsing_context = document->browsing_context();
auto& page = browsing_context->page();
if (navigable->is_traversable()) {
VERIFY(page.client().is_ready_to_paint());
page.client().paint_next_frame();
}
if (!navigable->is_traversable())
continue;
auto traversable = navigable->traversable_navigable();
if (traversable && traversable->needs_repaint()) {
auto& page = traversable->page();
VERIFY(page.client().is_ready_to_paint());
page.client().paint_next_frame();
}
}

View file

@ -2198,13 +2198,6 @@ void Navigable::perform_scroll_of_viewport(CSSPixelPoint new_position)
HTML::main_thread_event_loop().schedule();
}
void Navigable::set_needs_display(InvalidateDisplayList should_invalidate_display_list)
{
if (auto document = active_document(); document) {
document->set_needs_display(should_invalidate_display_list);
}
}
// https://html.spec.whatwg.org/#rendering-opportunity
bool Navigable::has_a_rendering_opportunity() const
{

View file

@ -173,8 +173,6 @@ public:
virtual void set_viewport_size(CSSPixelSize);
void perform_scroll_of_viewport(CSSPixelPoint position);
void set_needs_display(InvalidateDisplayList = InvalidateDisplayList::Yes);
// https://html.spec.whatwg.org/#rendering-opportunity
[[nodiscard]] bool has_a_rendering_opportunity() const;

View file

@ -1429,6 +1429,8 @@ NonnullRefPtr<Gfx::PaintingSurface> TraversableNavigable::painting_surface_for_b
void TraversableNavigable::paint(DevicePixelRect const& content_rect, Painting::BackingStore& target, PaintOptions paint_options)
{
m_needs_repaint = false;
auto document = active_document();
if (!document)
return;

View file

@ -113,6 +113,9 @@ public:
void set_viewport_size(CSSPixelSize) override;
bool needs_repaint() const { return m_needs_repaint; }
void set_needs_repaint() { m_needs_repaint = true; }
private:
TraversableNavigable(GC::Ref<Page>);
@ -161,6 +164,8 @@ private:
RefPtr<Gfx::SkiaBackendContext> m_skia_backend_context;
OwnPtr<Painting::DisplayListPlayerSkia> m_skia_player;
HashMap<Gfx::Bitmap*, NonnullRefPtr<Gfx::PaintingSurface>> m_bitmap_to_surface;
bool m_needs_repaint { true };
};
struct BrowsingContextAndDocument {