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 far fewer
items. For example on twitter profile page its size goes down from
~3000 to ~3 items.
This commit is contained in:
Aliaksandr Kalenik
2024-05-26 16:08:59 +01:00
committed by Andreas Kling
parent 9b65a2731b
commit 0eeae7ff24
7 changed files with 24 additions and 14 deletions

View File

@@ -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<DevicePixels>(), 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<DevicePixels>(), 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;
}

View File

@@ -49,6 +49,8 @@ public:
bool needs_prepare_glyphs_texture() const override { return false; }
void prepare_glyph_texture(HashMap<Gfx::Font const*, HashTable<u32>> 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<u32, Gfx::ImmutableBitmap const*>&) override {};
@@ -56,7 +58,7 @@ public:
private:
Gfx::Bitmap& m_target_bitmap;
Vector<RefPtr<BorderRadiusCornerClipper>> m_corner_clippers;
Vector<RefPtr<BorderRadiusCornerClipper>> m_corner_clippers_stack;
struct StackingContext {
MaybeOwned<Gfx::Painter> painter;

View File

@@ -429,7 +429,7 @@ void CommandExecutorGPU::prepare_glyph_texture(HashMap<Gfx::Font const*, HashTab
AccelGfx::GlyphAtlas::the().update(unique_glyphs);
}
void CommandExecutorGPU::prepare_to_execute()
void CommandExecutorGPU::prepare_to_execute([[maybe_unused]] size_t corner_clip_max_depth)
{
m_context.activate();
}

View File

@@ -50,7 +50,7 @@ public:
virtual bool needs_prepare_glyphs_texture() const override { return true; }
void prepare_glyph_texture(HashMap<Gfx::Font const*, HashTable<u32>> 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<u32, Gfx::ImmutableBitmap const*>&) override;

View File

@@ -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<Gfx::Font const*, HashTable<u32>> unique_glyphs;

View File

@@ -86,7 +86,7 @@ public:
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<Gfx::Font const*, HashTable<u32>> 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<u32, Gfx::ImmutableBitmap const*>&) = 0;
};
@@ -99,6 +99,9 @@ public:
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<i32> scroll_frame_id;
@@ -106,6 +109,7 @@ private:
bool skip { false };
};
size_t m_corner_clip_max_depth { 0 };
AK::SegmentedVector<CommandListItem, 512> m_commands;
};

View File

@@ -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,