diff --git a/impeller/aiks/aiks_unittests.cc b/impeller/aiks/aiks_unittests.cc index e91c705f68a12..286b4fe72211b 100644 --- a/impeller/aiks/aiks_unittests.cc +++ b/impeller/aiks/aiks_unittests.cc @@ -2837,5 +2837,19 @@ TEST_P(AiksTest, TextForegroundShaderWithTransform) { ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture())); } +TEST_P(AiksTest, CanCanvasDrawPicture) { + Canvas subcanvas; + subcanvas.DrawRect(Rect::MakeLTRB(-100, -50, 100, 50), + {.color = Color::CornflowerBlue()}); + auto picture = subcanvas.EndRecordingAsPicture(); + + Canvas canvas; + canvas.Translate({200, 200}); + canvas.Rotate(Radians(kPi / 4)); + canvas.DrawPicture(picture); + + ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture())); +} + } // namespace testing } // namespace impeller diff --git a/impeller/aiks/canvas.cc b/impeller/aiks/canvas.cc index df3d5fc540bba..82424b2c86d59 100644 --- a/impeller/aiks/canvas.cc +++ b/impeller/aiks/canvas.cc @@ -401,10 +401,14 @@ void Canvas::DrawPoints(std::vector points, GetCurrentPass().AddEntity(entity); } -void Canvas::DrawPicture(Picture picture) { +void Canvas::DrawPicture(const Picture& picture) { if (!picture.pass) { return; } + + auto save_count = GetSaveCount(); + Save(); + // Clone the base pass and account for the CTM updates. auto pass = picture.pass->Clone(); pass->IterateAllEntities([&](auto& entity) -> bool { @@ -413,7 +417,9 @@ void Canvas::DrawPicture(Picture picture) { entity.GetTransformation()); return true; }); - return; + GetCurrentPass().AddSubpassInline(std::move(pass)); + + RestoreToCount(save_count); } void Canvas::DrawImage(const std::shared_ptr& image, diff --git a/impeller/aiks/canvas.h b/impeller/aiks/canvas.h index 57a23671abf3f..aa3da9f0681a2 100644 --- a/impeller/aiks/canvas.h +++ b/impeller/aiks/canvas.h @@ -137,7 +137,7 @@ class Canvas { Scalar corner_radius, Entity::ClipOperation clip_op = Entity::ClipOperation::kIntersect); - void DrawPicture(Picture picture); + void DrawPicture(const Picture& picture); void DrawTextFrame(const TextFrame& text_frame, Point position, diff --git a/impeller/entity/entity_pass.cc b/impeller/entity/entity_pass.cc index 8b1aac582550e..a7cf79b09acbd 100644 --- a/impeller/entity/entity_pass.cc +++ b/impeller/entity/entity_pass.cc @@ -167,6 +167,22 @@ EntityPass* EntityPass::AddSubpass(std::unique_ptr pass) { return subpass_pointer; } +void EntityPass::AddSubpassInline(std::unique_ptr pass) { + if (!pass) { + return; + } + FML_DCHECK(pass->superpass_ == nullptr); + + elements_.insert(elements_.end(), + std::make_move_iterator(pass->elements_.begin()), + std::make_move_iterator(pass->elements_.end())); + + backdrop_filter_reads_from_pass_texture_ += + pass->backdrop_filter_reads_from_pass_texture_; + advanced_blend_reads_from_pass_texture_ += + pass->advanced_blend_reads_from_pass_texture_; +} + static RenderTarget::AttachmentConfig GetDefaultStencilConfig(bool readable) { return RenderTarget::AttachmentConfig{ .storage_mode = readable ? StorageMode::kDevicePrivate diff --git a/impeller/entity/entity_pass.h b/impeller/entity/entity_pass.h index ad83df5bbf284..e3dbada3d7eed 100644 --- a/impeller/entity/entity_pass.h +++ b/impeller/entity/entity_pass.h @@ -62,13 +62,21 @@ class EntityPass { void SetElements(std::vector elements); + /// @brief Appends a given pass as a subpass. EntityPass* AddSubpass(std::unique_ptr pass); + /// @brief Merges a given pass into this pass. Useful for drawing + /// pre-recorded pictures that don't require rendering into a separate + /// subpass. + void AddSubpassInline(std::unique_ptr pass); + EntityPass* GetSuperpass() const; bool Render(ContentContext& renderer, const RenderTarget& render_target) const; + /// @brief Iterate all entities in this pass, recursively including entities + /// of child passes. The iteration order is depth-first. void IterateAllEntities(const std::function& iterator); /// @brief Iterate entities in this pass up until the first subpass is found.