Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Prev Previous commit
Next Next commit
add test case and fix subpass coverage limits
  • Loading branch information
flar committed Oct 26, 2023
commit 821e7b1601c4f9590c53fbbcce3d3ce924be8629
30 changes: 30 additions & 0 deletions impeller/aiks/aiks_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2760,6 +2760,36 @@ TEST_P(AiksTest, TranslucentSaveLayerWithColorAndImageFilterDrawsCorrectly) {
ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
}

TEST_P(AiksTest, ImageFilteredSaveLayerWithUnboundedContents) {
Canvas canvas;

auto texture = CreateTextureForFixture("airplane.jpg");
auto blur_filter = ImageFilter::MakeBlur(Sigma{5.0}, Sigma{5.0},
FilterContents::BlurStyle::kNormal,
Entity::TileMode::kClamp);
auto image_source = ColorSource::MakeImage(texture, Entity::TileMode::kRepeat,
Entity::TileMode::kRepeat, {}, {});

canvas.SaveLayer({.image_filter = blur_filter},
Rect::MakeLTRB(100, 100, 200, 200));

canvas.DrawPaint({.color_source = image_source});

Paint blue = {.color = Color::Blue()};
Paint green = {.color = Color::Green()};

canvas.DrawRect(Rect::MakeLTRB(125, 125, 175, 175), blue);

canvas.DrawRect(Rect::MakeLTRB(125, 50, 175, 98), green);
canvas.DrawRect(Rect::MakeLTRB(202, 125, 250, 175), green);
canvas.DrawRect(Rect::MakeLTRB(125, 202, 175, 250), green);
canvas.DrawRect(Rect::MakeLTRB(50, 125, 98, 175), green);

canvas.Restore();

ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
}

TEST_P(AiksTest, TranslucentSaveLayerImageDrawsCorrectly) {
Canvas canvas;

Expand Down
17 changes: 7 additions & 10 deletions impeller/entity/entity_pass.cc
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,12 @@ std::optional<Rect> EntityPass::GetSubpassCoverage(
std::shared_ptr<FilterContents> image_filter =
subpass.delegate_->WithImageFilter(Rect(), subpass.xformation_);

if (subpass.bounds_limit_.has_value()) {
auto user_bounds_coverage =
subpass.bounds_limit_->TransformBounds(subpass.xformation_);
coverage_limit = Intersection(user_bounds_coverage, coverage_limit);
}

// If the subpass has an image filter, then its coverage space may deviate
// from the parent pass and make intersecting with the pass coverage limit
// unsafe.
Expand All @@ -201,17 +207,8 @@ std::optional<Rect> EntityPass::GetSubpassCoverage(
}

auto entities_coverage = subpass.GetElementsCoverage(coverage_limit);
// The entities don't cover anything. There is nothing to do.
if (!entities_coverage.has_value()) {
return std::nullopt;
}

if (!subpass.bounds_limit_.has_value()) {
return entities_coverage;
}
auto user_bounds_coverage =
subpass.bounds_limit_->TransformBounds(subpass.xformation_);
return entities_coverage->Intersection(user_bounds_coverage);
return entities_coverage;
}

EntityPass* EntityPass::GetSuperpass() const {
Expand Down
45 changes: 24 additions & 21 deletions impeller/geometry/rect.h
Original file line number Diff line number Diff line change
Expand Up @@ -315,31 +315,34 @@ struct TRect {
using Rect = TRect<Scalar>;
using IRect = TRect<int64_t>;

constexpr std::optional<Rect> Union(const Rect& a,
const std::optional<Rect> b) {
if (!b.has_value()) {
return a;
}
return a.Union(b.value());
constexpr inline std::optional<Rect> Union(const Rect& a,
const std::optional<Rect> b) {
return b.has_value() ? a.Union(b.value()) : a;
}

constexpr std::optional<Rect> Union(const std::optional<Rect> a,
const Rect& b) {
if (!a.has_value()) {
return b;
}
return a.value().Union(b);
constexpr inline std::optional<Rect> Union(const std::optional<Rect> a,
const Rect& b) {
return Union(b, a);
}

constexpr std::optional<Rect> Union(const std::optional<Rect> a,
const std::optional<Rect> b) {
if (!a.has_value()) {
return b;
}
if (!b.has_value()) {
return a;
}
return a.value().Union(b.value());
constexpr inline std::optional<Rect> Union(const std::optional<Rect> a,
const std::optional<Rect> b) {
return a.has_value() ? Union(a.value(), b) : b;
}

constexpr inline std::optional<Rect> Intersection(const Rect& a,
const std::optional<Rect> b) {
return b.has_value() ? a.Intersection(b.value()) : a;
}

constexpr inline std::optional<Rect> Intersection(const std::optional<Rect> a,
const Rect& b) {
return Intersection(b, a);
}

constexpr inline std::optional<Rect> Intersection(const std::optional<Rect> a,
const std::optional<Rect> b) {
return a.has_value() ? Intersection(a.value(), b) : b;
}
Copy link
Member

Choose a reason for hiding this comment

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

These are nice additions!


} // namespace impeller
Expand Down