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