LibWeb: Add support for nested painting command executors

This adds two new CommandResults: ContinueWithNestedExecutor and
ContinueWithParentExecutor.

ContinueWithNestedExecutor switches the command executor to the result
of calling `.nested_executor()` on the current CommandExecutor.

ContinueWithParentExecutor returns to the previous command executor
(i.e. what it was before the last ContinueWithNestedExecutor).
This commit is contained in:
MacDue 2024-05-27 19:08:44 +01:00 committed by Andreas Kling
parent a5442ad70d
commit 6333159108
2 changed files with 15 additions and 5 deletions

View file

@ -112,6 +112,8 @@ void CommandList::execute(CommandExecutor& executor)
HashTable<u32> skipped_sample_corner_commands;
size_t next_command_index = 0;
Vector<CommandExecutor&, 16> executor_stack;
CommandExecutor* current_executor = &executor;
while (next_command_index < m_commands.size()) {
if (m_commands[next_command_index].skip) {
next_command_index++;
@ -120,7 +122,7 @@ void CommandList::execute(CommandExecutor& executor)
auto& command = m_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() || current_executor->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);
@ -140,9 +142,9 @@ void CommandList::execute(CommandExecutor& executor)
}
}
#define HANDLE_COMMAND(command_type, executor_method) \
if (command.has<command_type>()) { \
result = executor.executor_method(command.get<command_type>()); \
#define HANDLE_COMMAND(command_type, executor_method) \
if (command.has<command_type>()) { \
result = current_executor->executor_method(command.get<command_type>()); \
}
// clang-format off
@ -179,7 +181,12 @@ void CommandList::execute(CommandExecutor& executor)
else VERIFY_NOT_REACHED();
// clang-format on
if (result == CommandResult::SkipStackingContext) {
if (result == CommandResult::ContinueWithNestedExecutor) {
executor_stack.append(*current_executor);
current_executor = &current_executor->nested_executor();
} else if (result == CommandResult::ContinueWithParentExecutor) {
current_executor = &executor_stack.take_last();
} else if (result == CommandResult::SkipStackingContext) {
auto stacking_context_nesting_level = 1;
while (next_command_index < m_commands.size()) {
if (m_commands[next_command_index].command.has<PushStackingContext>()) {

View file

@ -41,6 +41,8 @@ namespace Web::Painting {
enum class CommandResult {
Continue,
SkipStackingContext,
ContinueWithNestedExecutor,
ContinueWithParentExecutor
};
class CommandExecutor {
@ -82,6 +84,7 @@ public:
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;
virtual CommandExecutor& nested_executor() { VERIFY_NOT_REACHED(); }
};
class CommandList {