1 /*
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
17 #include <compositionengine/impl/OutputCompositionState.h>
18 #include <compositionengine/impl/planner/CachedSet.h>
19 #include <compositionengine/impl/planner/Flattener.h>
20 #include <compositionengine/impl/planner/LayerState.h>
21 #include <compositionengine/mock/LayerFE.h>
22 #include <compositionengine/mock/OutputLayer.h>
23 #include <gtest/gtest.h>
24 #include <renderengine/ExternalTexture.h>
25 #include <renderengine/LayerSettings.h>
26 #include <renderengine/impl/ExternalTexture.h>
27 #include <renderengine/mock/RenderEngine.h>
28 #include <chrono>
29
30 namespace android::compositionengine {
31 using namespace std::chrono_literals;
32 using impl::planner::CachedSet;
33 using impl::planner::Flattener;
34 using impl::planner::LayerState;
35 using impl::planner::NonBufferHash;
36
37 using testing::_;
38 using testing::ByMove;
39 using testing::ByRef;
40 using testing::DoAll;
41 using testing::Invoke;
42 using testing::Return;
43 using testing::ReturnRef;
44 using testing::Sequence;
45 using testing::SetArgPointee;
46
47 namespace {
48
49 class TestableFlattener : public Flattener {
50 public:
TestableFlattener(renderengine::RenderEngine & renderEngine,const Tunables & tunables)51 TestableFlattener(renderengine::RenderEngine& renderEngine, const Tunables& tunables)
52 : Flattener(renderEngine, tunables) {}
getNewCachedSetForTesting() const53 const std::optional<CachedSet>& getNewCachedSetForTesting() const { return mNewCachedSet; }
54 };
55
56 class FlattenerTest : public testing::Test {
57 public:
FlattenerTest()58 FlattenerTest()
59 : FlattenerTest(Flattener::Tunables{
60 .mActiveLayerTimeout = 100ms,
61 .mRenderScheduling = std::nullopt,
62 .mEnableHolePunch = true,
63 }) {}
64 void SetUp() override;
65
66 protected:
FlattenerTest(const Flattener::Tunables & tunables)67 FlattenerTest(const Flattener::Tunables& tunables)
68 : mFlattener(std::make_unique<TestableFlattener>(mRenderEngine, tunables)) {}
69 void initializeOverrideBuffer(const std::vector<const LayerState*>& layers);
70 void initializeFlattener(const std::vector<const LayerState*>& layers);
71 void expectAllLayersFlattened(const std::vector<const LayerState*>& layers);
72
73 // mRenderEngine is held as a reference in mFlattener, so explicitly destroy mFlattener first.
74 renderengine::mock::RenderEngine mRenderEngine;
75 std::unique_ptr<TestableFlattener> mFlattener;
76
77 const std::chrono::steady_clock::time_point kStartTime = std::chrono::steady_clock::now();
78 std::chrono::steady_clock::time_point mTime = kStartTime;
79
80 struct TestLayer {
81 std::string name;
82 mock::OutputLayer outputLayer;
83 impl::OutputLayerCompositionState outputLayerCompositionState;
84 // LayerFE inherits from RefBase and must be held by an sp<>
85 sp<mock::LayerFE> layerFE;
86 LayerFECompositionState layerFECompositionState;
87
88 std::unique_ptr<LayerState> layerState;
89 };
90
91 static constexpr size_t kNumLayers = 5;
92 std::vector<std::unique_ptr<TestLayer>> mTestLayers;
93 impl::OutputCompositionState mOutputState;
94 };
95
SetUp()96 void FlattenerTest::SetUp() {
97 mFlattener->setDisplaySize({1, 1});
98 for (size_t i = 0; i < kNumLayers; i++) {
99 auto testLayer = std::make_unique<TestLayer>();
100 auto pos = static_cast<int32_t>(i);
101 std::stringstream ss;
102 ss << "testLayer" << i;
103 testLayer->name = ss.str();
104
105 testLayer->outputLayerCompositionState.displayFrame = Rect(pos, pos, pos + 1, pos + 1);
106 testLayer->outputLayerCompositionState.visibleRegion =
107 Region(Rect(pos + 1, pos + 1, pos + 2, pos + 2));
108
109 const auto kUsageFlags =
110 static_cast<uint64_t>(GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN |
111 GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE);
112 testLayer->layerFECompositionState.buffer =
113 sp<GraphicBuffer>::make(100u, 100u, HAL_PIXEL_FORMAT_RGBA_8888, 1u, kUsageFlags,
114 "output");
115
116 testLayer->layerFE = sp<mock::LayerFE>::make();
117
118 EXPECT_CALL(*testLayer->layerFE, getSequence)
119 .WillRepeatedly(Return(static_cast<int32_t>(i)));
120 EXPECT_CALL(*testLayer->layerFE, getDebugName)
121 .WillRepeatedly(Return(testLayer->name.c_str()));
122 EXPECT_CALL(*testLayer->layerFE, getCompositionState)
123 .WillRepeatedly(Return(&testLayer->layerFECompositionState));
124
125 std::optional<LayerFE::LayerSettings> clientComposition;
126 clientComposition.emplace();
127
128 EXPECT_CALL(*testLayer->layerFE, prepareClientComposition)
129 .WillRepeatedly(Return(clientComposition));
130 EXPECT_CALL(testLayer->outputLayer, getLayerFE)
131 .WillRepeatedly(ReturnRef(*testLayer->layerFE));
132 EXPECT_CALL(testLayer->outputLayer, getState)
133 .WillRepeatedly(ReturnRef(testLayer->outputLayerCompositionState));
134 EXPECT_CALL(testLayer->outputLayer, editState)
135 .WillRepeatedly(ReturnRef(testLayer->outputLayerCompositionState));
136
137 testLayer->layerState = std::make_unique<LayerState>(&testLayer->outputLayer);
138 testLayer->layerState->incrementFramesSinceBufferUpdate();
139
140 mTestLayers.emplace_back(std::move(testLayer));
141
142 // set up minimium params needed for rendering
143 mOutputState.dataspace = ui::Dataspace::SRGB;
144 mOutputState.framebufferSpace = ProjectionSpace(ui::Size(10, 20), Rect(10, 5));
145 mOutputState.framebufferSpace.setOrientation(ui::ROTATION_90);
146 }
147 }
148
initializeOverrideBuffer(const std::vector<const LayerState * > & layers)149 void FlattenerTest::initializeOverrideBuffer(const std::vector<const LayerState*>& layers) {
150 for (const auto layer : layers) {
151 layer->getOutputLayer()->editState().overrideInfo = {};
152 }
153 }
154
initializeFlattener(const std::vector<const LayerState * > & layers)155 void FlattenerTest::initializeFlattener(const std::vector<const LayerState*>& layers) {
156 // layer stack is unknown, reset current geomentry
157 initializeOverrideBuffer(layers);
158 EXPECT_EQ(getNonBufferHash(layers),
159 mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime));
160 mFlattener->renderCachedSets(mOutputState, std::nullopt, true);
161
162 // same geometry, update the internal layer stack
163 initializeOverrideBuffer(layers);
164 EXPECT_EQ(getNonBufferHash(layers),
165 mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime));
166 mFlattener->renderCachedSets(mOutputState, std::nullopt, true);
167 }
168
expectAllLayersFlattened(const std::vector<const LayerState * > & layers)169 void FlattenerTest::expectAllLayersFlattened(const std::vector<const LayerState*>& layers) {
170 // layers would be flattened but the buffer would not be overridden
171 EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _, _))
172 .WillOnce(Return(ByMove(ftl::yield<FenceResult>(Fence::NO_FENCE))));
173
174 initializeOverrideBuffer(layers);
175 EXPECT_EQ(getNonBufferHash(layers),
176 mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime));
177 mFlattener->renderCachedSets(mOutputState, std::nullopt, true);
178
179 for (const auto layer : layers) {
180 EXPECT_EQ(nullptr, layer->getOutputLayer()->getState().overrideInfo.buffer);
181 }
182
183 // the new flattened layer is replaced
184 initializeOverrideBuffer(layers);
185 EXPECT_NE(getNonBufferHash(layers),
186 mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime));
187 mFlattener->renderCachedSets(mOutputState, std::nullopt, true);
188
189 const auto buffer = layers[0]->getOutputLayer()->getState().overrideInfo.buffer;
190 EXPECT_NE(nullptr, buffer);
191 for (const auto layer : layers) {
192 EXPECT_EQ(buffer, layer->getOutputLayer()->getState().overrideInfo.buffer);
193 }
194 }
195
TEST_F(FlattenerTest,flattenLayers_NewLayerStack)196 TEST_F(FlattenerTest, flattenLayers_NewLayerStack) {
197 auto& layerState1 = mTestLayers[0]->layerState;
198 auto& layerState2 = mTestLayers[1]->layerState;
199
200 const std::vector<const LayerState*> layers = {
201 layerState1.get(),
202 layerState2.get(),
203 };
204 initializeFlattener(layers);
205 }
206
TEST_F(FlattenerTest,flattenLayers_ActiveLayersAreNotFlattened)207 TEST_F(FlattenerTest, flattenLayers_ActiveLayersAreNotFlattened) {
208 auto& layerState1 = mTestLayers[0]->layerState;
209 auto& layerState2 = mTestLayers[1]->layerState;
210
211 const std::vector<const LayerState*> layers = {
212 layerState1.get(),
213 layerState2.get(),
214 };
215
216 initializeFlattener(layers);
217
218 // layers cannot be flattened yet, since they are still active
219 initializeOverrideBuffer(layers);
220 EXPECT_EQ(getNonBufferHash(layers),
221 mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime));
222 mFlattener->renderCachedSets(mOutputState, std::nullopt, true);
223 }
224
TEST_F(FlattenerTest,flattenLayers_ActiveLayersWithLowFpsAreFlattened)225 TEST_F(FlattenerTest, flattenLayers_ActiveLayersWithLowFpsAreFlattened) {
226 mTestLayers[0]->layerFECompositionState.fps = Flattener::kFpsActiveThreshold / 2;
227 mTestLayers[1]->layerFECompositionState.fps = Flattener::kFpsActiveThreshold;
228
229 auto& layerState1 = mTestLayers[0]->layerState;
230 auto& layerState2 = mTestLayers[1]->layerState;
231
232 const std::vector<const LayerState*> layers = {
233 layerState1.get(),
234 layerState2.get(),
235 };
236
237 initializeFlattener(layers);
238 expectAllLayersFlattened(layers);
239 }
240
TEST_F(FlattenerTest,flattenLayers_basicFlatten)241 TEST_F(FlattenerTest, flattenLayers_basicFlatten) {
242 auto& layerState1 = mTestLayers[0]->layerState;
243 auto& layerState2 = mTestLayers[1]->layerState;
244 auto& layerState3 = mTestLayers[2]->layerState;
245
246 const std::vector<const LayerState*> layers = {
247 layerState1.get(),
248 layerState2.get(),
249 layerState3.get(),
250 };
251
252 initializeFlattener(layers);
253
254 // make all layers inactive
255 mTime += 200ms;
256 expectAllLayersFlattened(layers);
257 }
258
TEST_F(FlattenerTest,flattenLayers_FlattenedLayersStayFlattenWhenNoUpdate)259 TEST_F(FlattenerTest, flattenLayers_FlattenedLayersStayFlattenWhenNoUpdate) {
260 auto& layerState1 = mTestLayers[0]->layerState;
261 const auto& overrideBuffer1 = layerState1->getOutputLayer()->getState().overrideInfo.buffer;
262
263 auto& layerState2 = mTestLayers[1]->layerState;
264 const auto& overrideBuffer2 = layerState2->getOutputLayer()->getState().overrideInfo.buffer;
265
266 auto& layerState3 = mTestLayers[2]->layerState;
267 const auto& overrideBuffer3 = layerState3->getOutputLayer()->getState().overrideInfo.buffer;
268
269 const std::vector<const LayerState*> layers = {
270 layerState1.get(),
271 layerState2.get(),
272 layerState3.get(),
273 };
274
275 initializeFlattener(layers);
276
277 // make all layers inactive
278 mTime += 200ms;
279 expectAllLayersFlattened(layers);
280
281 initializeOverrideBuffer(layers);
282 EXPECT_NE(getNonBufferHash(layers),
283 mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime));
284 mFlattener->renderCachedSets(mOutputState, std::nullopt, true);
285
286 EXPECT_NE(nullptr, overrideBuffer1);
287 EXPECT_EQ(overrideBuffer1, overrideBuffer2);
288 EXPECT_EQ(overrideBuffer2, overrideBuffer3);
289 }
290
TEST_F(FlattenerTest,flattenLayers_FlattenedLayersSetsProjectionSpace)291 TEST_F(FlattenerTest, flattenLayers_FlattenedLayersSetsProjectionSpace) {
292 auto& layerState1 = mTestLayers[0]->layerState;
293 const auto& overrideDisplaySpace =
294 layerState1->getOutputLayer()->getState().overrideInfo.displaySpace;
295
296 auto& layerState2 = mTestLayers[1]->layerState;
297
298 const std::vector<const LayerState*> layers = {
299 layerState1.get(),
300 layerState2.get(),
301 };
302
303 initializeFlattener(layers);
304
305 // make all layers inactive
306 mTime += 200ms;
307 expectAllLayersFlattened(layers);
308
309 EXPECT_EQ(overrideDisplaySpace, mOutputState.framebufferSpace);
310 }
311
TEST_F(FlattenerTest,flattenLayers_FlattenedLayersSetsDamageRegions)312 TEST_F(FlattenerTest, flattenLayers_FlattenedLayersSetsDamageRegions) {
313 auto& layerState1 = mTestLayers[0]->layerState;
314 const auto& overrideDamageRegion =
315 layerState1->getOutputLayer()->getState().overrideInfo.damageRegion;
316
317 auto& layerState2 = mTestLayers[1]->layerState;
318
319 const std::vector<const LayerState*> layers = {
320 layerState1.get(),
321 layerState2.get(),
322 };
323
324 initializeFlattener(layers);
325
326 // make all layers inactive
327 mTime += 200ms;
328 expectAllLayersFlattened(layers);
329 EXPECT_TRUE(overrideDamageRegion.isRect() &&
330 overrideDamageRegion.bounds() == Rect::INVALID_RECT);
331
332 initializeOverrideBuffer(layers);
333 EXPECT_NE(getNonBufferHash(layers),
334 mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime));
335 EXPECT_TRUE(overrideDamageRegion.isRect() && overrideDamageRegion.bounds() == Rect::EMPTY_RECT);
336 }
337
TEST_F(FlattenerTest,flattenLayers_FlattenedLayersSetsVisibleRegion)338 TEST_F(FlattenerTest, flattenLayers_FlattenedLayersSetsVisibleRegion) {
339 auto& layerState1 = mTestLayers[0]->layerState;
340 const auto& overrideVisibleRegion =
341 layerState1->getOutputLayer()->getState().overrideInfo.visibleRegion;
342
343 auto& layerState2 = mTestLayers[1]->layerState;
344
345 const std::vector<const LayerState*> layers = {
346 layerState1.get(),
347 layerState2.get(),
348 };
349
350 initializeFlattener(layers);
351
352 // make all layers inactive
353 mTime += 200ms;
354 expectAllLayersFlattened(layers);
355 Region expectedRegion;
356 expectedRegion.orSelf(Rect(1, 1, 2, 2));
357 expectedRegion.orSelf(Rect(2, 2, 3, 3));
358 EXPECT_TRUE(overrideVisibleRegion.hasSameRects(expectedRegion));
359 }
360
TEST_F(FlattenerTest,flattenLayers_addLayerToFlattenedCauseReset)361 TEST_F(FlattenerTest, flattenLayers_addLayerToFlattenedCauseReset) {
362 auto& layerState1 = mTestLayers[0]->layerState;
363 const auto& overrideBuffer1 = layerState1->getOutputLayer()->getState().overrideInfo.buffer;
364
365 auto& layerState2 = mTestLayers[1]->layerState;
366 const auto& overrideBuffer2 = layerState2->getOutputLayer()->getState().overrideInfo.buffer;
367
368 auto& layerState3 = mTestLayers[2]->layerState;
369 const auto& overrideBuffer3 = layerState3->getOutputLayer()->getState().overrideInfo.buffer;
370
371 std::vector<const LayerState*> layers = {
372 layerState1.get(),
373 layerState2.get(),
374 };
375
376 initializeFlattener(layers);
377 // make all layers inactive
378 mTime += 200ms;
379
380 initializeOverrideBuffer(layers);
381 expectAllLayersFlattened(layers);
382
383 // add a new layer to the stack, this will cause all the flatenner to reset
384 layers.push_back(layerState3.get());
385
386 initializeOverrideBuffer(layers);
387 EXPECT_EQ(getNonBufferHash(layers),
388 mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime));
389 mFlattener->renderCachedSets(mOutputState, std::nullopt, true);
390
391 EXPECT_EQ(nullptr, overrideBuffer1);
392 EXPECT_EQ(nullptr, overrideBuffer2);
393 EXPECT_EQ(nullptr, overrideBuffer3);
394 }
395
TEST_F(FlattenerTest,flattenLayers_BufferUpdateToFlatten)396 TEST_F(FlattenerTest, flattenLayers_BufferUpdateToFlatten) {
397 auto& layerState1 = mTestLayers[0]->layerState;
398 const auto& overrideBuffer1 = layerState1->getOutputLayer()->getState().overrideInfo.buffer;
399
400 auto& layerState2 = mTestLayers[1]->layerState;
401 const auto& overrideBuffer2 = layerState2->getOutputLayer()->getState().overrideInfo.buffer;
402
403 auto& layerState3 = mTestLayers[2]->layerState;
404 const auto& overrideBuffer3 = layerState3->getOutputLayer()->getState().overrideInfo.buffer;
405
406 const std::vector<const LayerState*> layers = {
407 layerState1.get(),
408 layerState2.get(),
409 layerState3.get(),
410 };
411
412 initializeFlattener(layers);
413
414 // make all layers inactive
415 mTime += 200ms;
416 expectAllLayersFlattened(layers);
417
418 // Layer 1 posted a buffer update, layers would be decomposed, and a new drawFrame would be
419 // caleed for Layer2 and Layer3
420 layerState1->resetFramesSinceBufferUpdate();
421
422 EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _, _))
423 .WillOnce(Return(ByMove(ftl::yield<FenceResult>(Fence::NO_FENCE))));
424 initializeOverrideBuffer(layers);
425 EXPECT_EQ(getNonBufferHash(layers),
426 mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime));
427 mFlattener->renderCachedSets(mOutputState, std::nullopt, true);
428
429 EXPECT_EQ(nullptr, overrideBuffer1);
430 EXPECT_EQ(nullptr, overrideBuffer2);
431 EXPECT_EQ(nullptr, overrideBuffer3);
432
433 initializeOverrideBuffer(layers);
434 EXPECT_NE(getNonBufferHash(layers),
435 mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime));
436 mFlattener->renderCachedSets(mOutputState, std::nullopt, true);
437
438 EXPECT_EQ(nullptr, overrideBuffer1);
439 EXPECT_NE(nullptr, overrideBuffer2);
440 EXPECT_EQ(overrideBuffer2, overrideBuffer3);
441
442 layerState1->incrementFramesSinceBufferUpdate();
443 mTime += 200ms;
444
445 EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _, _))
446 .WillOnce(Return(ByMove(ftl::yield<FenceResult>(Fence::NO_FENCE))));
447 initializeOverrideBuffer(layers);
448 EXPECT_NE(getNonBufferHash(layers),
449 mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime));
450 mFlattener->renderCachedSets(mOutputState, std::nullopt, true);
451
452 EXPECT_EQ(nullptr, overrideBuffer1);
453 EXPECT_NE(nullptr, overrideBuffer2);
454 EXPECT_EQ(overrideBuffer2, overrideBuffer3);
455
456 initializeOverrideBuffer(layers);
457 EXPECT_NE(getNonBufferHash(layers),
458 mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime));
459 mFlattener->renderCachedSets(mOutputState, std::nullopt, true);
460
461 EXPECT_NE(nullptr, overrideBuffer1);
462 EXPECT_EQ(overrideBuffer1, overrideBuffer2);
463 EXPECT_EQ(overrideBuffer2, overrideBuffer3);
464 }
465
TEST_F(FlattenerTest,flattenLayers_BufferUpdateForMiddleLayer)466 TEST_F(FlattenerTest, flattenLayers_BufferUpdateForMiddleLayer) {
467 auto& layerState1 = mTestLayers[0]->layerState;
468 const auto& overrideBuffer1 = layerState1->getOutputLayer()->getState().overrideInfo.buffer;
469
470 auto& layerState2 = mTestLayers[1]->layerState;
471 const auto& overrideBuffer2 = layerState2->getOutputLayer()->getState().overrideInfo.buffer;
472
473 auto& layerState3 = mTestLayers[2]->layerState;
474 const auto& overrideBuffer3 = layerState3->getOutputLayer()->getState().overrideInfo.buffer;
475
476 auto& layerState4 = mTestLayers[3]->layerState;
477 const auto& overrideBuffer4 = layerState4->getOutputLayer()->getState().overrideInfo.buffer;
478
479 auto& layerState5 = mTestLayers[4]->layerState;
480 const auto& overrideBuffer5 = layerState5->getOutputLayer()->getState().overrideInfo.buffer;
481
482 const std::vector<const LayerState*> layers = {
483 layerState1.get(), layerState2.get(), layerState3.get(),
484 layerState4.get(), layerState5.get(),
485 };
486
487 initializeFlattener(layers);
488
489 // make all layers inactive
490 mTime += 200ms;
491 expectAllLayersFlattened(layers);
492
493 // Layer 3 posted a buffer update, layers would be decomposed, and a new drawFrame would be
494 // called for Layer1 and Layer2
495 layerState3->resetFramesSinceBufferUpdate();
496
497 EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _, _))
498 .WillOnce(Return(ByMove(ftl::yield<FenceResult>(Fence::NO_FENCE))));
499 initializeOverrideBuffer(layers);
500 EXPECT_EQ(getNonBufferHash(layers),
501 mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime));
502 mFlattener->renderCachedSets(mOutputState, std::nullopt, true);
503
504 EXPECT_EQ(nullptr, overrideBuffer1);
505 EXPECT_EQ(nullptr, overrideBuffer2);
506 EXPECT_EQ(nullptr, overrideBuffer3);
507 EXPECT_EQ(nullptr, overrideBuffer4);
508 EXPECT_EQ(nullptr, overrideBuffer5);
509
510 // Layers 1 and 2 will be flattened a new drawFrame would be called for Layer4 and Layer5
511 EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _, _))
512 .WillOnce(Return(ByMove(ftl::yield<FenceResult>(Fence::NO_FENCE))));
513 initializeOverrideBuffer(layers);
514 EXPECT_NE(getNonBufferHash(layers),
515 mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime));
516 mOutputState.framebufferSpace.setOrientation(ui::ROTATION_90);
517 mFlattener->renderCachedSets(mOutputState, std::nullopt, true);
518
519 EXPECT_NE(nullptr, overrideBuffer1);
520 EXPECT_EQ(overrideBuffer1, overrideBuffer2);
521 EXPECT_EQ(nullptr, overrideBuffer3);
522 EXPECT_EQ(nullptr, overrideBuffer4);
523 EXPECT_EQ(nullptr, overrideBuffer5);
524
525 // Layers 4 and 5 will be flattened
526 initializeOverrideBuffer(layers);
527 EXPECT_NE(getNonBufferHash(layers),
528 mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime));
529 mOutputState.framebufferSpace.setOrientation(ui::ROTATION_180);
530 mFlattener->renderCachedSets(mOutputState, std::nullopt, true);
531
532 EXPECT_NE(nullptr, overrideBuffer1);
533 EXPECT_EQ(overrideBuffer1, overrideBuffer2);
534 EXPECT_EQ(nullptr, overrideBuffer3);
535 EXPECT_NE(nullptr, overrideBuffer4);
536 EXPECT_EQ(overrideBuffer4, overrideBuffer5);
537
538 layerState3->incrementFramesSinceBufferUpdate();
539 mTime += 200ms;
540 EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _, _))
541 .WillOnce(Return(ByMove(ftl::yield<FenceResult>(Fence::NO_FENCE))));
542 initializeOverrideBuffer(layers);
543 EXPECT_NE(getNonBufferHash(layers),
544 mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime));
545 mFlattener->renderCachedSets(mOutputState, std::nullopt, true);
546
547 EXPECT_NE(nullptr, overrideBuffer1);
548 EXPECT_EQ(overrideBuffer1, overrideBuffer2);
549 EXPECT_EQ(nullptr, overrideBuffer3);
550 EXPECT_NE(nullptr, overrideBuffer4);
551 EXPECT_EQ(overrideBuffer4, overrideBuffer5);
552
553 initializeOverrideBuffer(layers);
554 EXPECT_NE(getNonBufferHash(layers),
555 mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime));
556 mOutputState.framebufferSpace.setOrientation(ui::ROTATION_270);
557 mFlattener->renderCachedSets(mOutputState, std::nullopt, true);
558
559 EXPECT_NE(nullptr, overrideBuffer1);
560 EXPECT_EQ(overrideBuffer1, overrideBuffer2);
561 EXPECT_EQ(overrideBuffer2, overrideBuffer3);
562 EXPECT_EQ(overrideBuffer3, overrideBuffer4);
563 EXPECT_EQ(overrideBuffer4, overrideBuffer5);
564 }
565
566 // Tests for a PIP
TEST_F(FlattenerTest,flattenLayers_pipRequiresRoundedCorners)567 TEST_F(FlattenerTest, flattenLayers_pipRequiresRoundedCorners) {
568 auto& layerState1 = mTestLayers[0]->layerState;
569 const auto& overrideBuffer1 = layerState1->getOutputLayer()->getState().overrideInfo.buffer;
570
571 auto& layerState2 = mTestLayers[1]->layerState;
572 const auto& overrideBuffer2 = layerState2->getOutputLayer()->getState().overrideInfo.buffer;
573
574 auto& layerState3 = mTestLayers[2]->layerState;
575 const auto& overrideBuffer3 = layerState3->getOutputLayer()->getState().overrideInfo.buffer;
576
577 const std::vector<const LayerState*> layers = {
578 layerState1.get(),
579 layerState2.get(),
580 layerState3.get(),
581 };
582
583 initializeFlattener(layers);
584
585 // 3 has a buffer update, so it will not be merged, but it has no round
586 // corners, so it is not a PIP.
587 mTime += 200ms;
588 layerState3->resetFramesSinceBufferUpdate();
589
590 initializeOverrideBuffer(layers);
591 EXPECT_EQ(getNonBufferHash(layers),
592 mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime));
593
594 // This will render a CachedSet.
595 EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _, _))
596 .WillOnce(Return(ByMove(ftl::yield<FenceResult>(Fence::NO_FENCE))));
597 mFlattener->renderCachedSets(mOutputState, std::nullopt, true);
598
599 // We've rendered a CachedSet, but we haven't merged it in.
600 EXPECT_EQ(nullptr, overrideBuffer1);
601 EXPECT_EQ(nullptr, overrideBuffer2);
602 EXPECT_EQ(nullptr, overrideBuffer3);
603
604 // This time we merge the CachedSet in, so we have a new hash, and we should
605 // only have two sets.
606 EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _, _)).Times(0);
607 initializeOverrideBuffer(layers);
608 EXPECT_NE(getNonBufferHash(layers),
609 mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime));
610 mFlattener->renderCachedSets(mOutputState, std::nullopt, true);
611
612 EXPECT_NE(nullptr, overrideBuffer1);
613 EXPECT_EQ(overrideBuffer1, overrideBuffer2);
614 EXPECT_EQ(nullptr, overrideBuffer3);
615 }
616
TEST_F(FlattenerTest,flattenLayers_pip)617 TEST_F(FlattenerTest, flattenLayers_pip) {
618 mTestLayers[0]->outputLayerCompositionState.displayFrame = Rect(0, 0, 5, 5);
619 auto& layerState1 = mTestLayers[0]->layerState;
620 const auto& overrideBuffer1 = layerState1->getOutputLayer()->getState().overrideInfo.buffer;
621
622 auto& layerState2 = mTestLayers[1]->layerState;
623 const auto& overrideBuffer2 = layerState2->getOutputLayer()->getState().overrideInfo.buffer;
624
625 auto& layerState3 = mTestLayers[2]->layerState;
626 const auto& overrideBuffer3 = layerState3->getOutputLayer()->getState().overrideInfo.buffer;
627 mTestLayers[2]->layerFECompositionState.blendMode = hal::BlendMode::NONE;
628
629 EXPECT_CALL(*mTestLayers[2]->layerFE, hasRoundedCorners()).WillRepeatedly(Return(true));
630
631 std::optional<LayerFE::LayerSettings> clientComposition;
632 clientComposition.emplace();
633 clientComposition->source.buffer.buffer = std::make_shared<
634 renderengine::impl::ExternalTexture>(mTestLayers[2]->layerFECompositionState.buffer,
635 mRenderEngine,
636 renderengine::impl::ExternalTexture::Usage::
637 READABLE);
638 EXPECT_CALL(*mTestLayers[2]->layerFE, prepareClientComposition(_))
639 .WillOnce(Return(clientComposition));
640
641 const std::vector<const LayerState*> layers = {
642 layerState1.get(),
643 layerState2.get(),
644 layerState3.get(),
645 };
646
647 initializeFlattener(layers);
648
649 // 3 has a buffer update, so it will not be merged, and it has round
650 // corners, so it is a PIP.
651 mTime += 200ms;
652 layerState3->resetFramesSinceBufferUpdate();
653
654 initializeOverrideBuffer(layers);
655 EXPECT_EQ(getNonBufferHash(layers),
656 mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime));
657
658 // This will render a CachedSet.
659 EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _, _))
660 .WillOnce(Return(ByMove(ftl::yield<FenceResult>(Fence::NO_FENCE))));
661 mFlattener->renderCachedSets(mOutputState, std::nullopt, true);
662
663 // We've rendered a CachedSet, but we haven't merged it in.
664 EXPECT_EQ(nullptr, overrideBuffer1);
665 EXPECT_EQ(nullptr, overrideBuffer2);
666 EXPECT_EQ(nullptr, overrideBuffer3);
667
668 // This time we merge the CachedSet in, so we have a new hash, and we should
669 // only have two sets.
670 EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _, _)).Times(0);
671 initializeOverrideBuffer(layers);
672 EXPECT_NE(getNonBufferHash(layers),
673 mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime));
674 mFlattener->renderCachedSets(mOutputState, std::nullopt, true);
675
676 EXPECT_NE(nullptr, overrideBuffer1);
677 EXPECT_EQ(overrideBuffer1, overrideBuffer2);
678 EXPECT_EQ(nullptr, overrideBuffer3);
679
680 const auto* peekThroughLayer1 =
681 layerState1->getOutputLayer()->getState().overrideInfo.peekThroughLayer;
682 const auto* peekThroughLayer2 =
683 layerState2->getOutputLayer()->getState().overrideInfo.peekThroughLayer;
684 EXPECT_EQ(&mTestLayers[2]->outputLayer, peekThroughLayer1);
685 EXPECT_EQ(peekThroughLayer1, peekThroughLayer2);
686 }
687
688 // A test that verifies the hole puch optimization can be done on a single layer.
TEST_F(FlattenerTest,flattenLayers_holePunchSingleLayer)689 TEST_F(FlattenerTest, flattenLayers_holePunchSingleLayer) {
690 mTestLayers[0]->outputLayerCompositionState.displayFrame = Rect(0, 0, 5, 5);
691
692 // An opaque static background
693 auto& layerState0 = mTestLayers[0]->layerState;
694 const auto& overrideBuffer0 = layerState0->getOutputLayer()->getState().overrideInfo.buffer;
695
696 // a rounded updating layer
697 auto& layerState1 = mTestLayers[1]->layerState;
698 const auto& overrideBuffer1 = layerState1->getOutputLayer()->getState().overrideInfo.buffer;
699 mTestLayers[1]->layerFECompositionState.blendMode = hal::BlendMode::NONE;
700
701 EXPECT_CALL(*mTestLayers[1]->layerFE, hasRoundedCorners()).WillRepeatedly(Return(true));
702
703 std::optional<LayerFE::LayerSettings> clientComposition;
704 clientComposition.emplace();
705 clientComposition->source.buffer.buffer = std::make_shared<
706 renderengine::impl::ExternalTexture>(mTestLayers[1]->layerFECompositionState.buffer,
707 mRenderEngine,
708 renderengine::impl::ExternalTexture::Usage::
709 READABLE);
710 EXPECT_CALL(*mTestLayers[1]->layerFE, prepareClientComposition(_))
711 .WillOnce(Return(clientComposition));
712
713 const std::vector<const LayerState*> layers = {
714 layerState0.get(),
715 layerState1.get(),
716 };
717
718 initializeFlattener(layers);
719
720 // layer 1 satisfies every condition in CachedSet::requiresHolePunch()
721 mTime += 200ms;
722 layerState1->resetFramesSinceBufferUpdate(); // it is updating
723
724 initializeOverrideBuffer(layers);
725 // Expect no cache invalidation the first time (there's no cache yet)
726 EXPECT_EQ(getNonBufferHash(layers),
727 mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime));
728
729 // This will render a CachedSet of layer 0. Though it is just one layer, it satisfies the
730 // exception that there would be a hole punch above it.
731 EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _, _))
732 .WillOnce(Return(ByMove(ftl::yield<FenceResult>(Fence::NO_FENCE))));
733 mFlattener->renderCachedSets(mOutputState, std::nullopt, true);
734
735 // We've rendered a CachedSet, but we haven't merged it in.
736 EXPECT_EQ(nullptr, overrideBuffer0);
737
738 // This time we merge the CachedSet in and we should still have only two sets.
739 EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _, _)).Times(0);
740 initializeOverrideBuffer(layers);
741 EXPECT_EQ(getNonBufferHash(layers),
742 mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime));
743 mFlattener->renderCachedSets(mOutputState, std::nullopt, true);
744
745 EXPECT_NE(nullptr, overrideBuffer0); // got overridden
746 EXPECT_EQ(nullptr, overrideBuffer1); // did not
747
748 // expect 0's peek though layer to be 1's output layer
749 const auto* peekThroughLayer0 =
750 layerState0->getOutputLayer()->getState().overrideInfo.peekThroughLayer;
751 const auto* peekThroughLayer1 =
752 layerState1->getOutputLayer()->getState().overrideInfo.peekThroughLayer;
753 EXPECT_EQ(&mTestLayers[1]->outputLayer, peekThroughLayer0);
754 EXPECT_EQ(nullptr, peekThroughLayer1);
755 }
756
TEST_F(FlattenerTest,flattenLayers_holePunchSingleColorLayer)757 TEST_F(FlattenerTest, flattenLayers_holePunchSingleColorLayer) {
758 mTestLayers[0]->outputLayerCompositionState.displayFrame = Rect(0, 0, 5, 5);
759 mTestLayers[0]->layerFECompositionState.color = half4(255.f, 0.f, 0.f, 255.f);
760 mTestLayers[0]->layerFECompositionState.buffer = nullptr;
761
762 // An opaque static background
763 auto& layerState0 = mTestLayers[0]->layerState;
764 const auto& overrideBuffer0 = layerState0->getOutputLayer()->getState().overrideInfo.buffer;
765
766 // a rounded updating layer
767 auto& layerState1 = mTestLayers[1]->layerState;
768 const auto& overrideBuffer1 = layerState1->getOutputLayer()->getState().overrideInfo.buffer;
769 mTestLayers[1]->layerFECompositionState.blendMode = hal::BlendMode::NONE;
770
771 EXPECT_CALL(*mTestLayers[1]->layerFE, hasRoundedCorners()).WillRepeatedly(Return(true));
772
773 std::optional<LayerFE::LayerSettings> clientComposition;
774 clientComposition.emplace();
775 clientComposition->source.buffer.buffer = std::make_shared<
776 renderengine::impl::ExternalTexture>(mTestLayers[1]->layerFECompositionState.buffer,
777 mRenderEngine,
778 renderengine::impl::ExternalTexture::Usage::
779 READABLE);
780 EXPECT_CALL(*mTestLayers[1]->layerFE, prepareClientComposition(_))
781 .WillOnce(Return(clientComposition));
782
783 const std::vector<const LayerState*> layers = {
784 layerState0.get(),
785 layerState1.get(),
786 };
787
788 initializeFlattener(layers);
789
790 // layer 1 satisfies every condition in CachedSet::requiresHolePunch()
791 mTime += 200ms;
792 layerState1->resetFramesSinceBufferUpdate(); // it is updating
793
794 initializeOverrideBuffer(layers);
795 // Expect no cache invalidation the first time (there's no cache yet)
796 EXPECT_EQ(getNonBufferHash(layers),
797 mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime));
798
799 // This will render a CachedSet of layer 0. Though it is just one layer, it satisfies the
800 // exception that there would be a hole punch above it.
801 EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _, _))
802 .WillOnce(Return(ByMove(ftl::yield<FenceResult>(Fence::NO_FENCE))));
803 mFlattener->renderCachedSets(mOutputState, std::nullopt, true);
804
805 // We've rendered a CachedSet, but we haven't merged it in.
806 EXPECT_EQ(nullptr, overrideBuffer0);
807
808 // This time we merge the CachedSet in and we should still have only two sets.
809 EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _, _)).Times(0);
810 initializeOverrideBuffer(layers);
811 EXPECT_EQ(getNonBufferHash(layers),
812 mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime));
813 mFlattener->renderCachedSets(mOutputState, std::nullopt, true);
814
815 EXPECT_NE(nullptr, overrideBuffer0); // got overridden
816 EXPECT_EQ(nullptr, overrideBuffer1); // did not
817
818 // expect 0's peek though layer to be 1's output layer
819 const auto* peekThroughLayer0 =
820 layerState0->getOutputLayer()->getState().overrideInfo.peekThroughLayer;
821 const auto* peekThroughLayer1 =
822 layerState1->getOutputLayer()->getState().overrideInfo.peekThroughLayer;
823 EXPECT_EQ(&mTestLayers[1]->outputLayer, peekThroughLayer0);
824 EXPECT_EQ(nullptr, peekThroughLayer1);
825 }
826
TEST_F(FlattenerTest,flattenLayers_flattensBlurBehindRunIfFirstRun)827 TEST_F(FlattenerTest, flattenLayers_flattensBlurBehindRunIfFirstRun) {
828 auto& layerState1 = mTestLayers[0]->layerState;
829
830 auto& layerState2 = mTestLayers[1]->layerState;
831 mTestLayers[1]->layerFECompositionState.backgroundBlurRadius = 1;
832 layerState2->update(&mTestLayers[1]->outputLayer);
833
834 auto& layerState3 = mTestLayers[2]->layerState;
835 const auto& overrideBuffer1 = layerState1->getOutputLayer()->getState().overrideInfo.buffer;
836 const auto& overrideBuffer2 = layerState2->getOutputLayer()->getState().overrideInfo.buffer;
837 const auto& overrideBuffer3 = layerState3->getOutputLayer()->getState().overrideInfo.buffer;
838
839 const std::vector<const LayerState*> layers = {
840 layerState1.get(),
841 layerState2.get(),
842 layerState3.get(),
843 };
844
845 initializeFlattener(layers);
846
847 // Mark the first two layers inactive, which contain the blur behind
848 mTime += 200ms;
849 layerState3->resetFramesSinceBufferUpdate();
850
851 // layers would be flattened but the buffer would not be overridden
852 EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _, _))
853 .WillOnce(Return(ByMove(ftl::yield<FenceResult>(Fence::NO_FENCE))));
854
855 initializeOverrideBuffer(layers);
856 EXPECT_EQ(getNonBufferHash(layers),
857 mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime));
858 mFlattener->renderCachedSets(mOutputState, std::nullopt, true);
859
860 for (const auto layer : layers) {
861 EXPECT_EQ(nullptr, layer->getOutputLayer()->getState().overrideInfo.buffer);
862 }
863
864 // the new flattened layer is replaced
865 initializeOverrideBuffer(layers);
866 EXPECT_NE(getNonBufferHash(layers),
867 mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime));
868 mFlattener->renderCachedSets(mOutputState, std::nullopt, true);
869 EXPECT_NE(nullptr, overrideBuffer1);
870 EXPECT_EQ(overrideBuffer1, overrideBuffer2);
871 EXPECT_EQ(nullptr, overrideBuffer3);
872 }
873
TEST_F(FlattenerTest,flattenLayers_doesNotFlattenBlurBehindRun)874 TEST_F(FlattenerTest, flattenLayers_doesNotFlattenBlurBehindRun) {
875 auto& layerState1 = mTestLayers[0]->layerState;
876
877 auto& layerState2 = mTestLayers[1]->layerState;
878 mTestLayers[1]->layerFECompositionState.backgroundBlurRadius = 1;
879 layerState2->update(&mTestLayers[1]->outputLayer);
880
881 auto& layerState3 = mTestLayers[2]->layerState;
882
883 const std::vector<const LayerState*> layers = {
884 layerState1.get(),
885 layerState2.get(),
886 layerState3.get(),
887 };
888
889 initializeFlattener(layers);
890
891 // Mark the last two layers inactive, which contains the blur layer, but does not contain the
892 // first layer
893 mTime += 200ms;
894 layerState1->resetFramesSinceBufferUpdate();
895
896 // layers would be flattened but the buffer would not be overridden
897 EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _, _))
898 .WillRepeatedly(Return(ByMove(ftl::yield<FenceResult>(Fence::NO_FENCE))));
899
900 initializeOverrideBuffer(layers);
901 EXPECT_EQ(getNonBufferHash(layers),
902 mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime));
903 mFlattener->renderCachedSets(mOutputState, std::nullopt, true);
904
905 for (const auto layer : layers) {
906 EXPECT_EQ(nullptr, layer->getOutputLayer()->getState().overrideInfo.buffer);
907 }
908
909 // nothing is flattened because the last two frames cannot be cached due to containing a blur
910 // layer
911 initializeOverrideBuffer(layers);
912 EXPECT_EQ(getNonBufferHash(layers),
913 mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime));
914 mFlattener->renderCachedSets(mOutputState, std::nullopt, true);
915 for (const auto layer : layers) {
916 EXPECT_EQ(nullptr, layer->getOutputLayer()->getState().overrideInfo.buffer);
917 }
918 }
919
TEST_F(FlattenerTest,flattenLayers_flattenSkipsLayerWithBlurBehind)920 TEST_F(FlattenerTest, flattenLayers_flattenSkipsLayerWithBlurBehind) {
921 auto& layerState1 = mTestLayers[0]->layerState;
922
923 auto& layerStateWithBlurBehind = mTestLayers[1]->layerState;
924 mTestLayers[1]->layerFECompositionState.backgroundBlurRadius = 1;
925 layerStateWithBlurBehind->update(&mTestLayers[1]->outputLayer);
926
927 auto& layerState3 = mTestLayers[2]->layerState;
928 auto& layerState4 = mTestLayers[3]->layerState;
929 const auto& overrideBuffer1 = layerState1->getOutputLayer()->getState().overrideInfo.buffer;
930 const auto& blurOverrideBuffer =
931 layerStateWithBlurBehind->getOutputLayer()->getState().overrideInfo.buffer;
932 const auto& overrideBuffer3 = layerState3->getOutputLayer()->getState().overrideInfo.buffer;
933 const auto& overrideBuffer4 = layerState4->getOutputLayer()->getState().overrideInfo.buffer;
934
935 const std::vector<const LayerState*> layers = {
936 layerState1.get(),
937 layerStateWithBlurBehind.get(),
938 layerState3.get(),
939 layerState4.get(),
940 };
941
942 initializeFlattener(layers);
943
944 // Mark the last three layers inactive, which contains the blur layer, but does not contain the
945 // first layer
946 mTime += 200ms;
947 layerState1->resetFramesSinceBufferUpdate();
948
949 // layers would be flattened but the buffer would not be overridden
950 EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _, _))
951 .WillOnce(Return(ByMove(ftl::yield<FenceResult>(Fence::NO_FENCE))));
952
953 initializeOverrideBuffer(layers);
954 EXPECT_EQ(getNonBufferHash(layers),
955 mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime));
956 mFlattener->renderCachedSets(mOutputState, std::nullopt, true);
957
958 for (const auto layer : layers) {
959 EXPECT_EQ(nullptr, layer->getOutputLayer()->getState().overrideInfo.buffer);
960 }
961
962 // the new flattened layer is replaced
963 initializeOverrideBuffer(layers);
964 EXPECT_NE(getNonBufferHash(layers),
965 mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime));
966 mFlattener->renderCachedSets(mOutputState, std::nullopt, true);
967 EXPECT_EQ(nullptr, overrideBuffer1);
968 EXPECT_EQ(nullptr, blurOverrideBuffer);
969 EXPECT_NE(nullptr, overrideBuffer3);
970 EXPECT_EQ(overrideBuffer3, overrideBuffer4);
971 }
972
TEST_F(FlattenerTest,flattenLayers_whenBlurLayerIsChanging_appliesBlurToInactiveBehindLayers)973 TEST_F(FlattenerTest, flattenLayers_whenBlurLayerIsChanging_appliesBlurToInactiveBehindLayers) {
974 auto& layerState1 = mTestLayers[0]->layerState;
975 auto& layerState2 = mTestLayers[1]->layerState;
976
977 auto& layerStateWithBlurBehind = mTestLayers[2]->layerState;
978 mTestLayers[2]->layerFECompositionState.backgroundBlurRadius = 1;
979 layerStateWithBlurBehind->update(&mTestLayers[2]->outputLayer);
980 const auto& overrideBuffer1 = layerState1->getOutputLayer()->getState().overrideInfo.buffer;
981 const auto& overrideBuffer2 = layerState2->getOutputLayer()->getState().overrideInfo.buffer;
982 const auto& blurOverrideBuffer =
983 layerStateWithBlurBehind->getOutputLayer()->getState().overrideInfo.buffer;
984
985 const std::vector<const LayerState*> layers = {
986 layerState1.get(),
987 layerState2.get(),
988 layerStateWithBlurBehind.get(),
989 };
990
991 initializeFlattener(layers);
992
993 // Mark the first two layers inactive, but update the blur layer
994 mTime += 200ms;
995 layerStateWithBlurBehind->resetFramesSinceBufferUpdate();
996
997 // layers would be flattened but the buffer would not be overridden
998 EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _, _))
999 .WillOnce(Return(ByMove(ftl::yield<FenceResult>(Fence::NO_FENCE))));
1000
1001 initializeOverrideBuffer(layers);
1002 EXPECT_EQ(getNonBufferHash(layers),
1003 mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime));
1004 mFlattener->renderCachedSets(mOutputState, std::nullopt, true);
1005
1006 const auto& cachedSet = mFlattener->getNewCachedSetForTesting();
1007 ASSERT_NE(std::nullopt, cachedSet);
1008 EXPECT_EQ(&mTestLayers[2]->outputLayer, cachedSet->getBlurLayer());
1009
1010 for (const auto layer : layers) {
1011 EXPECT_EQ(nullptr, layer->getOutputLayer()->getState().overrideInfo.buffer);
1012 }
1013
1014 // the new flattened layer is replaced
1015 initializeOverrideBuffer(layers);
1016 EXPECT_NE(getNonBufferHash(layers),
1017 mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime));
1018 mFlattener->renderCachedSets(mOutputState, std::nullopt, true);
1019 EXPECT_NE(nullptr, overrideBuffer1);
1020 EXPECT_EQ(overrideBuffer2, overrideBuffer1);
1021 EXPECT_EQ(nullptr, blurOverrideBuffer);
1022 }
1023
TEST_F(FlattenerTest,flattenLayers_renderCachedSets_doesNotRenderTwice)1024 TEST_F(FlattenerTest, flattenLayers_renderCachedSets_doesNotRenderTwice) {
1025 auto& layerState1 = mTestLayers[0]->layerState;
1026 auto& layerState2 = mTestLayers[1]->layerState;
1027 const auto& overrideBuffer1 = layerState1->getOutputLayer()->getState().overrideInfo.buffer;
1028 const auto& overrideBuffer2 = layerState2->getOutputLayer()->getState().overrideInfo.buffer;
1029
1030 const std::vector<const LayerState*> layers = {
1031 layerState1.get(),
1032 layerState2.get(),
1033 };
1034
1035 initializeFlattener(layers);
1036
1037 // Mark the layers inactive
1038 mTime += 200ms;
1039 // layers would be flattened but the buffer would not be overridden
1040 EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _, _))
1041 .WillOnce(Return(ByMove(ftl::yield<FenceResult>(Fence::NO_FENCE))));
1042
1043 initializeOverrideBuffer(layers);
1044 EXPECT_EQ(getNonBufferHash(layers),
1045 mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime));
1046 mFlattener->renderCachedSets(mOutputState, std::nullopt, true);
1047
1048 EXPECT_EQ(nullptr, overrideBuffer1);
1049 EXPECT_EQ(nullptr, overrideBuffer2);
1050
1051 // Simulate attempting to render prior to merging the new cached set with the layer stack.
1052 // Here we should not try to re-render.
1053 EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _, _)).Times(0);
1054 mFlattener->renderCachedSets(mOutputState, std::nullopt, true);
1055
1056 // We provide the override buffer now that it's rendered
1057 EXPECT_NE(getNonBufferHash(layers),
1058 mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime));
1059 mFlattener->renderCachedSets(mOutputState, std::nullopt, true);
1060
1061 EXPECT_NE(nullptr, overrideBuffer1);
1062 EXPECT_EQ(overrideBuffer2, overrideBuffer1);
1063 }
1064
1065 const constexpr std::chrono::nanoseconds kCachedSetRenderDuration = 0ms;
1066 const constexpr size_t kMaxDeferRenderAttempts = 2;
1067
1068 class FlattenerRenderSchedulingTest : public FlattenerTest {
1069 public:
FlattenerRenderSchedulingTest()1070 FlattenerRenderSchedulingTest()
1071 : FlattenerTest(
1072 Flattener::Tunables{.mActiveLayerTimeout = 100ms,
1073 .mRenderScheduling = Flattener::Tunables::
1074 RenderScheduling{.cachedSetRenderDuration =
1075 kCachedSetRenderDuration,
1076 .maxDeferRenderAttempts =
1077 kMaxDeferRenderAttempts},
1078 .mEnableHolePunch = true}) {}
1079 };
1080
TEST_F(FlattenerRenderSchedulingTest,flattenLayers_renderCachedSets_defersUpToMaxAttempts)1081 TEST_F(FlattenerRenderSchedulingTest, flattenLayers_renderCachedSets_defersUpToMaxAttempts) {
1082 auto& layerState1 = mTestLayers[0]->layerState;
1083 auto& layerState2 = mTestLayers[1]->layerState;
1084
1085 const std::vector<const LayerState*> layers = {
1086 layerState1.get(),
1087 layerState2.get(),
1088 };
1089
1090 initializeFlattener(layers);
1091
1092 // Mark the layers inactive
1093 mTime += 200ms;
1094
1095 initializeOverrideBuffer(layers);
1096 EXPECT_EQ(getNonBufferHash(layers),
1097 mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime));
1098
1099 for (size_t i = 0; i < kMaxDeferRenderAttempts; i++) {
1100 EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _, _)).Times(0);
1101 mFlattener->renderCachedSets(mOutputState,
1102 std::chrono::steady_clock::now() -
1103 (kCachedSetRenderDuration + 10ms),
1104 true);
1105 }
1106
1107 EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _, _))
1108 .WillOnce(Return(ByMove(ftl::yield<FenceResult>(Fence::NO_FENCE))));
1109 mFlattener->renderCachedSets(mOutputState,
1110 std::chrono::steady_clock::now() -
1111 (kCachedSetRenderDuration + 10ms),
1112 true);
1113 }
1114
TEST_F(FlattenerTest,flattenLayers_skipsLayersDisabledFromCaching)1115 TEST_F(FlattenerTest, flattenLayers_skipsLayersDisabledFromCaching) {
1116 auto& layerState1 = mTestLayers[0]->layerState;
1117 const auto& overrideBuffer1 = layerState1->getOutputLayer()->getState().overrideInfo.buffer;
1118
1119 auto& layerState2 = mTestLayers[1]->layerState;
1120 const auto& overrideBuffer2 = layerState2->getOutputLayer()->getState().overrideInfo.buffer;
1121
1122 // The third layer has a CachingHint that prevents caching from running
1123 auto& layerState3 = mTestLayers[2]->layerState;
1124 const auto& overrideBuffer3 = layerState3->getOutputLayer()->getState().overrideInfo.buffer;
1125 mTestLayers[2]->layerFECompositionState.cachingHint = gui::CachingHint::Disabled;
1126 mTestLayers[2]->layerState->update(&mTestLayers[2]->outputLayer);
1127
1128 const std::vector<const LayerState*> layers = {
1129 layerState1.get(),
1130 layerState2.get(),
1131 layerState3.get(),
1132 };
1133
1134 initializeFlattener(layers);
1135
1136 mTime += 200ms;
1137 initializeOverrideBuffer(layers);
1138 EXPECT_EQ(getNonBufferHash(layers),
1139 mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime));
1140
1141 // This will render a CachedSet.
1142 EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _, _))
1143 .WillOnce(Return(ByMove(ftl::yield<FenceResult>(Fence::NO_FENCE))));
1144 mFlattener->renderCachedSets(mOutputState, std::nullopt, true);
1145
1146 // We've rendered a CachedSet, but we haven't merged it in.
1147 EXPECT_EQ(nullptr, overrideBuffer1);
1148 EXPECT_EQ(nullptr, overrideBuffer2);
1149 EXPECT_EQ(nullptr, overrideBuffer3);
1150
1151 // This time we merge the CachedSet in, so we have a new hash, and we should
1152 // only have two sets.
1153 EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _, _)).Times(0);
1154 initializeOverrideBuffer(layers);
1155 EXPECT_NE(getNonBufferHash(layers),
1156 mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime));
1157 mFlattener->renderCachedSets(mOutputState, std::nullopt, true);
1158
1159 EXPECT_NE(nullptr, overrideBuffer1);
1160 EXPECT_EQ(overrideBuffer1, overrideBuffer2);
1161 EXPECT_EQ(nullptr, overrideBuffer3);
1162 }
1163
TEST_F(FlattenerTest,flattenLayers_skipsBT601_625)1164 TEST_F(FlattenerTest, flattenLayers_skipsBT601_625) {
1165 auto& layerState1 = mTestLayers[0]->layerState;
1166 const auto& overrideBuffer1 = layerState1->getOutputLayer()->getState().overrideInfo.buffer;
1167
1168 auto& layerState2 = mTestLayers[1]->layerState;
1169 const auto& overrideBuffer2 = layerState2->getOutputLayer()->getState().overrideInfo.buffer;
1170
1171 // The third layer uses a dataspace that will not be flattened due to
1172 // possible mismatch with DPU rendering.
1173 auto& layerState3 = mTestLayers[2]->layerState;
1174 const auto& overrideBuffer3 = layerState3->getOutputLayer()->getState().overrideInfo.buffer;
1175 mTestLayers[2]->outputLayerCompositionState.dataspace = ui::Dataspace::STANDARD_BT601_625;
1176 mTestLayers[2]->layerState->update(&mTestLayers[2]->outputLayer);
1177
1178 const std::vector<const LayerState*> layers = {
1179 layerState1.get(),
1180 layerState2.get(),
1181 layerState3.get(),
1182 };
1183
1184 initializeFlattener(layers);
1185
1186 mTime += 200ms;
1187 initializeOverrideBuffer(layers);
1188 EXPECT_EQ(getNonBufferHash(layers),
1189 mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime));
1190
1191 // This will render a CachedSet.
1192 EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _, _))
1193 .WillOnce(Return(ByMove(ftl::yield<FenceResult>(Fence::NO_FENCE))));
1194 mFlattener->renderCachedSets(mOutputState, std::nullopt, true);
1195
1196 // We've rendered a CachedSet, but we haven't merged it in.
1197 EXPECT_EQ(nullptr, overrideBuffer1);
1198 EXPECT_EQ(nullptr, overrideBuffer2);
1199 EXPECT_EQ(nullptr, overrideBuffer3);
1200
1201 // This time we merge the CachedSet in, so we have a new hash, and we should
1202 // only have two sets.
1203 EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _, _)).Times(0);
1204 initializeOverrideBuffer(layers);
1205 EXPECT_NE(getNonBufferHash(layers),
1206 mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime));
1207 mFlattener->renderCachedSets(mOutputState, std::nullopt, true);
1208
1209 EXPECT_NE(nullptr, overrideBuffer1);
1210 EXPECT_EQ(overrideBuffer1, overrideBuffer2);
1211 EXPECT_EQ(nullptr, overrideBuffer3);
1212 }
1213
TEST_F(FlattenerTest,flattenLayers_skipsHDR)1214 TEST_F(FlattenerTest, flattenLayers_skipsHDR) {
1215 auto& layerState1 = mTestLayers[0]->layerState;
1216 const auto& overrideBuffer1 = layerState1->getOutputLayer()->getState().overrideInfo.buffer;
1217
1218 auto& layerState2 = mTestLayers[1]->layerState;
1219 const auto& overrideBuffer2 = layerState2->getOutputLayer()->getState().overrideInfo.buffer;
1220
1221 // The third layer uses a dataspace that will not be flattened due to
1222 // possible mismatch with DPU rendering.
1223 auto& layerState3 = mTestLayers[2]->layerState;
1224 const auto& overrideBuffer3 = layerState3->getOutputLayer()->getState().overrideInfo.buffer;
1225 mTestLayers[2]->outputLayerCompositionState.dataspace = ui::Dataspace::BT2020_ITU_HLG;
1226 mTestLayers[2]->layerState->update(&mTestLayers[2]->outputLayer);
1227
1228 const std::vector<const LayerState*> layers = {
1229 layerState1.get(),
1230 layerState2.get(),
1231 layerState3.get(),
1232 };
1233
1234 initializeFlattener(layers);
1235
1236 mTime += 200ms;
1237 initializeOverrideBuffer(layers);
1238 EXPECT_EQ(getNonBufferHash(layers),
1239 mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime));
1240
1241 // This will render a CachedSet.
1242 EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _, _))
1243 .WillOnce(Return(ByMove(ftl::yield<FenceResult>(Fence::NO_FENCE))));
1244 mFlattener->renderCachedSets(mOutputState, std::nullopt, true);
1245
1246 // We've rendered a CachedSet, but we haven't merged it in.
1247 EXPECT_EQ(nullptr, overrideBuffer1);
1248 EXPECT_EQ(nullptr, overrideBuffer2);
1249 EXPECT_EQ(nullptr, overrideBuffer3);
1250
1251 // This time we merge the CachedSet in, so we have a new hash, and we should
1252 // only have two sets.
1253 EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _, _)).Times(0);
1254 initializeOverrideBuffer(layers);
1255 EXPECT_NE(getNonBufferHash(layers),
1256 mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime));
1257 mFlattener->renderCachedSets(mOutputState, std::nullopt, true);
1258
1259 EXPECT_NE(nullptr, overrideBuffer1);
1260 EXPECT_EQ(overrideBuffer1, overrideBuffer2);
1261 EXPECT_EQ(nullptr, overrideBuffer3);
1262 }
1263
TEST_F(FlattenerTest,flattenLayers_skipsHDR2)1264 TEST_F(FlattenerTest, flattenLayers_skipsHDR2) {
1265 auto& layerState1 = mTestLayers[0]->layerState;
1266 const auto& overrideBuffer1 = layerState1->getOutputLayer()->getState().overrideInfo.buffer;
1267
1268 auto& layerState2 = mTestLayers[1]->layerState;
1269 const auto& overrideBuffer2 = layerState2->getOutputLayer()->getState().overrideInfo.buffer;
1270
1271 // The third layer uses a dataspace that will not be flattened due to
1272 // possible mismatch with DPU rendering.
1273 auto& layerState3 = mTestLayers[2]->layerState;
1274 const auto& overrideBuffer3 = layerState3->getOutputLayer()->getState().overrideInfo.buffer;
1275 mTestLayers[2]->outputLayerCompositionState.dataspace = ui::Dataspace::BT2020_PQ;
1276 mTestLayers[2]->layerState->update(&mTestLayers[2]->outputLayer);
1277
1278 const std::vector<const LayerState*> layers = {
1279 layerState1.get(),
1280 layerState2.get(),
1281 layerState3.get(),
1282 };
1283
1284 initializeFlattener(layers);
1285
1286 mTime += 200ms;
1287 initializeOverrideBuffer(layers);
1288 EXPECT_EQ(getNonBufferHash(layers),
1289 mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime));
1290
1291 // This will render a CachedSet.
1292 EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _, _))
1293 .WillOnce(Return(ByMove(ftl::yield<FenceResult>(Fence::NO_FENCE))));
1294 mFlattener->renderCachedSets(mOutputState, std::nullopt, true);
1295
1296 // We've rendered a CachedSet, but we haven't merged it in.
1297 EXPECT_EQ(nullptr, overrideBuffer1);
1298 EXPECT_EQ(nullptr, overrideBuffer2);
1299 EXPECT_EQ(nullptr, overrideBuffer3);
1300
1301 // This time we merge the CachedSet in, so we have a new hash, and we should
1302 // only have two sets.
1303 EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _, _)).Times(0);
1304 initializeOverrideBuffer(layers);
1305 EXPECT_NE(getNonBufferHash(layers),
1306 mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime));
1307 mFlattener->renderCachedSets(mOutputState, std::nullopt, true);
1308
1309 EXPECT_NE(nullptr, overrideBuffer1);
1310 EXPECT_EQ(overrideBuffer1, overrideBuffer2);
1311 EXPECT_EQ(nullptr, overrideBuffer3);
1312 }
1313
TEST_F(FlattenerTest,flattenLayers_skipsColorLayers)1314 TEST_F(FlattenerTest, flattenLayers_skipsColorLayers) {
1315 auto& layerState1 = mTestLayers[0]->layerState;
1316 const auto& overrideBuffer1 = layerState1->getOutputLayer()->getState().overrideInfo.buffer;
1317 auto& layerState2 = mTestLayers[1]->layerState;
1318 const auto& overrideBuffer2 = layerState2->getOutputLayer()->getState().overrideInfo.buffer;
1319 auto& layerState3 = mTestLayers[2]->layerState;
1320 const auto& overrideBuffer3 = layerState3->getOutputLayer()->getState().overrideInfo.buffer;
1321 auto& layerState4 = mTestLayers[3]->layerState;
1322 const auto& overrideBuffer4 = layerState4->getOutputLayer()->getState().overrideInfo.buffer;
1323
1324 // Rewrite the first two layers to just be a solid color.
1325 mTestLayers[0]->layerFECompositionState.color = half4(255.f, 0.f, 0.f, 255.f);
1326 mTestLayers[0]->layerFECompositionState.buffer = nullptr;
1327 mTestLayers[1]->layerFECompositionState.color = half4(0.f, 255.f, 0.f, 255.f);
1328 mTestLayers[1]->layerFECompositionState.buffer = nullptr;
1329
1330 const std::vector<const LayerState*> layers = {
1331 layerState1.get(),
1332 layerState2.get(),
1333 layerState3.get(),
1334 layerState4.get(),
1335 };
1336
1337 initializeFlattener(layers);
1338
1339 mTime += 200ms;
1340 initializeOverrideBuffer(layers);
1341 EXPECT_EQ(getNonBufferHash(layers),
1342 mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime));
1343
1344 // This will render a CachedSet.
1345 EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _, _))
1346 .WillOnce(Return(ByMove(ftl::yield<FenceResult>(Fence::NO_FENCE))));
1347 mFlattener->renderCachedSets(mOutputState, std::nullopt, true);
1348
1349 // We've rendered a CachedSet, but we haven't merged it in.
1350 EXPECT_EQ(nullptr, overrideBuffer1);
1351 EXPECT_EQ(nullptr, overrideBuffer2);
1352 EXPECT_EQ(nullptr, overrideBuffer3);
1353 EXPECT_EQ(nullptr, overrideBuffer4);
1354
1355 // This time we merge the CachedSet in, so we have a new hash, and we should
1356 // only have two sets.
1357 EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _, _)).Times(0);
1358 initializeOverrideBuffer(layers);
1359 EXPECT_NE(getNonBufferHash(layers),
1360 mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime));
1361 mFlattener->renderCachedSets(mOutputState, std::nullopt, true);
1362
1363 EXPECT_EQ(nullptr, overrideBuffer1);
1364 EXPECT_EQ(nullptr, overrideBuffer2);
1365 EXPECT_EQ(overrideBuffer3, overrideBuffer4);
1366 EXPECT_NE(nullptr, overrideBuffer4);
1367 }
1368
TEST_F(FlattenerTest,flattenLayers_includes_DISPLAY_DECORATION)1369 TEST_F(FlattenerTest, flattenLayers_includes_DISPLAY_DECORATION) {
1370 auto& layerState1 = mTestLayers[0]->layerState;
1371 const auto& overrideBuffer1 = layerState1->getOutputLayer()->getState().overrideInfo.buffer;
1372
1373 auto& layerState2 = mTestLayers[1]->layerState;
1374 const auto& overrideBuffer2 = layerState2->getOutputLayer()->getState().overrideInfo.buffer;
1375
1376 // The third layer uses DISPLAY_DECORATION, which should be cached.
1377 auto& layerState3 = mTestLayers[2]->layerState;
1378 const auto& overrideBuffer3 = layerState3->getOutputLayer()->getState().overrideInfo.buffer;
1379 mTestLayers[2]->layerFECompositionState.compositionType =
1380 aidl::android::hardware::graphics::composer3::Composition::DISPLAY_DECORATION;
1381 mTestLayers[2]->layerState->update(&mTestLayers[2]->outputLayer);
1382
1383 const std::vector<const LayerState*> layers = {
1384 layerState1.get(),
1385 layerState2.get(),
1386 layerState3.get(),
1387 };
1388
1389 initializeFlattener(layers);
1390
1391 mTime += 200ms;
1392 initializeOverrideBuffer(layers);
1393 EXPECT_EQ(getNonBufferHash(layers),
1394 mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime));
1395
1396 // This will render a CachedSet.
1397 EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _, _))
1398 .WillOnce(Return(ByMove(ftl::yield<FenceResult>(Fence::NO_FENCE))));
1399 mFlattener->renderCachedSets(mOutputState, std::nullopt, true);
1400
1401 // We've rendered a CachedSet, but we haven't merged it in.
1402 EXPECT_EQ(nullptr, overrideBuffer1);
1403 EXPECT_EQ(nullptr, overrideBuffer2);
1404 EXPECT_EQ(nullptr, overrideBuffer3);
1405
1406 // This time we merge the CachedSet in, so we have a new hash, and we should
1407 // only have two sets.
1408 EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _, _)).Times(0);
1409 initializeOverrideBuffer(layers);
1410 EXPECT_NE(getNonBufferHash(layers),
1411 mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime));
1412 mFlattener->renderCachedSets(mOutputState, std::nullopt, true);
1413
1414 EXPECT_NE(nullptr, overrideBuffer1);
1415 EXPECT_EQ(overrideBuffer1, overrideBuffer2);
1416 EXPECT_EQ(overrideBuffer1, overrideBuffer3);
1417 }
1418
1419 } // namespace
1420 } // namespace android::compositionengine
1421