| 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
5 #include "impeller/entity/contents/filters/filter_contents.h"
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"
17 #include "impeller/entity/contents/content_context.h"
18 #include "impeller/entity/contents/filters/border_mask_blur_filter_contents.h"
19 #include "impeller/entity/contents/filters/gaussian_blur_filter_contents.h"
20 #include "impeller/entity/contents/filters/inputs/filter_input.h"
21 #include "impeller/entity/contents/filters/local_matrix_filter_contents.h"
22 #include "impeller/entity/contents/filters/matrix_filter_contents.h"
23 #include "impeller/entity/contents/filters/morphology_filter_contents.h"
24 #include "impeller/entity/contents/filters/yuv_to_rgb_filter_contents.h"
25 #include "impeller/entity/contents/texture_contents.h"
26 #include "impeller/entity/entity.h"
27 #include "impeller/geometry/path_builder.h"
28 #include "impeller/renderer/command_buffer.h"
29 #include "impeller/renderer/render_pass.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
134 FilterContents::FilterContents() = default;
135
136 FilterContents::~FilterContents() = default;
137
138 void FilterContents::SetInputs(FilterInput::Vector inputs) {
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
150 bool FilterContents::Render(const ContentContext& renderer,
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
186 void FilterContents::PopulateGlyphAtlas(
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
262 const FilterContents* FilterContents::AsFilter() const {
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 }
273 bool FilterContents::IsTranslationOnly() const {
274 for (auto& input : inputs_) {
275 if (!input->IsTranslationOnly()) {
276 return false;
277 }
278 }
279 return true;
280 }
281
282 bool FilterContents::IsLeaf() const {
283 for (auto& input : inputs_) {
284 if (!input->IsLeaf()) {
285 return false;
286 }
287 }
288 return true;
289 }
290
291 void FilterContents::SetLeafInputs(const FilterInput::Vector& inputs) {
292 if (IsLeaf()) {
293 inputs_ = inputs;
294 return;
295 }
296 for (auto& input : inputs_) {
297 input->SetLeafInputs(inputs);
298 }
299 }
300
301 void FilterContents::SetRenderingMode(Entity::RenderingMode rendering_mode) {
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