| Flutter Impeller |

filter_contents.cc
Go to the documentation of this file.
1 // Copyright 2013 The Flutter Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "impeller/entity/contents/filters/filter_contents.h"
6
7 #include <algorithm>
8 #include <cmath>
9 #include <cstddef>
10 #include <memory>
11 #include <optional>
12 #include <tuple>
13 #include <utility>
14
15 #include "flutter/fml/logging.h"
16 #include "impeller/core/formats.h"
17 #include "impeller/entity/contents/content_context.h"
18 #include "impeller/entity/contents/filters/border_mask_blur_filter_contents.h"
19 #include "impeller/entity/contents/filters/directional_gaussian_blur_filter_contents.h"
20 #include "impeller/entity/contents/filters/gaussian_blur_filter_contents.h"
21 #include "impeller/entity/contents/filters/inputs/filter_input.h"
22 #include "impeller/entity/contents/filters/local_matrix_filter_contents.h"
23 #include "impeller/entity/contents/filters/matrix_filter_contents.h"
24 #include "impeller/entity/contents/filters/morphology_filter_contents.h"
25 #include "impeller/entity/contents/filters/yuv_to_rgb_filter_contents.h"
26 #include "impeller/entity/contents/texture_contents.h"
27 #include "impeller/entity/entity.h"
28 #include "impeller/geometry/path_builder.h"
29 #include "impeller/renderer/command_buffer.h"
30 #include "impeller/renderer/render_pass.h"
31
32 namespace impeller {
33
34 std::shared_ptr<FilterContents> FilterContents::MakeDirectionalGaussianBlur(
35 FilterInput::Ref input,
36 Sigma sigma,
37 Vector2 direction,
38 BlurStyle blur_style,
39 Entity::TileMode tile_mode,
40 bool is_second_pass,
41 Sigma secondary_sigma) {
42 auto blur = std::make_shared<DirectionalGaussianBlurFilterContents>();
43 blur->SetInputs({std::move(input)});
44 blur->SetSigma(sigma);
45 blur->SetDirection(direction);
46 blur->SetBlurStyle(blur_style);
47 blur->SetTileMode(tile_mode);
48 blur->SetIsSecondPass(is_second_pass);
49 blur->SetSecondarySigma(secondary_sigma);
50 return blur;
51 }
52
53 std::shared_ptr<FilterContents> FilterContents::MakeGaussianBlur(
54 const FilterInput::Ref& input,
55 Sigma sigma_x,
56 Sigma sigma_y,
57 BlurStyle blur_style,
58 Entity::TileMode tile_mode) {
59 constexpr bool use_new_filter =
60 #ifdef IMPELLER_ENABLE_NEW_GAUSSIAN_FILTER
61 true;
62 #else
63 false;
64 #endif
65
66 // TODO(https://github.com/flutter/flutter/issues/131580): Remove once the new
67 // blur handles all cases.
68 if (use_new_filter) {
69 auto blur = std::make_shared<GaussianBlurFilterContents>(
70 sigma_x.sigma, sigma_y.sigma, tile_mode);
71 blur->SetInputs({input});
72 return blur;
73 }
74 std::shared_ptr<FilterContents> x_blur = MakeDirectionalGaussianBlur(
75 /*input=*/input,
76 /*sigma=*/sigma_x,
77 /*direction=*/Point(1, 0),
78 /*blur_style=*/BlurStyle::kNormal,
79 /*tile_mode=*/tile_mode,
80 /*is_second_pass=*/false,
81 /*secondary_sigma=*/{});
82 std::shared_ptr<FilterContents> y_blur = MakeDirectionalGaussianBlur(
83 /*input=*/FilterInput::Make(x_blur),
84 /*sigma=*/sigma_y,
85 /*direction=*/Point(0, 1),
86 /*blur_style=*/blur_style,
87 /*tile_mode=*/tile_mode,
88 /*is_second_pass=*/true,
89 /*secondary_sigma=*/sigma_x);
90 return y_blur;
91 }
92
93 std::shared_ptr<FilterContents> FilterContents::MakeBorderMaskBlur(
94 FilterInput::Ref input,
95 Sigma sigma_x,
96 Sigma sigma_y,
97 BlurStyle blur_style) {
98 auto filter = std::make_shared<BorderMaskBlurFilterContents>();
99 filter->SetInputs({std::move(input)});
100 filter->SetSigma(sigma_x, sigma_y);
101 filter->SetBlurStyle(blur_style);
102 return filter;
103 }
104
105 std::shared_ptr<FilterContents> FilterContents::MakeDirectionalMorphology(
106 FilterInput::Ref input,
107 Radius radius,
108 Vector2 direction,
109 MorphType morph_type) {
110 auto filter = std::make_shared<DirectionalMorphologyFilterContents>();
111 filter->SetInputs({std::move(input)});
112 filter->SetRadius(radius);
113 filter->SetDirection(direction);
114 filter->SetMorphType(morph_type);
115 return filter;
116 }
117
118 std::shared_ptr<FilterContents> FilterContents::MakeMorphology(
119 FilterInput::Ref input,
120 Radius radius_x,
121 Radius radius_y,
122 MorphType morph_type) {
123 auto x_morphology = MakeDirectionalMorphology(std::move(input), radius_x,
124 Point(1, 0), morph_type);
125 auto y_morphology = MakeDirectionalMorphology(
126 FilterInput::Make(x_morphology), radius_y, Point(0, 1), morph_type);
127 return y_morphology;
128 }
129
130 std::shared_ptr<FilterContents> FilterContents::MakeMatrixFilter(
131 FilterInput::Ref input,
132 const Matrix& matrix,
133 const SamplerDescriptor& desc) {
134 auto filter = std::make_shared<MatrixFilterContents>();
135 filter->SetInputs({std::move(input)});
136 filter->SetMatrix(matrix);
137 filter->SetSamplerDescriptor(desc);
138 return filter;
139 }
140
141 std::shared_ptr<FilterContents> FilterContents::MakeLocalMatrixFilter(
142 FilterInput::Ref input,
143 const Matrix& matrix) {
144 auto filter = std::make_shared<LocalMatrixFilterContents>();
145 filter->SetInputs({std::move(input)});
146 filter->SetMatrix(matrix);
147 return filter;
148 }
149
150 std::shared_ptr<FilterContents> FilterContents::MakeYUVToRGBFilter(
151 std::shared_ptr<Texture> y_texture,
152 std::shared_ptr<Texture> uv_texture,
153 YUVColorSpace yuv_color_space) {
154 auto filter = std::make_shared<impeller::YUVToRGBFilterContents>();
155 filter->SetInputs({impeller::FilterInput::Make(y_texture),
156 impeller::FilterInput::Make(uv_texture)});
157 filter->SetYUVColorSpace(yuv_color_space);
158 return filter;
159 }
160
161 FilterContents::FilterContents() = default;
162
163 FilterContents::~FilterContents() = default;
164
165 void FilterContents::SetInputs(FilterInput::Vector inputs) {
166 inputs_ = std::move(inputs);
167 }
168
169 void FilterContents::SetEffectTransform(const Matrix& effect_transform) {
170 effect_transform_ = effect_transform;
171
172 for (auto& input : inputs_) {
173 input->SetEffectTransform(effect_transform);
174 }
175 }
176
177 bool FilterContents::Render(const ContentContext& renderer,
178 const Entity& entity,
179 RenderPass& pass) const {
180 auto filter_coverage = GetCoverage(entity);
181 if (!filter_coverage.has_value()) {
182 return true;
183 }
184
185 // Run the filter.
186
187 auto maybe_entity = GetEntity(renderer, entity, GetCoverageHint());
188 if (!maybe_entity.has_value()) {
189 return true;
190 }
191 return maybe_entity->Render(renderer, pass);
192 }
193
194 std::optional<Rect> FilterContents::GetLocalCoverage(
195 const Entity& local_entity) const {
196 auto coverage = GetFilterCoverage(inputs_, local_entity, effect_transform_);
197 auto coverage_hint = GetCoverageHint();
198 if (coverage_hint.has_value() && coverage.has_value()) {
199 coverage = coverage->Intersection(coverage_hint.value());
200 }
201
202 return coverage;
203 }
204
205 std::optional<Rect> FilterContents::GetCoverage(const Entity& entity) const {
206 Entity entity_with_local_transform = entity.Clone();
207 entity_with_local_transform.SetTransform(GetTransform(entity.GetTransform()));
208
209 return GetLocalCoverage(entity_with_local_transform);
210 }
211
212 void FilterContents::PopulateGlyphAtlas(
213 const std::shared_ptr<LazyGlyphAtlas>& lazy_glyph_atlas,
214 Scalar scale) {
215 for (auto& input : inputs_) {
216 input->PopulateGlyphAtlas(lazy_glyph_atlas, scale);
217 }
218 }
219
220 std::optional<Rect> FilterContents::GetFilterCoverage(
221 const FilterInput::Vector& inputs,
222 const Entity& entity,
223 const Matrix& effect_transform) const {
224 // The default coverage of FilterContents is just the union of its inputs'
225 // coverage. FilterContents implementations may choose to adjust this
226 // coverage depending on the use case.
227
228 if (inputs_.empty()) {
229 return std::nullopt;
230 }
231
232 std::optional<Rect> result;
233 for (const auto& input : inputs) {
234 auto coverage = input->GetCoverage(entity);
235 if (!coverage.has_value()) {
236 continue;
237 }
238 if (!result.has_value()) {
239 result = coverage;
240 continue;
241 }
242 result = result->Union(coverage.value());
243 }
244 return result;
245 }
246
247 std::optional<Rect> FilterContents::GetSourceCoverage(
248 const Matrix& effect_transform,
249 const Rect& output_limit) const {
250 auto filter_input_coverage =
251 GetFilterSourceCoverage(effect_transform_, output_limit);
252
253 if (!filter_input_coverage.has_value()) {
254 return std::nullopt;
255 }
256
257 std::optional<Rect> inputs_coverage;
258 for (const auto& input : inputs_) {
259 auto input_coverage = input->GetSourceCoverage(
260 effect_transform, filter_input_coverage.value());
261 if (!input_coverage.has_value()) {
262 return std::nullopt;
263 }
264 inputs_coverage = Rect::Union(inputs_coverage, input_coverage.value());
265 }
266 return inputs_coverage;
267 }
268
269 std::optional<Entity> FilterContents::GetEntity(
270 const ContentContext& renderer,
271 const Entity& entity,
272 const std::optional<Rect>& coverage_hint) const {
273 Entity entity_with_local_transform = entity.Clone();
274 entity_with_local_transform.SetTransform(GetTransform(entity.GetTransform()));
275
276 auto coverage = GetLocalCoverage(entity_with_local_transform);
277 if (!coverage.has_value() || coverage->IsEmpty()) {
278 return std::nullopt;
279 }
280
281 return RenderFilter(inputs_, renderer, entity_with_local_transform,
282 effect_transform_, coverage.value(), coverage_hint);
283 }
284
285 std::optional<Snapshot> FilterContents::RenderToSnapshot(
286 const ContentContext& renderer,
287 const Entity& entity,
288 std::optional<Rect> coverage_limit,
289 const std::optional<SamplerDescriptor>& sampler_descriptor,
290 bool msaa_enabled,
291 const std::string& label) const {
292 // Resolve the render instruction (entity) from the filter and render it to a
293 // snapshot.
294 if (std::optional<Entity> result =
295 GetEntity(renderer, entity, coverage_limit);
296 result.has_value()) {
297 return result->GetContents()->RenderToSnapshot(
298 renderer, // renderer
299 result.value(), // entity
300 coverage_limit, // coverage_limit
301 std::nullopt, // sampler_descriptor
302 true, // msaa_enabled
303 label); // label
304 }
305
306 return std::nullopt;
307 }
308
309 const FilterContents* FilterContents::AsFilter() const {
310 return this;
311 }
312
313 Matrix FilterContents::GetLocalTransform(const Matrix& parent_transform) const {
314 return Matrix();
315 }
316
317 Matrix FilterContents::GetTransform(const Matrix& parent_transform) const {
318 return parent_transform * GetLocalTransform(parent_transform);
319 }
320 bool FilterContents::IsTranslationOnly() const {
321 for (auto& input : inputs_) {
322 if (!input->IsTranslationOnly()) {
323 return false;
324 }
325 }
326 return true;
327 }
328
329 bool FilterContents::IsLeaf() const {
330 for (auto& input : inputs_) {
331 if (!input->IsLeaf()) {
332 return false;
333 }
334 }
335 return true;
336 }
337
338 void FilterContents::SetLeafInputs(const FilterInput::Vector& inputs) {
339 if (IsLeaf()) {
340 inputs_ = inputs;
341 return;
342 }
343 for (auto& input : inputs_) {
344 input->SetLeafInputs(inputs);
345 }
346 }
347
348 void FilterContents::SetRenderingMode(Entity::RenderingMode rendering_mode) {
349 for (auto& input : inputs_) {
350 input->SetRenderingMode(rendering_mode);
351 }
352 }
353
354 } // namespace impeller
impeller::FilterContents::PopulateGlyphAtlas
void PopulateGlyphAtlas(const std::shared_ptr< LazyGlyphAtlas > &lazy_glyph_atlas, Scalar scale) override
Add any text data to the specified lazy atlas. The scale parameter must be used again later when draw...
Definition: filter_contents.cc:212
impeller::Sigma::sigma
Scalar sigma
Definition: sigma.h:33
impeller::FilterContents::IsLeaf
bool IsLeaf() const
Returns true if this filter does not have any FilterInput children.
Definition: filter_contents.cc:329
impeller::FilterContents::SetInputs
void SetInputs(FilterInput::Vector inputs)
The input texture sources for this filter. Each input's emitted texture is expected to have premultip...
Definition: filter_contents.cc:165
impeller::Scalar
float Scalar
Definition: scalar.h:18
impeller::FilterContents::FilterContents
FilterContents()
texture_contents.h
impeller::Entity::GetTransform
const Matrix & GetTransform() const
Get the global transform matrix for this Entity.
Definition: entity.cc:49
impeller::FilterContents::GetSourceCoverage
std::optional< Rect > GetSourceCoverage(const Matrix &effect_transform, const Rect &output_limit) const
Determines the coverage of source pixels that will be needed to produce results for the specified |ou...
Definition: filter_contents.cc:247
entity.h
impeller::FilterContents::SetEffectTransform
void SetEffectTransform(const Matrix &effect_transform)
Sets the transform which gets appended to the effect of this filter. Note that this is in addition to...
Definition: filter_contents.cc:169
impeller::FilterContents::BlurStyle
BlurStyle
Definition: filter_contents.h:23
impeller::FilterInput::Make
static FilterInput::Ref Make(Variant input, bool msaa_enabled=true)
Definition: filter_input.cc:19
impeller::FilterContents::GetTransform
Matrix GetTransform(const Matrix &parent_transform) const
Definition: filter_contents.cc:317
impeller::FilterContents::RenderToSnapshot
std::optional< Snapshot > RenderToSnapshot(const ContentContext &renderer, const Entity &entity, std::optional< Rect > coverage_limit=std::nullopt, const std::optional< SamplerDescriptor > &sampler_descriptor=std::nullopt, bool msaa_enabled=true, const std::string &label="Filter Snapshot") const override
Render this contents to a snapshot, respecting the entity's transform, path, clip depth,...
Definition: filter_contents.cc:285
formats.h
impeller::FilterInput::Ref
std::shared_ptr< FilterInput > Ref
Definition: filter_input.h:32
border_mask_blur_filter_contents.h
local_matrix_filter_contents.h
impeller::FilterContents::MakeDirectionalGaussianBlur
static std::shared_ptr< FilterContents > MakeDirectionalGaussianBlur(FilterInput::Ref input, Sigma sigma, Vector2 direction, BlurStyle blur_style=BlurStyle::kNormal, Entity::TileMode tile_mode=Entity::TileMode::kDecal, bool is_second_pass=false, Sigma secondary_sigma={})
Definition: filter_contents.cc:34
gaussian_blur_filter_contents.h
impeller::FilterContents::BlurStyle::kNormal
@ kNormal
Blurred inside and outside.
path_builder.h
impeller::SamplerDescriptor
Definition: sampler_descriptor.h:15
impeller::Entity
Definition: entity.h:21
impeller::Contents::GetCoverageHint
const std::optional< Rect > & GetCoverageHint() const
Definition: contents.cc:152
morphology_filter_contents.h
impeller::Point
TPoint< Scalar > Point
Definition: point.h:308
impeller::FilterContents::MakeGaussianBlur
static std::shared_ptr< FilterContents > MakeGaussianBlur(const FilterInput::Ref &input, Sigma sigma_x, Sigma sigma_y, BlurStyle blur_style=BlurStyle::kNormal, Entity::TileMode tile_mode=Entity::TileMode::kDecal)
Definition: filter_contents.cc:53
filter_contents.h
impeller::FilterContents::Render
bool Render(const ContentContext &renderer, const Entity &entity, RenderPass &pass) const override
Definition: filter_contents.cc:177
render_pass.h
impeller::Radius
For convolution filters, the "radius" is the size of the convolution kernel to use on the local space...
Definition: sigma.h:48
impeller::FilterContents::IsTranslationOnly
virtual bool IsTranslationOnly() const
Returns true if this filter graph doesn't perform any basis transforms to the filtered content....
Definition: filter_contents.cc:320
impeller::FilterContents::MakeDirectionalMorphology
static std::shared_ptr< FilterContents > MakeDirectionalMorphology(FilterInput::Ref input, Radius radius, Vector2 direction, MorphType morph_type)
Definition: filter_contents.cc:105
impeller::Sigma
In filters that use Gaussian distributions, "sigma" is a size of one standard deviation in terms of t...
Definition: sigma.h:32
matrix_filter_contents.h
filter_input.h
impeller::FilterContents::MakeBorderMaskBlur
static std::shared_ptr< FilterContents > MakeBorderMaskBlur(FilterInput::Ref input, Sigma sigma_x, Sigma sigma_y, BlurStyle blur_style=BlurStyle::kNormal)
Definition: filter_contents.cc:93
impeller::Entity::TileMode
TileMode
Definition: entity.h:40
impeller::FilterContents::MakeYUVToRGBFilter
static std::shared_ptr< FilterContents > MakeYUVToRGBFilter(std::shared_ptr< Texture > y_texture, std::shared_ptr< Texture > uv_texture, YUVColorSpace yuv_color_space)
Definition: filter_contents.cc:150
impeller::RenderPass
Render passes encode render commands directed as one specific render target into an underlying comman...
Definition: render_pass.h:29
impeller::FilterContents::MorphType
MorphType
Definition: filter_contents.h:34
command_buffer.h
content_context.h
impeller::Entity::SetTransform
void SetTransform(const Matrix &transform)
Set the global transform matrix for this Entity.
Definition: entity.cc:53
impeller::FilterContents::MakeMorphology
static std::shared_ptr< FilterContents > MakeMorphology(FilterInput::Ref input, Radius radius_x, Radius radius_y, MorphType morph_type)
Definition: filter_contents.cc:118
impeller::FilterContents::GetCoverage
std::optional< Rect > GetCoverage(const Entity &entity) const override
Get the area of the render pass that will be affected when this contents is rendered.
Definition: filter_contents.cc:205
impeller::FilterContents::GetEntity
std::optional< Entity > GetEntity(const ContentContext &renderer, const Entity &entity, const std::optional< Rect > &coverage_hint) const
Create an Entity that renders this filter's output.
Definition: filter_contents.cc:269
directional_gaussian_blur_filter_contents.h
impeller::FilterContents::SetLeafInputs
void SetLeafInputs(const FilterInput::Vector &inputs)
Replaces the set of all leaf FilterContents with a new set of FilterInputs.
Definition: filter_contents.cc:338
impeller::Entity::Clone
Entity Clone() const
Definition: entity.cc:181
impeller::TPoint< Scalar >
impeller::FilterContents::MakeMatrixFilter
static std::shared_ptr< FilterContents > MakeMatrixFilter(FilterInput::Ref input, const Matrix &matrix, const SamplerDescriptor &desc)
Definition: filter_contents.cc:130
impeller::YUVColorSpace
YUVColorSpace
Definition: color.h:55
impeller::FilterContents::GetLocalTransform
virtual Matrix GetLocalTransform(const Matrix &parent_transform) const
Definition: filter_contents.cc:313
impeller::TRect< Scalar >::Union
constexpr TRect Union(const TRect &o) const
Definition: rect.h:302
impeller::FilterContents::SetRenderingMode
virtual void SetRenderingMode(Entity::RenderingMode rendering_mode)
Marks this filter chain as applying in a subpass scenario.
Definition: filter_contents.cc:348
impeller::Entity::RenderingMode
RenderingMode
Definition: entity.h:26
impeller::FilterContents::MakeLocalMatrixFilter
static std::shared_ptr< FilterContents > MakeLocalMatrixFilter(FilterInput::Ref input, const Matrix &matrix)
Definition: filter_contents.cc:141
impeller::FilterInput::Vector
std::vector< FilterInput::Ref > Vector
Definition: filter_input.h:33
impeller::FilterContents::~FilterContents
~FilterContents() override
impeller
Definition: aiks_context.cc:10
yuv_to_rgb_filter_contents.h
impeller::ContentContext
Definition: content_context.h:332
impeller::FilterContents::AsFilter
const FilterContents * AsFilter() const override
Cast to a filter. Returns nullptr if this Contents is not a filter.
Definition: filter_contents.cc:309
impeller::TRect< Scalar >
impeller::Matrix
A 4x4 matrix using column-major storage.
Definition: matrix.h:37
impeller::FilterContents
Definition: filter_contents.h:21