Skip to content

Commit 0c5b61b

Browse files
kalenikaliaksandrawesomekling
authored andcommitted
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.
1 parent 0cfe90b commit 0c5b61b

File tree

9 files changed

+17
-25
lines changed

9 files changed

+17
-25
lines changed

Libraries/LibWeb/DOM/Document.cpp

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6093,8 +6093,6 @@ void Document::set_needs_display(CSSPixelRect const&, InvalidateDisplayList shou
60936093
// FIXME: Ignore updates outside the visible viewport rect.
60946094
// This requires accounting for fixed-position elements in the input rect, which we don't do yet.
60956095

6096-
m_needs_repaint = true;
6097-
60986096
if (should_invalidate_display_list == InvalidateDisplayList::Yes) {
60996097
invalidate_display_list();
61006098
}
@@ -6104,6 +6102,7 @@ void Document::set_needs_display(CSSPixelRect const&, InvalidateDisplayList shou
61046102
return;
61056103

61066104
if (navigable->is_traversable()) {
6105+
navigable->traversable_navigable()->set_needs_repaint();
61076106
Web::HTML::main_thread_event_loop().schedule();
61086107
return;
61096108
}
@@ -6188,8 +6187,6 @@ RefPtr<Painting::DisplayList> Document::record_display_list(PaintConfig config)
61886187
display_list->set_device_pixels_per_css_pixel(page().client().device_pixels_per_css_pixel());
61896188
display_list->set_scroll_state(viewport_paintable.scroll_state());
61906189

6191-
m_needs_repaint = false;
6192-
61936190
m_cached_display_list = display_list;
61946191
m_cached_display_list_paint_config = config;
61956192

Libraries/LibWeb/DOM/Document.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -735,7 +735,6 @@ class Document
735735
GC::Ptr<HTML::Navigable> cached_navigable();
736736
void set_cached_navigable(GC::Ptr<HTML::Navigable>);
737737

738-
[[nodiscard]] bool needs_repaint() const { return m_needs_repaint; }
739738
void set_needs_display(InvalidateDisplayList = InvalidateDisplayList::Yes);
740739
void set_needs_display(CSSPixelRect const&, InvalidateDisplayList = InvalidateDisplayList::Yes);
741740

@@ -1101,8 +1100,6 @@ class Document
11011100
// NOTE: This is WeakPtr, not GCPtr, on purpose. We don't want the document to keep some old detached navigable alive.
11021101
WeakPtr<HTML::Navigable> m_cached_navigable;
11031102

1104-
bool m_needs_repaint { false };
1105-
11061103
bool m_enable_cookies_on_file_domains { false };
11071104

11081105
Optional<PaintConfig> m_cached_display_list_paint_config;

Libraries/LibWeb/HTML/EventLoop/EventLoop.cpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -411,13 +411,13 @@ void EventLoop::update_the_rendering()
411411
for (auto& document : docs) {
412412
document->page().client().process_screenshot_requests();
413413
auto navigable = document->navigable();
414-
if (navigable && document->needs_repaint()) {
415-
auto* browsing_context = document->browsing_context();
416-
auto& page = browsing_context->page();
417-
if (navigable->is_traversable()) {
418-
VERIFY(page.client().is_ready_to_paint());
419-
page.client().paint_next_frame();
420-
}
414+
if (!navigable->is_traversable())
415+
continue;
416+
auto traversable = navigable->traversable_navigable();
417+
if (traversable && traversable->needs_repaint()) {
418+
auto& page = traversable->page();
419+
VERIFY(page.client().is_ready_to_paint());
420+
page.client().paint_next_frame();
421421
}
422422
}
423423

Libraries/LibWeb/HTML/Navigable.cpp

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2198,13 +2198,6 @@ void Navigable::perform_scroll_of_viewport(CSSPixelPoint new_position)
21982198
HTML::main_thread_event_loop().schedule();
21992199
}
22002200

2201-
void Navigable::set_needs_display(InvalidateDisplayList should_invalidate_display_list)
2202-
{
2203-
if (auto document = active_document(); document) {
2204-
document->set_needs_display(should_invalidate_display_list);
2205-
}
2206-
}
2207-
22082201
// https://html.spec.whatwg.org/#rendering-opportunity
22092202
bool Navigable::has_a_rendering_opportunity() const
22102203
{

Libraries/LibWeb/HTML/Navigable.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -173,8 +173,6 @@ class Navigable : public JS::Cell {
173173
virtual void set_viewport_size(CSSPixelSize);
174174
void perform_scroll_of_viewport(CSSPixelPoint position);
175175

176-
void set_needs_display(InvalidateDisplayList = InvalidateDisplayList::Yes);
177-
178176
// https://html.spec.whatwg.org/#rendering-opportunity
179177
[[nodiscard]] bool has_a_rendering_opportunity() const;
180178

Libraries/LibWeb/HTML/TraversableNavigable.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1429,6 +1429,8 @@ NonnullRefPtr<Gfx::PaintingSurface> TraversableNavigable::painting_surface_for_b
14291429

14301430
void TraversableNavigable::paint(DevicePixelRect const& content_rect, Painting::BackingStore& target, PaintOptions paint_options)
14311431
{
1432+
m_needs_repaint = false;
1433+
14321434
auto document = active_document();
14331435
if (!document)
14341436
return;

Libraries/LibWeb/HTML/TraversableNavigable.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,9 @@ class TraversableNavigable final : public Navigable {
113113

114114
void set_viewport_size(CSSPixelSize) override;
115115

116+
bool needs_repaint() const { return m_needs_repaint; }
117+
void set_needs_repaint() { m_needs_repaint = true; }
118+
116119
private:
117120
TraversableNavigable(GC::Ref<Page>);
118121

@@ -161,6 +164,8 @@ class TraversableNavigable final : public Navigable {
161164
RefPtr<Gfx::SkiaBackendContext> m_skia_backend_context;
162165
OwnPtr<Painting::DisplayListPlayerSkia> m_skia_player;
163166
HashMap<Gfx::Bitmap*, NonnullRefPtr<Gfx::PaintingSurface>> m_bitmap_to_surface;
167+
168+
bool m_needs_repaint { true };
164169
};
165170

166171
struct BrowsingContextAndDocument {

Services/WebContent/ConnectionFromClient.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -374,7 +374,7 @@ void ConnectionFromClient::debug_request(u64 page_id, ByteString const& request,
374374
if (request == "set-line-box-borders") {
375375
bool state = argument == "on";
376376
page->set_should_show_line_box_borders(state);
377-
page->page().top_level_traversable()->set_needs_display();
377+
page->page().top_level_traversable()->set_needs_repaint();
378378
return;
379379
}
380380

Services/WebContent/PageClient.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -879,6 +879,6 @@ Web::DisplayListPlayerType PageClient::display_list_player_type() const
879879
void PageClient::queue_screenshot_task(Optional<Web::UniqueNodeID> node_id)
880880
{
881881
m_screenshot_tasks.enqueue({ node_id });
882-
page().top_level_traversable()->set_needs_display();
882+
page().top_level_traversable()->set_needs_repaint();
883883
}
884884
}

0 commit comments

Comments
 (0)