Flutter Engine
 
Loading...
Searching...
No Matches
matrix_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
7namespace impeller {
8
10
12
14 matrix_ = matrix;
15}
16
18 Entity::RenderingMode rendering_mode) {
19 rendering_mode_ = rendering_mode;
21}
22
24 sampler_descriptor_ = desc;
25}
26
27namespace {
28Matrix CalculateSubpassTransform(const Matrix& snapshot_transform,
29 const Matrix& effect_transform,
30 const Matrix& matrix,
31 Entity::RenderingMode rendering_mode) {
32 if (rendering_mode ==
34 return snapshot_transform * //
35 effect_transform * //
36 matrix * //
37 effect_transform.Invert();
38 } else {
39 FML_DCHECK(rendering_mode ==
41 return effect_transform * //
42 matrix * //
43 effect_transform.Invert() * //
44 snapshot_transform;
45 }
46}
47} // namespace
48
49std::optional<Entity> MatrixFilterContents::RenderFilter(
50 const FilterInput::Vector& inputs,
51 const ContentContext& renderer,
52 const Entity& entity,
53 const Matrix& effect_transform,
54 const Rect& coverage,
55 const std::optional<Rect>& coverage_hint) const {
56 auto snapshot = inputs[0]->GetSnapshot("Matrix", renderer, entity);
57 if (!snapshot.has_value()) {
58 return std::nullopt;
59 }
60
61 if (rendering_mode_ ==
63 rendering_mode_ ==
65 // There are two special quirks with how Matrix filters behave when used as
66 // subpass backdrop filters:
67 //
68 // 1. For subpass backdrop filters, the snapshot transform is always just a
69 // translation that positions the parent pass texture correctly relative
70 // to the subpass texture. However, this translation always needs to be
71 // applied in screen space.
72 //
73 // Since we know the snapshot transform will always have an identity
74 // basis in this case, we safely reverse the order and apply the filter's
75 // matrix within the snapshot transform space.
76 //
77 // 2. The filter's matrix needs to be applied within the space defined by
78 // the scene's current transformation matrix (CTM). For example: If the
79 // CTM is scaled up, then translations applied by the matrix should be
80 // magnified accordingly.
81 //
82 // To accomplish this, we sandwitch the filter's matrix within the CTM in
83 // both cases. But notice that for the subpass backdrop filter case, we
84 // use the "effect transform" instead of the Entity's transform!
85 //
86 // That's because in the subpass backdrop filter case, the Entity's
87 // transform isn't actually the captured CTM of the scene like it usually
88 // is; instead, it's just a screen space translation that offsets the
89 // backdrop texture (as mentioned above). And so we sneak the subpass's
90 // captured CTM in through the effect transform.
91 //
92 snapshot->transform = CalculateSubpassTransform(
93 snapshot->transform, effect_transform, matrix_, rendering_mode_);
94 } else {
95 snapshot->transform = entity.GetTransform() * //
96 matrix_ * //
97 entity.GetTransform().Invert() * //
98 snapshot->transform;
99 }
100 snapshot->sampler_descriptor = sampler_descriptor_;
101 if (!snapshot.has_value()) {
102 return std::nullopt;
103 }
104 return Entity::FromSnapshot(snapshot.value(), entity.GetBlendMode());
105}
106
107std::optional<Rect> MatrixFilterContents::GetFilterSourceCoverage(
108 const Matrix& effect_transform,
109 const Rect& output_limit) const {
110 auto transform = effect_transform * //
111 matrix_ * //
112 effect_transform.Invert(); //
113 if (!transform.IsInvertible()) {
114 return std::nullopt;
115 }
116 auto inverse = transform.Invert();
117 return output_limit.TransformBounds(inverse);
118}
119
121 const FilterInput::Vector& inputs,
122 const Entity& entity,
123 const Matrix& effect_transform) const {
124 if (inputs.empty()) {
125 return std::nullopt;
126 }
127
128 std::optional<Rect> coverage = inputs[0]->GetCoverage(entity);
129 if (!coverage.has_value()) {
130 return std::nullopt;
131 }
132
133 Matrix input_transform = inputs[0]->GetTransform(entity);
134 if (rendering_mode_ ==
136 rendering_mode_ ==
138 Rect coverage_bounds = coverage->TransformBounds(input_transform.Invert());
139 Matrix transform = CalculateSubpassTransform(
140 input_transform, effect_transform, matrix_, rendering_mode_);
141 return coverage_bounds.TransformBounds(transform);
142 } else {
143 Matrix transform = input_transform * //
144 matrix_ * //
145 input_transform.Invert(); //
146 return coverage->TransformBounds(transform);
147 }
148}
149
150} // namespace impeller
static Entity FromSnapshot(const Snapshot &snapshot, BlendMode blend_mode=BlendMode::kSrcOver)
Create an entity that can be used to render a given snapshot.
Definition entity.cc:18
virtual void SetRenderingMode(Entity::RenderingMode rendering_mode)
Marks this filter chain as applying in a subpass scenario.
std::vector< FilterInput::Ref > Vector
std::optional< Rect > GetFilterCoverage(const FilterInput::Vector &inputs, const Entity &entity, const Matrix &effect_transform) const override
Internal utility method for |GetLocalCoverage| that computes the output coverage of this filter acros...
void SetRenderingMode(Entity::RenderingMode rendering_mode) override
Marks this filter chain as applying in a subpass scenario.
void SetSamplerDescriptor(const SamplerDescriptor &desc)
#define FML_DCHECK(condition)
Definition logging.h:122
TRect< Scalar > Rect
Definition rect.h:788
A 4x4 matrix using column-major storage.
Definition matrix.h:37
Matrix Invert() const
Definition matrix.cc:99
constexpr TRect TransformBounds(const Matrix &transform) const
Creates a new bounding box that contains this transformed rectangle.
Definition rect.h:472