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