Flutter Impeller
filter_contents.h
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 #ifndef FLUTTER_IMPELLER_ENTITY_CONTENTS_FILTERS_FILTER_CONTENTS_H_
6 #define FLUTTER_IMPELLER_ENTITY_CONTENTS_FILTERS_FILTER_CONTENTS_H_
7 
8 #include <memory>
9 #include <optional>
10 #include <variant>
11 #include <vector>
12 
13 #include "impeller/core/formats.h"
16 #include "impeller/entity/entity.h"
21 
22 namespace impeller {
23 
24 class FilterContents : public Contents {
25  public:
26  static const int32_t kBlurFilterRequiredMipCount;
27 
28  enum class BlurStyle {
29  /// Blurred inside and outside.
30  kNormal,
31  /// Solid inside, blurred outside.
32  kSolid,
33  /// Nothing inside, blurred outside.
34  kOuter,
35  /// Blurred inside, nothing outside.
36  kInner,
37  };
38 
39  enum class MorphType { kDilate, kErode };
40 
41  /// Creates a gaussian blur that operates in 2 dimensions.
42  /// See also: `MakeDirectionalGaussianBlur`
43  static std::shared_ptr<FilterContents> MakeGaussianBlur(
44  const FilterInput::Ref& input,
45  Sigma sigma_x,
46  Sigma sigma_y,
48  BlurStyle mask_blur_style = BlurStyle::kNormal,
49  const Geometry* mask_geometry = nullptr);
50 
51  static std::shared_ptr<FilterContents> MakeBorderMaskBlur(
52  FilterInput::Ref input,
53  Sigma sigma_x,
54  Sigma sigma_y,
55  BlurStyle blur_style = BlurStyle::kNormal);
56 
57  static std::shared_ptr<FilterContents> MakeDirectionalMorphology(
58  FilterInput::Ref input,
59  Radius radius,
60  Vector2 direction,
61  MorphType morph_type);
62 
63  static std::shared_ptr<FilterContents> MakeMorphology(FilterInput::Ref input,
64  Radius radius_x,
65  Radius radius_y,
66  MorphType morph_type);
67 
68  static std::shared_ptr<FilterContents> MakeMatrixFilter(
69  FilterInput::Ref input,
70  const Matrix& matrix,
71  const SamplerDescriptor& desc);
72 
73  static std::shared_ptr<FilterContents> MakeLocalMatrixFilter(
74  FilterInput::Ref input,
75  const Matrix& matrix);
76 
77  static std::shared_ptr<FilterContents> MakeYUVToRGBFilter(
78  std::shared_ptr<Texture> y_texture,
79  std::shared_ptr<Texture> uv_texture,
80  YUVColorSpace yuv_color_space);
81 
82  static std::shared_ptr<FilterContents> MakeRuntimeEffect(
83  FilterInput::Ref input,
84  std::shared_ptr<RuntimeStage> runtime_stage,
85  std::shared_ptr<std::vector<uint8_t>> uniforms,
86  std::vector<RuntimeEffectContents::TextureInput> texture_inputs);
87 
89 
90  ~FilterContents() override;
91 
92  /// @brief The input texture sources for this filter. Each input's emitted
93  /// texture is expected to have premultiplied alpha colors.
94  ///
95  /// The number of required or optional textures depends on the
96  /// particular filter's implementation.
97  void SetInputs(FilterInput::Vector inputs);
98 
99  /// @brief Sets the transform which gets appended to the effect of this
100  /// filter. Note that this is in addition to the entity's transform.
101  ///
102  /// This is useful for subpass rendering scenarios where it's
103  /// difficult to encode the current transform of the layer into the
104  /// Entity being rendered.
105  void SetEffectTransform(const Matrix& effect_transform);
106 
107  /// @brief Create an Entity that renders this filter's output.
108  std::optional<Entity> GetEntity(
109  const ContentContext& renderer,
110  const Entity& entity,
111  const std::optional<Rect>& coverage_hint) const;
112 
113  // |Contents|
114  bool Render(const ContentContext& renderer,
115  const Entity& entity,
116  RenderPass& pass) const override;
117 
118  // |Contents|
119  std::optional<Rect> GetCoverage(const Entity& entity) const override;
120 
121  // |Contents|
122  std::optional<Snapshot> RenderToSnapshot(
123  const ContentContext& renderer,
124  const Entity& entity,
125  std::optional<Rect> coverage_limit = std::nullopt,
126  const std::optional<SamplerDescriptor>& sampler_descriptor = std::nullopt,
127  bool msaa_enabled = true,
128  int32_t mip_count = 1,
129  std::string_view label = "Filter Snapshot") const override;
130 
131  /// @brief Determines the coverage of source pixels that will be needed
132  /// to produce results for the specified |output_limit| under the
133  /// specified |effect_transform|. This is essentially a reverse of
134  /// the |GetCoverage| method computing a source coverage from
135  /// an intended |output_limit| coverage.
136  ///
137  /// Both the |output_limit| and the return value are in the
138  /// transformed coordinate space, and so do not need to be
139  /// transformed or inverse transformed by the |effect_transform|
140  /// but individual parameters on the filter might be in the
141  /// untransformed space and should be transformed by the
142  /// |effect_transform| before applying them to the coverages.
143  ///
144  /// The method computes a result such that if the filter is applied
145  /// to a set of pixels filling the computed source coverage, it
146  /// should produce an output that covers the entire specified
147  /// |output_limit|.
148  ///
149  /// This is useful for subpass rendering scenarios where a filter
150  /// will be applied to the output of the subpass and we need to
151  /// determine how large of a render target to allocate in order
152  /// to collect all pixels that might affect the supplied output
153  /// coverage limit. While we might end up clipping the rendering
154  /// of the subpass to its destination, we want to avoid clipping
155  /// out any pixels that contribute to the output limit via the
156  /// filtering operation.
157  ///
158  /// @return The coverage bounds in the transformed space of any source pixel
159  /// that may be needed to produce output for the indicated filter
160  /// that covers the indicated |output_limit|.
161  std::optional<Rect> GetSourceCoverage(const Matrix& effect_transform,
162  const Rect& output_limit) const;
163 
164  virtual Matrix GetLocalTransform(const Matrix& parent_transform) const;
165 
166  Matrix GetTransform(const Matrix& parent_transform) const;
167 
168  /// @brief Marks this filter chain as applying in a subpass scenario.
169  ///
170  /// Subpasses render in screenspace, and this setting informs filters
171  /// that the current transform matrix of the entity is not stored
172  /// in the Entity transform matrix. Instead, the effect transform
173  /// is used in this case.
174  virtual void SetRenderingMode(Entity::RenderingMode rendering_mode);
175 
176  private:
177  /// @brief Internal utility method for |GetLocalCoverage| that computes
178  /// the output coverage of this filter across the specified inputs,
179  /// ignoring the coverage hint.
180  virtual std::optional<Rect> GetFilterCoverage(
181  const FilterInput::Vector& inputs,
182  const Entity& entity,
183  const Matrix& effect_transform) const;
184 
185  /// @brief Internal utility method for |GetSourceCoverage| that computes
186  /// the inverse effect of this transform on the specified output
187  /// coverage, ignoring the inputs which will be accommodated by
188  /// the caller.
189  virtual std::optional<Rect> GetFilterSourceCoverage(
190  const Matrix& effect_transform,
191  const Rect& output_limit) const = 0;
192 
193  /// Applies the specific filter logic to the given inputs and returns an
194  /// Entity representing the filtered result.
195  ///
196  /// This is the primary method that subclasses must implement to define their
197  /// filtering behavior. It takes the results of evaluating the filter inputs
198  /// (as Snapshots) and produces a new Entity containing the filtered output.
199  ///
200  /// @param[in] inputs The evaluated inputs to the filter, typically as
201  /// Snapshots.
202  /// @param[in] renderer The content context providing rendering resources.
203  /// @param[in] entity The entity applying this filter, providing transform,
204  /// blend mode, and other context.
205  /// @param[in] effect_transform An additional transform applied after the
206  /// entity's transform, often used in subpass scenarios.
207  /// @param[in] coverage The calculated coverage area of the filter's output
208  /// in the coordinate space after applying the entity and effect transforms.
209  /// @param[in] coverage_hint An optional hint representing the desired output
210  /// coverage area, which can be used for optimization (e.g., rendering only a
211  /// portion of the input).
212  ///
213  /// @return An optional Entity containing the rendered result of the filter.
214  /// Returns `std::nullopt` if the filter cannot be applied or results in empty
215  /// output.
216  virtual std::optional<Entity> RenderFilter(
217  const FilterInput::Vector& inputs,
218  const ContentContext& renderer,
219  const Entity& entity,
220  const Matrix& effect_transform,
221  const Rect& coverage,
222  const std::optional<Rect>& coverage_hint) const = 0;
223 
224  /// @brief Internal utility method to compute the coverage of this
225  /// filter across its internally specified inputs and subject
226  /// to the coverage hint.
227  ///
228  /// Uses |GetFilterCoverage|.
229  std::optional<Rect> GetLocalCoverage(const Entity& local_entity) const;
230 
231  FilterInput::Vector inputs_;
232  Matrix effect_transform_ = Matrix();
233 
234  FilterContents(const FilterContents&) = delete;
235 
236  FilterContents& operator=(const FilterContents&) = delete;
237 };
238 
239 } // namespace impeller
240 
241 #endif // FLUTTER_IMPELLER_ENTITY_CONTENTS_FILTERS_FILTER_CONTENTS_H_
static const int32_t kBlurFilterRequiredMipCount
@ kNormal
Blurred inside and outside.
@ kOuter
Nothing inside, blurred outside.
@ kInner
Blurred inside, nothing outside.
@ kSolid
Solid inside, blurred outside.
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
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
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