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