Skip to content

Commit 7b569d5

Browse files
authored
[Impeller] Minimally crop advanced blends in EntityPass (flutter#34347)
1 parent 8e63563 commit 7b569d5

File tree

5 files changed

+62
-14
lines changed

5 files changed

+62
-14
lines changed

impeller/entity/contents/filters/filter_contents.cc

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,10 @@ void FilterContents::SetInputs(FilterInput::Vector inputs) {
116116
inputs_ = std::move(inputs);
117117
}
118118

119+
void FilterContents::SetCoverageCrop(std::optional<Rect> coverage_crop) {
120+
coverage_crop_ = coverage_crop;
121+
}
122+
119123
bool FilterContents::Render(const ContentContext& renderer,
120124
const Entity& entity,
121125
RenderPass& pass) const {
@@ -146,11 +150,22 @@ bool FilterContents::Render(const ContentContext& renderer,
146150
return contents->Render(renderer, e, pass);
147151
}
148152

153+
std::optional<Rect> FilterContents::GetLocalCoverage(
154+
const Entity& local_entity) const {
155+
auto coverage = GetFilterCoverage(inputs_, local_entity);
156+
if (coverage_crop_.has_value() && coverage.has_value()) {
157+
coverage = coverage->Intersection(coverage_crop_.value());
158+
}
159+
160+
return coverage;
161+
}
162+
149163
std::optional<Rect> FilterContents::GetCoverage(const Entity& entity) const {
150164
Entity entity_with_local_transform = entity;
151165
entity_with_local_transform.SetTransformation(
152166
GetTransform(entity.GetTransformation()));
153-
return GetFilterCoverage(inputs_, entity_with_local_transform);
167+
168+
return GetLocalCoverage(entity_with_local_transform);
154169
}
155170

156171
std::optional<Rect> FilterContents::GetFilterCoverage(
@@ -186,7 +201,7 @@ std::optional<Snapshot> FilterContents::RenderToSnapshot(
186201
entity_with_local_transform.SetTransformation(
187202
GetTransform(entity.GetTransformation()));
188203

189-
auto coverage = GetFilterCoverage(inputs_, entity_with_local_transform);
204+
auto coverage = GetLocalCoverage(entity_with_local_transform);
190205
if (!coverage.has_value() || coverage->IsEmpty()) {
191206
return std::nullopt;
192207
}

impeller/entity/contents/filters/filter_contents.h

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -109,13 +109,16 @@ class FilterContents : public Contents {
109109

110110
~FilterContents() override;
111111

112-
/// @brief The input texture sources for this filter. Each input's emitted
113-
/// texture is expected to have premultiplied alpha colors.
112+
/// @brief The input texture sources for this filter. Each input's emitted
113+
/// texture is expected to have premultiplied alpha colors.
114114
///
115-
/// The number of required or optional textures depends on the
116-
/// particular filter's implementation.
115+
/// The number of required or optional textures depends on the
116+
/// particular filter's implementation.
117117
void SetInputs(FilterInput::Vector inputs);
118118

119+
/// @brief Screen space bounds to use for cropping the filter output.
120+
void SetCoverageCrop(std::optional<Rect> coverage_crop);
121+
119122
// |Contents|
120123
bool Render(const ContentContext& renderer,
121124
const Entity& entity,
@@ -145,7 +148,10 @@ class FilterContents : public Contents {
145148
RenderPass& pass,
146149
const Rect& coverage) const = 0;
147150

151+
std::optional<Rect> GetLocalCoverage(const Entity& local_entity) const;
152+
148153
FilterInput::Vector inputs_;
154+
std::optional<Rect> coverage_crop_;
149155

150156
FML_DISALLOW_COPY_AND_ASSIGN(FilterContents);
151157
};

impeller/entity/entity_pass.cc

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -65,20 +65,20 @@ const std::shared_ptr<LazyGlyphAtlas>& EntityPass::GetLazyGlyphAtlas() const {
6565
}
6666

6767
std::optional<Rect> EntityPass::GetElementsCoverage(
68-
std::optional<Rect> coverage_clip) const {
68+
std::optional<Rect> coverage_crop) const {
6969
std::optional<Rect> result;
7070
for (const auto& element : elements_) {
7171
std::optional<Rect> coverage;
7272

7373
if (auto entity = std::get_if<Entity>(&element)) {
7474
coverage = entity->GetCoverage();
7575

76-
if (coverage.has_value() && coverage_clip.has_value()) {
77-
coverage = coverage->Intersection(coverage_clip.value());
76+
if (coverage.has_value() && coverage_crop.has_value()) {
77+
coverage = coverage->Intersection(coverage_crop.value());
7878
}
7979
} else if (auto subpass =
8080
std::get_if<std::unique_ptr<EntityPass>>(&element)) {
81-
coverage = GetSubpassCoverage(*subpass->get(), coverage_clip);
81+
coverage = GetSubpassCoverage(*subpass->get(), coverage_crop);
8282
} else {
8383
FML_UNREACHABLE();
8484
}
@@ -427,8 +427,10 @@ bool EntityPass::OnRender(ContentContext& renderer,
427427
FilterInput::Make(result.entity.GetContents()),
428428
FilterInput::Make(texture,
429429
result.entity.GetTransformation().Invert())};
430-
result.entity.SetContents(
431-
FilterContents::MakeBlend(result.entity.GetBlendMode(), inputs));
430+
auto contents =
431+
FilterContents::MakeBlend(result.entity.GetBlendMode(), inputs);
432+
contents->SetCoverageCrop(result.entity.GetCoverage());
433+
result.entity.SetContents(std::move(contents));
432434
result.entity.SetBlendMode(Entity::BlendMode::kSourceOver);
433435
}
434436

impeller/entity/entity_pass.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,10 +62,10 @@ class EntityPass {
6262

6363
std::optional<Rect> GetSubpassCoverage(
6464
const EntityPass& subpass,
65-
std::optional<Rect> coverage_clip) const;
65+
std::optional<Rect> coverage_crop) const;
6666

6767
std::optional<Rect> GetElementsCoverage(
68-
std::optional<Rect> coverage_clip) const;
68+
std::optional<Rect> coverage_crop) const;
6969

7070
private:
7171
struct EntityResult {

impeller/entity/entity_unittests.cc

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,31 @@ TEST_P(EntityTest, EntityPassCoverageRespectsCoverageLimit) {
131131
}
132132
}
133133

134+
TEST_P(EntityTest, FilterCoverageRespectsCropRect) {
135+
auto image = CreateTextureForFixture("boston.jpg");
136+
auto filter = FilterContents::MakeBlend(Entity::BlendMode::kSoftLight,
137+
FilterInput::Make({image}));
138+
139+
// Without the crop rect (default behavior).
140+
{
141+
auto actual = filter->GetCoverage({});
142+
auto expected = Rect::MakeSize(Size(image->GetSize()));
143+
144+
ASSERT_TRUE(actual.has_value());
145+
ASSERT_RECT_NEAR(actual.value(), expected);
146+
}
147+
148+
// With the crop rect.
149+
{
150+
auto expected = Rect::MakeLTRB(50, 50, 100, 100);
151+
filter->SetCoverageCrop(expected);
152+
auto actual = filter->GetCoverage({});
153+
154+
ASSERT_TRUE(actual.has_value());
155+
ASSERT_RECT_NEAR(actual.value(), expected);
156+
}
157+
}
158+
134159
TEST_P(EntityTest, CanDrawRect) {
135160
Entity entity;
136161
entity.SetTransformation(Matrix::MakeScale(GetContentScale()));

0 commit comments

Comments
 (0)