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

View file

@ -76,19 +76,21 @@ void DisplayList::mark_unnecessary_commands()
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;
size_t next_command_index = 0;
while (next_command_index < m_commands.size()) {
if (m_commands[next_command_index].skip) {
while (next_command_index < commands.size()) {
if (commands[next_command_index].skip) {
next_command_index++;
continue;
}
auto& command = m_commands[next_command_index++].command;
auto& command = commands[next_command_index++].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>()) {
auto const& sample_under_corners = command.get<SampleUnderCorners>();
skipped_sample_corner_commands.set(sample_under_corners.id);
@ -108,9 +110,9 @@ void DisplayList::execute(DisplayListPlayer& executor)
}
}
#define HANDLE_COMMAND(command_type, executor_method) \
if (command.has<command_type>()) { \
executor.executor_method(command.get<command_type>()); \
#define HANDLE_COMMAND(command_type, executor_method) \
if (command.has<command_type>()) { \
executor_method(command.get<command_type>()); \
}
// clang-format off

View file

@ -32,10 +32,15 @@
namespace Web::Painting {
class DisplayList;
class DisplayListPlayer {
public:
virtual ~DisplayListPlayer() = default;
void execute(DisplayList& display_list);
private:
virtual void draw_glyph_run(DrawGlyphRun const&) = 0;
virtual void fill_rect(FillRect 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 mark_unnecessary_commands();
void execute(DisplayListPlayer&);
private:
struct CommandListItem {
Optional<i32> scroll_frame_id;
Command command;
bool skip { false };
};
AK::SegmentedVector<CommandListItem, 512> const& commands() const { return m_commands; }
private:
AK::SegmentedVector<CommandListItem, 512> m_commands;
};

View file

@ -33,6 +33,21 @@ public:
class DisplayListPlayerSkia : public DisplayListPlayer {
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 fill_rect(FillRect 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;
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;
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_draw_svg_geometry_for_clip_path(is<SVGClipPaintable>(paintable));
StackingContext::paint_node_as_stacking_context(paintable, paint_context);
DisplayListPlayerSkia executor { *mask_bitmap };
display_list.execute(executor);
DisplayListPlayerSkia display_list_player { *mask_bitmap };
display_list_player.execute(display_list);
return 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) {
case DisplayListPlayerType::SkiaGPUIfAvailable:
case DisplayListPlayerType::SkiaCPU: {
Painting::DisplayListPlayerSkia executor { *bitmap };
display_list.execute(executor);
Painting::DisplayListPlayerSkia display_list_player { *bitmap };
display_list_player.execute(display_list);
break;
}
default: