blob: 8884711619f82706b177d4aba5168a9770bc4c01 [file] [log] [blame]
Ady Abrahamcf027d62021-03-02 18:48:57 -08001/*
2 * Copyright 2021 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Huihong Luoa5825112021-03-24 12:28:29 -070017#include <compositionengine/impl/OutputCompositionState.h>
Ady Abrahamcf027d62021-03-02 18:48:57 -080018#include <compositionengine/impl/planner/CachedSet.h>
19#include <compositionengine/impl/planner/LayerState.h>
20#include <compositionengine/mock/LayerFE.h>
21#include <compositionengine/mock/OutputLayer.h>
22#include <gtest/gtest.h>
23#include <renderengine/mock/RenderEngine.h>
24
25namespace android::compositionengine {
26using namespace std::chrono_literals;
27
28using testing::_;
29using testing::DoAll;
30using testing::Invoke;
31using testing::Return;
32using testing::ReturnRef;
33using testing::SetArgPointee;
34
35using impl::planner::CachedSet;
36using impl::planner::LayerState;
37using impl::planner::LayerStateField;
38
39namespace {
40
41class CachedSetTest : public testing::Test {
42public:
43 CachedSetTest() = default;
44 void SetUp() override;
45 void TearDown() override;
46
47protected:
48 const std::chrono::steady_clock::time_point kStartTime = std::chrono::steady_clock::now();
49
50 struct TestLayer {
51 mock::OutputLayer outputLayer;
52 impl::OutputLayerCompositionState outputLayerCompositionState;
53 // LayerFE inherits from RefBase and must be held by an sp<>
54 sp<mock::LayerFE> layerFE;
55 LayerFECompositionState layerFECompositionState;
56
57 std::unique_ptr<LayerState> layerState;
58 std::unique_ptr<CachedSet::Layer> cachedSetLayer;
59 };
60
61 static constexpr size_t kNumLayers = 5;
62 std::vector<std::unique_ptr<TestLayer>> mTestLayers;
Huihong Luoa5825112021-03-24 12:28:29 -070063 impl::OutputCompositionState mOutputState;
Ady Abrahamcf027d62021-03-02 18:48:57 -080064
65 android::renderengine::mock::RenderEngine mRenderEngine;
66};
67
68void CachedSetTest::SetUp() {
69 for (size_t i = 0; i < kNumLayers; i++) {
70 auto testLayer = std::make_unique<TestLayer>();
71 auto pos = static_cast<int32_t>(i);
72 testLayer->outputLayerCompositionState.displayFrame = Rect(pos, pos, pos + 1, pos + 1);
Alec Mouri464352b2021-03-24 16:33:21 -070073 testLayer->outputLayerCompositionState.visibleRegion =
74 Region(Rect(pos + 1, pos + 1, pos + 2, pos + 2));
Ady Abrahamcf027d62021-03-02 18:48:57 -080075
76 testLayer->layerFE = sp<mock::LayerFE>::make();
77
78 EXPECT_CALL(*testLayer->layerFE, getSequence)
79 .WillRepeatedly(Return(static_cast<int32_t>(i)));
80 EXPECT_CALL(*testLayer->layerFE, getDebugName).WillRepeatedly(Return("testLayer"));
81 EXPECT_CALL(*testLayer->layerFE, getCompositionState)
82 .WillRepeatedly(Return(&testLayer->layerFECompositionState));
83 EXPECT_CALL(testLayer->outputLayer, getLayerFE)
84 .WillRepeatedly(ReturnRef(*testLayer->layerFE));
85 EXPECT_CALL(testLayer->outputLayer, getState)
86 .WillRepeatedly(ReturnRef(testLayer->outputLayerCompositionState));
87
88 testLayer->layerState = std::make_unique<LayerState>(&testLayer->outputLayer);
89 testLayer->layerState->incrementFramesSinceBufferUpdate();
90 testLayer->cachedSetLayer =
91 std::make_unique<CachedSet::Layer>(testLayer->layerState.get(), kStartTime);
92
93 mTestLayers.emplace_back(std::move(testLayer));
Huihong Luoa5825112021-03-24 12:28:29 -070094
95 // set up minimium params needed for rendering
96 mOutputState.dataspace = ui::Dataspace::SRGB;
Alec Mouri7be6c0a2021-03-19 15:22:01 -070097 mOutputState.framebufferSpace = ProjectionSpace(ui::Size(10, 20), Rect(10, 5));
98 mOutputState.framebufferSpace.orientation = ui::ROTATION_90;
99 mOutputState.layerStackSpace = ProjectionSpace(ui::Size(20, 10), Rect(5, 10));
Ady Abrahamcf027d62021-03-02 18:48:57 -0800100 }
101}
102
103void CachedSetTest::TearDown() {
104 mTestLayers.clear();
105}
106
107void expectEqual(const CachedSet& cachedSet, const CachedSet::Layer& layer) {
108 EXPECT_EQ(layer.getHash(), cachedSet.getFingerprint());
109 EXPECT_EQ(layer.getLastUpdate(), cachedSet.getLastUpdate());
110 EXPECT_EQ(layer.getDisplayFrame(), cachedSet.getBounds());
Alec Mouri464352b2021-03-24 16:33:21 -0700111 EXPECT_TRUE(layer.getVisibleRegion().hasSameRects(cachedSet.getVisibleRegion()));
Ady Abrahamcf027d62021-03-02 18:48:57 -0800112 EXPECT_EQ(1u, cachedSet.getLayerCount());
113 EXPECT_EQ(layer.getState(), cachedSet.getFirstLayer().getState());
114 EXPECT_EQ(0u, cachedSet.getAge());
115 EXPECT_EQ(layer.getHash(), cachedSet.getNonBufferHash());
116}
117
118void expectEqual(const CachedSet& cachedSet, const LayerState& layerState,
119 std::chrono::steady_clock::time_point lastUpdate) {
120 CachedSet::Layer layer(&layerState, lastUpdate);
121 expectEqual(cachedSet, layer);
122}
123
124void expectNoBuffer(const CachedSet& cachedSet) {
125 EXPECT_EQ(nullptr, cachedSet.getBuffer());
126 EXPECT_EQ(nullptr, cachedSet.getDrawFence());
127 EXPECT_FALSE(cachedSet.hasReadyBuffer());
128}
129
130void expectReadyBuffer(const CachedSet& cachedSet) {
131 EXPECT_NE(nullptr, cachedSet.getBuffer());
132 EXPECT_NE(nullptr, cachedSet.getDrawFence());
133 EXPECT_TRUE(cachedSet.hasReadyBuffer());
134}
135
136TEST_F(CachedSetTest, createFromLayer) {
137 CachedSet::Layer& layer = *mTestLayers[0]->cachedSetLayer.get();
138 CachedSet cachedSet(layer);
139 expectEqual(cachedSet, layer);
140 expectNoBuffer(cachedSet);
141}
142
143TEST_F(CachedSetTest, createFromLayerState) {
144 LayerState& layerState = *mTestLayers[0]->layerState.get();
145 CachedSet cachedSet(&layerState, kStartTime);
146 expectEqual(cachedSet, layerState, kStartTime);
147 expectNoBuffer(cachedSet);
148}
149
150TEST_F(CachedSetTest, addLayer) {
151 CachedSet::Layer& layer1 = *mTestLayers[0]->cachedSetLayer.get();
152 CachedSet::Layer& layer2 = *mTestLayers[1]->cachedSetLayer.get();
153
154 CachedSet cachedSet(layer1);
155 cachedSet.addLayer(layer2.getState(), kStartTime + 10ms);
156
157 EXPECT_EQ(layer1.getHash(), cachedSet.getFingerprint());
158 EXPECT_EQ(kStartTime, cachedSet.getLastUpdate());
159 EXPECT_EQ(Rect(0, 0, 2, 2), cachedSet.getBounds());
Alec Mouri464352b2021-03-24 16:33:21 -0700160 Region expectedRegion;
161 expectedRegion.orSelf(Rect(1, 1, 2, 2));
162 expectedRegion.orSelf(Rect(2, 2, 3, 3));
163 EXPECT_TRUE(cachedSet.getVisibleRegion().hasSameRects(expectedRegion));
Ady Abrahamcf027d62021-03-02 18:48:57 -0800164 EXPECT_EQ(2u, cachedSet.getLayerCount());
165 EXPECT_EQ(0u, cachedSet.getAge());
166 expectNoBuffer(cachedSet);
167 // TODO(b/181192080): check that getNonBufferHash returns the correct hash value
168 // EXPECT_EQ(android::hashCombine(layer1.getHash(), layer2.getHash()),
169 // cachedSet.getNonBufferHash());
170}
171
172TEST_F(CachedSetTest, decompose) {
173 CachedSet::Layer& layer1 = *mTestLayers[0]->cachedSetLayer.get();
174 CachedSet::Layer& layer2 = *mTestLayers[1]->cachedSetLayer.get();
175 CachedSet::Layer& layer3 = *mTestLayers[2]->cachedSetLayer.get();
176
177 CachedSet cachedSet(layer1);
178 cachedSet.addLayer(layer2.getState(), kStartTime + 10ms);
179 cachedSet.addLayer(layer3.getState(), kStartTime + 20ms);
180
181 std::vector<CachedSet> decomposed = cachedSet.decompose();
182 EXPECT_EQ(3u, decomposed.size());
183 expectEqual(decomposed[0], *layer1.getState(), kStartTime);
184 expectNoBuffer(decomposed[0]);
185
186 expectEqual(decomposed[1], *layer2.getState(), kStartTime + 10ms);
187 expectNoBuffer(decomposed[1]);
188
189 expectEqual(decomposed[2], *layer3.getState(), kStartTime + 20ms);
190 expectNoBuffer(decomposed[2]);
191}
192
193TEST_F(CachedSetTest, setLastUpdate) {
194 LayerState& layerState = *mTestLayers[0]->layerState.get();
195 CachedSet cachedSet(&layerState, kStartTime);
196 cachedSet.setLastUpdate(kStartTime + 10ms);
197 expectEqual(cachedSet, layerState, kStartTime + 10ms);
198}
199
200TEST_F(CachedSetTest, incrementAge) {
201 CachedSet::Layer& layer = *mTestLayers[0]->cachedSetLayer.get();
202 CachedSet cachedSet(layer);
203 EXPECT_EQ(0u, cachedSet.getAge());
204 cachedSet.incrementAge();
205 EXPECT_EQ(1u, cachedSet.getAge());
206 cachedSet.incrementAge();
207 EXPECT_EQ(2u, cachedSet.getAge());
208}
209
210TEST_F(CachedSetTest, hasBufferUpdate_NoUpdate) {
211 CachedSet::Layer& layer1 = *mTestLayers[0]->cachedSetLayer.get();
212 CachedSet::Layer& layer2 = *mTestLayers[1]->cachedSetLayer.get();
213 CachedSet::Layer& layer3 = *mTestLayers[2]->cachedSetLayer.get();
214
215 CachedSet cachedSet(layer1);
216 cachedSet.addLayer(layer2.getState(), kStartTime + 10ms);
217 cachedSet.addLayer(layer3.getState(), kStartTime + 20ms);
218
Leon Scroggins III6dfcedf2021-03-25 11:17:03 -0400219 EXPECT_FALSE(cachedSet.hasBufferUpdate());
Ady Abrahamcf027d62021-03-02 18:48:57 -0800220}
221
222TEST_F(CachedSetTest, hasBufferUpdate_BufferUpdate) {
223 CachedSet::Layer& layer1 = *mTestLayers[0]->cachedSetLayer.get();
224 CachedSet::Layer& layer2 = *mTestLayers[1]->cachedSetLayer.get();
225 CachedSet::Layer& layer3 = *mTestLayers[2]->cachedSetLayer.get();
226
227 CachedSet cachedSet(layer1);
228 cachedSet.addLayer(layer2.getState(), kStartTime + 10ms);
229 cachedSet.addLayer(layer3.getState(), kStartTime + 20ms);
230
231 mTestLayers[1]->layerState->resetFramesSinceBufferUpdate();
232
Leon Scroggins III6dfcedf2021-03-25 11:17:03 -0400233 EXPECT_TRUE(cachedSet.hasBufferUpdate());
Ady Abrahamcf027d62021-03-02 18:48:57 -0800234}
235
236TEST_F(CachedSetTest, append) {
237 CachedSet::Layer& layer1 = *mTestLayers[0]->cachedSetLayer.get();
238 CachedSet::Layer& layer2 = *mTestLayers[1]->cachedSetLayer.get();
239 CachedSet::Layer& layer3 = *mTestLayers[2]->cachedSetLayer.get();
240
241 CachedSet cachedSet1(layer1);
242 CachedSet cachedSet2(layer2);
243 cachedSet1.addLayer(layer3.getState(), kStartTime + 10ms);
244 cachedSet1.append(cachedSet2);
245
246 EXPECT_EQ(layer1.getHash(), cachedSet1.getFingerprint());
247 EXPECT_EQ(kStartTime, cachedSet1.getLastUpdate());
248 EXPECT_EQ(Rect(0, 0, 3, 3), cachedSet1.getBounds());
Alec Mouri464352b2021-03-24 16:33:21 -0700249 Region expectedRegion;
250 expectedRegion.orSelf(Rect(1, 1, 2, 2));
251 expectedRegion.orSelf(Rect(2, 2, 3, 3));
252 expectedRegion.orSelf(Rect(3, 3, 4, 4));
253 EXPECT_TRUE(cachedSet1.getVisibleRegion().hasSameRects(expectedRegion));
Ady Abrahamcf027d62021-03-02 18:48:57 -0800254 EXPECT_EQ(3u, cachedSet1.getLayerCount());
255 EXPECT_EQ(0u, cachedSet1.getAge());
256 expectNoBuffer(cachedSet1);
257 // TODO(b/181192080): check that getNonBufferHash returns the correct hash value
258 // EXPECT_EQ(android::hashCombine(layer1.getHash(), layer2.getHash()),
259 // cachedSet1.getNonBufferHash());
260}
261
262TEST_F(CachedSetTest, updateAge_NoUpdate) {
263 CachedSet::Layer& layer = *mTestLayers[0]->cachedSetLayer.get();
264
265 CachedSet cachedSet(layer);
266 cachedSet.incrementAge();
267 EXPECT_EQ(kStartTime, cachedSet.getLastUpdate());
268 EXPECT_EQ(1u, cachedSet.getAge());
269
270 cachedSet.updateAge(kStartTime + 10ms);
271 EXPECT_EQ(kStartTime, cachedSet.getLastUpdate());
272 EXPECT_EQ(1u, cachedSet.getAge());
273}
274
275TEST_F(CachedSetTest, updateAge_BufferUpdate) {
276 CachedSet::Layer& layer = *mTestLayers[0]->cachedSetLayer.get();
277 mTestLayers[0]->layerState->resetFramesSinceBufferUpdate();
278
279 CachedSet cachedSet(layer);
280 cachedSet.incrementAge();
281 EXPECT_EQ(kStartTime, cachedSet.getLastUpdate());
282 EXPECT_EQ(1u, cachedSet.getAge());
283
284 cachedSet.updateAge(kStartTime + 10ms);
285 EXPECT_EQ(kStartTime + 10ms, cachedSet.getLastUpdate());
286 EXPECT_EQ(0u, cachedSet.getAge());
287}
288
289TEST_F(CachedSetTest, render) {
Alec Mouricf165b62021-04-13 15:45:36 -0700290 // Skip the 0th layer to ensure that the bounding box of the layers is offset from (0, 0)
291 CachedSet::Layer& layer1 = *mTestLayers[1]->cachedSetLayer.get();
292 sp<mock::LayerFE> layerFE1 = mTestLayers[1]->layerFE;
293 CachedSet::Layer& layer2 = *mTestLayers[2]->cachedSetLayer.get();
294 sp<mock::LayerFE> layerFE2 = mTestLayers[2]->layerFE;
Ady Abrahamcf027d62021-03-02 18:48:57 -0800295
296 CachedSet cachedSet(layer1);
297 cachedSet.append(CachedSet(layer2));
298
299 std::vector<compositionengine::LayerFE::LayerSettings> clientCompList1;
300 clientCompList1.push_back({});
301 clientCompList1[0].alpha = 0.5f;
302
303 std::vector<compositionengine::LayerFE::LayerSettings> clientCompList2;
304 clientCompList2.push_back({});
305 clientCompList2[0].alpha = 0.75f;
306
307 const auto drawLayers = [&](const renderengine::DisplaySettings& displaySettings,
308 const std::vector<const renderengine::LayerSettings*>& layers,
Alec Mouria90a5702021-04-16 16:36:21 +0000309 const std::shared_ptr<renderengine::ExternalTexture>&, const bool,
310 base::unique_fd&&, base::unique_fd*) -> size_t {
Alec Mouricf165b62021-04-13 15:45:36 -0700311 EXPECT_EQ(Rect(-1, -1, 9, 4), displaySettings.physicalDisplay);
Alec Mouri7be6c0a2021-03-19 15:22:01 -0700312 EXPECT_EQ(mOutputState.layerStackSpace.content, displaySettings.clip);
313 EXPECT_EQ(ui::Transform::toRotationFlags(mOutputState.framebufferSpace.orientation),
314 displaySettings.orientation);
Ady Abrahamcf027d62021-03-02 18:48:57 -0800315 EXPECT_EQ(0.5f, layers[0]->alpha);
316 EXPECT_EQ(0.75f, layers[1]->alpha);
Alec Mouri9c8fce02021-03-12 18:30:42 -0800317 EXPECT_EQ(ui::Dataspace::SRGB, displaySettings.outputDataspace);
Ady Abrahamcf027d62021-03-02 18:48:57 -0800318
319 return NO_ERROR;
320 };
321
322 EXPECT_CALL(*layerFE1, prepareClientCompositionList(_)).WillOnce(Return(clientCompList1));
323 EXPECT_CALL(*layerFE2, prepareClientCompositionList(_)).WillOnce(Return(clientCompList2));
324 EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _, _, _)).WillOnce(Invoke(drawLayers));
Huihong Luoa5825112021-03-24 12:28:29 -0700325 cachedSet.render(mRenderEngine, mOutputState);
Ady Abrahamcf027d62021-03-02 18:48:57 -0800326 expectReadyBuffer(cachedSet);
Alec Mouri49da70d2021-03-10 21:11:25 -0800327
Alec Mouri73e09c32021-04-26 15:02:16 -0700328 EXPECT_EQ(mOutputState.framebufferSpace, cachedSet.getOutputSpace());
329
330 // Now check that appending a new cached set properly cleans up RenderEngine resources.
331 CachedSet::Layer& layer3 = *mTestLayers[2]->cachedSetLayer.get();
332 cachedSet.append(CachedSet(layer3));
333}
334
335TEST_F(CachedSetTest, rendersWithOffsetFramebufferContent) {
336 // Skip the 0th layer to ensure that the bounding box of the layers is offset from (0, 0)
337 CachedSet::Layer& layer1 = *mTestLayers[1]->cachedSetLayer.get();
338 sp<mock::LayerFE> layerFE1 = mTestLayers[1]->layerFE;
339 CachedSet::Layer& layer2 = *mTestLayers[2]->cachedSetLayer.get();
340 sp<mock::LayerFE> layerFE2 = mTestLayers[2]->layerFE;
341
342 CachedSet cachedSet(layer1);
343 cachedSet.append(CachedSet(layer2));
344
345 std::vector<compositionengine::LayerFE::LayerSettings> clientCompList1;
346 clientCompList1.push_back({});
347 clientCompList1[0].alpha = 0.5f;
348
349 std::vector<compositionengine::LayerFE::LayerSettings> clientCompList2;
350 clientCompList2.push_back({});
351 clientCompList2[0].alpha = 0.75f;
352
353 mOutputState.framebufferSpace = ProjectionSpace(ui::Size(10, 20), Rect(2, 3, 10, 5));
354
355 const auto drawLayers = [&](const renderengine::DisplaySettings& displaySettings,
356 const std::vector<const renderengine::LayerSettings*>& layers,
357 const std::shared_ptr<renderengine::ExternalTexture>&, const bool,
358 base::unique_fd&&, base::unique_fd*) -> size_t {
359 EXPECT_EQ(Rect(1, 2, 9, 4), displaySettings.physicalDisplay);
360 EXPECT_EQ(mOutputState.layerStackSpace.content, displaySettings.clip);
361 EXPECT_EQ(ui::Transform::toRotationFlags(mOutputState.framebufferSpace.orientation),
362 displaySettings.orientation);
363 EXPECT_EQ(0.5f, layers[0]->alpha);
364 EXPECT_EQ(0.75f, layers[1]->alpha);
365 EXPECT_EQ(ui::Dataspace::SRGB, displaySettings.outputDataspace);
366
367 return NO_ERROR;
368 };
369
370 EXPECT_CALL(*layerFE1, prepareClientCompositionList(_)).WillOnce(Return(clientCompList1));
371 EXPECT_CALL(*layerFE2, prepareClientCompositionList(_)).WillOnce(Return(clientCompList2));
372 EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _, _, _)).WillOnce(Invoke(drawLayers));
373 cachedSet.render(mRenderEngine, mOutputState);
374 expectReadyBuffer(cachedSet);
375
376 EXPECT_EQ(mOutputState.framebufferSpace, cachedSet.getOutputSpace());
Alec Mouri7be6c0a2021-03-19 15:22:01 -0700377
Alec Mouri49da70d2021-03-10 21:11:25 -0800378 // Now check that appending a new cached set properly cleans up RenderEngine resources.
Alec Mouri49da70d2021-03-10 21:11:25 -0800379 CachedSet::Layer& layer3 = *mTestLayers[2]->cachedSetLayer.get();
380 cachedSet.append(CachedSet(layer3));
Ady Abrahamcf027d62021-03-02 18:48:57 -0800381}
382
383} // namespace
384} // namespace android::compositionengine