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