Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit c39eb69

Browse files
authored
[Impeller] Incorporate filters in subpass coverage. (#45778)
I adjusted the size of the matrix filtered circle in both SaveLayer Matrix filter test variants (post-filter and backdrop filter) to move the transformed circle outside the coverage area that would be computed if subpass filters aren't being accounted for. Further, we need to avoid intersecting with the pass coverage hint when the transformation being applied by the paint's filter graph causes the Entity's space basis to deviate from the parent pass basis. We're still able to apply it for simple translations, though.
1 parent 2cd34d2 commit c39eb69

20 files changed

+163
-14
lines changed

impeller/aiks/aiks_unittests.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3220,7 +3220,7 @@ TEST_P(AiksTest, MatrixSaveLayerFilter) {
32203220
canvas.SaveLayer({.image_filter = ImageFilter::MakeMatrix(
32213221
Matrix::MakeTranslation(Vector2(1, 1) *
32223222
(200 + 100 * k1OverSqrt2)) *
3223-
Matrix::MakeScale(Vector2(1, 1) * 0.2) *
3223+
Matrix::MakeScale(Vector2(1, 1) * 0.5) *
32243224
Matrix::MakeTranslation(Vector2(-200, -200)),
32253225
SamplerDescriptor{})},
32263226
std::nullopt);
@@ -3248,7 +3248,7 @@ TEST_P(AiksTest, MatrixBackdropFilter) {
32483248
{}, std::nullopt,
32493249
ImageFilter::MakeMatrix(
32503250
Matrix::MakeTranslation(Vector2(1, 1) * (100 + 100 * k1OverSqrt2)) *
3251-
Matrix::MakeScale(Vector2(1, 1) * 0.2) *
3251+
Matrix::MakeScale(Vector2(1, 1) * 0.5) *
32523252
Matrix::MakeTranslation(Vector2(-100, -100)),
32533253
SamplerDescriptor{}));
32543254
canvas.Restore();

impeller/aiks/paint.cc

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -60,14 +60,21 @@ std::shared_ptr<Contents> Paint::WithFilters(
6060
std::shared_ptr<Contents> input) const {
6161
input = WithColorFilter(input, /*absorb_opacity=*/true);
6262
input = WithInvertFilter(input);
63-
input = WithImageFilter(input, Matrix(), /*is_subpass=*/false);
63+
auto image_filter = WithImageFilter(input, Matrix(), /*is_subpass=*/false);
64+
if (image_filter) {
65+
input = image_filter;
66+
}
6467
return input;
6568
}
6669

6770
std::shared_ptr<Contents> Paint::WithFiltersForSubpassTarget(
6871
std::shared_ptr<Contents> input,
6972
const Matrix& effect_transform) const {
70-
input = WithImageFilter(input, effect_transform, /*is_subpass=*/true);
73+
auto image_filter =
74+
WithImageFilter(input, effect_transform, /*is_subpass=*/true);
75+
if (image_filter) {
76+
input = image_filter;
77+
}
7178
input = WithColorFilter(input, /*absorb_opacity=*/true);
7279
return input;
7380
}
@@ -81,12 +88,12 @@ std::shared_ptr<Contents> Paint::WithMaskBlur(std::shared_ptr<Contents> input,
8188
return input;
8289
}
8390

84-
std::shared_ptr<Contents> Paint::WithImageFilter(
85-
std::shared_ptr<Contents> input,
91+
std::shared_ptr<FilterContents> Paint::WithImageFilter(
92+
const FilterInput::Variant& input,
8693
const Matrix& effect_transform,
8794
bool is_subpass) const {
8895
if (!image_filter) {
89-
return input;
96+
return nullptr;
9097
}
9198
auto filter = image_filter->WrapInput(FilterInput::Make(input));
9299
filter->SetIsForSubpass(is_subpass);

impeller/aiks/paint.h

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -98,11 +98,12 @@ struct Paint {
9898
std::shared_ptr<Contents> WithMaskBlur(std::shared_ptr<Contents> input,
9999
bool is_solid_color) const;
100100

101-
private:
102-
std::shared_ptr<Contents> WithImageFilter(std::shared_ptr<Contents> input,
103-
const Matrix& effect_transform,
104-
bool is_subpass) const;
101+
std::shared_ptr<FilterContents> WithImageFilter(
102+
const FilterInput::Variant& input,
103+
const Matrix& effect_transform,
104+
bool is_subpass) const;
105105

106+
private:
106107
std::shared_ptr<Contents> WithColorFilter(std::shared_ptr<Contents> input,
107108
bool absorb_opacity = false) const;
108109

impeller/aiks/paint_pass_delegate.cc

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,13 @@ std::shared_ptr<Contents> PaintPassDelegate::CreateContentsForSubpassTarget(
4747
effect_transform);
4848
}
4949

50+
// |EntityPassDelgate|
51+
std::shared_ptr<FilterContents> PaintPassDelegate::WithImageFilter(
52+
const FilterInput::Variant& input,
53+
const Matrix& effect_transform) const {
54+
return paint_.WithImageFilter(input, effect_transform, true);
55+
}
56+
5057
/// OpacityPeepholePassDelegate
5158
/// ----------------------------------------------
5259

@@ -140,4 +147,11 @@ OpacityPeepholePassDelegate::CreateContentsForSubpassTarget(
140147
effect_transform);
141148
}
142149

150+
// |EntityPassDelgate|
151+
std::shared_ptr<FilterContents> OpacityPeepholePassDelegate::WithImageFilter(
152+
const FilterInput::Variant& input,
153+
const Matrix& effect_transform) const {
154+
return paint_.WithImageFilter(input, effect_transform, true);
155+
}
156+
143157
} // namespace impeller

impeller/aiks/paint_pass_delegate.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,11 @@ class PaintPassDelegate final : public EntityPassDelegate {
3232
std::shared_ptr<Texture> target,
3333
const Matrix& effect_transform) override;
3434

35+
// |EntityPassDelgate|
36+
std::shared_ptr<FilterContents> WithImageFilter(
37+
const FilterInput::Variant& input,
38+
const Matrix& effect_transform) const override;
39+
3540
private:
3641
const Paint paint_;
3742

@@ -61,6 +66,11 @@ class OpacityPeepholePassDelegate final : public EntityPassDelegate {
6166
std::shared_ptr<Texture> target,
6267
const Matrix& effect_transform) override;
6368

69+
// |EntityPassDelgate|
70+
std::shared_ptr<FilterContents> WithImageFilter(
71+
const FilterInput::Variant& input,
72+
const Matrix& effect_transform) const override;
73+
6474
private:
6575
const Paint paint_;
6676

impeller/entity/contents/contents.cc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,10 @@ std::optional<Color> Contents::AsBackgroundColor(const Entity& entity,
123123
return {};
124124
}
125125

126+
const FilterContents* Contents::AsFilter() const {
127+
return nullptr;
128+
}
129+
126130
bool Contents::ApplyColorFilter(
127131
const Contents::ColorFilterProc& color_filter_proc) {
128132
return false;

impeller/entity/contents/contents.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ struct ContentContextOptions;
2323
class Entity;
2424
class Surface;
2525
class RenderPass;
26+
class FilterContents;
2627

2728
ContentContextOptions OptionsFromPass(const RenderPass& pass);
2829

@@ -155,6 +156,12 @@ class Contents {
155156
virtual std::optional<Color> AsBackgroundColor(const Entity& entity,
156157
ISize target_size) const;
157158

159+
//----------------------------------------------------------------------------
160+
/// @brief Cast to a filter. Returns `nullptr` if this Contents is not a
161+
/// filter.
162+
///
163+
virtual const FilterContents* AsFilter() const;
164+
158165
//----------------------------------------------------------------------------
159166
/// @brief If possible, applies a color filter to this contents inputs on
160167
/// the CPU.

impeller/entity/contents/filters/filter_contents.cc

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,13 +259,25 @@ std::optional<Snapshot> FilterContents::RenderToSnapshot(
259259
return std::nullopt;
260260
}
261261

262+
const FilterContents* FilterContents::AsFilter() const {
263+
return this;
264+
}
265+
262266
Matrix FilterContents::GetLocalTransform(const Matrix& parent_transform) const {
263267
return Matrix();
264268
}
265269

266270
Matrix FilterContents::GetTransform(const Matrix& parent_transform) const {
267271
return parent_transform * GetLocalTransform(parent_transform);
268272
}
273+
bool FilterContents::IsTranslationOnly() const {
274+
for (auto& input : inputs_) {
275+
if (!input->IsTranslationOnly()) {
276+
return false;
277+
}
278+
}
279+
return true;
280+
}
269281

270282
bool FilterContents::IsLeaf() const {
271283
for (auto& input : inputs_) {

impeller/entity/contents/filters/filter_contents.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,10 +125,23 @@ class FilterContents : public Contents {
125125
bool msaa_enabled = true,
126126
const std::string& label = "Filter Snapshot") const override;
127127

128+
// |Contents|
129+
const FilterContents* AsFilter() const override;
130+
128131
virtual Matrix GetLocalTransform(const Matrix& parent_transform) const;
129132

130133
Matrix GetTransform(const Matrix& parent_transform) const;
131134

135+
/// @brief Returns true if this filter graph doesn't perform any basis
136+
/// transformations to the filtered content. For example: Rotating,
137+
/// scaling, and skewing are all basis transformations, but
138+
/// translating is not.
139+
///
140+
/// This is useful for determining whether a filtered object's space
141+
/// is compatible enough with the parent pass space to perform certain
142+
/// subpass clipping optimizations.
143+
virtual bool IsTranslationOnly() const;
144+
132145
/// @brief Returns `true` if this filter does not have any `FilterInput`
133146
/// children.
134147
bool IsLeaf() const;

impeller/entity/contents/filters/inputs/filter_contents_filter_input.cc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,10 @@ void FilterContentsFilterInput::PopulateGlyphAtlas(
5858
filter_->PopulateGlyphAtlas(lazy_glyph_atlas, scale);
5959
}
6060

61+
bool FilterContentsFilterInput::IsTranslationOnly() const {
62+
return filter_->IsTranslationOnly();
63+
}
64+
6165
bool FilterContentsFilterInput::IsLeaf() const {
6266
return false;
6367
}

0 commit comments

Comments
 (0)