| 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"
7 #include "impeller/entity/contents/filters/matrix_filter_contents.h"
8 #include "impeller/entity/entity_playground.h"
9 #include "impeller/geometry/geometry_asserts.h"
10
11 namespace impeller {
12 namespace testing {
13
14 class MatrixFilterContentsTest : public EntityPlayground {
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
45 TEST(MatrixFilterContentsTest, Create) {
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
70 TEST(MatrixFilterContentsTest, Coverage2x) {
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
143 TEST_P(MatrixFilterContentsTest,
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(
151 Entity::RenderingMode::kSubpassAppendSnapshotTransform);
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
180 TEST_P(MatrixFilterContentsTest,
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(
188 Entity::RenderingMode::kSubpassAppendSnapshotTransform);
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(
207 Entity::RenderingMode::kSubpassPrependSnapshotTransform);
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::TEST
TEST(AiksCanvasTest, EmptyCullRect)
Definition: canvas_unittests.cc:18
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::TEST_P
TEST_P(AiksTest, CanRenderAdvancedBlendColorFilterWithSaveLayer)
Definition: aiks_blend_unittests.cc:21
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::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:17
impeller::Entity::SetTransform
void SetTransform(const Matrix &transform)
Set the global transform matrix for this Entity.
Definition: entity.cc:62
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:226
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
Definition: aiks_blend_unittests.cc:18
impeller::Matrix::MakeScale
static constexpr Matrix MakeScale(const Vector3 &s)
Definition: matrix.h:104
impeller::ContentContext
Definition: content_context.h:366
impeller::TRect< Scalar >
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:45
impeller::Matrix
A 4x4 matrix using column-major storage.
Definition: matrix.h:37
impeller::BlendMode::kSourceOver
@ kSourceOver
entity_playground.h