diff --git a/engine/src/flutter/impeller/aiks/BUILD.gn b/engine/src/flutter/impeller/aiks/BUILD.gn index 0c6bc01a005..a179fa24580 100644 --- a/engine/src/flutter/impeller/aiks/BUILD.gn +++ b/engine/src/flutter/impeller/aiks/BUILD.gn @@ -12,6 +12,8 @@ impeller_component("aiks") { "canvas.h", "canvas_pass.cc", "canvas_pass.h", + "canvas_pass_delegate.cc", + "canvas_pass_delegate.h", "image.cc", "image.h", "paint.cc", diff --git a/engine/src/flutter/impeller/aiks/aiks_unittests.cc b/engine/src/flutter/impeller/aiks/aiks_unittests.cc index e29d40d8bc7..c64d8940031 100644 --- a/engine/src/flutter/impeller/aiks/aiks_unittests.cc +++ b/engine/src/flutter/impeller/aiks/aiks_unittests.cc @@ -110,16 +110,16 @@ TEST_F(AiksTest, CanRenderGroupOpacity) { Canvas canvas; Paint red; - red.color = Color::Red(); //.WithAlpha(0.5); + red.color = Color::Red(); Paint green; - green.color = Color::Green(); //.WithAlpha(0.5); + green.color = Color::Green(); Paint blue; - blue.color = Color::Blue(); //.WithAlpha(0.5); + blue.color = Color::Blue(); Paint alpha; alpha.color = Color::Red().WithAlpha(0.5); - // canvas.SaveLayer(alpha); + canvas.SaveLayer(alpha); canvas.DrawRect({000, 000, 100, 100}, red); canvas.DrawRect({020, 020, 100, 100}, green); diff --git a/engine/src/flutter/impeller/aiks/canvas_pass.cc b/engine/src/flutter/impeller/aiks/canvas_pass.cc index ad3aa1fb528..c177f6c221a 100644 --- a/engine/src/flutter/impeller/aiks/canvas_pass.cc +++ b/engine/src/flutter/impeller/aiks/canvas_pass.cc @@ -8,11 +8,15 @@ #include "impeller/geometry/path_builder.h" #include "impeller/renderer/command_buffer.h" #include "impeller/renderer/render_pass.h" -#include "impeller/renderer/render_target.h" namespace impeller { -CanvasPass::CanvasPass() = default; +CanvasPass::CanvasPass(std::unique_ptr delegate) + : delegate_(std::move(delegate)) { + if (!delegate_) { + delegate_ = CanvasPassDelegate::MakeDefault(); + } +} CanvasPass::~CanvasPass() = default; @@ -85,8 +89,12 @@ bool CanvasPass::Render(ContentRenderer& renderer, } } for (const auto& subpass : subpasses_) { - if (!subpass) { - return false; + if (delegate_->CanCollapseIntoParentPass()) { + // Directly render into the parent pass and move on. + if (!subpass->Render(renderer, parent_pass)) { + return false; + } + continue; } const auto subpass_coverage = subpass->GetCoverageRect(); @@ -102,6 +110,27 @@ bool CanvasPass::Render(ContentRenderer& renderer, auto subpass_target = RenderTarget::CreateOffscreen( *context, ISize::Ceil(subpass_coverage.size)); + auto subpass_texture = subpass_target.GetRenderTargetTexture(); + + if (!subpass_texture) { + return false; + } + + auto offscreen_texture_contents = + delegate_->CreateContentsForSubpassTarget(*subpass_texture); + + if (!offscreen_texture_contents) { + // This is an error because the subpass delegate said the pass couldn't be + // collapsed into its parent. Yet, when asked how it want's to postprocess + // the offscreen texture, it couldn't give us an answer. + // + // Theoretically, we could collapse the pass now. But that would be + // wasteful as we already have the offscreen texture and we don't want to + // discard it without ever using it. Just make the delegate do the right + // thing. + return false; + } + auto sub_command_buffer = context->CreateRenderCommandBuffer(); sub_command_buffer->SetLabel("Offscreen Command Buffer"); @@ -130,12 +159,6 @@ bool CanvasPass::Render(ContentRenderer& renderer, return false; } - auto offscreen_texture_contents = std::make_shared(); - offscreen_texture_contents->SetTexture( - subpass_target.GetRenderTargetTexture()); - offscreen_texture_contents->SetSourceRect( - IRect::MakeSize(subpass_target.GetRenderTargetTexture()->GetSize())); - Entity entity; entity.SetPath(PathBuilder{}.AddRect(subpass_coverage).CreatePath()); entity.SetContents(std::move(offscreen_texture_contents)); diff --git a/engine/src/flutter/impeller/aiks/canvas_pass.h b/engine/src/flutter/impeller/aiks/canvas_pass.h index 4a942010acb..6f846321be8 100644 --- a/engine/src/flutter/impeller/aiks/canvas_pass.h +++ b/engine/src/flutter/impeller/aiks/canvas_pass.h @@ -9,8 +9,10 @@ #include #include "flutter/fml/macros.h" +#include "impeller/aiks/canvas_pass_delegate.h" #include "impeller/entity/contents.h" #include "impeller/entity/entity.h" +#include "impeller/renderer/render_target.h" namespace impeller { @@ -21,7 +23,7 @@ class CanvasPass { using Entities = std::vector; using Subpasses = std::vector>; - CanvasPass(); + CanvasPass(std::unique_ptr delegate = nullptr); ~CanvasPass(); @@ -57,6 +59,7 @@ class CanvasPass { CanvasPass* superpass_ = nullptr; Matrix xformation_; size_t stencil_depth_ = 0u; + std::unique_ptr delegate_; FML_DISALLOW_COPY_AND_ASSIGN(CanvasPass); }; diff --git a/engine/src/flutter/impeller/aiks/canvas_pass_delegate.cc b/engine/src/flutter/impeller/aiks/canvas_pass_delegate.cc new file mode 100644 index 00000000000..cd5a07f11a6 --- /dev/null +++ b/engine/src/flutter/impeller/aiks/canvas_pass_delegate.cc @@ -0,0 +1,35 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "impeller/aiks/canvas_pass_delegate.h" + +namespace impeller { + +CanvasPassDelegate::CanvasPassDelegate() = default; + +CanvasPassDelegate::~CanvasPassDelegate() = default; + +class DefaultCanvasPassDelegate final : public CanvasPassDelegate { + public: + DefaultCanvasPassDelegate() = default; + + ~DefaultCanvasPassDelegate() override = default; + + bool CanCollapseIntoParentPass() override { return true; } + + std::shared_ptr CreateContentsForSubpassTarget( + const Texture& target) override { + // Not possible since this pass always collapses into its parent. + FML_UNREACHABLE(); + } + + private: + FML_DISALLOW_COPY_AND_ASSIGN(DefaultCanvasPassDelegate); +}; + +std::unique_ptr CanvasPassDelegate::MakeDefault() { + return std::make_unique(); +} + +} // namespace impeller diff --git a/engine/src/flutter/impeller/aiks/canvas_pass_delegate.h b/engine/src/flutter/impeller/aiks/canvas_pass_delegate.h new file mode 100644 index 00000000000..b41feb3c978 --- /dev/null +++ b/engine/src/flutter/impeller/aiks/canvas_pass_delegate.h @@ -0,0 +1,32 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#pragma once + +#include + +#include "flutter/fml/macros.h" +#include "impeller/entity/contents.h" +#include "impeller/renderer/texture.h" + +namespace impeller { + +class CanvasPassDelegate { + public: + static std::unique_ptr MakeDefault(); + + CanvasPassDelegate(); + + virtual ~CanvasPassDelegate(); + + virtual bool CanCollapseIntoParentPass() = 0; + + virtual std::shared_ptr CreateContentsForSubpassTarget( + const Texture& target) = 0; + + private: + FML_DISALLOW_COPY_AND_ASSIGN(CanvasPassDelegate); +}; + +} // namespace impeller