Flutter Engine
The Flutter Engine
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"
30
31namespace impeller {
32
35
36std::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
49std::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
61std::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
74std::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
86std::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
97std::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
106std::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
125void 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->SetClipDepth(entity.GetClipDepth());
148 return maybe_entity->Render(renderer, pass);
149}
150
151std::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
162std::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
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()) {
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
226std::optional<Entity> FilterContents::GetEntity(
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
242std::optional<Snapshot> FilterContents::RenderToSnapshot(
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
272Matrix FilterContents::GetLocalTransform(const Matrix& parent_transform) const {
273 return Matrix();
274}
275
276Matrix 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
const std::optional< Rect > & GetCoverageHint() const
Definition: contents.cc:173
void SetTransform(const Matrix &transform)
Set the global transform matrix for this Entity.
Definition: entity.cc:62
Entity Clone() const
Definition: entity.cc:191
const Matrix & GetTransform() const
Get the global transform matrix for this Entity.
Definition: entity.cc:46
uint32_t GetClipDepth() const
Definition: entity.cc:102
virtual std::optional< Rect > GetFilterSourceCoverage(const Matrix &effect_transform, const Rect &output_limit) const =0
Internal utility method for |GetSourceCoverage| that computes the inverse effect of this transform on...
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)
static const int32_t kBlurFilterRequiredMipCount
virtual bool IsTranslationOnly() const
Returns true if this filter graph doesn't perform any basis transforms to the filtered content....
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.
virtual std::optional< Entity > RenderFilter(const FilterInput::Vector &inputs, const ContentContext &renderer, const Entity &entity, const Matrix &effect_transform, const Rect &coverage, const std::optional< Rect > &coverage_hint) const =0
Converts zero or more filter inputs into a render instruction.
Matrix GetTransform(const Matrix &parent_transform) const
void SetLeafInputs(const FilterInput::Vector &inputs)
Replaces the set of all leaf FilterContents with a new set of FilterInputs.
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)
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...
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)
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...
bool IsLeaf() const
Returns true if this filter does not have any FilterInput children.
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...
const FilterContents * AsFilter() const override
Cast to a filter. Returns nullptr if this Contents is not a filter.
virtual std::optional< Rect > GetFilterCoverage(const FilterInput::Vector &inputs, const Entity &entity, const Matrix &effect_transform) const
Internal utility method for |GetLocalCoverage| that computes the output coverage of this filter acros...
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, const std::string &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)
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:33
GAsyncResult * result
unsigned useCenter Optional< SkMatrix > matrix
Definition: SkRecords.h:258
YUVColorSpace
Definition: color.h:55
float Scalar
Definition: scalar.h:18
TPoint< Scalar > Point
Definition: point.h:322
SK_API sk_sp< PrecompileColorFilter > Matrix()
const Scalar scale
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:504