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 
44 
45 TEST(MatrixFilterContentsTest, CoverageEmpty) {
46  MatrixFilterContents contents;
47  FilterInput::Vector inputs = {};
48  Entity entity;
49  std::optional<Rect> coverage =
50  contents.GetFilterCoverage(inputs, entity, /*effect_transform=*/Matrix());
51  ASSERT_FALSE(coverage.has_value());
52 }
53 
54 TEST(MatrixFilterContentsTest, CoverageSimple) {
55  MatrixFilterContents contents;
56  FilterInput::Vector inputs = {
57  FilterInput::Make(Rect::MakeLTRB(10, 10, 110, 110))};
58  Entity entity;
59  std::optional<Rect> coverage =
60  contents.GetFilterCoverage(inputs, entity, /*effect_transform=*/Matrix());
61 
62  ASSERT_EQ(coverage, Rect::MakeLTRB(10, 10, 110, 110));
63 }
64 
66  MatrixFilterContents contents;
67  contents.SetMatrix(Matrix::MakeScale({2.0, 2.0, 1.0}));
68  FilterInput::Vector inputs = {
69  FilterInput::Make(Rect::MakeXYWH(10, 10, 100, 100))};
70  Entity entity;
71  std::optional<Rect> coverage =
72  contents.GetFilterCoverage(inputs, entity, /*effect_transform=*/Matrix());
73 
74  ASSERT_EQ(coverage, Rect::MakeXYWH(20, 20, 200, 200));
75 }
76 
77 TEST(MatrixFilterContentsTest, Coverage2xEffect) {
78  MatrixFilterContents contents;
79  FilterInput::Vector inputs = {
80  FilterInput::Make(Rect::MakeXYWH(10, 10, 100, 100))};
81  Entity entity;
82  std::optional<Rect> coverage = contents.GetFilterCoverage(
83  inputs, entity, /*effect_transform=*/Matrix::MakeScale({2.0, 2.0, 1.0}));
84 
85  ASSERT_EQ(coverage, Rect::MakeXYWH(10, 10, 100, 100));
86 }
87 
88 namespace {
89 void expectRenderCoverageEqual(const std::optional<Entity>& result,
90  const std::optional<Rect> contents_coverage,
91  const Rect& expected) {
92  EXPECT_TRUE(result.has_value());
93  if (result.has_value()) {
94  EXPECT_EQ(result.value().GetBlendMode(), BlendMode::kSrcOver);
95  std::optional<Rect> result_coverage = result.value().GetCoverage();
96  EXPECT_TRUE(result_coverage.has_value());
97  EXPECT_TRUE(contents_coverage.has_value());
98  if (result_coverage.has_value() && contents_coverage.has_value()) {
99  EXPECT_TRUE(RectNear(contents_coverage.value(), expected));
100  EXPECT_TRUE(RectNear(result_coverage.value(), expected));
101  }
102  }
103 }
104 } // namespace
105 
106 TEST_P(MatrixFilterContentsTest, RenderCoverageMatchesGetCoverageIdentity) {
107  std::shared_ptr<Texture> texture = MakeTexture(ISize(100, 100));
108  MatrixFilterContents contents;
109  contents.SetInputs({FilterInput::Make(texture)});
110 
111  Entity entity;
112  entity.SetTransform(Matrix::MakeTranslation({100, 200, 0}));
113 
114  std::shared_ptr<ContentContext> renderer = GetContentContext();
115  std::optional<Entity> result =
116  contents.GetEntity(*renderer, entity, /*coverage_hint=*/{});
117  expectRenderCoverageEqual(result, contents.GetCoverage(entity),
118  Rect::MakeXYWH(100, 200, 100, 100));
119 }
120 
121 TEST_P(MatrixFilterContentsTest, RenderCoverageMatchesGetCoverageTranslate) {
122  std::shared_ptr<Texture> texture = MakeTexture(ISize(100, 100));
123  MatrixFilterContents contents;
124  contents.SetInputs({FilterInput::Make(texture)});
125  contents.SetMatrix(Matrix::MakeTranslation({50, 100, 0}));
126  contents.SetEffectTransform(Matrix::MakeScale({2, 2, 1}));
127 
128  Entity entity;
129  entity.SetTransform(Matrix::MakeTranslation({100, 200, 0}));
130 
131  std::shared_ptr<ContentContext> renderer = GetContentContext();
132  std::optional<Entity> result =
133  contents.GetEntity(*renderer, entity, /*coverage_hint=*/{});
134  expectRenderCoverageEqual(result, contents.GetCoverage(entity),
135  Rect::MakeXYWH(150, 300, 100, 100));
136 }
137 
139  RenderCoverageMatchesGetCoverageClippedSubpassTranslate) {
140  std::shared_ptr<Texture> texture = MakeTexture(ISize(100, 100));
141  MatrixFilterContents contents;
142  contents.SetInputs({FilterInput::Make(texture)});
143  contents.SetMatrix(Matrix::MakeTranslation({50, 100, 0}));
144  contents.SetEffectTransform(Matrix::MakeScale({2, 2, 1}));
145  contents.SetRenderingMode(
147 
148  Entity entity;
149  entity.SetTransform(Matrix::MakeTranslation({100, 200, 0}));
150 
151  std::shared_ptr<ContentContext> renderer = GetContentContext();
152  std::optional<Entity> result =
153  contents.GetEntity(*renderer, entity, /*coverage_hint=*/{});
154  expectRenderCoverageEqual(result, contents.GetCoverage(entity),
155  Rect::MakeXYWH(200, 400, 100, 100));
156 }
157 
158 TEST_P(MatrixFilterContentsTest, RenderCoverageMatchesGetCoverageScale) {
159  std::shared_ptr<Texture> texture = MakeTexture(ISize(100, 100));
160  MatrixFilterContents contents;
161  contents.SetInputs({FilterInput::Make(texture)});
162  contents.SetMatrix(Matrix::MakeScale({3, 3, 1}));
163  contents.SetEffectTransform(Matrix::MakeScale({2, 2, 1}));
164 
165  Entity entity;
166  entity.SetTransform(Matrix::MakeTranslation({100, 200, 0}));
167 
168  std::shared_ptr<ContentContext> renderer = GetContentContext();
169  std::optional<Entity> result =
170  contents.GetEntity(*renderer, entity, /*coverage_hint=*/{});
171  expectRenderCoverageEqual(result, contents.GetCoverage(entity),
172  Rect::MakeXYWH(100, 200, 300, 300));
173 }
174 
176  RenderCoverageMatchesGetCoverageClippedSubpassScale) {
177  std::shared_ptr<Texture> texture = MakeTexture(ISize(100, 100));
178  MatrixFilterContents contents;
179  contents.SetInputs({FilterInput::Make(texture)});
180  contents.SetMatrix(Matrix::MakeScale({3, 3, 1}));
181  contents.SetEffectTransform(Matrix::MakeScale({2, 2, 1}));
182  contents.SetRenderingMode(
184 
185  Entity entity;
186  entity.SetTransform(Matrix::MakeTranslation({100, 200, 0}));
187 
188  std::shared_ptr<ContentContext> renderer = GetContentContext();
189  std::optional<Entity> result =
190  contents.GetEntity(*renderer, entity, /*coverage_hint=*/{});
191  expectRenderCoverageEqual(result, contents.GetCoverage(entity),
192  Rect::MakeXYWH(100, 200, 300, 300));
193 }
194 
195 TEST_P(MatrixFilterContentsTest, RenderCoverageMatchesGetCoverageSubpassScale) {
196  std::shared_ptr<Texture> texture = MakeTexture(ISize(100, 100));
197  MatrixFilterContents contents;
198  contents.SetInputs({FilterInput::Make(texture)});
199  contents.SetMatrix(Matrix::MakeScale({3, 3, 1}));
200  contents.SetEffectTransform(Matrix::MakeScale({2, 2, 1}));
201  contents.SetRenderingMode(
203 
204  Entity entity;
205  entity.SetTransform(Matrix::MakeTranslation({100, 200, 0}));
206 
207  std::shared_ptr<ContentContext> renderer = GetContentContext();
208  std::optional<Entity> result =
209  contents.GetEntity(*renderer, entity, /*coverage_hint=*/{});
210  expectRenderCoverageEqual(result, contents.GetCoverage(entity),
211  Rect::MakeXYWH(300, 600, 300, 300));
212 }
213 
214 } // namespace testing
215 } // namespace impeller
void SetTransform(const Matrix &transform)
Set the global transform matrix for this Entity.
Definition: entity.cc:60
std::shared_ptr< ContentContext > GetContentContext() const
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.
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.
void SetInputs(FilterInput::Vector inputs)
The input texture sources for this filter. Each input's emitted texture is expected to have premultip...
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 FilterInput::Ref Make(Variant input, bool msaa_enabled=true)
Definition: filter_input.cc:19
std::vector< FilterInput::Ref > Vector
Definition: filter_input.h:33
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.
std::shared_ptr< Context > GetContext() const
Definition: playground.cc:91
Render passes encode render commands directed as one specific render target into an underlying comman...
Definition: render_pass.h:30
std::shared_ptr< Texture > MakeTexture(ISize size)
Create a texture that has been cleared to transparent black.
inline ::testing::AssertionResult RectNear(impeller::Rect a, impeller::Rect b)
TEST(AllocationSizeTest, CanCreateTypedAllocations)
TEST_P(AiksTest, DrawAtlasNoColor)
INSTANTIATE_PLAYGROUND_SUITE(AiksTest)
ISize64 ISize
Definition: size.h:162
A 4x4 matrix using column-major storage.
Definition: matrix.h:37
static constexpr Matrix MakeTranslation(const Vector3 &t)
Definition: matrix.h:95
static constexpr Matrix MakeScale(const Vector3 &s)
Definition: matrix.h:104
constexpr static TRect MakeXYWH(Type x, Type y, Type width, Type height)
Definition: rect.h:136
constexpr static TRect MakeLTRB(Type left, Type top, Type right, Type bottom)
Definition: rect.h:129