Skip to content

Commit

Permalink
Setup canvas pass hierarchies.
Browse files Browse the repository at this point in the history
  • Loading branch information
chinmaygarde authored and dnfield committed Apr 27, 2022
1 parent 3f41788 commit ab16b0b
Show file tree
Hide file tree
Showing 6 changed files with 131 additions and 54 deletions.
12 changes: 3 additions & 9 deletions impeller/aiks/aiks_renderer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down
81 changes: 47 additions & 34 deletions impeller/aiks/canvas.cc
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,25 @@
namespace impeller {

Canvas::Canvas() {
Save(true);
Initialize();
}

Canvas::~Canvas() = default;

void Canvas::Initialize() {
base_pass_ = std::make_unique<CanvasPass>();
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);
}
Expand All @@ -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;
}
Expand Down Expand Up @@ -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<Rect> bounds) {
Save();
Save(true);
}

void Canvas::ClipPath(Path path) {
Expand All @@ -85,23 +103,24 @@ void Canvas::ClipPath(Path path) {
entity.SetContents(std::make_shared<ClipContents>());
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> image,
Expand Down Expand Up @@ -140,23 +159,23 @@ void Canvas::DrawImageRect(std::shared_ptr<Image> 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() {
Expand All @@ -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<CanvasPass>());
}

xformation_stack_.emplace_back(std::move(entry));
}

Expand Down
8 changes: 7 additions & 1 deletion impeller/aiks/canvas.h
Original file line number Diff line number Diff line change
Expand Up @@ -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<CanvasPass> base_pass_;
CanvasPass* current_pass_ = nullptr;
std::deque<CanvasStackEntry> xformation_stack_;

void Initialize();

void Reset();

CanvasPass& GetCurrentPass();

void IncrementStencilDepth();
Expand Down
58 changes: 54 additions & 4 deletions impeller/aiks/canvas_pass.cc
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,26 @@ CanvasPass::CanvasPass() = default;

CanvasPass::~CanvasPass() = default;

void CanvasPass::PushEntity(Entity entity) {
void CanvasPass::AddEntity(Entity entity) {
entities_.emplace_back(std::move(entity));
}

const std::vector<Entity>& 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<Point> min, max;
for (const auto& entity : entities_) {
Expand All @@ -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<CanvasPass> 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,
Expand All @@ -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<bool(Entity&)> iterator) {
if (!iterator) {
return;
}

for (auto& entity : entities_) {
if (!iterator(entity)) {
return;
}
}

for (auto& subpass : subpasses_) {
subpass->IterateAllEntities(iterator);
}
}

std::unique_ptr<CanvasPass> CanvasPass::Clone() const {
auto pass = std::make_unique<CanvasPass>();
pass->SetEntities(entities_);
for (const auto& subpass : subpasses_) {
pass->AddSubpass(subpass->Clone());
}
return pass;
}

} // namespace impeller
24 changes: 19 additions & 5 deletions impeller/aiks/canvas_pass.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,33 +18,47 @@ class ContentRenderer;

class CanvasPass {
public:
using Subpasses = std::vector<CanvasPass>;
using Entities = std::vector<Entity>;
using Subpasses = std::vector<std::unique_ptr<CanvasPass>>;

CanvasPass();

~CanvasPass();

void PushEntity(Entity entity);
size_t GetDepth() const;

std::unique_ptr<CanvasPass> Clone() const;

Rect GetCoverageRect() const;

void AddEntity(Entity entity);

void SetEntities(Entities entities);

const std::vector<Entity>& GetEntities() const;

const Subpasses& GetSubpasses() const;

bool AddSubpass(CanvasPass pass);
CanvasPass* AddSubpass(std::unique_ptr<CanvasPass> pass);

CanvasPass* GetSuperpass() const;

bool Render(ContentRenderer& renderer, RenderPass& parent_pass) const;

void IterateAllEntities(std::function<bool(Entity&)> iterator);

private:
std::vector<Entity> 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<CanvasPass> pass;
bool is_subpass = false;
};

} // namespace impeller
2 changes: 1 addition & 1 deletion impeller/aiks/picture.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
namespace impeller {

struct Picture {
std::deque<CanvasStackEntry> entries;
std::unique_ptr<CanvasPass> pass;
};

} // namespace impeller

0 comments on commit ab16b0b

Please sign in to comment.