Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions impeller/aiks/aiks_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2000,5 +2000,17 @@ TEST_P(AiksTest, OpacityPeepHoleApplicationTest) {
ASSERT_TRUE(delegate->CanCollapseIntoParentPass(entity_pass.get()));
}

TEST_P(AiksTest, DrawPaintAbsorbsClears) {
Canvas canvas;
canvas.DrawPaint({.color = Color::Red(), .blend_mode = BlendMode::kSource});
canvas.DrawPaint(
{.color = Color::CornflowerBlue(), .blend_mode = BlendMode::kSource});

Picture picture = canvas.EndRecordingAsPicture();

ASSERT_EQ(picture.pass->GetElementCount(), 0u);
ASSERT_EQ(picture.pass->GetClearColor(), Color::CornflowerBlue());
}

} // namespace testing
} // namespace impeller
12 changes: 12 additions & 0 deletions impeller/aiks/canvas.cc
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,18 @@ void Canvas::DrawPath(const Path& path, const Paint& paint) {
}

void Canvas::DrawPaint(const Paint& paint) {
bool is_clear =
paint.blend_mode == BlendMode::kSource ||
(paint.blend_mode == BlendMode::kSourceOver && paint.color.alpha == 1);
if (xformation_stack_.size() == 1 && // If we're recording the root pass,
GetCurrentPass().GetElementCount() == 0 && // and this is the first item,
is_clear // and the backdrop is being replaced
) {
// Then we can absorb this drawPaint as the clear color of the pass.
GetCurrentPass().SetClearColor(paint.color);
return;
}

Entity entity;
entity.SetTransformation(GetCurrentTransformation());
entity.SetStencilDepth(GetStencilDepth());
Expand Down
2 changes: 1 addition & 1 deletion impeller/aiks/paint_pass_delegate.cc
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ bool OpacityPeepholePassDelegate::CanCollapseIntoParentPass(
// command wrapped in save layer. This would indicate something like an
// Opacity or FadeTransition wrapping a very simple widget, like in the
// CupertinoPicker.
if (entity_pass->GetEntityCount() > 3) {
if (entity_pass->GetElementCount() > 3) {
// Single paint command with a save layer would be:
// 1. clip
// 2. draw command
Expand Down
56 changes: 39 additions & 17 deletions impeller/entity/entity_pass.cc
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,8 @@ EntityPass* EntityPass::AddSubpass(std::unique_ptr<EntityPass> pass) {

static EntityPassTarget CreateRenderTarget(ContentContext& renderer,
ISize size,
bool readable) {
bool readable,
const Color& clear_color) {
auto context = renderer.GetContext();

/// All of the load/store actions are managed by `InlinePassContext` when
Expand All @@ -163,7 +164,7 @@ static EntityPassTarget CreateRenderTarget(ContentContext& renderer,
.resolve_storage_mode = StorageMode::kDevicePrivate,
.load_action = LoadAction::kDontCare,
.store_action = StoreAction::kMultisampleResolve,
}, // color_attachment_config
.clear_color = clear_color}, // color_attachment_config
RenderTarget::AttachmentConfig{
.storage_mode = readable ? StorageMode::kDevicePrivate
: StorageMode::kDeviceTransient,
Expand Down Expand Up @@ -203,13 +204,18 @@ uint32_t EntityPass::GetTotalPassReads(ContentContext& renderer) const {

bool EntityPass::Render(ContentContext& renderer,
const RenderTarget& render_target) const {
if (render_target.GetColorAttachments().empty()) {
VALIDATION_LOG << "The root RenderTarget must have a color attachment.";
return false;
}

StencilCoverageStack stencil_coverage_stack = {StencilCoverageLayer{
.coverage = Rect::MakeSize(render_target.GetRenderTargetSize()),
.stencil_depth = 0}};

if (GetTotalPassReads(renderer) > 0) {
auto offscreen_target =
CreateRenderTarget(renderer, render_target.GetRenderTargetSize(), true);
auto offscreen_target = CreateRenderTarget(
renderer, render_target.GetRenderTargetSize(), true, clear_color_);

if (!OnRender(renderer, // renderer
offscreen_target.GetRenderTarget()
Expand Down Expand Up @@ -269,18 +275,25 @@ bool EntityPass::Render(ContentContext& renderer,
return true;
}

// Set up the clear color of the root pass.
auto color0 = render_target.GetColorAttachments().find(0)->second;
color0.clear_color = clear_color_;

auto root_render_target = render_target;
root_render_target.SetColorAttachment(color0, 0);

EntityPassTarget pass_target(
render_target,
root_render_target,
renderer.GetDeviceCapabilities().SupportsReadFromResolve());

return OnRender( //
renderer, // renderer
render_target.GetRenderTargetSize(), // root_pass_size
pass_target, // pass_target
Point(), // global_pass_position
Point(), // local_pass_position
0, // pass_depth
stencil_coverage_stack); // stencil_coverage_stack
return OnRender( //
renderer, // renderer
root_render_target.GetRenderTargetSize(), // root_pass_size
pass_target, // pass_target
Point(), // global_pass_position
Point(), // local_pass_position
0, // pass_depth
stencil_coverage_stack); // stencil_coverage_stack
}

EntityPass::EntityResult EntityPass::GetEntityForElement(
Expand Down Expand Up @@ -386,9 +399,10 @@ EntityPass::EntityResult EntityPass::GetEntityForElement(
subpass_coverage->Intersection(Rect::MakeSize(root_pass_size));

auto subpass_target =
CreateRenderTarget(renderer, //
ISize(subpass_coverage->size), //
subpass->GetTotalPassReads(renderer) > 0);
CreateRenderTarget(renderer, //
ISize(subpass_coverage->size), //
subpass->GetTotalPassReads(renderer) > 0, //
clear_color_);

auto subpass_texture =
subpass_target.GetRenderTarget().GetRenderTargetTexture();
Expand Down Expand Up @@ -701,7 +715,7 @@ bool EntityPass::IterateUntilSubpass(
return false;
}

size_t EntityPass::GetEntityCount() const {
size_t EntityPass::GetElementCount() const {
return elements_.size();
}

Expand Down Expand Up @@ -739,6 +753,14 @@ void EntityPass::SetBlendMode(BlendMode blend_mode) {
cover_whole_screen_ = Entity::IsBlendModeDestructive(blend_mode);
}

void EntityPass::SetClearColor(Color clear_color) {
clear_color_ = clear_color;
}

Color EntityPass::GetClearColor() const {
return clear_color_;
}

void EntityPass::SetBackdropFilter(std::optional<BackdropFilterProc> proc) {
if (superpass_) {
VALIDATION_LOG << "Backdrop filters cannot be set on EntityPasses that "
Expand Down
9 changes: 7 additions & 2 deletions impeller/entity/entity_pass.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,15 +77,19 @@ class EntityPass {
/// @return Returns whether a subpass was encountered.
bool IterateUntilSubpass(const std::function<bool(Entity&)>& iterator);

/// @brief Return the number of entities on this pass.
size_t GetEntityCount() const;
/// @brief Return the number of elements on this pass.
size_t GetElementCount() const;

void SetTransformation(Matrix xformation);

void SetStencilDepth(size_t stencil_depth);

void SetBlendMode(BlendMode blend_mode);

void SetClearColor(Color clear_color);

Color GetClearColor() const;

void SetBackdropFilter(std::optional<BackdropFilterProc> proc);

std::optional<Rect> GetSubpassCoverage(
Expand Down Expand Up @@ -204,6 +208,7 @@ class EntityPass {
size_t stencil_depth_ = 0u;
BlendMode blend_mode_ = BlendMode::kSourceOver;
bool cover_whole_screen_ = false;
Color clear_color_ = Color::BlackTransparent();

/// These values are incremented whenever something is added to the pass that
/// requires reading from the backdrop texture. Currently, this can happen in
Expand Down
11 changes: 8 additions & 3 deletions impeller/renderer/render_target.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,30 +23,35 @@ class RenderTarget final {
StorageMode storage_mode;
LoadAction load_action;
StoreAction store_action;
Color clear_color;
};

struct AttachmentConfigMSAA {
StorageMode storage_mode;
StorageMode resolve_storage_mode;
LoadAction load_action;
StoreAction store_action;
Color clear_color;
};

static constexpr AttachmentConfig kDefaultColorAttachmentConfig = {
.storage_mode = StorageMode::kDevicePrivate,
.load_action = LoadAction::kClear,
.store_action = StoreAction::kStore};
.store_action = StoreAction::kStore,
.clear_color = Color::BlackTransparent()};

static constexpr AttachmentConfigMSAA kDefaultColorAttachmentConfigMSAA = {
.storage_mode = StorageMode::kDeviceTransient,
.resolve_storage_mode = StorageMode::kDevicePrivate,
.load_action = LoadAction::kClear,
.store_action = StoreAction::kMultisampleResolve};
.store_action = StoreAction::kMultisampleResolve,
.clear_color = Color::BlackTransparent()};

static constexpr AttachmentConfig kDefaultStencilAttachmentConfig = {
.storage_mode = StorageMode::kDeviceTransient,
.load_action = LoadAction::kClear,
.store_action = StoreAction::kDontCare};
.store_action = StoreAction::kDontCare,
.clear_color = Color::BlackTransparent()};

static RenderTarget CreateOffscreen(
const Context& context,
Expand Down