LibWeb: Don't produce save & restore commands for scroll frame id change
Some checks are pending
CI / Lagom (false, FUZZ, ubuntu-24.04, Linux, Clang) (push) Waiting to run
CI / Lagom (false, NO_FUZZ, macos-14, macOS, Clang) (push) Waiting to run
CI / Lagom (false, NO_FUZZ, ubuntu-24.04, Linux, GNU) (push) Waiting to run
CI / Lagom (true, NO_FUZZ, ubuntu-24.04, Linux, Clang) (push) Waiting to run
Package the js repl as a binary artifact / build-and-package (macos-14, macOS, macOS-universal2) (push) Waiting to run
Package the js repl as a binary artifact / build-and-package (ubuntu-24.04, Linux, Linux-x86_64) (push) Waiting to run
Run test262 and test-wasm / run_and_update_results (push) Waiting to run
Lint Code / lint (push) Waiting to run
Push notes / build (push) Waiting to run

This allows to substantially decrease display list length and
save/restore churn during painting.

Display list size comparison:

|               | Before | After  |
| ------------- | ------ | ------ |
| basecamp.com  | 19066  | 12248  |
| ladybird.org  | 8878   | 2220   |
| react.dev     | 39074  | 24382  |
This commit is contained in:
Aliaksandr Kalenik 2024-10-11 15:18:39 +02:00 committed by Andreas Kling
parent 4eec621d3a
commit 34261e5490
Notes: github-actions[bot] 2024-10-11 15:27:49 +00:00
7 changed files with 41 additions and 40 deletions

View file

@ -47,12 +47,11 @@ void ClippableAndScrollable::apply_clip(PaintContext& context) const
auto& display_list_recorder = context.display_list_recorder();
display_list_recorder.save();
auto saved_scroll_frame_id = display_list_recorder.scroll_frame_id();
for (auto const& clip_rect : clip_rects) {
Optional<i32> clip_scroll_frame_id;
if (clip_rect.enclosing_scroll_frame)
clip_scroll_frame_id = clip_rect.enclosing_scroll_frame->id();
display_list_recorder.set_scroll_frame_id(clip_scroll_frame_id);
display_list_recorder.push_scroll_frame_id(clip_scroll_frame_id);
auto rect = context.rounded_device_rect(clip_rect.rect).to_type<int>();
auto corner_radii = clip_rect.corner_radii.as_corners(context);
if (corner_radii.has_any_radius()) {
@ -60,8 +59,8 @@ void ClippableAndScrollable::apply_clip(PaintContext& context) const
} else {
display_list_recorder.add_clip_rect(rect);
}
display_list_recorder.pop_scroll_frame_id();
}
display_list_recorder.set_scroll_frame_id(saved_scroll_frame_id);
}
void ClippableAndScrollable::restore_clip(PaintContext& context) const

View file

@ -12,14 +12,16 @@ namespace Web::Painting {
DisplayListRecorder::DisplayListRecorder(DisplayList& command_list)
: m_command_list(command_list)
{
m_state_stack.append(State());
}
DisplayListRecorder::~DisplayListRecorder() = default;
void DisplayListRecorder::append(Command&& command)
{
m_command_list.append(move(command), state().scroll_frame_id);
Optional<i32> scroll_frame_id;
if (!m_scroll_frame_id_stack.is_empty())
scroll_frame_id = m_scroll_frame_id_stack.last();
m_command_list.append(move(command), scroll_frame_id);
}
void DisplayListRecorder::paint_nested_display_list(RefPtr<DisplayList> display_list, Gfx::IntRect rect)
@ -261,15 +263,21 @@ void DisplayListRecorder::translate(Gfx::IntPoint delta)
void DisplayListRecorder::save()
{
append(Save {});
m_state_stack.append(m_state_stack.last());
}
void DisplayListRecorder::restore()
{
append(Restore {});
}
VERIFY(m_state_stack.size() > 1);
m_state_stack.take_last();
void DisplayListRecorder::push_scroll_frame_id(Optional<i32> id)
{
m_scroll_frame_id_stack.append(id);
}
void DisplayListRecorder::pop_scroll_frame_id()
{
(void)m_scroll_frame_id_stack.take_last();
}
void DisplayListRecorder::push_stacking_context(PushStackingContextParams params)
@ -282,12 +290,12 @@ void DisplayListRecorder::push_stacking_context(PushStackingContextParams params
.matrix = params.transform.matrix,
},
.clip_path = params.clip_path });
m_state_stack.append(State());
m_scroll_frame_id_stack.append({});
}
void DisplayListRecorder::pop_stacking_context()
{
m_state_stack.take_last();
(void)m_scroll_frame_id_stack.take_last();
append(PopStackingContext {});
}

View file

@ -103,15 +103,8 @@ public:
void translate(Gfx::IntPoint delta);
void set_scroll_frame_id(Optional<i32> id)
{
state().scroll_frame_id = id;
}
Optional<i32> scroll_frame_id() const
{
return state().scroll_frame_id;
}
void push_scroll_frame_id(Optional<i32> id);
void pop_scroll_frame_id();
void save();
void restore();
@ -157,13 +150,7 @@ public:
void append(Command&& command);
private:
struct State {
Optional<i32> scroll_frame_id;
};
State& state() { return m_state_stack.last(); }
State const& state() const { return m_state_stack.last(); }
Vector<State> m_state_stack;
Vector<Optional<i32>> m_scroll_frame_id_stack;
DisplayList& m_command_list;
};

View file

@ -37,15 +37,15 @@ void InlinePaintable::before_paint(PaintContext& context, PaintPhase) const
apply_clip(context);
if (scroll_frame_id().has_value()) {
context.display_list_recorder().save();
context.display_list_recorder().set_scroll_frame_id(scroll_frame_id().value());
context.display_list_recorder().push_scroll_frame_id(scroll_frame_id().value());
}
}
void InlinePaintable::after_paint(PaintContext& context, PaintPhase) const
{
if (scroll_frame_id().has_value())
context.display_list_recorder().restore();
if (scroll_frame_id().has_value()) {
context.display_list_recorder().pop_scroll_frame_id();
}
restore_clip(context);
}

View file

@ -477,15 +477,15 @@ BorderRadiiData PaintableBox::normalized_border_radii_data(ShrinkRadiiForBorders
void PaintableBox::apply_scroll_offset(PaintContext& context, PaintPhase) const
{
if (scroll_frame_id().has_value()) {
context.display_list_recorder().save();
context.display_list_recorder().set_scroll_frame_id(scroll_frame_id().value());
context.display_list_recorder().push_scroll_frame_id(scroll_frame_id().value());
}
}
void PaintableBox::reset_scroll_offset(PaintContext& context, PaintPhase) const
{
if (scroll_frame_id().has_value())
context.display_list_recorder().restore();
if (scroll_frame_id().has_value()) {
context.display_list_recorder().pop_scroll_frame_id();
}
}
void PaintableBox::apply_clip_overflow_rect(PaintContext& context, PaintPhase phase) const
@ -687,7 +687,7 @@ void PaintableWithLines::paint(PaintContext& context, PaintPhase phase) const
}
if (own_scroll_frame_id().has_value()) {
context.display_list_recorder().set_scroll_frame_id(own_scroll_frame_id().value());
context.display_list_recorder().push_scroll_frame_id(own_scroll_frame_id().value());
}
}
@ -716,6 +716,10 @@ void PaintableWithLines::paint(PaintContext& context, PaintPhase phase) const
if (should_clip_overflow) {
context.display_list_recorder().restore();
if (own_scroll_frame_id().has_value()) {
context.display_list_recorder().pop_scroll_frame_id();
}
}
}

View file

@ -31,8 +31,7 @@ void SVGSVGPaintable::before_children_paint(PaintContext& context, PaintPhase ph
PaintableBox::before_children_paint(context, phase);
if (phase != PaintPhase::Foreground)
return;
context.display_list_recorder().save();
context.display_list_recorder().set_scroll_frame_id(scroll_frame_id());
context.display_list_recorder().push_scroll_frame_id(scroll_frame_id());
}
void SVGSVGPaintable::after_children_paint(PaintContext& context, PaintPhase phase) const
@ -40,7 +39,7 @@ void SVGSVGPaintable::after_children_paint(PaintContext& context, PaintPhase pha
PaintableBox::after_children_paint(context, phase);
if (phase != PaintPhase::Foreground)
return;
context.display_list_recorder().restore();
context.display_list_recorder().pop_scroll_frame_id();
}
static Gfx::FloatMatrix4x4 matrix_with_scaled_translation(Gfx::FloatMatrix4x4 matrix, float scale)

View file

@ -335,8 +335,9 @@ void StackingContext::paint(PaintContext& context) const
if (has_css_transform) {
paintable_box().apply_clip_overflow_rect(context, PaintPhase::Foreground);
}
if (paintable().is_paintable_box() && paintable_box().scroll_frame_id().has_value())
context.display_list_recorder().set_scroll_frame_id(*paintable_box().scroll_frame_id());
if (paintable().is_paintable_box() && paintable_box().scroll_frame_id().has_value()) {
context.display_list_recorder().push_scroll_frame_id(*paintable_box().scroll_frame_id());
}
context.display_list_recorder().push_stacking_context(push_stacking_context_params);
if (paintable().is_paintable_box()) {
@ -353,6 +354,9 @@ void StackingContext::paint(PaintContext& context) const
paint_internal(context);
context.display_list_recorder().pop_stacking_context();
if (paintable().is_paintable_box() && paintable_box().scroll_frame_id().has_value()) {
context.display_list_recorder().pop_scroll_frame_id();
}
if (has_css_transform)
paintable_box().clear_clip_overflow_rect(context, PaintPhase::Foreground);
context.display_list_recorder().restore();