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 
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"
27 #include "impeller/entity/entity.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 
162 
164 
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 
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 
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 
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 
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 }
321  for (auto& input : inputs_) {
322  if (!input->IsTranslationOnly()) {
323  return false;
324  }
325  }
326  return true;
327 }
328 
330  for (auto& input : inputs_) {
331  if (!input->IsLeaf()) {
332  return false;
333  }
334  }
335  return true;
336 }
337 
339  if (IsLeaf()) {
340  inputs_ = inputs;
341  return;
342  }
343  for (auto& input : inputs_) {
344  input->SetLeafInputs(inputs);
345  }
346 }
347 
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