瀏覽代碼

LibWeb: Paint page only if something that requires repaint happened

Resolves a performance regression from
8ba18dfd404543290774f21ee3ed6c802e3371cd, where moving paint scheduling
to `EventLoop::process()` led to unnecessary repaints.

This update introduces a flag to trigger repaints only when necessary,
addressing the issue where repaints previously occurred with each event
loop process, irrespective of actual changes.
Aliaksandr Kalenik 1 年之前
父節點
當前提交
c3f5dbb101

+ 5 - 3
Userland/Libraries/LibWeb/HTML/EventLoop/EventLoop.cpp

@@ -256,9 +256,11 @@ void EventLoop::process()
 
     // 16. For each fully active Document in docs, update the rendering or user interface of that Document and its browsing context to reflect the current state.
     for_each_fully_active_document_in_docs([&](DOM::Document& document) {
-        auto* browsing_context = document.browsing_context();
-        auto& page = browsing_context->page();
-        page.client().schedule_repaint();
+        if (document.navigable() && document.navigable()->needs_repaint()) {
+            auto* browsing_context = document.browsing_context();
+            auto& page = browsing_context->page();
+            page.client().schedule_repaint();
+        }
     });
 
     // 13. If all of the following are true

+ 6 - 0
Userland/Libraries/LibWeb/HTML/Navigable.cpp

@@ -1980,12 +1980,14 @@ void Navigable::set_viewport_rect(CSSPixelRect const& rect)
             document->set_needs_layout();
         }
         did_change = true;
+        m_needs_repaint = true;
     }
 
     if (m_viewport_scroll_offset != rect.location()) {
         m_viewport_scroll_offset = rect.location();
         scroll_offset_did_change();
         did_change = true;
+        m_needs_repaint = true;
     }
 
     if (did_change && active_document()) {
@@ -2036,6 +2038,8 @@ void Navigable::set_needs_display(CSSPixelRect const& rect)
     // FIXME: Ignore updates outside the visible viewport rect.
     //        This requires accounting for fixed-position elements in the input rect, which we don't do yet.
 
+    m_needs_repaint = true;
+
     if (is<TraversableNavigable>(*this)) {
         static_cast<TraversableNavigable*>(this)->page().client().page_did_invalidate(to_top_level_rect(rect));
         return;
@@ -2128,6 +2132,8 @@ void Navigable::paint(Painting::RecordingPainter& recording_painter, PaintConfig
         }
         recording_painter.commands_list().apply_scroll_offsets(scroll_offsets_by_frame_id);
     }
+
+    m_needs_repaint = false;
 }
 
 // https://html.spec.whatwg.org/multipage/browsing-the-web.html#event-uni

+ 4 - 0
Userland/Libraries/LibWeb/HTML/Navigable.h

@@ -173,6 +173,8 @@ public:
 
     [[nodiscard]] TargetSnapshotParams snapshot_target_snapshot_params();
 
+    [[nodiscard]] bool needs_repaint() const { return m_needs_repaint; }
+
     struct PaintConfig {
         bool paint_overlay { false };
         bool should_show_line_box_borders { false };
@@ -221,6 +223,8 @@ private:
 
     CSSPixelSize m_size;
     CSSPixelPoint m_viewport_scroll_offset;
+
+    bool m_needs_repaint { false };
 };
 
 HashTable<Navigable*>& all_navigables();

+ 0 - 1
Userland/Services/WebContent/PageClient.cpp

@@ -222,7 +222,6 @@ void PageClient::paint(Web::DevicePixelRect const& content_rect, Gfx::Bitmap& ta
 void PageClient::set_viewport_rect(Web::DevicePixelRect const& rect)
 {
     page().top_level_traversable()->set_viewport_rect(page().device_to_css_rect(rect));
-    Web::HTML::main_thread_event_loop().schedule();
 }
 
 void PageClient::page_did_invalidate(Web::CSSPixelRect const&)