Flutter Engine
 
Loading...
Searching...
No Matches
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"
31
32namespace impeller {
33
36
37std::shared_ptr<FilterContents> FilterContents::MakeGaussianBlur(
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
50std::shared_ptr<FilterContents> FilterContents::MakeBorderMaskBlur(
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
62std::shared_ptr<FilterContents> FilterContents::MakeDirectionalMorphology(
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
75std::shared_ptr<FilterContents> FilterContents::MakeMorphology(
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
87std::shared_ptr<FilterContents> FilterContents::MakeMatrixFilter(
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
98std::shared_ptr<FilterContents> FilterContents::MakeLocalMatrixFilter(
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
107std::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
118std::shared_ptr<FilterContents> FilterContents::MakeRuntimeEffect(
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
139void 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
165std::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
176std::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
183std::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
232std::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
253std::optional<Snapshot> FilterContents::RenderToSnapshot(
254 const ContentContext& renderer,
255 const Entity& entity,
256 const SnapshotOptions& options) const {
257 // Resolve the render instruction (entity) from the filter and render it to a
258 // snapshot.
259 if (std::optional<Entity> result =
260 GetEntity(renderer, entity, options.coverage_limit);
261 result.has_value()) {
262 return result->GetContents()->RenderToSnapshot(
263 renderer, result.value(),
264 {.coverage_limit = options.coverage_limit,
265 .sampler_descriptor = std::nullopt,
266 .msaa_enabled = true,
267 .mip_count = options.mip_count,
268 .label = options.label});
269 }
270
271 return std::nullopt;
272}
273
274Matrix FilterContents::GetLocalTransform(const Matrix& parent_transform) const {
275 return Matrix();
276}
277
278Matrix FilterContents::GetTransform(const Matrix& parent_transform) const {
279 return parent_transform * GetLocalTransform(parent_transform);
280}
281
283 for (auto& input : inputs_) {
284 input->SetRenderingMode(rendering_mode);
285 }
286}
287
288} // namespace impeller
const std::optional< Rect > & GetCoverageHint() const
Definition contents.cc:137
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 > MakeRuntimeEffect(FilterInput::Ref input, std::shared_ptr< RuntimeStage > runtime_stage, std::shared_ptr< std::vector< uint8_t > > uniforms, std::vector< RuntimeEffectContents::TextureInput > texture_inputs)
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)
std::optional< Snapshot > RenderToSnapshot(const ContentContext &renderer, const Entity &entity, const SnapshotOptions &options) const override
Render this contents to a snapshot, respecting the entity's transform, path, clip depth,...
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)
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
static FilterInput::Ref Make(Variant input, bool msaa_enabled=true)
std::vector< FilterInput::Ref > Vector
Render passes encode render commands directed as one specific render target into an underlying comman...
Definition render_pass.h:30
static int input(yyscan_t yyscanner)
YUVColorSpace
Definition color.h:54
TPoint< Scalar > Point
Definition point.h:327
std::optional< Rect > coverage_limit
Definition contents.h:86
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:513