Setup a framework to collapse passes.

This commit is contained in:
Chinmay Garde 2021-11-28 13:33:14 -08:00 committed by Dan Field
parent 5c0de80dd1
commit 30b243cdf7
6 changed files with 110 additions and 15 deletions

View File

@ -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",

View File

@ -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);

View File

@ -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<CanvasPassDelegate> 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<TextureContents>();
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));

View File

@ -9,8 +9,10 @@
#include <vector>
#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<Entity>;
using Subpasses = std::vector<std::unique_ptr<CanvasPass>>;
CanvasPass();
CanvasPass(std::unique_ptr<CanvasPassDelegate> delegate = nullptr);
~CanvasPass();
@ -57,6 +59,7 @@ class CanvasPass {
CanvasPass* superpass_ = nullptr;
Matrix xformation_;
size_t stencil_depth_ = 0u;
std::unique_ptr<CanvasPassDelegate> delegate_;
FML_DISALLOW_COPY_AND_ASSIGN(CanvasPass);
};

View File

@ -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<Contents> 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> CanvasPassDelegate::MakeDefault() {
return std::make_unique<DefaultCanvasPassDelegate>();
}
} // namespace impeller

View File

@ -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 <memory>
#include "flutter/fml/macros.h"
#include "impeller/entity/contents.h"
#include "impeller/renderer/texture.h"
namespace impeller {
class CanvasPassDelegate {
public:
static std::unique_ptr<CanvasPassDelegate> MakeDefault();
CanvasPassDelegate();
virtual ~CanvasPassDelegate();
virtual bool CanCollapseIntoParentPass() = 0;
virtual std::shared_ptr<Contents> CreateContentsForSubpassTarget(
const Texture& target) = 0;
private:
FML_DISALLOW_COPY_AND_ASSIGN(CanvasPassDelegate);
};
} // namespace impeller