From 3b360a1ccda2fa1151760cbbc67a04265545acaa Mon Sep 17 00:00:00 2001 From: Aliaksandr Kalenik Date: Sun, 26 May 2024 16:08:59 +0100 Subject: [PATCH] LibWeb: Use stack to represent blit/sample corners commands state ...instead of allocating separate BorderRadiusCornerClipper for each executed sample/blit commands pair. With this change a vector of BorderRadiusCornerClipper has much less items. For example on twitter profile page its size goes down from ~3000 to ~3 items. --- .../LibWeb/Painting/CommandExecutorCPU.cpp | 20 ++++++++++--------- .../LibWeb/Painting/CommandExecutorCPU.h | 4 +++- .../LibWeb/Painting/CommandExecutorGPU.cpp | 2 +- .../LibWeb/Painting/CommandExecutorGPU.h | 2 +- .../Libraries/LibWeb/Painting/CommandList.cpp | 2 +- .../Libraries/LibWeb/Painting/CommandList.h | 6 +++++- .../LibWeb/Painting/RecordingPainter.cpp | 2 ++ 7 files changed, 24 insertions(+), 14 deletions(-) diff --git a/Userland/Libraries/LibWeb/Painting/CommandExecutorCPU.cpp b/Userland/Libraries/LibWeb/Painting/CommandExecutorCPU.cpp index dbbeef74df55b78..0dd412e97827c12 100644 --- a/Userland/Libraries/LibWeb/Painting/CommandExecutorCPU.cpp +++ b/Userland/Libraries/LibWeb/Painting/CommandExecutorCPU.cpp @@ -453,21 +453,23 @@ CommandResult CommandExecutorCPU::draw_triangle_wave(Gfx::IntPoint const& p1, Gf return CommandResult::Continue; } -CommandResult CommandExecutorCPU::sample_under_corners(u32 id, CornerRadii const& corner_radii, Gfx::IntRect const& border_rect, CornerClip corner_clip) +void CommandExecutorCPU::prepare_to_execute(size_t corner_clip_max_depth) { - if (id >= m_corner_clippers.size()) - m_corner_clippers.resize(id + 1); + m_corner_clippers_stack.ensure_capacity(corner_clip_max_depth); +} - auto clipper = BorderRadiusCornerClipper::create(corner_radii, border_rect.to_type(), corner_clip); - m_corner_clippers[id] = clipper.release_value(); - m_corner_clippers[id]->sample_under_corners(painter()); +CommandResult CommandExecutorCPU::sample_under_corners([[maybe_unused]] u32 id, CornerRadii const& corner_radii, Gfx::IntRect const& border_rect, CornerClip corner_clip) +{ + auto clipper = BorderRadiusCornerClipper::create(corner_radii, border_rect.to_type(), corner_clip).release_value(); + clipper->sample_under_corners(painter()); + m_corner_clippers_stack.append(clipper); return CommandResult::Continue; } -CommandResult CommandExecutorCPU::blit_corner_clipping(u32 id) +CommandResult CommandExecutorCPU::blit_corner_clipping([[maybe_unused]] u32 id) { - m_corner_clippers[id]->blit_corner_clipping(painter()); - m_corner_clippers[id] = nullptr; + auto clipper = m_corner_clippers_stack.take_last(); + clipper->blit_corner_clipping(painter()); return CommandResult::Continue; } diff --git a/Userland/Libraries/LibWeb/Painting/CommandExecutorCPU.h b/Userland/Libraries/LibWeb/Painting/CommandExecutorCPU.h index b2e933e9e1e5ca2..996a49089637014 100644 --- a/Userland/Libraries/LibWeb/Painting/CommandExecutorCPU.h +++ b/Userland/Libraries/LibWeb/Painting/CommandExecutorCPU.h @@ -49,6 +49,8 @@ class CommandExecutorCPU : public CommandExecutor { bool needs_prepare_glyphs_texture() const override { return false; } void prepare_glyph_texture(HashMap> const&) override {}; + virtual void prepare_to_execute(size_t corner_clip_max_depth) override; + bool needs_update_immutable_bitmap_texture_cache() const override { return false; } void update_immutable_bitmap_texture_cache(HashMap&) override {}; @@ -56,7 +58,7 @@ class CommandExecutorCPU : public CommandExecutor { private: Gfx::Bitmap& m_target_bitmap; - Vector> m_corner_clippers; + Vector> m_corner_clippers_stack; struct StackingContext { MaybeOwned painter; diff --git a/Userland/Libraries/LibWeb/Painting/CommandExecutorGPU.cpp b/Userland/Libraries/LibWeb/Painting/CommandExecutorGPU.cpp index dd37590ecfbbf93..ff4e11403b07357 100644 --- a/Userland/Libraries/LibWeb/Painting/CommandExecutorGPU.cpp +++ b/Userland/Libraries/LibWeb/Painting/CommandExecutorGPU.cpp @@ -429,7 +429,7 @@ void CommandExecutorGPU::prepare_glyph_texture(HashMap> const&) override; - virtual void prepare_to_execute() override; + virtual void prepare_to_execute(size_t corner_clip_max_depth) override; bool needs_update_immutable_bitmap_texture_cache() const override { return true; } void update_immutable_bitmap_texture_cache(HashMap&) override; diff --git a/Userland/Libraries/LibWeb/Painting/CommandList.cpp b/Userland/Libraries/LibWeb/Painting/CommandList.cpp index 20116272e22ddc7..345b76d8d8b4fa6 100644 --- a/Userland/Libraries/LibWeb/Painting/CommandList.cpp +++ b/Userland/Libraries/LibWeb/Painting/CommandList.cpp @@ -78,7 +78,7 @@ void CommandList::mark_unnecessary_commands() void CommandList::execute(CommandExecutor& executor) { - executor.prepare_to_execute(); + executor.prepare_to_execute(m_corner_clip_max_depth); if (executor.needs_prepare_glyphs_texture()) { HashMap> unique_glyphs; diff --git a/Userland/Libraries/LibWeb/Painting/CommandList.h b/Userland/Libraries/LibWeb/Painting/CommandList.h index 80c5186a4dc4924..efa970a0a2427a7 100644 --- a/Userland/Libraries/LibWeb/Painting/CommandList.h +++ b/Userland/Libraries/LibWeb/Painting/CommandList.h @@ -86,7 +86,7 @@ class CommandExecutor { virtual bool would_be_fully_clipped_by_painter(Gfx::IntRect) const = 0; virtual bool needs_prepare_glyphs_texture() const { return false; } virtual void prepare_glyph_texture(HashMap> const& unique_glyphs) = 0; - virtual void prepare_to_execute() { } + virtual void prepare_to_execute([[maybe_unused]] size_t corner_clip_max_depth) { } virtual bool needs_update_immutable_bitmap_texture_cache() const = 0; virtual void update_immutable_bitmap_texture_cache(HashMap&) = 0; }; @@ -99,6 +99,9 @@ class CommandList { void mark_unnecessary_commands(); void execute(CommandExecutor&); + size_t corner_clip_max_depth() const { return m_corner_clip_max_depth; } + void set_corner_clip_max_depth(size_t depth) { m_corner_clip_max_depth = depth; } + private: struct CommandListItem { Optional scroll_frame_id; @@ -106,6 +109,7 @@ class CommandList { bool skip { false }; }; + size_t m_corner_clip_max_depth { 0 }; AK::SegmentedVector m_commands; }; diff --git a/Userland/Libraries/LibWeb/Painting/RecordingPainter.cpp b/Userland/Libraries/LibWeb/Painting/RecordingPainter.cpp index 0bdfb4351744abd..a3a5c64b81cfff4 100644 --- a/Userland/Libraries/LibWeb/Painting/RecordingPainter.cpp +++ b/Userland/Libraries/LibWeb/Painting/RecordingPainter.cpp @@ -28,6 +28,8 @@ void RecordingPainter::append(Command&& command) void RecordingPainter::sample_under_corners(u32 id, CornerRadii corner_radii, Gfx::IntRect border_rect, CornerClip corner_clip) { m_corner_clip_state_stack.append({ id, border_rect }); + if (m_corner_clip_state_stack.size() > commands_list().corner_clip_max_depth()) + commands_list().set_corner_clip_max_depth(m_corner_clip_state_stack.size()); append(SampleUnderCorners { id, corner_radii,