Browse Source

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.
Aliaksandr Kalenik 1 year ago
parent
commit
04a4ffaa3d

+ 19 - 22
Userland/Libraries/LibWeb/Painting/RecordingPainter.cpp

@@ -123,23 +123,10 @@ CommandResult DrawScaledBitmap::execute(CommandExecutionState& state) const
     return CommandResult::Continue;
     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();
     auto& painter = state.painter();
+    painter.clear_clip_rect();
     painter.add_clip_rect(rect);
     painter.add_clip_rect(rect);
     return CommandResult::Continue;
     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)
 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)
 void RecordingPainter::translate(int dx, int dy)
@@ -674,14 +664,21 @@ void RecordingPainter::set_font(Gfx::Font const& font)
 void RecordingPainter::save()
 void RecordingPainter::save()
 {
 {
     m_state_stack.append(m_state_stack.last());
     m_state_stack.append(m_state_stack.last());
-    push_command(SaveState {});
 }
 }
 
 
 void RecordingPainter::restore()
 void RecordingPainter::restore()
 {
 {
+    auto prev_clip_rect = state().clip_rect;
+
     VERIFY(m_state_stack.size() > 1);
     VERIFY(m_state_stack.size() > 1);
     m_state_stack.take_last();
     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)
 void RecordingPainter::push_stacking_context(PushStackingContextParams params)

+ 3 - 13
Userland/Libraries/LibWeb/Painting/RecordingPainter.h

@@ -83,15 +83,7 @@ struct DrawScaledBitmap {
     [[nodiscard]] CommandResult execute(CommandExecutionState&) const;
     [[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;
     Gfx::IntRect rect;
 
 
     [[nodiscard]] CommandResult execute(CommandExecutionState&) const;
     [[nodiscard]] CommandResult execute(CommandExecutionState&) const;
@@ -361,9 +353,7 @@ using PaintingCommand = Variant<
     DrawText,
     DrawText,
     FillRect,
     FillRect,
     DrawScaledBitmap,
     DrawScaledBitmap,
-    SaveState,
-    RestoreState,
-    AddClipRect,
+    SetClipRect,
     ClearClipRect,
     ClearClipRect,
     SetFont,
     SetFont,
     PushStackingContext,
     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 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 add_clip_rect(Gfx::IntRect const& rect);
-    void clear_clip_rect();
 
 
     void translate(int dx, int dy);
     void translate(int dx, int dy);
     void translate(Gfx::IntPoint delta);
     void translate(Gfx::IntPoint delta);
@@ -510,6 +499,7 @@ public:
 
 
     struct State {
     struct State {
         Gfx::AffineTransform translation;
         Gfx::AffineTransform translation;
+        Optional<Gfx::IntRect> clip_rect;
     };
     };
     State& state() { return m_state_stack.last(); }
     State& state() { return m_state_stack.last(); }
     State const& state() const { return m_state_stack.last(); }
     State const& state() const { return m_state_stack.last(); }