diff --git a/impeller/aiks/aiks_renderer.cc b/impeller/aiks/aiks_renderer.cc index f491e4d083882..dbdc2838ad121 100644 --- a/impeller/aiks/aiks_renderer.cc +++ b/impeller/aiks/aiks_renderer.cc @@ -33,16 +33,10 @@ bool AiksRenderer::Render(const Picture& picture, RenderPass& parent_pass) { return false; } - for (const auto& entry : picture.entries) { - if (!entry.pass.has_value()) { - continue; - ; - } - - if (!entry.pass->Render(*content_renderer_, parent_pass)) { - return false; - } + if (picture.pass) { + return picture.pass->Render(*content_renderer_, parent_pass); } + return true; } diff --git a/impeller/aiks/canvas.cc b/impeller/aiks/canvas.cc index 87ec026a6321f..d5b12962fc272 100644 --- a/impeller/aiks/canvas.cc +++ b/impeller/aiks/canvas.cc @@ -12,11 +12,25 @@ namespace impeller { Canvas::Canvas() { - Save(true); + Initialize(); } Canvas::~Canvas() = default; +void Canvas::Initialize() { + base_pass_ = std::make_unique(); + current_pass_ = base_pass_.get(); + xformation_stack_.emplace_back(CanvasStackEntry{}); + FML_DCHECK(GetSaveCount() == 1u); + FML_DCHECK(base_pass_->GetDepth() == 1u); +} + +void Canvas::Reset() { + base_pass_ = nullptr; + current_pass_ = nullptr; + xformation_stack_ = {}; +} + void Canvas::Save() { Save(false); } @@ -26,6 +40,10 @@ bool Canvas::Restore() { if (xformation_stack_.size() == 1) { return false; } + if (xformation_stack_.back().is_subpass) { + current_pass_ = GetCurrentPass().GetSuperpass(); + FML_DCHECK(current_pass_); + } xformation_stack_.pop_back(); return true; } @@ -69,11 +87,11 @@ void Canvas::DrawPath(Path path, Paint paint) { entity.SetStencilDepth(GetStencilDepth()); entity.SetContents(paint.CreateContentsForEntity()); - GetCurrentPass().PushEntity(std::move(entity)); + GetCurrentPass().AddEntity(std::move(entity)); } void Canvas::SaveLayer(const Paint& paint, std::optional bounds) { - Save(); + Save(true); } void Canvas::ClipPath(Path path) { @@ -85,23 +103,24 @@ void Canvas::ClipPath(Path path) { entity.SetContents(std::make_shared()); entity.SetStencilDepth(GetStencilDepth()); - GetCurrentPass().PushEntity(std::move(entity)); + GetCurrentPass().AddEntity(std::move(entity)); } void Canvas::DrawShadow(Path path, Color color, Scalar elevation) {} -void Canvas::DrawPicture(const Picture& picture) { - for (const auto& stack_entry : picture.entries) { - auto new_stack_entry = stack_entry; - if (auto pass = new_stack_entry.pass) { - for (auto entity : pass->GetEntities()) { - entity.IncrementStencilDepth(GetStencilDepth()); - entity.SetTransformation(GetCurrentTransformation() * - entity.GetTransformation()); - } - } - xformation_stack_.emplace_back(std::move(new_stack_entry)); +void Canvas::DrawPicture(Picture picture) { + if (!picture.pass) { + return; } + // Clone the base pass and account for the CTM updates. + auto pass = picture.pass->Clone(); + pass->IterateAllEntities([&](auto& entity) -> bool { + entity.IncrementStencilDepth(GetStencilDepth()); + entity.SetTransformation(GetCurrentTransformation() * + entity.GetTransformation()); + return true; + }); + return; } void Canvas::DrawImage(std::shared_ptr image, @@ -140,23 +159,23 @@ void Canvas::DrawImageRect(std::shared_ptr image, entity.SetPath(PathBuilder{}.AddRect(dest).CreatePath()); entity.SetContents(contents); entity.SetTransformation(GetCurrentTransformation()); - GetCurrentPass().PushEntity(std::move(entity)); + + GetCurrentPass().AddEntity(std::move(entity)); } Picture Canvas::EndRecordingAsPicture() { Picture picture; - picture.entries = std::move(xformation_stack_); + picture.pass = std::move(base_pass_); + + Reset(); + Initialize(); + return picture; } CanvasPass& Canvas::GetCurrentPass() { - for (auto i = xformation_stack_.rbegin(), end = xformation_stack_.rend(); - i < end; i++) { - if (i->pass.has_value()) { - return i->pass.value(); - } - } - FML_UNREACHABLE(); + FML_DCHECK(current_pass_ != nullptr); + return *current_pass_; } void Canvas::IncrementStencilDepth() { @@ -172,21 +191,15 @@ void Canvas::DrawRect(Rect rect, Paint paint) { } void Canvas::Save(bool create_subpass) { - // Check if called from the ctor. - if (xformation_stack_.empty()) { - FML_DCHECK(create_subpass) << "Base entries must have a pass."; - CanvasStackEntry entry; - entry.pass = CanvasPass{}; - xformation_stack_.emplace_back(std::move(entry)); - } - auto entry = CanvasStackEntry{}; - entry.xformation = xformation_stack_.back().xformation; entry.stencil_depth = xformation_stack_.back().stencil_depth; + entry.is_subpass = create_subpass; + if (create_subpass) { - entry.pass = CanvasPass{}; + current_pass_ = GetCurrentPass().AddSubpass(std::make_unique()); } + xformation_stack_.emplace_back(std::move(entry)); } diff --git a/impeller/aiks/canvas.h b/impeller/aiks/canvas.h index b2a5d8c3ff1fa..06d90e54f334c 100644 --- a/impeller/aiks/canvas.h +++ b/impeller/aiks/canvas.h @@ -64,13 +64,19 @@ class Canvas { void DrawShadow(Path path, Color color, Scalar elevation); - void DrawPicture(const Picture& picture); + void DrawPicture(Picture picture); Picture EndRecordingAsPicture(); private: + std::unique_ptr base_pass_; + CanvasPass* current_pass_ = nullptr; std::deque xformation_stack_; + void Initialize(); + + void Reset(); + CanvasPass& GetCurrentPass(); void IncrementStencilDepth(); diff --git a/impeller/aiks/canvas_pass.cc b/impeller/aiks/canvas_pass.cc index edada76473835..09eea3934e645 100644 --- a/impeller/aiks/canvas_pass.cc +++ b/impeller/aiks/canvas_pass.cc @@ -12,7 +12,7 @@ CanvasPass::CanvasPass() = default; CanvasPass::~CanvasPass() = default; -void CanvasPass::PushEntity(Entity entity) { +void CanvasPass::AddEntity(Entity entity) { entities_.emplace_back(std::move(entity)); } @@ -20,6 +20,18 @@ const std::vector& CanvasPass::GetEntities() const { return entities_; } +void CanvasPass::SetEntities(Entities entities) { + entities_ = std::move(entities); +} + +size_t CanvasPass::GetDepth() const { + size_t max_subpass_depth = 0u; + for (const auto& subpass : subpasses_) { + max_subpass_depth = std::max(max_subpass_depth, subpass->GetDepth()); + } + return max_subpass_depth + 1u; +} + Rect CanvasPass::GetCoverageRect() const { std::optional min, max; for (const auto& entity : entities_) { @@ -43,13 +55,21 @@ Rect CanvasPass::GetCoverageRect() const { return {min->x, min->y, diff.x, diff.y}; } +CanvasPass* CanvasPass::GetSuperpass() const { + return superpass_; +} + const CanvasPass::Subpasses& CanvasPass::GetSubpasses() const { return subpasses_; } -bool CanvasPass::AddSubpass(CanvasPass pass) { - subpasses_.emplace_back(std::move(pass)); - return true; +CanvasPass* CanvasPass::AddSubpass(std::unique_ptr pass) { + if (!pass) { + return nullptr; + } + FML_DCHECK(pass->superpass_ == nullptr); + pass->superpass_ = this; + return subpasses_.emplace_back(std::move(pass)).get(); } bool CanvasPass::Render(ContentRenderer& renderer, @@ -59,7 +79,37 @@ bool CanvasPass::Render(ContentRenderer& renderer, return false; } } + for (const auto& subpass : subpasses_) { + if (!subpass->Render(renderer, parent_pass)) { + return false; + } + } return true; } +void CanvasPass::IterateAllEntities(std::function iterator) { + if (!iterator) { + return; + } + + for (auto& entity : entities_) { + if (!iterator(entity)) { + return; + } + } + + for (auto& subpass : subpasses_) { + subpass->IterateAllEntities(iterator); + } +} + +std::unique_ptr CanvasPass::Clone() const { + auto pass = std::make_unique(); + pass->SetEntities(entities_); + for (const auto& subpass : subpasses_) { + pass->AddSubpass(subpass->Clone()); + } + return pass; +} + } // namespace impeller diff --git a/impeller/aiks/canvas_pass.h b/impeller/aiks/canvas_pass.h index 3aa7cb825c3eb..55ea2ea6e2f2c 100644 --- a/impeller/aiks/canvas_pass.h +++ b/impeller/aiks/canvas_pass.h @@ -18,33 +18,47 @@ class ContentRenderer; class CanvasPass { public: - using Subpasses = std::vector; + using Entities = std::vector; + using Subpasses = std::vector>; CanvasPass(); ~CanvasPass(); - void PushEntity(Entity entity); + size_t GetDepth() const; + + std::unique_ptr Clone() const; Rect GetCoverageRect() const; + void AddEntity(Entity entity); + + void SetEntities(Entities entities); + const std::vector& GetEntities() const; const Subpasses& GetSubpasses() const; - bool AddSubpass(CanvasPass pass); + CanvasPass* AddSubpass(std::unique_ptr pass); + + CanvasPass* GetSuperpass() const; bool Render(ContentRenderer& renderer, RenderPass& parent_pass) const; + void IterateAllEntities(std::function iterator); + private: - std::vector entities_; + Entities entities_; Subpasses subpasses_; + CanvasPass* superpass_ = nullptr; + + FML_DISALLOW_COPY_AND_ASSIGN(CanvasPass); }; struct CanvasStackEntry { Matrix xformation; size_t stencil_depth = 0u; - std::optional pass; + bool is_subpass = false; }; } // namespace impeller diff --git a/impeller/aiks/picture.h b/impeller/aiks/picture.h index 4b5fed22a6e40..cf676f91c886f 100644 --- a/impeller/aiks/picture.h +++ b/impeller/aiks/picture.h @@ -14,7 +14,7 @@ namespace impeller { struct Picture { - std::deque entries; + std::unique_ptr pass; }; } // namespace impeller