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"
26 #include "impeller/entity/entity.h"
30 
31 namespace impeller {
32 
33 std::shared_ptr<FilterContents> FilterContents::MakeDirectionalGaussianBlur(
34  FilterInput::Ref input,
35  Sigma sigma,
36  Vector2 direction,
37  BlurStyle blur_style,
38  Entity::TileMode tile_mode,
39  bool is_second_pass,
40  Sigma secondary_sigma) {
41  auto blur = std::make_shared<DirectionalGaussianBlurFilterContents>();
42  blur->SetInputs({std::move(input)});
43  blur->SetSigma(sigma);
44  blur->SetDirection(direction);
45  blur->SetBlurStyle(blur_style);
46  blur->SetTileMode(tile_mode);
47  blur->SetIsSecondPass(is_second_pass);
48  blur->SetSecondarySigma(secondary_sigma);
49  return blur;
50 }
51 
52 std::shared_ptr<FilterContents> FilterContents::MakeGaussianBlur(
53  const FilterInput::Ref& input,
54  Sigma sigma_x,
55  Sigma sigma_y,
56  BlurStyle blur_style,
57  Entity::TileMode tile_mode) {
58  auto x_blur = MakeDirectionalGaussianBlur(
59  input, sigma_x, Point(1, 0), BlurStyle::kNormal, tile_mode, false, {});
60  auto y_blur = MakeDirectionalGaussianBlur(FilterInput::Make(x_blur), sigma_y,
61  Point(0, 1), blur_style, tile_mode,
62  true, sigma_x);
63  return y_blur;
64 }
65 
66 std::shared_ptr<FilterContents> FilterContents::MakeBorderMaskBlur(
67  FilterInput::Ref input,
68  Sigma sigma_x,
69  Sigma sigma_y,
70  BlurStyle blur_style) {
71  auto filter = std::make_shared<BorderMaskBlurFilterContents>();
72  filter->SetInputs({std::move(input)});
73  filter->SetSigma(sigma_x, sigma_y);
74  filter->SetBlurStyle(blur_style);
75  return filter;
76 }
77 
78 std::shared_ptr<FilterContents> FilterContents::MakeDirectionalMorphology(
79  FilterInput::Ref input,
80  Radius radius,
81  Vector2 direction,
82  MorphType morph_type) {
83  auto filter = std::make_shared<DirectionalMorphologyFilterContents>();
84  filter->SetInputs({std::move(input)});
85  filter->SetRadius(radius);
86  filter->SetDirection(direction);
87  filter->SetMorphType(morph_type);
88  return filter;
89 }
90 
91 std::shared_ptr<FilterContents> FilterContents::MakeMorphology(
92  FilterInput::Ref input,
93  Radius radius_x,
94  Radius radius_y,
95  MorphType morph_type) {
96  auto x_morphology = MakeDirectionalMorphology(std::move(input), radius_x,
97  Point(1, 0), morph_type);
98  auto y_morphology = MakeDirectionalMorphology(
99  FilterInput::Make(x_morphology), radius_y, Point(0, 1), morph_type);
100  return y_morphology;
101 }
102 
103 std::shared_ptr<FilterContents> FilterContents::MakeMatrixFilter(
104  FilterInput::Ref input,
105  const Matrix& matrix,
106  const SamplerDescriptor& desc) {
107  auto filter = std::make_shared<MatrixFilterContents>();
108  filter->SetInputs({std::move(input)});
109  filter->SetMatrix(matrix);
110  filter->SetSamplerDescriptor(desc);
111  return filter;
112 }
113 
114 std::shared_ptr<FilterContents> FilterContents::MakeLocalMatrixFilter(
115  FilterInput::Ref input,
116  const Matrix& matrix) {
117  auto filter = std::make_shared<LocalMatrixFilterContents>();
118  filter->SetInputs({std::move(input)});
119  filter->SetMatrix(matrix);
120  return filter;
121 }
122 
123 std::shared_ptr<FilterContents> FilterContents::MakeYUVToRGBFilter(
124  std::shared_ptr<Texture> y_texture,
125  std::shared_ptr<Texture> uv_texture,
126  YUVColorSpace yuv_color_space) {
127  auto filter = std::make_shared<impeller::YUVToRGBFilterContents>();
128  filter->SetInputs({impeller::FilterInput::Make(y_texture),
129  impeller::FilterInput::Make(uv_texture)});
130  filter->SetYUVColorSpace(yuv_color_space);
131  return filter;
132 }
133 
135 
137 
139  inputs_ = std::move(inputs);
140 }
141 
142 void FilterContents::SetEffectTransform(const Matrix& effect_transform) {
143  effect_transform_ = effect_transform;
144 
145  for (auto& input : inputs_) {
146  input->SetEffectTransform(effect_transform);
147  }
148 }
149 
151  const Entity& entity,
152  RenderPass& pass) const {
153  auto filter_coverage = GetCoverage(entity);
154  if (!filter_coverage.has_value()) {
155  return true;
156  }
157 
158  // Run the filter.
159 
160  auto maybe_entity = GetEntity(renderer, entity, GetCoverageHint());
161  if (!maybe_entity.has_value()) {
162  return true;
163  }
164  return maybe_entity->Render(renderer, pass);
165 }
166 
167 std::optional<Rect> FilterContents::GetLocalCoverage(
168  const Entity& local_entity) const {
169  auto coverage = GetFilterCoverage(inputs_, local_entity, effect_transform_);
170  auto coverage_hint = GetCoverageHint();
171  if (coverage_hint.has_value() && coverage.has_value()) {
172  coverage = coverage->Intersection(coverage_hint.value());
173  }
174 
175  return coverage;
176 }
177 
178 std::optional<Rect> FilterContents::GetCoverage(const Entity& entity) const {
179  Entity entity_with_local_transform = entity;
180  entity_with_local_transform.SetTransformation(
181  GetTransform(entity.GetTransformation()));
182 
183  return GetLocalCoverage(entity_with_local_transform);
184 }
185 
187  const std::shared_ptr<LazyGlyphAtlas>& lazy_glyph_atlas,
188  Scalar scale) {
189  for (auto& input : inputs_) {
190  input->PopulateGlyphAtlas(lazy_glyph_atlas, scale);
191  }
192 }
193 
194 std::optional<Rect> FilterContents::GetFilterCoverage(
195  const FilterInput::Vector& inputs,
196  const Entity& entity,
197  const Matrix& effect_transform) const {
198  // The default coverage of FilterContents is just the union of its inputs'
199  // coverage. FilterContents implementations may choose to adjust this
200  // coverage depending on the use case.
201 
202  if (inputs_.empty()) {
203  return std::nullopt;
204  }
205 
206  std::optional<Rect> result;
207  for (const auto& input : inputs) {
208  auto coverage = input->GetCoverage(entity);
209  if (!coverage.has_value()) {
210  continue;
211  }
212  if (!result.has_value()) {
213  result = coverage;
214  continue;
215  }
216  result = result->Union(coverage.value());
217  }
218  return result;
219 }
220 
221 std::optional<Entity> FilterContents::GetEntity(
222  const ContentContext& renderer,
223  const Entity& entity,
224  const std::optional<Rect>& coverage_hint) const {
225  Entity entity_with_local_transform = entity;
226  entity_with_local_transform.SetTransformation(
227  GetTransform(entity.GetTransformation()));
228 
229  auto coverage = GetLocalCoverage(entity_with_local_transform);
230  if (!coverage.has_value() || coverage->IsEmpty()) {
231  return std::nullopt;
232  }
233 
234  return RenderFilter(inputs_, renderer, entity_with_local_transform,
235  effect_transform_, coverage.value(), coverage_hint);
236 }
237 
238 std::optional<Snapshot> FilterContents::RenderToSnapshot(
239  const ContentContext& renderer,
240  const Entity& entity,
241  std::optional<Rect> coverage_limit,
242  const std::optional<SamplerDescriptor>& sampler_descriptor,
243  bool msaa_enabled,
244  const std::string& label) const {
245  // Resolve the render instruction (entity) from the filter and render it to a
246  // snapshot.
247  if (std::optional<Entity> result =
248  GetEntity(renderer, entity, coverage_limit);
249  result.has_value()) {
250  return result->GetContents()->RenderToSnapshot(
251  renderer, // renderer
252  result.value(), // entity
253  coverage_limit, // coverage_limit
254  std::nullopt, // sampler_descriptor
255  true, // msaa_enabled
256  label); // label
257  }
258 
259  return std::nullopt;
260 }
261 
263  return this;
264 }
265 
266 Matrix FilterContents::GetLocalTransform(const Matrix& parent_transform) const {
267  return Matrix();
268 }
269 
270 Matrix FilterContents::GetTransform(const Matrix& parent_transform) const {
271  return parent_transform * GetLocalTransform(parent_transform);
272 }
274  for (auto& input : inputs_) {
275  if (!input->IsTranslationOnly()) {
276  return false;
277  }
278  }
279  return true;
280 }
281 
283  for (auto& input : inputs_) {
284  if (!input->IsLeaf()) {
285  return false;
286  }
287  }
288  return true;
289 }
290 
292  if (IsLeaf()) {
293  inputs_ = inputs;
294  return;
295  }
296  for (auto& input : inputs_) {
297  input->SetLeafInputs(inputs);
298  }
299 }
300 
302  for (auto& input : inputs_) {
303  input->SetRenderingMode(rendering_mode);
304  }
305 }
306 
307 } // 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:186
impeller::FilterContents::IsLeaf
bool IsLeaf() const
Returns true if this filter does not have any FilterInput children.
Definition: filter_contents.cc:282
impeller::Entity::SetTransformation
void SetTransformation(const Matrix &transformation)
Definition: entity.cc:53
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:138
impeller::Scalar
float Scalar
Definition: scalar.h:15
impeller::FilterContents::FilterContents
FilterContents()
texture_contents.h
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:142
impeller::FilterContents::BlurStyle
BlurStyle
Definition: filter_contents.h:21
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:270
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, stencil depth,...
Definition: filter_contents.cc:238
formats.h
impeller::FilterInput::Ref
std::shared_ptr< FilterInput > Ref
Definition: filter_input.h:31
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:33
gaussian_blur_filter_contents.h
impeller::FilterContents::BlurStyle::kNormal
@ kNormal
Blurred inside and outside.
impeller::Entity::GetTransformation
const Matrix & GetTransformation() const
Definition: entity.cc:49
path_builder.h
impeller::SamplerDescriptor
Definition: sampler_descriptor.h:18
impeller::Entity
Definition: entity.h:21
impeller::Contents::GetCoverageHint
const std::optional< Rect > & GetCoverageHint() const
Definition: contents.cc:155
morphology_filter_contents.h
impeller::Point
TPoint< Scalar > Point
Definition: point.h:306
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:52
filter_contents.h
impeller::FilterContents::Render
bool Render(const ContentContext &renderer, const Entity &entity, RenderPass &pass) const override
Definition: filter_contents.cc:150
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:47
impeller::FilterContents::IsTranslationOnly
virtual bool IsTranslationOnly() const
Returns true if this filter graph doesn't perform any basis transformations to the filtered content....
Definition: filter_contents.cc:273
impeller::FilterContents::MakeDirectionalMorphology
static std::shared_ptr< FilterContents > MakeDirectionalMorphology(FilterInput::Ref input, Radius radius, Vector2 direction, MorphType morph_type)
Definition: filter_contents.cc:78
impeller::Sigma
In filters that use Gaussian distributions, "sigma" is a size of one standard deviation in terms of t...
Definition: sigma.h:31
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:66
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:123
impeller::RenderPass
Render passes encode render commands directed as one specific render target into an underlying comman...
Definition: render_pass.h:27
impeller::FilterContents::MorphType
MorphType
Definition: filter_contents.h:32
command_buffer.h
content_context.h
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:91
impeller::FilterContents::GetCoverage
std::optional< Rect > GetCoverage(const Entity &entity) const override
Get the screen space bounding rectangle that this contents affects.
Definition: filter_contents.cc:178
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:221
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:291
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:103
impeller::YUVColorSpace
YUVColorSpace
Definition: color.h:53
impeller::FilterContents::GetLocalTransform
virtual Matrix GetLocalTransform(const Matrix &parent_transform) const
Definition: filter_contents.cc:266
impeller::FilterContents::SetRenderingMode
virtual void SetRenderingMode(Entity::RenderingMode rendering_mode)
Marks this filter chain as applying in a subpass scenario.
Definition: filter_contents.cc:301
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:114
impeller::FilterInput::Vector
std::vector< FilterInput::Ref > Vector
Definition: filter_input.h:32
impeller::FilterContents::~FilterContents
~FilterContents() override
impeller
Definition: aiks_context.cc:10
yuv_to_rgb_filter_contents.h
impeller::ContentContext
Definition: content_context.h:344
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:262
impeller::Matrix
A 4x4 matrix using column-major storage.
Definition: matrix.h:36
impeller::FilterContents
Definition: filter_contents.h:19