LibWeb: Reuse display list across repaints

...if only the scroll offset is updated.

Currently, on any document with a large amount of content, the process
of building a display list is often more expensive than its
rasterization. This is because the amount of work required to build a
display list is proportional to the size of the paintable tree, whereas
rasterization only occurs for the portion visible in the viewport.

This change is the first step toward improving this process by caching
the display list across repaints when neither style nor layout requires
invalidation. This means that repainting while scrolling becomes
significantly less expensive, as we only need to reapply the scroll
offsets to the existing display list.

The performance improvement is especially visible on pages like
https://ziglang.org/documentation/master/ or
https://www.w3.org/TR/css-grid-2/
This commit is contained in:
Aliaksandr Kalenik 2024-08-12 00:49:32 +02:00 committed by Andreas Kling
commit 18fc23b3d6
Notes: github-actions[bot] 2024-08-19 16:58:08 +00:00
6 changed files with 46 additions and 1 deletions

View file

@ -186,6 +186,7 @@ Gfx::Painter* CanvasRenderingContext2D::painter()
if (!canvas_element().bitmap()) {
if (!canvas_element().create_bitmap())
return nullptr;
canvas_element().document().invalidate_display_list();
m_painter = make<Gfx::Painter>(*canvas_element().bitmap());
}
return m_painter.ptr();

View file

@ -22,6 +22,7 @@
#include <LibWeb/HTML/StructuredSerialize.h>
#include <LibWeb/HTML/TokenizedFeatures.h>
#include <LibWeb/Page/EventHandler.h>
#include <LibWeb/Painting/DisplayList.h>
#include <LibWeb/PixelUnits.h>
#include <LibWeb/XHR/FormDataEntry.h>

View file

@ -16,6 +16,7 @@
#include <LibWeb/HTML/TraversableNavigable.h>
#include <LibWeb/HTML/Window.h>
#include <LibWeb/Page/Page.h>
#include <LibWeb/Painting/ViewportPaintable.h>
#include <LibWeb/Platform/EventLoopPlugin.h>
namespace Web::HTML {
@ -1193,6 +1194,12 @@ void TraversableNavigable::paint(DevicePixelRect const& content_rect, Painting::
if (!document)
return;
for (auto& navigable : all_navigables()) {
if (auto active_document = navigable->active_document(); active_document && active_document->paintable()) {
active_document->paintable()->refresh_scroll_state();
}
}
DOM::Document::PaintConfig paint_config;
paint_config.paint_overlay = paint_options.paint_overlay == PaintOptions::PaintOverlay::Yes;
paint_config.should_show_line_box_borders = paint_options.should_show_line_box_borders;