LibWeb: Move display list command dispatch into player

With this change display list player will be able to recurse into
executing another display list, without having to construct new display
list player. It is going to be useful in the upcoming changes to paint
a mask from a display list owned by a command.
This commit is contained in:
Aliaksandr Kalenik 2024-07-24 16:48:32 +03:00 committed by Andreas Kling
parent 5a796629c6
commit e8b7c88881
Notes: github-actions[bot] 2024-07-25 12:34:47 +00:00
6 changed files with 41 additions and 33 deletions

View file

@ -1209,7 +1209,7 @@ void TraversableNavigable::paint(DevicePixelRect const& content_rect, Painting::
auto& iosurface_backing_store = static_cast<Painting::IOSurfaceBackingStore&>(target); auto& iosurface_backing_store = static_cast<Painting::IOSurfaceBackingStore&>(target);
auto texture = m_metal_context->create_texture_from_iosurface(iosurface_backing_store.iosurface_handle()); auto texture = m_metal_context->create_texture_from_iosurface(iosurface_backing_store.iosurface_handle());
Painting::DisplayListPlayerSkia player(*m_skia_backend_context, *texture); Painting::DisplayListPlayerSkia player(*m_skia_backend_context, *texture);
display_list.execute(player); player.execute(display_list);
return; return;
} }
#endif #endif
@ -1217,19 +1217,19 @@ void TraversableNavigable::paint(DevicePixelRect const& content_rect, Painting::
#ifdef USE_VULKAN #ifdef USE_VULKAN
if (m_skia_backend_context) { if (m_skia_backend_context) {
Painting::DisplayListPlayerSkia player(*m_skia_backend_context, target.bitmap()); Painting::DisplayListPlayerSkia player(*m_skia_backend_context, target.bitmap());
display_list.execute(player); player.execute(display_list);
return; return;
} }
#endif #endif
// Fallback to CPU backend if GPU is not available // Fallback to CPU backend if GPU is not available
Painting::DisplayListPlayerSkia player(target.bitmap()); Painting::DisplayListPlayerSkia player(target.bitmap());
display_list.execute(player); player.execute(display_list);
break; break;
} }
case DisplayListPlayerType::SkiaCPU: { case DisplayListPlayerType::SkiaCPU: {
Painting::DisplayListPlayerSkia player(target.bitmap()); Painting::DisplayListPlayerSkia player(target.bitmap());
display_list.execute(player); player.execute(display_list);
break; break;
} }
default: default:

View file

@ -76,19 +76,21 @@ void DisplayList::mark_unnecessary_commands()
VERIFY(sample_blit_ranges.is_empty()); VERIFY(sample_blit_ranges.is_empty());
} }
void DisplayList::execute(DisplayListPlayer& executor) void DisplayListPlayer::execute(DisplayList& display_list)
{ {
auto const& commands = display_list.commands();
HashTable<u32> skipped_sample_corner_commands; HashTable<u32> skipped_sample_corner_commands;
size_t next_command_index = 0; size_t next_command_index = 0;
while (next_command_index < m_commands.size()) { while (next_command_index < commands.size()) {
if (m_commands[next_command_index].skip) { if (commands[next_command_index].skip) {
next_command_index++; next_command_index++;
continue; continue;
} }
auto& command = m_commands[next_command_index++].command; auto& command = commands[next_command_index++].command;
auto bounding_rect = command_bounding_rectangle(command); auto bounding_rect = command_bounding_rectangle(command);
if (bounding_rect.has_value() && (bounding_rect->is_empty() || executor.would_be_fully_clipped_by_painter(*bounding_rect))) { if (bounding_rect.has_value() && (bounding_rect->is_empty() || would_be_fully_clipped_by_painter(*bounding_rect))) {
if (command.has<SampleUnderCorners>()) { if (command.has<SampleUnderCorners>()) {
auto const& sample_under_corners = command.get<SampleUnderCorners>(); auto const& sample_under_corners = command.get<SampleUnderCorners>();
skipped_sample_corner_commands.set(sample_under_corners.id); skipped_sample_corner_commands.set(sample_under_corners.id);
@ -110,7 +112,7 @@ void DisplayList::execute(DisplayListPlayer& executor)
#define HANDLE_COMMAND(command_type, executor_method) \ #define HANDLE_COMMAND(command_type, executor_method) \
if (command.has<command_type>()) { \ if (command.has<command_type>()) { \
executor.executor_method(command.get<command_type>()); \ executor_method(command.get<command_type>()); \
} }
// clang-format off // clang-format off

View file

@ -32,10 +32,15 @@
namespace Web::Painting { namespace Web::Painting {
class DisplayList;
class DisplayListPlayer { class DisplayListPlayer {
public: public:
virtual ~DisplayListPlayer() = default; virtual ~DisplayListPlayer() = default;
void execute(DisplayList& display_list);
private:
virtual void draw_glyph_run(DrawGlyphRun const&) = 0; virtual void draw_glyph_run(DrawGlyphRun const&) = 0;
virtual void fill_rect(FillRect const&) = 0; virtual void fill_rect(FillRect const&) = 0;
virtual void draw_scaled_bitmap(DrawScaledBitmap const&) = 0; virtual void draw_scaled_bitmap(DrawScaledBitmap const&) = 0;
@ -74,15 +79,16 @@ public:
void apply_scroll_offsets(Vector<Gfx::IntPoint> const& offsets_by_frame_id); void apply_scroll_offsets(Vector<Gfx::IntPoint> const& offsets_by_frame_id);
void mark_unnecessary_commands(); void mark_unnecessary_commands();
void execute(DisplayListPlayer&);
private:
struct CommandListItem { struct CommandListItem {
Optional<i32> scroll_frame_id; Optional<i32> scroll_frame_id;
Command command; Command command;
bool skip { false }; bool skip { false };
}; };
AK::SegmentedVector<CommandListItem, 512> const& commands() const { return m_commands; }
private:
AK::SegmentedVector<CommandListItem, 512> m_commands; AK::SegmentedVector<CommandListItem, 512> m_commands;
}; };

View file

@ -33,6 +33,21 @@ public:
class DisplayListPlayerSkia : public DisplayListPlayer { class DisplayListPlayerSkia : public DisplayListPlayer {
public: public:
DisplayListPlayerSkia(Gfx::Bitmap&);
#ifdef USE_VULKAN
static OwnPtr<SkiaBackendContext> create_vulkan_context(Core::VulkanContext&);
DisplayListPlayerSkia(SkiaBackendContext&, Gfx::Bitmap&);
#endif
#ifdef AK_OS_MACOS
static OwnPtr<SkiaBackendContext> create_metal_context(Core::MetalContext const&);
DisplayListPlayerSkia(SkiaBackendContext&, Core::MetalTexture&);
#endif
virtual ~DisplayListPlayerSkia() override;
private:
void draw_glyph_run(DrawGlyphRun const&) override; void draw_glyph_run(DrawGlyphRun const&) override;
void fill_rect(FillRect const&) override; void fill_rect(FillRect const&) override;
void draw_scaled_bitmap(DrawScaledBitmap const&) override; void draw_scaled_bitmap(DrawScaledBitmap const&) override;
@ -65,21 +80,6 @@ public:
bool would_be_fully_clipped_by_painter(Gfx::IntRect) const override; bool would_be_fully_clipped_by_painter(Gfx::IntRect) const override;
DisplayListPlayerSkia(Gfx::Bitmap&);
#ifdef USE_VULKAN
static OwnPtr<SkiaBackendContext> create_vulkan_context(Core::VulkanContext&);
DisplayListPlayerSkia(SkiaBackendContext&, Gfx::Bitmap&);
#endif
#ifdef AK_OS_MACOS
static OwnPtr<SkiaBackendContext> create_metal_context(Core::MetalContext const&);
DisplayListPlayerSkia(SkiaBackendContext&, Core::MetalTexture&);
#endif
virtual ~DisplayListPlayerSkia() override;
private:
class SkiaSurface; class SkiaSurface;
SkiaSurface& surface() const; SkiaSurface& surface() const;

View file

@ -88,8 +88,8 @@ RefPtr<Gfx::Bitmap> SVGMaskable::calculate_mask_of_svg(PaintContext& context, CS
paint_context.set_svg_transform(graphics_element.get_transform()); paint_context.set_svg_transform(graphics_element.get_transform());
paint_context.set_draw_svg_geometry_for_clip_path(is<SVGClipPaintable>(paintable)); paint_context.set_draw_svg_geometry_for_clip_path(is<SVGClipPaintable>(paintable));
StackingContext::paint_node_as_stacking_context(paintable, paint_context); StackingContext::paint_node_as_stacking_context(paintable, paint_context);
DisplayListPlayerSkia executor { *mask_bitmap }; DisplayListPlayerSkia display_list_player { *mask_bitmap };
display_list.execute(executor); display_list_player.execute(display_list);
return mask_bitmap; return mask_bitmap;
}; };
RefPtr<Gfx::Bitmap> mask_bitmap = {}; RefPtr<Gfx::Bitmap> mask_bitmap = {};

View file

@ -101,8 +101,8 @@ RefPtr<Gfx::Bitmap> SVGDecodedImageData::render(Gfx::IntSize size) const
switch (painting_command_executor_type) { switch (painting_command_executor_type) {
case DisplayListPlayerType::SkiaGPUIfAvailable: case DisplayListPlayerType::SkiaGPUIfAvailable:
case DisplayListPlayerType::SkiaCPU: { case DisplayListPlayerType::SkiaCPU: {
Painting::DisplayListPlayerSkia executor { *bitmap }; Painting::DisplayListPlayerSkia display_list_player { *bitmap };
display_list.execute(executor); display_list_player.execute(display_list);
break; break;
} }
default: default: