Flutter Impeller
matrix_filter_contents_unittests.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 "flutter/testing/testing.h"
6 #include "gmock/gmock.h"
10 
11 namespace impeller {
12 namespace testing {
13 
15  public:
16  /// Create a texture that has been cleared to transparent black.
17  std::shared_ptr<Texture> MakeTexture(ISize size) {
18  std::shared_ptr<CommandBuffer> command_buffer =
19  GetContentContext()->GetContext()->CreateCommandBuffer();
20  if (!command_buffer) {
21  return nullptr;
22  }
23 
24  auto render_target = GetContentContext()->MakeSubpass(
25  "Clear Subpass", size, command_buffer,
26  [](const ContentContext&, RenderPass&) { return true; });
27 
28  if (!GetContentContext()
29  ->GetContext()
30  ->GetCommandQueue()
31  ->Submit(/*buffers=*/{command_buffer})
32  .ok()) {
33  return nullptr;
34  }
35 
36  if (render_target.ok()) {
37  return render_target.value().GetRenderTargetTexture();
38  }
39  return nullptr;
40  }
41 };
42 
43 INSTANTIATE_PLAYGROUND_SUITE(MatrixFilterContentsTest);
44 
46  MatrixFilterContents contents;
47  EXPECT_TRUE(contents.IsTranslationOnly());
48 }
49 
50 TEST(MatrixFilterContentsTest, CoverageEmpty) {
51  MatrixFilterContents contents;
52  FilterInput::Vector inputs = {};
53  Entity entity;
54  std::optional<Rect> coverage =
55  contents.GetFilterCoverage(inputs, entity, /*effect_transform=*/Matrix());
56  ASSERT_FALSE(coverage.has_value());
57 }
58 
59 TEST(MatrixFilterContentsTest, CoverageSimple) {
60  MatrixFilterContents contents;
61  FilterInput::Vector inputs = {
62  FilterInput::Make(Rect::MakeLTRB(10, 10, 110, 110))};
63  Entity entity;
64  std::optional<Rect> coverage =
65  contents.GetFilterCoverage(inputs, entity, /*effect_transform=*/Matrix());
66 
67  ASSERT_EQ(coverage, Rect::MakeLTRB(10, 10, 110, 110));
68 }
69 
71  MatrixFilterContents contents;
72  contents.SetMatrix(Matrix::MakeScale({2.0, 2.0, 1.0}));
73  FilterInput::Vector inputs = {
74  FilterInput::Make(Rect::MakeXYWH(10, 10, 100, 100))};
75  Entity entity;
76  std::optional<Rect> coverage =
77  contents.GetFilterCoverage(inputs, entity, /*effect_transform=*/Matrix());
78 
79  ASSERT_EQ(coverage, Rect::MakeXYWH(20, 20, 200, 200));
80 }
81 
82 TEST(MatrixFilterContentsTest, Coverage2xEffect) {
83  MatrixFilterContents contents;
84  FilterInput::Vector inputs = {
85  FilterInput::Make(Rect::MakeXYWH(10, 10, 100, 100))};
86  Entity entity;
87  std::optional<Rect> coverage = contents.GetFilterCoverage(
88  inputs, entity, /*effect_transform=*/Matrix::MakeScale({2.0, 2.0, 1.0}));
89 
90  ASSERT_EQ(coverage, Rect::MakeXYWH(10, 10, 100, 100));
91 }
92 
93 namespace {
94 void expectRenderCoverageEqual(const std::optional<Entity>& result,
95  const std::optional<Rect> contents_coverage,
96  const Rect& expected) {
97  EXPECT_TRUE(result.has_value());
98  if (result.has_value()) {
99  EXPECT_EQ(result.value().GetBlendMode(), BlendMode::kSourceOver);
100  std::optional<Rect> result_coverage = result.value().GetCoverage();
101  EXPECT_TRUE(result_coverage.has_value());
102  EXPECT_TRUE(contents_coverage.has_value());
103  if (result_coverage.has_value() && contents_coverage.has_value()) {
104  EXPECT_TRUE(RectNear(contents_coverage.value(), expected));
105  EXPECT_TRUE(RectNear(result_coverage.value(), expected));
106  }
107  }
108 }
109 } // namespace
110 
111 TEST_P(MatrixFilterContentsTest, RenderCoverageMatchesGetCoverageIdentity) {
112  std::shared_ptr<Texture> texture = MakeTexture(ISize(100, 100));
113  MatrixFilterContents contents;
114  contents.SetInputs({FilterInput::Make(texture)});
115 
116  Entity entity;
117  entity.SetTransform(Matrix::MakeTranslation({100, 200, 0}));
118 
119  std::shared_ptr<ContentContext> renderer = GetContentContext();
120  std::optional<Entity> result =
121  contents.GetEntity(*renderer, entity, /*coverage_hint=*/{});
122  expectRenderCoverageEqual(result, contents.GetCoverage(entity),
123  Rect::MakeXYWH(100, 200, 100, 100));
124 }
125 
126 TEST_P(MatrixFilterContentsTest, RenderCoverageMatchesGetCoverageTranslate) {
127  std::shared_ptr<Texture> texture = MakeTexture(ISize(100, 100));
128  MatrixFilterContents contents;
129  contents.SetInputs({FilterInput::Make(texture)});
130  contents.SetMatrix(Matrix::MakeTranslation({50, 100, 0}));
131  contents.SetEffectTransform(Matrix::MakeScale({2, 2, 1}));
132 
133  Entity entity;
134  entity.SetTransform(Matrix::MakeTranslation({100, 200, 0}));
135 
136  std::shared_ptr<ContentContext> renderer = GetContentContext();
137  std::optional<Entity> result =
138  contents.GetEntity(*renderer, entity, /*coverage_hint=*/{});
139  expectRenderCoverageEqual(result, contents.GetCoverage(entity),
140  Rect::MakeXYWH(150, 300, 100, 100));
141 }
142 
144  RenderCoverageMatchesGetCoverageClippedSubpassTranslate) {
145  std::shared_ptr<Texture> texture = MakeTexture(ISize(100, 100));
146  MatrixFilterContents contents;
147  contents.SetInputs({FilterInput::Make(texture)});
148  contents.SetMatrix(Matrix::MakeTranslation({50, 100, 0}));
149  contents.SetEffectTransform(Matrix::MakeScale({2, 2, 1}));
150  contents.SetRenderingMode(
152 
153  Entity entity;
154  entity.SetTransform(Matrix::MakeTranslation({100, 200, 0}));
155 
156  std::shared_ptr<ContentContext> renderer = GetContentContext();
157  std::optional<Entity> result =
158  contents.GetEntity(*renderer, entity, /*coverage_hint=*/{});
159  expectRenderCoverageEqual(result, contents.GetCoverage(entity),
160  Rect::MakeXYWH(200, 400, 100, 100));
161 }
162 
163 TEST_P(MatrixFilterContentsTest, RenderCoverageMatchesGetCoverageScale) {
164  std::shared_ptr<Texture> texture = MakeTexture(ISize(100, 100));
165  MatrixFilterContents contents;
166  contents.SetInputs({FilterInput::Make(texture)});
167  contents.SetMatrix(Matrix::MakeScale({3, 3, 1}));
168  contents.SetEffectTransform(Matrix::MakeScale({2, 2, 1}));
169 
170  Entity entity;
171  entity.SetTransform(Matrix::MakeTranslation({100, 200, 0}));
172 
173  std::shared_ptr<ContentContext> renderer = GetContentContext();
174  std::optional<Entity> result =
175  contents.GetEntity(*renderer, entity, /*coverage_hint=*/{});
176  expectRenderCoverageEqual(result, contents.GetCoverage(entity),
177  Rect::MakeXYWH(100, 200, 300, 300));
178 }
179 
181  RenderCoverageMatchesGetCoverageClippedSubpassScale) {
182  std::shared_ptr<Texture> texture = MakeTexture(ISize(100, 100));
183  MatrixFilterContents contents;
184  contents.SetInputs({FilterInput::Make(texture)});
185  contents.SetMatrix(Matrix::MakeScale({3, 3, 1}));
186  contents.SetEffectTransform(Matrix::MakeScale({2, 2, 1}));
187  contents.SetRenderingMode(
189 
190  Entity entity;
191  entity.SetTransform(Matrix::MakeTranslation({100, 200, 0}));
192 
193  std::shared_ptr<ContentContext> renderer = GetContentContext();
194  std::optional<Entity> result =
195  contents.GetEntity(*renderer, entity, /*coverage_hint=*/{});
196  expectRenderCoverageEqual(result, contents.GetCoverage(entity),
197  Rect::MakeXYWH(100, 200, 300, 300));
198 }
199 
200 TEST_P(MatrixFilterContentsTest, RenderCoverageMatchesGetCoverageSubpassScale) {
201  std::shared_ptr<Texture> texture = MakeTexture(ISize(100, 100));
202  MatrixFilterContents contents;
203  contents.SetInputs({FilterInput::Make(texture)});
204  contents.SetMatrix(Matrix::MakeScale({3, 3, 1}));
205  contents.SetEffectTransform(Matrix::MakeScale({2, 2, 1}));
206  contents.SetRenderingMode(
208 
209  Entity entity;
210  entity.SetTransform(Matrix::MakeTranslation({100, 200, 0}));
211 
212  std::shared_ptr<ContentContext> renderer = GetContentContext();
213  std::optional<Entity> result =
214  contents.GetEntity(*renderer, entity, /*coverage_hint=*/{});
215  expectRenderCoverageEqual(result, contents.GetCoverage(entity),
216  Rect::MakeXYWH(300, 600, 300, 300));
217 }
218 
219 } // namespace testing
220 } // namespace impeller
impeller::ISize
ISize64 ISize
Definition: size.h:140
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:121
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
geometry_asserts.h
impeller::TRect< Scalar >::MakeXYWH
constexpr static TRect MakeXYWH(Type x, Type y, Type width, Type height)
Definition: rect.h:136
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:125
impeller::FilterInput::Make
static FilterInput::Ref Make(Variant input, bool msaa_enabled=true)
Definition: filter_input.cc:19
impeller::MatrixFilterContents::SetMatrix
void SetMatrix(Matrix matrix)
Definition: matrix_filter_contents.cc:13
impeller::Entity::RenderingMode::kSubpassAppendSnapshotTransform
@ kSubpassAppendSnapshotTransform
impeller::testing::MatrixFilterContentsTest
Definition: matrix_filter_contents_unittests.cc:14
impeller::Matrix::MakeTranslation
static constexpr Matrix MakeTranslation(const Vector3 &t)
Definition: matrix.h:95
impeller::MatrixFilterContents
Definition: matrix_filter_contents.h:13
impeller::testing::INSTANTIATE_PLAYGROUND_SUITE
INSTANTIATE_PLAYGROUND_SUITE(AiksTest)
impeller::Entity
Definition: entity.h:20
impeller::TSize
Definition: size.h:19
matrix_filter_contents.h
impeller::testing::TEST_P
TEST_P(AiksTest, DrawAtlasNoColor)
Definition: aiks_dl_atlas_unittests.cc:78
impeller::RenderPass
Render passes encode render commands directed as one specific render target into an underlying comman...
Definition: render_pass.h:33
impeller::EntityPlayground
Definition: entity_playground.h:16
impeller::Entity::SetTransform
void SetTransform(const Matrix &transform)
Set the global transform matrix for this Entity.
Definition: entity.cc:63
impeller::Entity::RenderingMode::kSubpassPrependSnapshotTransform
@ kSubpassPrependSnapshotTransform
RectNear
inline ::testing::AssertionResult RectNear(impeller::Rect a, impeller::Rect b)
Definition: geometry_asserts.h:89
impeller::FilterContents::GetCoverage
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.
Definition: filter_contents.cc:162
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:218
impeller::TRect< Scalar >::MakeLTRB
constexpr static TRect MakeLTRB(Type left, Type top, Type right, Type bottom)
Definition: rect.h:129
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::Playground::GetContext
std::shared_ptr< Context > GetContext() const
Definition: playground.cc:90
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::interop::Create
ScopedObject< Object > Create(CtorArgs &&... args)
Definition: object.h:160
impeller
Definition: allocation.cc:12
impeller::Matrix::MakeScale
static constexpr Matrix MakeScale(const Vector3 &s)
Definition: matrix.h:104
impeller::testing::TEST
TEST(AllocationSizeTest, CanCreateTypedAllocations)
Definition: allocation_size_unittests.cc:10
impeller::ContentContext
Definition: content_context.h:366
impeller::TRect
Definition: rect.h:122
impeller::testing::MatrixFilterContentsTest::MakeTexture
std::shared_ptr< Texture > MakeTexture(ISize size)
Create a texture that has been cleared to transparent black.
Definition: matrix_filter_contents_unittests.cc:17
impeller::EntityPlayground::GetContentContext
std::shared_ptr< ContentContext > GetContentContext() const
Definition: entity_playground.cc:23
impeller::Matrix
A 4x4 matrix using column-major storage.
Definition: matrix.h:37
impeller::BlendMode::kSourceOver
@ kSourceOver
entity_playground.h