From 04a4ffaa3dca91ac47fd282b1e7856b66877e2bc Mon Sep 17 00:00:00 2001 From: Aliaksandr Kalenik Date: Thu, 26 Oct 2023 04:12:57 +0200 Subject: [PATCH] LibWeb/Painting: Remove Save and Restore commands in RecordingPainter Removing State and Restore reduces painting commands count by 30-50% on an average website. Due to this change, it was also necessary to replace AddClipRect with SetClipRect command. --- .../LibWeb/Painting/RecordingPainter.cpp | 41 +++++++++---------- .../LibWeb/Painting/RecordingPainter.h | 16 ++------ 2 files changed, 22 insertions(+), 35 deletions(-) diff --git a/Userland/Libraries/LibWeb/Painting/RecordingPainter.cpp b/Userland/Libraries/LibWeb/Painting/RecordingPainter.cpp index 8b47473de3..f1c3d877c0 100644 --- a/Userland/Libraries/LibWeb/Painting/RecordingPainter.cpp +++ b/Userland/Libraries/LibWeb/Painting/RecordingPainter.cpp @@ -123,23 +123,10 @@ CommandResult DrawScaledBitmap::execute(CommandExecutionState& state) const return CommandResult::Continue; } -CommandResult SaveState::execute(CommandExecutionState& state) const -{ - auto& painter = state.painter(); - painter.save(); - return CommandResult::Continue; -} - -CommandResult RestoreState::execute(CommandExecutionState& state) const -{ - auto& painter = state.painter(); - painter.restore(); - return CommandResult::Continue; -} - -CommandResult AddClipRect::execute(CommandExecutionState& state) const +CommandResult SetClipRect::execute(CommandExecutionState& state) const { auto& painter = state.painter(); + painter.clear_clip_rect(); painter.add_clip_rect(rect); return CommandResult::Continue; } @@ -648,12 +635,15 @@ void RecordingPainter::draw_text_run(Gfx::IntPoint baseline_start, Utf8View stri void RecordingPainter::add_clip_rect(Gfx::IntRect const& rect) { - push_command(AddClipRect { .rect = state().translation.map(rect) }); -} + auto prev_clip_rect = state().clip_rect; + if (!state().clip_rect.has_value()) { + state().clip_rect = state().translation.map(rect); + } else { + state().clip_rect->intersect(state().translation.map(rect)); + } -void RecordingPainter::clear_clip_rect() -{ - push_command(ClearClipRect {}); + if (prev_clip_rect != state().clip_rect) + push_command(SetClipRect { .rect = *state().clip_rect }); } void RecordingPainter::translate(int dx, int dy) @@ -674,14 +664,21 @@ void RecordingPainter::set_font(Gfx::Font const& font) void RecordingPainter::save() { m_state_stack.append(m_state_stack.last()); - push_command(SaveState {}); } void RecordingPainter::restore() { + auto prev_clip_rect = state().clip_rect; + VERIFY(m_state_stack.size() > 1); m_state_stack.take_last(); - push_command(RestoreState {}); + + if (state().clip_rect != prev_clip_rect) { + if (state().clip_rect.has_value()) + push_command(SetClipRect { .rect = *state().clip_rect }); + else + push_command(ClearClipRect {}); + } } void RecordingPainter::push_stacking_context(PushStackingContextParams params) diff --git a/Userland/Libraries/LibWeb/Painting/RecordingPainter.h b/Userland/Libraries/LibWeb/Painting/RecordingPainter.h index 6e0149c9fa..6996bb0815 100644 --- a/Userland/Libraries/LibWeb/Painting/RecordingPainter.h +++ b/Userland/Libraries/LibWeb/Painting/RecordingPainter.h @@ -83,15 +83,7 @@ struct DrawScaledBitmap { [[nodiscard]] CommandResult execute(CommandExecutionState&) const; }; -struct SaveState { - [[nodiscard]] CommandResult execute(CommandExecutionState&) const; -}; - -struct RestoreState { - [[nodiscard]] CommandResult execute(CommandExecutionState&) const; -}; - -struct AddClipRect { +struct SetClipRect { Gfx::IntRect rect; [[nodiscard]] CommandResult execute(CommandExecutionState&) const; @@ -361,9 +353,7 @@ using PaintingCommand = Variant< DrawText, FillRect, DrawScaledBitmap, - SaveState, - RestoreState, - AddClipRect, + SetClipRect, ClearClipRect, SetFont, PushStackingContext, @@ -454,7 +444,6 @@ public: void draw_text_run(Gfx::IntPoint baseline_start, Utf8View string, Gfx::Font const& font, Color color, Gfx::IntRect const& rect); void add_clip_rect(Gfx::IntRect const& rect); - void clear_clip_rect(); void translate(int dx, int dy); void translate(Gfx::IntPoint delta); @@ -510,6 +499,7 @@ public: struct State { Gfx::AffineTransform translation; + Optional clip_rect; }; State& state() { return m_state_stack.last(); } State const& state() const { return m_state_stack.last(); }