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
31 changes: 18 additions & 13 deletions impeller/aiks/aiks_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1989,11 +1989,13 @@ TEST_P(AiksTest, OpacityPeepHoleApplicationTest) {
TEST_P(AiksTest, DrawPaintAbsorbsClears) {
Canvas canvas;
canvas.DrawPaint({.color = Color::Red(), .blend_mode = BlendMode::kSource});
canvas.DrawPaint(
{.color = Color::CornflowerBlue(), .blend_mode = BlendMode::kSource});
canvas.DrawPaint({.color = Color::CornflowerBlue().WithAlpha(0.75),
.blend_mode = BlendMode::kSourceOver});

Picture picture = canvas.EndRecordingAsPicture();
ASSERT_EQ(picture.pass->GetClearColor(), Color::CornflowerBlue());
auto expected = Color::Red().Blend(Color::CornflowerBlue().WithAlpha(0.75),
BlendMode::kSourceOver);
ASSERT_EQ(picture.pass->GetClearColor(), expected);

std::shared_ptr<ContextSpy> spy = ContextSpy::Make();
std::shared_ptr<Context> real_context = GetContext();
Expand All @@ -2010,8 +2012,9 @@ TEST_P(AiksTest, DrawRectAbsorbsClears) {
Canvas canvas;
canvas.DrawRect({0, 0, 300, 300},
{.color = Color::Red(), .blend_mode = BlendMode::kSource});
canvas.DrawRect({0, 0, 300, 300}, {.color = Color::CornflowerBlue(),
.blend_mode = BlendMode::kSource});
canvas.DrawRect({0, 0, 300, 300},
{.color = Color::CornflowerBlue().WithAlpha(0.75),
.blend_mode = BlendMode::kSourceOver});

std::shared_ptr<ContextSpy> spy = ContextSpy::Make();
Picture picture = canvas.EndRecordingAsPicture();
Expand All @@ -2029,9 +2032,9 @@ TEST_P(AiksTest, DrawRectAbsorbsClearsNegativeRRect) {
Canvas canvas;
canvas.DrawRRect({0, 0, 300, 300}, 5.0,
{.color = Color::Red(), .blend_mode = BlendMode::kSource});
canvas.DrawRRect(
{0, 0, 300, 300}, 5.0,
{.color = Color::CornflowerBlue(), .blend_mode = BlendMode::kSource});
canvas.DrawRRect({0, 0, 300, 300}, 5.0,
{.color = Color::CornflowerBlue().WithAlpha(0.75),
.blend_mode = BlendMode::kSourceOver});

std::shared_ptr<ContextSpy> spy = ContextSpy::Make();
Picture picture = canvas.EndRecordingAsPicture();
Expand Down Expand Up @@ -2069,8 +2072,9 @@ TEST_P(AiksTest, DrawRectAbsorbsClearsNegative) {
Canvas canvas;
canvas.DrawRect({0, 0, 300, 300},
{.color = Color::Red(), .blend_mode = BlendMode::kSource});
canvas.DrawRect({0, 0, 300, 300}, {.color = Color::CornflowerBlue(),
.blend_mode = BlendMode::kSource});
canvas.DrawRect({0, 0, 300, 300},
{.color = Color::CornflowerBlue().WithAlpha(0.75),
.blend_mode = BlendMode::kSourceOver});

std::shared_ptr<ContextSpy> spy = ContextSpy::Make();
Picture picture = canvas.EndRecordingAsPicture();
Expand All @@ -2089,7 +2093,8 @@ TEST_P(AiksTest, CollapsedDrawPaintInSubpass) {
canvas.DrawPaint(
{.color = Color::Yellow(), .blend_mode = BlendMode::kSource});
canvas.SaveLayer({.blend_mode = BlendMode::kMultiply});
canvas.DrawPaint({.color = Color::Red(), .blend_mode = BlendMode::kSource});
canvas.DrawPaint({.color = Color::CornflowerBlue().WithAlpha(0.75),
.blend_mode = BlendMode::kSourceOver});

ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
}
Expand Down Expand Up @@ -2171,7 +2176,7 @@ static Picture BlendModeTest(BlendMode blend_mode,
canvas.DrawPaint({.color = Color::Black()});

//----------------------------------------------------------------------------
/// 1. Save layer blending (top left).
/// 1. Save layer blending (top squares).
///

canvas.Save();
Expand Down Expand Up @@ -2201,7 +2206,7 @@ static Picture BlendModeTest(BlendMode blend_mode,
canvas.RestoreToCount(0);

//----------------------------------------------------------------------------
/// 2. CPU blend modes (top left).
/// 2. CPU blend modes (bottom squares).
///

canvas.Save();
Expand Down
5 changes: 5 additions & 0 deletions impeller/entity/contents/contents.cc
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,11 @@ void Contents::SetInheritedOpacity(Scalar opacity) {
"Contents::CanAcceptOpacity returns false.";
}

std::optional<Color> Contents::AsBackgroundColor(const Entity& entity,
ISize target_size) const {
return {};
}

bool Contents::ShouldRender(const Entity& entity,
const std::optional<Rect>& stencil_coverage) const {
if (!stencil_coverage.has_value()) {
Expand Down
10 changes: 7 additions & 3 deletions impeller/entity/contents/contents.h
Original file line number Diff line number Diff line change
Expand Up @@ -117,10 +117,14 @@ class Contents {
/// Use of this method is invalid if CanAcceptOpacity returns false.
virtual void SetInheritedOpacity(Scalar opacity);

/// @brief Returns a color if this Contents will flood the given `target_size`
/// with a color. This output color is the "Source" color that will be
/// used for the Entity's blend operation.
///
/// This is useful for absorbing full screen solid color draws into
/// subpass clear colors.
Comment on lines +120 to +125
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

virtual std::optional<Color> AsBackgroundColor(const Entity& entity,
ISize target_size) const {
return {};
}
ISize target_size) const;

private:
std::optional<Rect> coverage_hint_;
Expand Down
6 changes: 0 additions & 6 deletions impeller/entity/contents/solid_color_contents.cc
Original file line number Diff line number Diff line change
Expand Up @@ -104,12 +104,6 @@ std::unique_ptr<SolidColorContents> SolidColorContents::Make(const Path& path,
std::optional<Color> SolidColorContents::AsBackgroundColor(
const Entity& entity,
ISize target_size) const {
if (!(GetColor().IsOpaque() &&
(entity.GetBlendMode() == BlendMode::kSource ||
entity.GetBlendMode() == BlendMode::kSourceOver))) {
return {};
}

Rect target_rect = Rect::MakeSize(target_size);
return GetGeometry()->CoversArea(entity.GetTransformation(), target_rect)
? GetColor()
Expand Down
4 changes: 4 additions & 0 deletions impeller/entity/entity.cc
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,10 @@ bool Entity::SetInheritedOpacity(Scalar alpha) {
return true;
}

std::optional<Color> Entity::AsBackgroundColor(ISize target_size) const {
return contents_->AsBackgroundColor(*this, target_size);
}

/// @brief Returns true if the blend mode is "destructive", meaning that even
/// fully transparent source colors would result in the destination
/// getting changed.
Expand Down
2 changes: 2 additions & 0 deletions impeller/entity/entity.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,8 @@ class Entity {

bool SetInheritedOpacity(Scalar alpha);

std::optional<Color> AsBackgroundColor(ISize target_size) const;

private:
Matrix transformation_;
std::shared_ptr<Contents> contents_;
Expand Down
32 changes: 15 additions & 17 deletions impeller/entity/entity_pass.cc
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,13 @@
namespace impeller {

namespace {
std::optional<Color> AsBackgroundColor(const EntityPass::Element& element,
ISize target_size) {
std::tuple<std::optional<Color>, BlendMode> ElementAsBackgroundColor(
const EntityPass::Element& element,
ISize target_size) {
if (const Entity* entity = std::get_if<Entity>(&element)) {
std::optional<Color> entity_color =
entity->GetContents()->AsBackgroundColor(*entity, target_size);
std::optional<Color> entity_color = entity->AsBackgroundColor(target_size);
if (entity_color.has_value()) {
return entity_color.value();
return {entity_color.value(), entity->GetBlendMode()};
}
}
return {};
Expand Down Expand Up @@ -251,7 +251,7 @@ bool EntityPass::Render(ContentContext& renderer,
if (!supports_onscreen_backdrop_reads && reads_from_onscreen_backdrop) {
auto offscreen_target = CreateRenderTarget(
renderer, root_render_target.GetRenderTargetSize(), true,
GetClearColor(render_target.GetRenderTargetSize()).Premultiply());
GetClearColor(render_target.GetRenderTargetSize()));

if (!OnRender(renderer, // renderer
offscreen_target.GetRenderTarget()
Expand Down Expand Up @@ -356,8 +356,7 @@ bool EntityPass::Render(ContentContext& renderer,
}

// Set up the clear color of the root pass.
color0.clear_color =
GetClearColor(render_target.GetRenderTargetSize()).Premultiply();
color0.clear_color = GetClearColor(render_target.GetRenderTargetSize());
root_render_target.SetColorAttachment(color0, 0);

EntityPassTarget pass_target(
Expand Down Expand Up @@ -723,13 +722,12 @@ bool EntityPass::OnRender(
for (const auto& element : elements_) {
// Skip elements that are incorporated into the clear color.
if (is_collapsing_clear_colors) {
std::optional<Color> entity_color =
AsBackgroundColor(element, root_pass_size);
auto [entity_color, _] =
ElementAsBackgroundColor(element, root_pass_size);
if (entity_color.has_value()) {
continue;
} else {
is_collapsing_clear_colors = false;
}
is_collapsing_clear_colors = false;
}

EntityResult result =
Expand Down Expand Up @@ -922,14 +920,14 @@ void EntityPass::SetBlendMode(BlendMode blend_mode) {
Color EntityPass::GetClearColor(ISize target_size) const {
Color result = Color::BlackTransparent();
for (const Element& element : elements_) {
std::optional<Color> entity_color = AsBackgroundColor(element, target_size);
if (entity_color.has_value()) {
result = entity_color.value();
} else {
auto [entity_color, blend_mode] =
ElementAsBackgroundColor(element, target_size);
if (!entity_color.has_value()) {
break;
}
result = result.Blend(entity_color.value(), blend_mode);
}
return result;
return result.Premultiply();
}

void EntityPass::SetBackdropFilter(BackdropFilterProc proc) {
Expand Down
4 changes: 4 additions & 0 deletions impeller/entity/geometry/geometry.cc
Original file line number Diff line number Diff line change
Expand Up @@ -138,4 +138,8 @@ std::unique_ptr<Geometry> Geometry::MakeRect(Rect rect) {
return std::make_unique<RectGeometry>(rect);
}

bool Geometry::CoversArea(const Matrix& transform, const Rect& rect) const {
return false;
}

} // namespace impeller
4 changes: 1 addition & 3 deletions impeller/entity/geometry/geometry.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,9 +90,7 @@ class Geometry {

/// @return `true` if this geometry will completely cover all fragments in
/// `rect` when the `transform` is applied to it.
virtual bool CoversArea(const Matrix& transform, const Rect& rect) const {
return false;
}
virtual bool CoversArea(const Matrix& transform, const Rect& rect) const;
};

} // namespace impeller