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

Commit 13b6e9e

Browse files
committed
Add FilterContents::GetSourceCoverage to enable filterd saveLayer clipping
1 parent ef568c3 commit 13b6e9e

22 files changed

+207
-3
lines changed

impeller/entity/contents/filters/border_mask_blur_filter_contents.cc

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,4 +169,15 @@ std::optional<Rect> BorderMaskBlurFilterContents::GetFilterCoverage(
169169
Size(extent.x, extent.y));
170170
}
171171

172+
std::optional<Rect> BorderMaskBlurFilterContents::GetFilterSourceCoverage(
173+
const Matrix& effect_transform,
174+
const Rect& output_limit) const {
175+
auto transformed_blur_vector =
176+
effect_transform.TransformDirection(Vector2(Radius{sigma_x_}.radius, 0))
177+
.Abs() +
178+
effect_transform.TransformDirection(Vector2(0, Radius{sigma_y_}.radius))
179+
.Abs();
180+
return output_limit.Expand(transformed_blur_vector);
181+
}
182+
172183
} // namespace impeller

impeller/entity/contents/filters/border_mask_blur_filter_contents.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,11 @@ class BorderMaskBlurFilterContents final : public FilterContents {
2727
const Entity& entity,
2828
const Matrix& effect_transform) const override;
2929

30+
// |FilterContents|
31+
std::optional<Rect> GetFilterSourceCoverage(
32+
const Matrix& effect_transform,
33+
const Rect& output_limit) const override;
34+
3035
private:
3136
// |FilterContents|
3237
std::optional<Entity> RenderFilter(

impeller/entity/contents/filters/color_filter_contents.cc

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,4 +99,10 @@ std::optional<Scalar> ColorFilterContents::GetAlpha() const {
9999
return alpha_;
100100
}
101101

102+
std::optional<Rect> ColorFilterContents::GetFilterSourceCoverage(
103+
const Matrix& effect_transform,
104+
const Rect& output_limit) const {
105+
return output_limit;
106+
}
107+
102108
} // namespace impeller

impeller/entity/contents/filters/color_filter_contents.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,11 @@ class ColorFilterContents : public FilterContents {
4444

4545
std::optional<Scalar> GetAlpha() const;
4646

47+
// |FilterContents|
48+
std::optional<Rect> GetFilterSourceCoverage(
49+
const Matrix& effect_transform,
50+
const Rect& output_limit) const override;
51+
4752
private:
4853
AbsorbOpacity absorb_opacity_ = AbsorbOpacity::kNo;
4954
std::optional<Scalar> alpha_;

impeller/entity/contents/filters/filter_contents.cc

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,28 @@ std::optional<Rect> FilterContents::GetFilterCoverage(
218218
return result;
219219
}
220220

221+
std::optional<Rect> FilterContents::GetSourceCoverage(
222+
const Matrix& effect_transform,
223+
const Rect& output_limit) const {
224+
auto filter_input_coverage =
225+
GetFilterSourceCoverage(effect_transform_, output_limit);
226+
227+
if (!filter_input_coverage.has_value()) {
228+
return std::nullopt;
229+
}
230+
231+
std::optional<Rect> inputs_coverage;
232+
for (auto input : inputs_) {
233+
auto input_coverage = input->GetSourceCoverage(
234+
effect_transform, filter_input_coverage.value());
235+
if (!input_coverage.has_value()) {
236+
return std::nullopt;
237+
}
238+
inputs_coverage = Union(inputs_coverage, input_coverage.value());
239+
}
240+
return inputs_coverage;
241+
}
242+
221243
std::optional<Entity> FilterContents::GetEntity(
222244
const ContentContext& renderer,
223245
const Entity& entity,

impeller/entity/contents/filters/filter_contents.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,20 @@ class FilterContents : public Contents {
128128
// |Contents|
129129
const FilterContents* AsFilter() const override;
130130

131+
/// @brief Determines the coverage of source pixels that will be needed
132+
/// to apply this filter under the given transform and produce
133+
/// results anywhere within the indicated coverage limit.
134+
///
135+
/// This is useful for subpass rendering scenarios where a filter
136+
/// will be applied to the output of the subpass and we need to
137+
/// determine how large of a render target to allocate in order
138+
/// to collect all pixels that might affect the supplied output
139+
/// coverage limit. While we might clip the rendering of the subpass,
140+
/// we want to avoid clipping out any pixels that contribute to
141+
/// the output limit via the filtering operation.
142+
std::optional<Rect> GetSourceCoverage(const Matrix& effect_transform,
143+
const Rect& output_limit) const;
144+
131145
virtual Matrix GetLocalTransform(const Matrix& parent_transform) const;
132146

133147
Matrix GetTransform(const Matrix& parent_transform) const;
@@ -165,6 +179,10 @@ class FilterContents : public Contents {
165179
const Entity& entity,
166180
const Matrix& effect_transform) const;
167181

182+
virtual std::optional<Rect> GetFilterSourceCoverage(
183+
const Matrix& effect_transform,
184+
const Rect& output_limit) const = 0;
185+
168186
/// @brief Converts zero or more filter inputs into a render instruction.
169187
virtual std::optional<Entity> RenderFilter(
170188
const FilterInput::Vector& inputs,

impeller/entity/contents/filters/gaussian_blur_filter_contents.cc

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@ namespace impeller {
2626
DirectionalGaussianBlurFilterContents::DirectionalGaussianBlurFilterContents() =
2727
default;
2828

29-
DirectionalGaussianBlurFilterContents::
30-
~DirectionalGaussianBlurFilterContents() = default;
29+
DirectionalGaussianBlurFilterContents::~
30+
DirectionalGaussianBlurFilterContents() = default;
3131

3232
void DirectionalGaussianBlurFilterContents::SetSigma(Sigma sigma) {
3333
blur_sigma_ = sigma;
@@ -273,6 +273,17 @@ std::optional<Entity> DirectionalGaussianBlurFilterContents::RenderFilter(
273273
entity.GetBlendMode(), entity.GetClipDepth());
274274
}
275275

276+
std::optional<Rect>
277+
DirectionalGaussianBlurFilterContents::GetFilterSourceCoverage(
278+
const Matrix& effect_transform,
279+
const Rect& output_limit) const {
280+
auto transform = effect_transform.Basis();
281+
auto transformed_blur_vector =
282+
transform.TransformDirection(blur_direction_ * Radius{blur_sigma_}.radius)
283+
.Abs();
284+
return output_limit.Expand(transformed_blur_vector);
285+
}
286+
276287
std::optional<Rect> DirectionalGaussianBlurFilterContents::GetFilterCoverage(
277288
const FilterInput::Vector& inputs,
278289
const Entity& entity,

impeller/entity/contents/filters/gaussian_blur_filter_contents.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,11 @@ class DirectionalGaussianBlurFilterContents final : public FilterContents {
2929

3030
void SetIsSecondPass(bool is_second_pass);
3131

32+
// |FilterContents|
33+
std::optional<Rect> GetFilterSourceCoverage(
34+
const Matrix& effect_transform,
35+
const Rect& output_limit) const override;
36+
3237
// |FilterContents|
3338
std::optional<Rect> GetFilterCoverage(
3439
const FilterInput::Vector& inputs,

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,12 @@ std::optional<Rect> FilterContentsFilterInput::GetCoverage(
4343
return filter_->GetCoverage(entity);
4444
}
4545

46+
std::optional<Rect> FilterContentsFilterInput::GetSourceCoverage(
47+
const Matrix& effect_transform,
48+
const Rect& output_limit) const {
49+
return filter_->GetSourceCoverage(effect_transform, output_limit);
50+
}
51+
4652
Matrix FilterContentsFilterInput::GetLocalTransform(
4753
const Entity& entity) const {
4854
return filter_->GetLocalTransform(entity.GetTransformation());

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,11 @@ class FilterContentsFilterInput final : public FilterInput {
2525
// |FilterInput|
2626
std::optional<Rect> GetCoverage(const Entity& entity) const override;
2727

28+
// |FilterInput|
29+
std::optional<Rect> GetSourceCoverage(
30+
const Matrix& effect_transform,
31+
const Rect& output_limit) const override;
32+
2833
// |FilterInput|
2934
Matrix GetLocalTransform(const Entity& entity) const override;
3035

0 commit comments

Comments
 (0)