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/LayerState.h>
20 #include <compositionengine/mock/LayerFE.h>
21 #include <compositionengine/mock/OutputLayer.h>
22 #include <gmock/gmock-actions.h>
23 #include <gtest/gtest.h>
24 #include <renderengine/ExternalTexture.h>
25 #include <renderengine/mock/FakeExternalTexture.h>
26 #include <renderengine/mock/RenderEngine.h>
27 #include <ui/GraphicTypes.h>
28 #include <utils/Errors.h>
29 #include <memory>
30
31 namespace android::compositionengine {
32 using namespace std::chrono_literals;
33
34 using testing::_;
35 using testing::DoAll;
36 using testing::Invoke;
37 using testing::Return;
38 using testing::ReturnRef;
39 using testing::SetArgPointee;
40
41 using impl::planner::CachedSet;
42 using impl::planner::LayerState;
43 using impl::planner::LayerStateField;
44 using impl::planner::TexturePool;
45
46 namespace {
47
48 MATCHER_P(ClientCompositionTargetSettingsBlurSettingsEq, expectedBlurSetting, "") {
49 *result_listener << "ClientCompositionTargetSettings' BlurSettings aren't equal \n";
50 *result_listener << "expected " << expectedBlurSetting << "\n";
51 *result_listener << "actual " << arg.blurSetting << "\n";
52
53 return expectedBlurSetting == arg.blurSetting;
54 }
55
56 MATCHER_P(ClientCompositionTargetSettingsSecureEq, expectedSecureSetting, "") {
57 *result_listener << "ClientCompositionTargetSettings' isSecure bits aren't equal \n";
58 *result_listener << "expected " << expectedSecureSetting << "\n";
59 *result_listener << "actual " << arg.isSecure << "\n";
60
61 return expectedSecureSetting == arg.isSecure;
62 }
63
64 MATCHER_P(ClientCompositionTargetSettingsWhitePointEq, expectedWhitePoint, "") {
65 *result_listener << "ClientCompositionTargetSettings' white points aren't equal \n";
66 *result_listener << "expected " << expectedWhitePoint << "\n";
67 *result_listener << "actual " << arg.whitePointNits << "\n";
68
69 return expectedWhitePoint == arg.whitePointNits;
70 }
71
72 static const ui::Size kOutputSize = ui::Size(1, 1);
73
74 class CachedSetTest : public testing::Test {
75 public:
76 CachedSetTest() = default;
77 void SetUp() override;
78 void TearDown() override;
79
80 protected:
81 const std::chrono::steady_clock::time_point kStartTime = std::chrono::steady_clock::now();
82
83 struct TestLayer {
84 mock::OutputLayer outputLayer;
85 impl::OutputLayerCompositionState outputLayerCompositionState;
86 // LayerFE inherits from RefBase and must be held by an sp<>
87 sp<mock::LayerFE> layerFE;
88 LayerFECompositionState layerFECompositionState;
89
90 std::unique_ptr<LayerState> layerState;
91 std::unique_ptr<CachedSet::Layer> cachedSetLayer;
92 };
93
94 static constexpr size_t kNumLayers = 5;
95 std::vector<std::unique_ptr<TestLayer>> mTestLayers;
96 impl::OutputCompositionState mOutputState;
97
98 android::renderengine::mock::RenderEngine mRenderEngine;
99 TexturePool mTexturePool = TexturePool(mRenderEngine);
100 };
101
SetUp()102 void CachedSetTest::SetUp() {
103 mTexturePool.setDisplaySize(kOutputSize);
104 for (size_t i = 0; i < kNumLayers; i++) {
105 auto testLayer = std::make_unique<TestLayer>();
106 auto pos = static_cast<int32_t>(i);
107 testLayer->outputLayerCompositionState.displayFrame = Rect(pos, pos, pos + 1, pos + 1);
108 testLayer->outputLayerCompositionState.visibleRegion =
109 Region(Rect(pos + 1, pos + 1, pos + 2, pos + 2));
110
111 testLayer->layerFE = sp<mock::LayerFE>::make();
112
113 EXPECT_CALL(*testLayer->layerFE, getSequence)
114 .WillRepeatedly(Return(static_cast<int32_t>(i)));
115 EXPECT_CALL(*testLayer->layerFE, getDebugName).WillRepeatedly(Return("testLayer"));
116 EXPECT_CALL(*testLayer->layerFE, getCompositionState)
117 .WillRepeatedly(Return(&testLayer->layerFECompositionState));
118 EXPECT_CALL(testLayer->outputLayer, getLayerFE)
119 .WillRepeatedly(ReturnRef(*testLayer->layerFE));
120 EXPECT_CALL(testLayer->outputLayer, getState)
121 .WillRepeatedly(ReturnRef(testLayer->outputLayerCompositionState));
122
123 testLayer->layerState = std::make_unique<LayerState>(&testLayer->outputLayer);
124 testLayer->layerState->incrementFramesSinceBufferUpdate();
125 testLayer->cachedSetLayer =
126 std::make_unique<CachedSet::Layer>(testLayer->layerState.get(), kStartTime);
127
128 mTestLayers.emplace_back(std::move(testLayer));
129
130 // set up minimium params needed for rendering
131 mOutputState.dataspace = ui::Dataspace::SRGB;
132 mOutputState.framebufferSpace = ProjectionSpace(ui::Size(10, 20), Rect(10, 5));
133 mOutputState.framebufferSpace.setOrientation(ui::ROTATION_90);
134 mOutputState.layerStackSpace = ProjectionSpace(ui::Size(20, 10), Rect(5, 10));
135 }
136 }
137
TearDown()138 void CachedSetTest::TearDown() {
139 mTestLayers.clear();
140 }
141
expectEqual(const CachedSet & cachedSet,const CachedSet::Layer & layer)142 void expectEqual(const CachedSet& cachedSet, const CachedSet::Layer& layer) {
143 EXPECT_EQ(layer.getLastUpdate(), cachedSet.getLastUpdate());
144 EXPECT_EQ(layer.getDisplayFrame(), cachedSet.getBounds());
145 EXPECT_TRUE(layer.getVisibleRegion().hasSameRects(cachedSet.getVisibleRegion()));
146 EXPECT_EQ(1u, cachedSet.getLayerCount());
147 EXPECT_EQ(layer.getState(), cachedSet.getFirstLayer().getState());
148 EXPECT_EQ(0u, cachedSet.getAge());
149 EXPECT_EQ(layer.getHash(), cachedSet.getNonBufferHash());
150 }
151
expectEqual(const CachedSet & cachedSet,const LayerState & layerState,std::chrono::steady_clock::time_point lastUpdate)152 void expectEqual(const CachedSet& cachedSet, const LayerState& layerState,
153 std::chrono::steady_clock::time_point lastUpdate) {
154 CachedSet::Layer layer(&layerState, lastUpdate);
155 expectEqual(cachedSet, layer);
156 }
157
expectNoBuffer(const CachedSet & cachedSet)158 void expectNoBuffer(const CachedSet& cachedSet) {
159 EXPECT_EQ(nullptr, cachedSet.getBuffer());
160 EXPECT_EQ(nullptr, cachedSet.getDrawFence());
161 EXPECT_FALSE(cachedSet.hasReadyBuffer());
162 }
163
expectReadyBuffer(const CachedSet & cachedSet)164 void expectReadyBuffer(const CachedSet& cachedSet) {
165 EXPECT_NE(nullptr, cachedSet.getBuffer());
166 EXPECT_NE(nullptr, cachedSet.getDrawFence());
167 EXPECT_TRUE(cachedSet.hasReadyBuffer());
168 EXPECT_TRUE(cachedSet.hasRenderedBuffer());
169 }
170
TEST_F(CachedSetTest,createFromLayer)171 TEST_F(CachedSetTest, createFromLayer) {
172 CachedSet::Layer& layer = *mTestLayers[0]->cachedSetLayer.get();
173 CachedSet cachedSet(layer);
174 expectEqual(cachedSet, layer);
175 expectNoBuffer(cachedSet);
176 }
177
TEST_F(CachedSetTest,createFromLayerState)178 TEST_F(CachedSetTest, createFromLayerState) {
179 LayerState& layerState = *mTestLayers[0]->layerState.get();
180 CachedSet cachedSet(&layerState, kStartTime);
181 expectEqual(cachedSet, layerState, kStartTime);
182 expectNoBuffer(cachedSet);
183 }
184
TEST_F(CachedSetTest,addLayer)185 TEST_F(CachedSetTest, addLayer) {
186 CachedSet::Layer& layer1 = *mTestLayers[0]->cachedSetLayer.get();
187 CachedSet::Layer& layer2 = *mTestLayers[1]->cachedSetLayer.get();
188
189 CachedSet cachedSet(layer1);
190 cachedSet.addLayer(layer2.getState(), kStartTime + 10ms);
191
192 EXPECT_EQ(kStartTime, cachedSet.getLastUpdate());
193 EXPECT_EQ(Rect(0, 0, 2, 2), cachedSet.getBounds());
194 Region expectedRegion;
195 expectedRegion.orSelf(Rect(1, 1, 2, 2));
196 expectedRegion.orSelf(Rect(2, 2, 3, 3));
197 EXPECT_TRUE(cachedSet.getVisibleRegion().hasSameRects(expectedRegion));
198 EXPECT_EQ(2u, cachedSet.getLayerCount());
199 EXPECT_EQ(0u, cachedSet.getAge());
200 expectNoBuffer(cachedSet);
201 // TODO(b/181192080): check that getNonBufferHash returns the correct hash value
202 // EXPECT_EQ(android::hashCombine(layer1.getHash(), layer2.getHash()),
203 // cachedSet.getNonBufferHash());
204 }
205
TEST_F(CachedSetTest,decompose)206 TEST_F(CachedSetTest, decompose) {
207 CachedSet::Layer& layer1 = *mTestLayers[0]->cachedSetLayer.get();
208 CachedSet::Layer& layer2 = *mTestLayers[1]->cachedSetLayer.get();
209 CachedSet::Layer& layer3 = *mTestLayers[2]->cachedSetLayer.get();
210
211 CachedSet cachedSet(layer1);
212 cachedSet.addLayer(layer2.getState(), kStartTime + 10ms);
213 cachedSet.addLayer(layer3.getState(), kStartTime + 20ms);
214
215 std::vector<CachedSet> decomposed = cachedSet.decompose();
216 EXPECT_EQ(3u, decomposed.size());
217 expectEqual(decomposed[0], *layer1.getState(), kStartTime);
218 expectNoBuffer(decomposed[0]);
219
220 expectEqual(decomposed[1], *layer2.getState(), kStartTime + 10ms);
221 expectNoBuffer(decomposed[1]);
222
223 expectEqual(decomposed[2], *layer3.getState(), kStartTime + 20ms);
224 expectNoBuffer(decomposed[2]);
225 }
226
TEST_F(CachedSetTest,setLastUpdate)227 TEST_F(CachedSetTest, setLastUpdate) {
228 LayerState& layerState = *mTestLayers[0]->layerState.get();
229 CachedSet cachedSet(&layerState, kStartTime);
230 cachedSet.setLastUpdate(kStartTime + 10ms);
231 expectEqual(cachedSet, layerState, kStartTime + 10ms);
232 }
233
TEST_F(CachedSetTest,incrementAge)234 TEST_F(CachedSetTest, incrementAge) {
235 CachedSet::Layer& layer = *mTestLayers[0]->cachedSetLayer.get();
236 CachedSet cachedSet(layer);
237 EXPECT_EQ(0u, cachedSet.getAge());
238 cachedSet.incrementAge();
239 EXPECT_EQ(1u, cachedSet.getAge());
240 cachedSet.incrementAge();
241 EXPECT_EQ(2u, cachedSet.getAge());
242 }
243
TEST_F(CachedSetTest,incrementSkipCount)244 TEST_F(CachedSetTest, incrementSkipCount) {
245 CachedSet::Layer& layer = *mTestLayers[0]->cachedSetLayer.get();
246 CachedSet cachedSet(layer);
247 EXPECT_EQ(0u, cachedSet.getSkipCount());
248 cachedSet.incrementSkipCount();
249 EXPECT_EQ(1u, cachedSet.getSkipCount());
250 cachedSet.incrementSkipCount();
251 EXPECT_EQ(2u, cachedSet.getSkipCount());
252 }
253
TEST_F(CachedSetTest,hasBufferUpdate_NoUpdate)254 TEST_F(CachedSetTest, hasBufferUpdate_NoUpdate) {
255 CachedSet::Layer& layer1 = *mTestLayers[0]->cachedSetLayer.get();
256 CachedSet::Layer& layer2 = *mTestLayers[1]->cachedSetLayer.get();
257 CachedSet::Layer& layer3 = *mTestLayers[2]->cachedSetLayer.get();
258
259 CachedSet cachedSet(layer1);
260 cachedSet.addLayer(layer2.getState(), kStartTime + 10ms);
261 cachedSet.addLayer(layer3.getState(), kStartTime + 20ms);
262
263 EXPECT_FALSE(cachedSet.hasBufferUpdate());
264 }
265
TEST_F(CachedSetTest,hasBufferUpdate_BufferUpdate)266 TEST_F(CachedSetTest, hasBufferUpdate_BufferUpdate) {
267 CachedSet::Layer& layer1 = *mTestLayers[0]->cachedSetLayer.get();
268 CachedSet::Layer& layer2 = *mTestLayers[1]->cachedSetLayer.get();
269 CachedSet::Layer& layer3 = *mTestLayers[2]->cachedSetLayer.get();
270
271 CachedSet cachedSet(layer1);
272 cachedSet.addLayer(layer2.getState(), kStartTime + 10ms);
273 cachedSet.addLayer(layer3.getState(), kStartTime + 20ms);
274
275 mTestLayers[1]->layerState->resetFramesSinceBufferUpdate();
276
277 EXPECT_TRUE(cachedSet.hasBufferUpdate());
278 }
279
TEST_F(CachedSetTest,append)280 TEST_F(CachedSetTest, append) {
281 CachedSet::Layer& layer1 = *mTestLayers[0]->cachedSetLayer.get();
282 CachedSet::Layer& layer2 = *mTestLayers[1]->cachedSetLayer.get();
283 CachedSet::Layer& layer3 = *mTestLayers[2]->cachedSetLayer.get();
284
285 CachedSet cachedSet1(layer1);
286 CachedSet cachedSet2(layer2);
287 cachedSet1.addLayer(layer3.getState(), kStartTime + 10ms);
288 cachedSet1.incrementSkipCount();
289 EXPECT_EQ(1u, cachedSet1.getSkipCount());
290 cachedSet1.append(cachedSet2);
291
292 EXPECT_EQ(kStartTime, cachedSet1.getLastUpdate());
293 EXPECT_EQ(Rect(0, 0, 3, 3), cachedSet1.getBounds());
294 Region expectedRegion;
295 expectedRegion.orSelf(Rect(1, 1, 2, 2));
296 expectedRegion.orSelf(Rect(2, 2, 3, 3));
297 expectedRegion.orSelf(Rect(3, 3, 4, 4));
298 EXPECT_TRUE(cachedSet1.getVisibleRegion().hasSameRects(expectedRegion));
299 EXPECT_EQ(3u, cachedSet1.getLayerCount());
300 EXPECT_EQ(0u, cachedSet1.getAge());
301 EXPECT_EQ(0u, cachedSet1.getSkipCount());
302
303 expectNoBuffer(cachedSet1);
304 // TODO(b/181192080): check that getNonBufferHash returns the correct hash value
305 // EXPECT_EQ(android::hashCombine(layer1.getHash(), layer2.getHash()),
306 // cachedSet1.getNonBufferHash());
307 }
308
TEST_F(CachedSetTest,updateAge_NoUpdate)309 TEST_F(CachedSetTest, updateAge_NoUpdate) {
310 CachedSet::Layer& layer = *mTestLayers[0]->cachedSetLayer.get();
311
312 CachedSet cachedSet(layer);
313 cachedSet.incrementAge();
314 EXPECT_EQ(kStartTime, cachedSet.getLastUpdate());
315 EXPECT_EQ(1u, cachedSet.getAge());
316
317 cachedSet.updateAge(kStartTime + 10ms);
318 EXPECT_EQ(kStartTime, cachedSet.getLastUpdate());
319 EXPECT_EQ(1u, cachedSet.getAge());
320 }
321
TEST_F(CachedSetTest,updateAge_BufferUpdate)322 TEST_F(CachedSetTest, updateAge_BufferUpdate) {
323 CachedSet::Layer& layer = *mTestLayers[0]->cachedSetLayer.get();
324 mTestLayers[0]->layerState->resetFramesSinceBufferUpdate();
325
326 CachedSet cachedSet(layer);
327 cachedSet.incrementAge();
328 EXPECT_EQ(kStartTime, cachedSet.getLastUpdate());
329 EXPECT_EQ(1u, cachedSet.getAge());
330
331 cachedSet.updateAge(kStartTime + 10ms);
332 EXPECT_EQ(kStartTime + 10ms, cachedSet.getLastUpdate());
333 EXPECT_EQ(0u, cachedSet.getAge());
334 }
335
TEST_F(CachedSetTest,renderUnsecureOutput)336 TEST_F(CachedSetTest, renderUnsecureOutput) {
337 // Skip the 0th layer to ensure that the bounding box of the layers is offset from (0, 0)
338 CachedSet::Layer& layer1 = *mTestLayers[1]->cachedSetLayer.get();
339 sp<mock::LayerFE> layerFE1 = mTestLayers[1]->layerFE;
340 CachedSet::Layer& layer2 = *mTestLayers[2]->cachedSetLayer.get();
341 sp<mock::LayerFE> layerFE2 = mTestLayers[2]->layerFE;
342
343 CachedSet cachedSet(layer1);
344 cachedSet.append(CachedSet(layer2));
345
346 std::optional<compositionengine::LayerFE::LayerSettings> clientComp1;
347 clientComp1.emplace();
348 clientComp1->alpha = 0.5f;
349
350 std::optional<compositionengine::LayerFE::LayerSettings> clientComp2;
351 clientComp2.emplace();
352 clientComp2->alpha = 0.75f;
353
354 const auto drawLayers = [&](const renderengine::DisplaySettings& displaySettings,
355 const std::vector<renderengine::LayerSettings>& layers,
356 const std::shared_ptr<renderengine::ExternalTexture>&,
357 base::unique_fd&&) -> ftl::Future<FenceResult> {
358 EXPECT_EQ(mOutputState.framebufferSpace.getContent(), displaySettings.physicalDisplay);
359 EXPECT_EQ(mOutputState.layerStackSpace.getContent(), displaySettings.clip);
360 EXPECT_EQ(ui::Transform::toRotationFlags(mOutputState.framebufferSpace.getOrientation()),
361 displaySettings.orientation);
362 EXPECT_EQ(0.5f, layers[0].alpha);
363 EXPECT_EQ(0.75f, layers[1].alpha);
364 EXPECT_EQ(ui::Dataspace::SRGB, displaySettings.outputDataspace);
365 return ftl::yield<FenceResult>(Fence::NO_FENCE);
366 };
367
368 EXPECT_CALL(*layerFE1, prepareClientComposition(ClientCompositionTargetSettingsSecureEq(false)))
369 .WillOnce(Return(clientComp1));
370 EXPECT_CALL(*layerFE2, prepareClientComposition(ClientCompositionTargetSettingsSecureEq(false)))
371 .WillOnce(Return(clientComp2));
372 EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _)).WillOnce(Invoke(drawLayers));
373 mOutputState.isSecure = false;
374 cachedSet.render(mRenderEngine, mTexturePool, mOutputState, true);
375 expectReadyBuffer(cachedSet);
376
377 EXPECT_EQ(mOutputState.framebufferSpace, cachedSet.getOutputSpace());
378 EXPECT_EQ(Rect(kOutputSize.width, kOutputSize.height), cachedSet.getTextureBounds());
379
380 // Now check that appending a new cached set properly cleans up RenderEngine resources.
381 CachedSet::Layer& layer3 = *mTestLayers[2]->cachedSetLayer.get();
382 cachedSet.append(CachedSet(layer3));
383 }
384
TEST_F(CachedSetTest,renderSecureOutput)385 TEST_F(CachedSetTest, renderSecureOutput) {
386 // Skip the 0th layer to ensure that the bounding box of the layers is offset from (0, 0)
387 CachedSet::Layer& layer1 = *mTestLayers[1]->cachedSetLayer.get();
388 sp<mock::LayerFE> layerFE1 = mTestLayers[1]->layerFE;
389 CachedSet::Layer& layer2 = *mTestLayers[2]->cachedSetLayer.get();
390 sp<mock::LayerFE> layerFE2 = mTestLayers[2]->layerFE;
391
392 CachedSet cachedSet(layer1);
393 cachedSet.append(CachedSet(layer2));
394
395 std::optional<compositionengine::LayerFE::LayerSettings> clientComp1;
396 clientComp1.emplace();
397 clientComp1->alpha = 0.5f;
398
399 std::optional<compositionengine::LayerFE::LayerSettings> clientComp2;
400 clientComp2.emplace();
401 clientComp2->alpha = 0.75f;
402
403 const auto drawLayers = [&](const renderengine::DisplaySettings& displaySettings,
404 const std::vector<renderengine::LayerSettings>& layers,
405 const std::shared_ptr<renderengine::ExternalTexture>&,
406 base::unique_fd&&) -> ftl::Future<FenceResult> {
407 EXPECT_EQ(mOutputState.framebufferSpace.getContent(), displaySettings.physicalDisplay);
408 EXPECT_EQ(mOutputState.layerStackSpace.getContent(), displaySettings.clip);
409 EXPECT_EQ(ui::Transform::toRotationFlags(mOutputState.framebufferSpace.getOrientation()),
410 displaySettings.orientation);
411 EXPECT_EQ(0.5f, layers[0].alpha);
412 EXPECT_EQ(0.75f, layers[1].alpha);
413 EXPECT_EQ(ui::Dataspace::SRGB, displaySettings.outputDataspace);
414
415 return ftl::yield<FenceResult>(Fence::NO_FENCE);
416 };
417
418 EXPECT_CALL(*layerFE1, prepareClientComposition(ClientCompositionTargetSettingsSecureEq(true)))
419 .WillOnce(Return(clientComp1));
420 EXPECT_CALL(*layerFE2, prepareClientComposition(ClientCompositionTargetSettingsSecureEq(true)))
421 .WillOnce(Return(clientComp2));
422 EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _)).WillOnce(Invoke(drawLayers));
423 mOutputState.isSecure = true;
424 cachedSet.render(mRenderEngine, mTexturePool, mOutputState, true);
425 expectReadyBuffer(cachedSet);
426
427 EXPECT_EQ(mOutputState.framebufferSpace, cachedSet.getOutputSpace());
428 EXPECT_EQ(Rect(kOutputSize.width, kOutputSize.height), cachedSet.getTextureBounds());
429
430 // Now check that appending a new cached set properly cleans up RenderEngine resources.
431 CachedSet::Layer& layer3 = *mTestLayers[2]->cachedSetLayer.get();
432 cachedSet.append(CachedSet(layer3));
433 }
434
TEST_F(CachedSetTest,renderWhitePoint)435 TEST_F(CachedSetTest, renderWhitePoint) {
436 // Skip the 0th layer to ensure that the bounding box of the layers is offset from (0, 0)
437 CachedSet::Layer& layer1 = *mTestLayers[1]->cachedSetLayer.get();
438 sp<mock::LayerFE> layerFE1 = mTestLayers[1]->layerFE;
439 CachedSet::Layer& layer2 = *mTestLayers[2]->cachedSetLayer.get();
440 sp<mock::LayerFE> layerFE2 = mTestLayers[2]->layerFE;
441
442 CachedSet cachedSet(layer1);
443 cachedSet.append(CachedSet(layer2));
444
445 std::optional<compositionengine::LayerFE::LayerSettings> clientComp1;
446 clientComp1.emplace();
447
448 std::optional<compositionengine::LayerFE::LayerSettings> clientComp2;
449 clientComp2.emplace();
450
451 mOutputState.displayBrightnessNits = 400.f;
452
453 const auto drawLayers = [&](const renderengine::DisplaySettings& displaySettings,
454 const std::vector<renderengine::LayerSettings>&,
455 const std::shared_ptr<renderengine::ExternalTexture>&,
456 base::unique_fd&&) -> ftl::Future<FenceResult> {
457 EXPECT_EQ(mOutputState.displayBrightnessNits, displaySettings.targetLuminanceNits);
458 return ftl::yield<FenceResult>(Fence::NO_FENCE);
459 };
460
461 EXPECT_CALL(*layerFE1,
462 prepareClientComposition(ClientCompositionTargetSettingsWhitePointEq(
463 mOutputState.displayBrightnessNits)))
464 .WillOnce(Return(clientComp1));
465 EXPECT_CALL(*layerFE2,
466 prepareClientComposition(ClientCompositionTargetSettingsWhitePointEq(
467 mOutputState.displayBrightnessNits)))
468 .WillOnce(Return(clientComp2));
469 EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _)).WillOnce(Invoke(drawLayers));
470 mOutputState.isSecure = true;
471 cachedSet.render(mRenderEngine, mTexturePool, mOutputState, true);
472 expectReadyBuffer(cachedSet);
473
474 EXPECT_EQ(mOutputState.framebufferSpace, cachedSet.getOutputSpace());
475 EXPECT_EQ(Rect(kOutputSize.width, kOutputSize.height), cachedSet.getTextureBounds());
476
477 // Now check that appending a new cached set properly cleans up RenderEngine resources.
478 CachedSet::Layer& layer3 = *mTestLayers[2]->cachedSetLayer.get();
479 cachedSet.append(CachedSet(layer3));
480 }
481
TEST_F(CachedSetTest,renderWhitePointNoColorTransform)482 TEST_F(CachedSetTest, renderWhitePointNoColorTransform) {
483 // Skip the 0th layer to ensure that the bounding box of the layers is offset from (0, 0)
484 // This is a duplicate of the "renderWhitePoint" test, but setting "deviceHandlesColorTransform"
485 // to false, in the render call.
486
487 CachedSet::Layer& layer1 = *mTestLayers[1]->cachedSetLayer.get();
488 sp<mock::LayerFE> layerFE1 = mTestLayers[1]->layerFE;
489 CachedSet::Layer& layer2 = *mTestLayers[2]->cachedSetLayer.get();
490 sp<mock::LayerFE> layerFE2 = mTestLayers[2]->layerFE;
491
492 CachedSet cachedSet(layer1);
493 cachedSet.append(CachedSet(layer2));
494
495 std::optional<compositionengine::LayerFE::LayerSettings> clientComp1;
496 clientComp1.emplace();
497
498 std::optional<compositionengine::LayerFE::LayerSettings> clientComp2;
499 clientComp2.emplace();
500
501 mOutputState.displayBrightnessNits = 400.f;
502
503 const auto drawLayers = [&](const renderengine::DisplaySettings& displaySettings,
504 const std::vector<renderengine::LayerSettings>&,
505 const std::shared_ptr<renderengine::ExternalTexture>&,
506 base::unique_fd&&) -> ftl::Future<FenceResult> {
507 EXPECT_EQ(mOutputState.displayBrightnessNits, displaySettings.targetLuminanceNits);
508 return ftl::yield<FenceResult>(Fence::NO_FENCE);
509 };
510
511 EXPECT_CALL(*layerFE1,
512 prepareClientComposition(ClientCompositionTargetSettingsWhitePointEq(
513 mOutputState.displayBrightnessNits)))
514 .WillOnce(Return(clientComp1));
515 EXPECT_CALL(*layerFE2,
516 prepareClientComposition(ClientCompositionTargetSettingsWhitePointEq(
517 mOutputState.displayBrightnessNits)))
518 .WillOnce(Return(clientComp2));
519 EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _)).WillOnce(Invoke(drawLayers));
520 mOutputState.isSecure = true;
521 cachedSet.render(mRenderEngine, mTexturePool, mOutputState, false);
522 expectReadyBuffer(cachedSet);
523
524 EXPECT_EQ(mOutputState.framebufferSpace, cachedSet.getOutputSpace());
525 EXPECT_EQ(Rect(kOutputSize.width, kOutputSize.height), cachedSet.getTextureBounds());
526
527 // Now check that appending a new cached set properly cleans up RenderEngine resources.
528 CachedSet::Layer& layer3 = *mTestLayers[2]->cachedSetLayer.get();
529 cachedSet.append(CachedSet(layer3));
530 }
531
TEST_F(CachedSetTest,rendersWithOffsetFramebufferContent)532 TEST_F(CachedSetTest, rendersWithOffsetFramebufferContent) {
533 // Skip the 0th layer to ensure that the bounding box of the layers is offset from (0, 0)
534 CachedSet::Layer& layer1 = *mTestLayers[1]->cachedSetLayer.get();
535 sp<mock::LayerFE> layerFE1 = mTestLayers[1]->layerFE;
536 CachedSet::Layer& layer2 = *mTestLayers[2]->cachedSetLayer.get();
537 sp<mock::LayerFE> layerFE2 = mTestLayers[2]->layerFE;
538
539 CachedSet cachedSet(layer1);
540 cachedSet.append(CachedSet(layer2));
541
542 std::optional<compositionengine::LayerFE::LayerSettings> clientComp1;
543 clientComp1.emplace();
544 clientComp1->alpha = 0.5f;
545
546 std::optional<compositionengine::LayerFE::LayerSettings> clientComp2;
547 clientComp2.emplace();
548 clientComp2->alpha = 0.75f;
549
550 mOutputState.framebufferSpace = ProjectionSpace(ui::Size(10, 20), Rect(2, 3, 10, 5));
551
552 const auto drawLayers = [&](const renderengine::DisplaySettings& displaySettings,
553 const std::vector<renderengine::LayerSettings>& layers,
554 const std::shared_ptr<renderengine::ExternalTexture>&,
555 base::unique_fd&&) -> ftl::Future<FenceResult> {
556 EXPECT_EQ(mOutputState.framebufferSpace.getContent(), displaySettings.physicalDisplay);
557 EXPECT_EQ(mOutputState.layerStackSpace.getContent(), displaySettings.clip);
558 EXPECT_EQ(ui::Transform::toRotationFlags(mOutputState.framebufferSpace.getOrientation()),
559 displaySettings.orientation);
560 EXPECT_EQ(0.5f, layers[0].alpha);
561 EXPECT_EQ(0.75f, layers[1].alpha);
562 EXPECT_EQ(ui::Dataspace::SRGB, displaySettings.outputDataspace);
563
564 return ftl::yield<FenceResult>(Fence::NO_FENCE);
565 };
566
567 EXPECT_CALL(*layerFE1, prepareClientComposition(_)).WillOnce(Return(clientComp1));
568 EXPECT_CALL(*layerFE2, prepareClientComposition(_)).WillOnce(Return(clientComp2));
569 EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _)).WillOnce(Invoke(drawLayers));
570 cachedSet.render(mRenderEngine, mTexturePool, mOutputState, true);
571 expectReadyBuffer(cachedSet);
572
573 EXPECT_EQ(mOutputState.framebufferSpace, cachedSet.getOutputSpace());
574
575 // Now check that appending a new cached set properly cleans up RenderEngine resources.
576 CachedSet::Layer& layer3 = *mTestLayers[2]->cachedSetLayer.get();
577 cachedSet.append(CachedSet(layer3));
578 }
579
TEST_F(CachedSetTest,cachingHintIncludesLayersByDefault)580 TEST_F(CachedSetTest, cachingHintIncludesLayersByDefault) {
581 CachedSet cachedSet(*mTestLayers[0]->cachedSetLayer.get());
582 EXPECT_FALSE(cachedSet.cachingHintExcludesLayers());
583 }
584
TEST_F(CachedSetTest,cachingHintExcludesLayersWhenDisabled)585 TEST_F(CachedSetTest, cachingHintExcludesLayersWhenDisabled) {
586 CachedSet::Layer& layer1 = *mTestLayers[0]->cachedSetLayer.get();
587 mTestLayers[0]->layerFECompositionState.cachingHint = gui::CachingHint::Disabled;
588 mTestLayers[0]->layerState->update(&mTestLayers[0]->outputLayer);
589
590 CachedSet cachedSet(layer1);
591 EXPECT_TRUE(cachedSet.cachingHintExcludesLayers());
592 }
593
TEST_F(CachedSetTest,holePunch_requiresBuffer)594 TEST_F(CachedSetTest, holePunch_requiresBuffer) {
595 CachedSet::Layer& layer1 = *mTestLayers[0]->cachedSetLayer.get();
596 auto& layerFECompositionState = mTestLayers[0]->layerFECompositionState;
597 layerFECompositionState.blendMode = hal::BlendMode::NONE;
598 sp<mock::LayerFE> layerFE1 = mTestLayers[0]->layerFE;
599
600 CachedSet cachedSet(layer1);
601 EXPECT_CALL(*layerFE1, hasRoundedCorners()).WillRepeatedly(Return(true));
602
603 EXPECT_FALSE(cachedSet.requiresHolePunch());
604 }
605
TEST_F(CachedSetTest,holePunch_requiresRoundedCorners)606 TEST_F(CachedSetTest, holePunch_requiresRoundedCorners) {
607 CachedSet::Layer& layer1 = *mTestLayers[0]->cachedSetLayer.get();
608 auto& layerFECompositionState = mTestLayers[0]->layerFECompositionState;
609 layerFECompositionState.buffer = sp<GraphicBuffer>::make();
610 layerFECompositionState.blendMode = hal::BlendMode::NONE;
611
612 CachedSet cachedSet(layer1);
613
614 EXPECT_FALSE(cachedSet.requiresHolePunch());
615 }
616
TEST_F(CachedSetTest,holePunch_requiresSingleLayer)617 TEST_F(CachedSetTest, holePunch_requiresSingleLayer) {
618 CachedSet::Layer& layer1 = *mTestLayers[0]->cachedSetLayer.get();
619 auto& layerFECompositionState = mTestLayers[0]->layerFECompositionState;
620 layerFECompositionState.buffer = sp<GraphicBuffer>::make();
621 layerFECompositionState.blendMode = hal::BlendMode::NONE;
622 sp<mock::LayerFE> layerFE = mTestLayers[0]->layerFE;
623 EXPECT_CALL(*layerFE, hasRoundedCorners()).WillRepeatedly(Return(true));
624
625 CachedSet::Layer& layer2 = *mTestLayers[1]->cachedSetLayer.get();
626
627 CachedSet cachedSet(layer1);
628 cachedSet.append(layer2);
629
630 EXPECT_FALSE(cachedSet.requiresHolePunch());
631 }
632
TEST_F(CachedSetTest,holePunch_requiresNonHdr)633 TEST_F(CachedSetTest, holePunch_requiresNonHdr) {
634 mTestLayers[0]->outputLayerCompositionState.dataspace = ui::Dataspace::BT2020_PQ;
635 mTestLayers[0]->layerState->update(&mTestLayers[0]->outputLayer);
636
637 CachedSet::Layer& layer = *mTestLayers[0]->cachedSetLayer.get();
638 auto& layerFECompositionState = mTestLayers[0]->layerFECompositionState;
639 layerFECompositionState.buffer = sp<GraphicBuffer>::make();
640 layerFECompositionState.blendMode = hal::BlendMode::NONE;
641 sp<mock::LayerFE> layerFE = mTestLayers[0]->layerFE;
642
643 CachedSet cachedSet(layer);
644 EXPECT_CALL(*layerFE, hasRoundedCorners()).WillRepeatedly(Return(true));
645
646 EXPECT_FALSE(cachedSet.requiresHolePunch());
647 }
648
TEST_F(CachedSetTest,holePunch_requiresNonBT601_625)649 TEST_F(CachedSetTest, holePunch_requiresNonBT601_625) {
650 mTestLayers[0]->outputLayerCompositionState.dataspace = ui::Dataspace::STANDARD_BT601_625;
651 mTestLayers[0]->layerState->update(&mTestLayers[0]->outputLayer);
652
653 CachedSet::Layer& layer = *mTestLayers[0]->cachedSetLayer.get();
654 auto& layerFECompositionState = mTestLayers[0]->layerFECompositionState;
655 layerFECompositionState.buffer = sp<GraphicBuffer>::make();
656 layerFECompositionState.blendMode = hal::BlendMode::NONE;
657 sp<mock::LayerFE> layerFE = mTestLayers[0]->layerFE;
658
659 CachedSet cachedSet(layer);
660 EXPECT_CALL(*layerFE, hasRoundedCorners()).WillRepeatedly(Return(true));
661
662 EXPECT_FALSE(cachedSet.requiresHolePunch());
663 }
664
TEST_F(CachedSetTest,holePunch_requiresNonHdrWithExtendedBrightness)665 TEST_F(CachedSetTest, holePunch_requiresNonHdrWithExtendedBrightness) {
666 const auto dataspace = static_cast<ui::Dataspace>(ui::Dataspace::STANDARD_DCI_P3 |
667 ui::Dataspace::TRANSFER_SRGB |
668 ui::Dataspace::RANGE_EXTENDED);
669 mTestLayers[0]->outputLayerCompositionState.dataspace = dataspace;
670 mTestLayers[0]->layerFECompositionState.currentHdrSdrRatio = 5.f;
671 mTestLayers[0]->layerState->update(&mTestLayers[0]->outputLayer);
672
673 CachedSet::Layer& layer = *mTestLayers[0]->cachedSetLayer.get();
674 auto& layerFECompositionState = mTestLayers[0]->layerFECompositionState;
675 layerFECompositionState.buffer = sp<GraphicBuffer>::make();
676 layerFECompositionState.blendMode = hal::BlendMode::NONE;
677 sp<mock::LayerFE> layerFE = mTestLayers[0]->layerFE;
678
679 CachedSet cachedSet(layer);
680 EXPECT_CALL(*layerFE, hasRoundedCorners()).WillRepeatedly(Return(true));
681
682 EXPECT_FALSE(cachedSet.requiresHolePunch());
683 }
684
TEST_F(CachedSetTest,holePunch_requiresNoBlending)685 TEST_F(CachedSetTest, holePunch_requiresNoBlending) {
686 CachedSet::Layer& layer = *mTestLayers[0]->cachedSetLayer.get();
687 auto& layerFECompositionState = mTestLayers[0]->layerFECompositionState;
688 layerFECompositionState.buffer = sp<GraphicBuffer>::make();
689 layerFECompositionState.blendMode = hal::BlendMode::PREMULTIPLIED;
690 sp<mock::LayerFE> layerFE = mTestLayers[0]->layerFE;
691
692 CachedSet cachedSet(layer);
693 EXPECT_CALL(*layerFE, hasRoundedCorners()).WillRepeatedly(Return(true));
694
695 EXPECT_FALSE(cachedSet.requiresHolePunch());
696 }
697
TEST_F(CachedSetTest,requiresHolePunch)698 TEST_F(CachedSetTest, requiresHolePunch) {
699 CachedSet::Layer& layer = *mTestLayers[0]->cachedSetLayer.get();
700 auto& layerFECompositionState = mTestLayers[0]->layerFECompositionState;
701 layerFECompositionState.buffer = sp<GraphicBuffer>::make();
702 layerFECompositionState.blendMode = hal::BlendMode::NONE;
703 sp<mock::LayerFE> layerFE = mTestLayers[0]->layerFE;
704
705 CachedSet cachedSet(layer);
706 EXPECT_CALL(*layerFE, hasRoundedCorners()).WillRepeatedly(Return(true));
707
708 EXPECT_TRUE(cachedSet.requiresHolePunch());
709 }
710
TEST_F(CachedSetTest,holePunch_requiresDeviceComposition)711 TEST_F(CachedSetTest, holePunch_requiresDeviceComposition) {
712 CachedSet::Layer& layer = *mTestLayers[0]->cachedSetLayer.get();
713 sp<mock::LayerFE> layerFE = mTestLayers[0]->layerFE;
714 auto& layerFECompositionState = mTestLayers[0]->layerFECompositionState;
715 layerFECompositionState.buffer = sp<GraphicBuffer>::make();
716 layerFECompositionState.blendMode = hal::BlendMode::NONE;
717 layerFECompositionState.forceClientComposition = true;
718
719 CachedSet cachedSet(layer);
720 EXPECT_CALL(*layerFE, hasRoundedCorners()).WillRepeatedly(Return(true));
721
722 EXPECT_FALSE(cachedSet.requiresHolePunch());
723 }
724
TEST_F(CachedSetTest,addHolePunch_requiresOverlap)725 TEST_F(CachedSetTest, addHolePunch_requiresOverlap) {
726 CachedSet::Layer& layer1 = *mTestLayers[0]->cachedSetLayer.get();
727 CachedSet::Layer& layer2 = *mTestLayers[1]->cachedSetLayer.get();
728 CachedSet::Layer& layer3 = *mTestLayers[2]->cachedSetLayer.get();
729
730 CachedSet cachedSet(layer1);
731 cachedSet.addLayer(layer2.getState(), kStartTime + 10ms);
732
733 cachedSet.addHolePunchLayerIfFeasible(layer3, true);
734
735 ASSERT_EQ(nullptr, cachedSet.getHolePunchLayer());
736 }
737
TEST_F(CachedSetTest,addHolePunch_requiresOpaque)738 TEST_F(CachedSetTest, addHolePunch_requiresOpaque) {
739 mTestLayers[0]->outputLayerCompositionState.displayFrame = Rect(0, 0, 5, 5);
740 mTestLayers[0]->layerFECompositionState.isOpaque = false;
741 CachedSet::Layer& layer1 = *mTestLayers[0]->cachedSetLayer.get();
742 CachedSet::Layer& layer2 = *mTestLayers[1]->cachedSetLayer.get();
743 CachedSet::Layer& layer3 = *mTestLayers[2]->cachedSetLayer.get();
744
745 CachedSet cachedSet(layer1);
746 cachedSet.addLayer(layer2.getState(), kStartTime + 10ms);
747
748 cachedSet.addHolePunchLayerIfFeasible(layer3, false);
749
750 ASSERT_EQ(nullptr, cachedSet.getHolePunchLayer());
751 }
752
TEST_F(CachedSetTest,addHolePunch_opaque)753 TEST_F(CachedSetTest, addHolePunch_opaque) {
754 mTestLayers[0]->outputLayerCompositionState.displayFrame = Rect(0, 0, 5, 5);
755 mTestLayers[0]->layerFECompositionState.isOpaque = true;
756 CachedSet::Layer& layer1 = *mTestLayers[0]->cachedSetLayer.get();
757 CachedSet::Layer& layer2 = *mTestLayers[1]->cachedSetLayer.get();
758 CachedSet::Layer& layer3 = *mTestLayers[2]->cachedSetLayer.get();
759
760 CachedSet cachedSet(layer1);
761 cachedSet.addLayer(layer2.getState(), kStartTime + 10ms);
762
763 cachedSet.addHolePunchLayerIfFeasible(layer3, false);
764
765 ASSERT_EQ(&mTestLayers[2]->outputLayer, cachedSet.getHolePunchLayer());
766 }
767
TEST_F(CachedSetTest,addHolePunch_firstLayer)768 TEST_F(CachedSetTest, addHolePunch_firstLayer) {
769 mTestLayers[0]->outputLayerCompositionState.displayFrame = Rect(0, 0, 5, 5);
770 mTestLayers[0]->layerFECompositionState.isOpaque = false;
771 CachedSet::Layer& layer1 = *mTestLayers[0]->cachedSetLayer.get();
772 CachedSet::Layer& layer2 = *mTestLayers[1]->cachedSetLayer.get();
773 CachedSet::Layer& layer3 = *mTestLayers[2]->cachedSetLayer.get();
774
775 CachedSet cachedSet(layer1);
776 cachedSet.addLayer(layer2.getState(), kStartTime + 10ms);
777
778 cachedSet.addHolePunchLayerIfFeasible(layer3, true);
779
780 ASSERT_EQ(&mTestLayers[2]->outputLayer, cachedSet.getHolePunchLayer());
781 }
782
TEST_F(CachedSetTest,addHolePunch)783 TEST_F(CachedSetTest, addHolePunch) {
784 mTestLayers[0]->outputLayerCompositionState.displayFrame = Rect(0, 0, 5, 5);
785 CachedSet::Layer& layer1 = *mTestLayers[0]->cachedSetLayer.get();
786 sp<mock::LayerFE> layerFE1 = mTestLayers[0]->layerFE;
787
788 CachedSet::Layer& layer2 = *mTestLayers[1]->cachedSetLayer.get();
789 sp<mock::LayerFE> layerFE2 = mTestLayers[1]->layerFE;
790
791 CachedSet::Layer& layer3 = *mTestLayers[2]->cachedSetLayer.get();
792 sp<mock::LayerFE> layerFE3 = mTestLayers[2]->layerFE;
793
794 CachedSet cachedSet(layer1);
795 cachedSet.addLayer(layer2.getState(), kStartTime + 10ms);
796
797 cachedSet.addHolePunchLayerIfFeasible(layer3, true);
798
799 std::optional<compositionengine::LayerFE::LayerSettings> clientComp1;
800 clientComp1.emplace();
801 std::optional<compositionengine::LayerFE::LayerSettings> clientComp2;
802 clientComp2.emplace();
803 std::optional<compositionengine::LayerFE::LayerSettings> clientComp3;
804 clientComp3.emplace();
805
806 clientComp3->source.buffer.buffer =
807 std::make_shared<renderengine::mock::FakeExternalTexture>(1U /*width*/, 1U /*height*/,
808 1ULL /* bufferId */,
809 HAL_PIXEL_FORMAT_RGBA_8888,
810 0ULL /*usage*/);
811
812 EXPECT_CALL(*layerFE1, prepareClientComposition(_)).WillOnce(Return(clientComp1));
813 EXPECT_CALL(*layerFE2, prepareClientComposition(_)).WillOnce(Return(clientComp2));
814 EXPECT_CALL(*layerFE3, prepareClientComposition(_)).WillOnce(Return(clientComp3));
815
816 const auto drawLayers = [&](const renderengine::DisplaySettings&,
817 const std::vector<renderengine::LayerSettings>& layers,
818 const std::shared_ptr<renderengine::ExternalTexture>&,
819 base::unique_fd&&) -> ftl::Future<FenceResult> {
820 // If the highlight layer is enabled, it will increase the size by 1.
821 // We're interested in the third layer either way.
822 EXPECT_GE(layers.size(), 4u);
823 {
824 const auto holePunchSettings = layers[3];
825 EXPECT_EQ(nullptr, holePunchSettings.source.buffer.buffer);
826 EXPECT_EQ(half3(0.0f, 0.0f, 0.0f), holePunchSettings.source.solidColor);
827 EXPECT_TRUE(holePunchSettings.disableBlending);
828 EXPECT_EQ(0.0f, holePunchSettings.alpha);
829 }
830
831 {
832 const auto holePunchBackgroundSettings = layers[0];
833 EXPECT_EQ(nullptr, holePunchBackgroundSettings.source.buffer.buffer);
834 EXPECT_EQ(half3(0.0f, 0.0f, 0.0f), holePunchBackgroundSettings.source.solidColor);
835 EXPECT_FALSE(holePunchBackgroundSettings.disableBlending);
836 EXPECT_EQ(1.0f, holePunchBackgroundSettings.alpha);
837 }
838
839 return ftl::yield<FenceResult>(Fence::NO_FENCE);
840 };
841
842 EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _)).WillOnce(Invoke(drawLayers));
843 cachedSet.render(mRenderEngine, mTexturePool, mOutputState, true);
844 }
845
TEST_F(CachedSetTest,addHolePunch_noBuffer)846 TEST_F(CachedSetTest, addHolePunch_noBuffer) {
847 // Same as addHolePunch, except that clientComp3 does not contain a
848 // buffer. This imitates the case where the buffer had protected content, so
849 // BufferLayer did not add it to the LayerSettings. This should not assert.
850 mTestLayers[0]->outputLayerCompositionState.displayFrame = Rect(0, 0, 5, 5);
851 CachedSet::Layer& layer1 = *mTestLayers[0]->cachedSetLayer.get();
852 sp<mock::LayerFE> layerFE1 = mTestLayers[0]->layerFE;
853
854 CachedSet::Layer& layer2 = *mTestLayers[1]->cachedSetLayer.get();
855 sp<mock::LayerFE> layerFE2 = mTestLayers[1]->layerFE;
856
857 CachedSet::Layer& layer3 = *mTestLayers[2]->cachedSetLayer.get();
858 sp<mock::LayerFE> layerFE3 = mTestLayers[2]->layerFE;
859
860 CachedSet cachedSet(layer1);
861 cachedSet.addLayer(layer2.getState(), kStartTime + 10ms);
862
863 cachedSet.addHolePunchLayerIfFeasible(layer3, true);
864
865 std::optional<compositionengine::LayerFE::LayerSettings> clientComp1;
866 clientComp1.emplace();
867 std::optional<compositionengine::LayerFE::LayerSettings> clientComp2;
868 clientComp2.emplace();
869 std::optional<compositionengine::LayerFE::LayerSettings> clientComp3;
870 clientComp3.emplace();
871
872 EXPECT_CALL(*layerFE1, prepareClientComposition(_)).WillOnce(Return(clientComp1));
873 EXPECT_CALL(*layerFE2, prepareClientComposition(_)).WillOnce(Return(clientComp2));
874 EXPECT_CALL(*layerFE3, prepareClientComposition(_)).WillOnce(Return(clientComp3));
875
876 const auto drawLayers = [&](const renderengine::DisplaySettings&,
877 const std::vector<renderengine::LayerSettings>& layers,
878 const std::shared_ptr<renderengine::ExternalTexture>&,
879 base::unique_fd&&) -> ftl::Future<FenceResult> {
880 // If the highlight layer is enabled, it will increase the size by 1.
881 // We're interested in the third layer either way.
882 EXPECT_GE(layers.size(), 4u);
883
884 {
885 const auto holePunchSettings = layers[3];
886 EXPECT_EQ(nullptr, holePunchSettings.source.buffer.buffer);
887 EXPECT_EQ(half3(0.0f, 0.0f, 0.0f), holePunchSettings.source.solidColor);
888 EXPECT_TRUE(holePunchSettings.disableBlending);
889 EXPECT_EQ(0.0f, holePunchSettings.alpha);
890 }
891
892 {
893 const auto holePunchBackgroundSettings = layers[0];
894 EXPECT_EQ(nullptr, holePunchBackgroundSettings.source.buffer.buffer);
895 EXPECT_EQ(half3(0.0f, 0.0f, 0.0f), holePunchBackgroundSettings.source.solidColor);
896 EXPECT_FALSE(holePunchBackgroundSettings.disableBlending);
897 EXPECT_EQ(1.0f, holePunchBackgroundSettings.alpha);
898 }
899
900 return ftl::yield<FenceResult>(Fence::NO_FENCE);
901 };
902
903 EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _)).WillOnce(Invoke(drawLayers));
904 cachedSet.render(mRenderEngine, mTexturePool, mOutputState, true);
905 }
906
TEST_F(CachedSetTest,append_removesHolePunch)907 TEST_F(CachedSetTest, append_removesHolePunch) {
908 mTestLayers[0]->outputLayerCompositionState.displayFrame = Rect(0, 0, 5, 5);
909 mTestLayers[0]->layerFECompositionState.isOpaque = true;
910 CachedSet::Layer& layer1 = *mTestLayers[0]->cachedSetLayer.get();
911 CachedSet::Layer& layer2 = *mTestLayers[1]->cachedSetLayer.get();
912 CachedSet::Layer& layer3 = *mTestLayers[2]->cachedSetLayer.get();
913
914 CachedSet cachedSet(layer1);
915 cachedSet.addLayer(layer2.getState(), kStartTime + 10ms);
916
917 cachedSet.addHolePunchLayerIfFeasible(layer3, false);
918
919 ASSERT_EQ(&mTestLayers[2]->outputLayer, cachedSet.getHolePunchLayer());
920
921 CachedSet cachedSet3(layer3);
922 cachedSet.append(cachedSet3);
923 ASSERT_EQ(nullptr, cachedSet.getHolePunchLayer());
924 }
925
TEST_F(CachedSetTest,decompose_removesHolePunch)926 TEST_F(CachedSetTest, decompose_removesHolePunch) {
927 mTestLayers[0]->outputLayerCompositionState.displayFrame = Rect(0, 0, 5, 5);
928 CachedSet::Layer& layer1 = *mTestLayers[0]->cachedSetLayer.get();
929 CachedSet::Layer& layer2 = *mTestLayers[1]->cachedSetLayer.get();
930 CachedSet::Layer& layer3 = *mTestLayers[2]->cachedSetLayer.get();
931
932 CachedSet cachedSet(layer1);
933 cachedSet.addLayer(layer2.getState(), kStartTime + 10ms);
934
935 cachedSet.addHolePunchLayerIfFeasible(layer3, true);
936
937 ASSERT_EQ(&mTestLayers[2]->outputLayer, cachedSet.getHolePunchLayer());
938
939 std::vector<CachedSet> decomposed = cachedSet.decompose();
940 EXPECT_EQ(2u, decomposed.size());
941 for (const auto& set : decomposed) {
942 EXPECT_EQ(nullptr, set.getHolePunchLayer());
943 }
944 }
945
TEST_F(CachedSetTest,hasBlurBehind)946 TEST_F(CachedSetTest, hasBlurBehind) {
947 mTestLayers[1]->layerFECompositionState.backgroundBlurRadius = 1;
948 mTestLayers[1]->layerState->update(&mTestLayers[1]->outputLayer);
949 mTestLayers[2]->layerFECompositionState.blurRegions.push_back(
950 BlurRegion{1, 0, 0, 0, 0, 0, 0, 0, 0, 0});
951 mTestLayers[2]->layerState->update(&mTestLayers[2]->outputLayer);
952
953 CachedSet::Layer& layer1 = *mTestLayers[0]->cachedSetLayer.get();
954 CachedSet::Layer& layer2 = *mTestLayers[1]->cachedSetLayer.get();
955 CachedSet::Layer& layer3 = *mTestLayers[2]->cachedSetLayer.get();
956
957 CachedSet cachedSet1(layer1);
958 CachedSet cachedSet2(layer2);
959 CachedSet cachedSet3(layer3);
960
961 // Cached set 4 will consist of layers 1 and 2, which will contain a blur behind
962 CachedSet cachedSet4(layer1);
963 cachedSet4.addLayer(layer2.getState(), kStartTime);
964
965 EXPECT_FALSE(cachedSet1.hasBlurBehind());
966 EXPECT_TRUE(cachedSet2.hasBlurBehind());
967 EXPECT_TRUE(cachedSet3.hasBlurBehind());
968 EXPECT_TRUE(cachedSet4.hasBlurBehind());
969 }
970
TEST_F(CachedSetTest,addBackgroundBlurLayer)971 TEST_F(CachedSetTest, addBackgroundBlurLayer) {
972 CachedSet::Layer& layer1 = *mTestLayers[0]->cachedSetLayer.get();
973 CachedSet::Layer& layer2 = *mTestLayers[1]->cachedSetLayer.get();
974 CachedSet cachedSet(layer1);
975
976 EXPECT_EQ(nullptr, cachedSet.getBlurLayer());
977
978 cachedSet.addBackgroundBlurLayer(layer2);
979 EXPECT_EQ(layer2.getState()->getOutputLayer(), cachedSet.getBlurLayer());
980 }
981
TEST_F(CachedSetTest,addBlur)982 TEST_F(CachedSetTest, addBlur) {
983 mTestLayers[0]->outputLayerCompositionState.displayFrame = Rect(0, 0, 5, 5);
984 CachedSet::Layer& layer1 = *mTestLayers[0]->cachedSetLayer.get();
985 sp<mock::LayerFE> layerFE1 = mTestLayers[0]->layerFE;
986
987 CachedSet::Layer& layer2 = *mTestLayers[1]->cachedSetLayer.get();
988 sp<mock::LayerFE> layerFE2 = mTestLayers[1]->layerFE;
989
990 CachedSet::Layer& layer3 = *mTestLayers[2]->cachedSetLayer.get();
991 sp<mock::LayerFE> layerFE3 = mTestLayers[2]->layerFE;
992
993 CachedSet cachedSet(layer1);
994 cachedSet.addLayer(layer2.getState(), kStartTime + 10ms);
995
996 cachedSet.addBackgroundBlurLayer(layer3);
997
998 std::optional<compositionengine::LayerFE::LayerSettings> clientComp1;
999 clientComp1.emplace();
1000 std::optional<compositionengine::LayerFE::LayerSettings> clientComp2;
1001 clientComp2.emplace();
1002 std::optional<compositionengine::LayerFE::LayerSettings> clientComp3;
1003 clientComp3.emplace();
1004
1005 clientComp3->source.buffer.buffer =
1006 std::make_shared<renderengine::mock::FakeExternalTexture>(1U /*width*/, 1U /*height*/,
1007 1ULL /* bufferId */,
1008 HAL_PIXEL_FORMAT_RGBA_8888,
1009 0ULL /*usage*/);
1010
1011 EXPECT_CALL(*layerFE1,
1012 prepareClientComposition(ClientCompositionTargetSettingsBlurSettingsEq(
1013 compositionengine::LayerFE::ClientCompositionTargetSettings::BlurSetting::
1014 Enabled)))
1015 .WillOnce(Return(clientComp1));
1016 EXPECT_CALL(*layerFE2,
1017 prepareClientComposition(ClientCompositionTargetSettingsBlurSettingsEq(
1018 compositionengine::LayerFE::ClientCompositionTargetSettings::BlurSetting::
1019 Enabled)))
1020 .WillOnce(Return(clientComp2));
1021 EXPECT_CALL(*layerFE3,
1022 prepareClientComposition(ClientCompositionTargetSettingsBlurSettingsEq(
1023 compositionengine::LayerFE::ClientCompositionTargetSettings::BlurSetting::
1024 BackgroundBlurOnly)))
1025 .WillOnce(Return(clientComp3));
1026
1027 const auto drawLayers = [&](const renderengine::DisplaySettings&,
1028 const std::vector<renderengine::LayerSettings>& layers,
1029 const std::shared_ptr<renderengine::ExternalTexture>&,
1030 base::unique_fd&&) -> ftl::Future<FenceResult> {
1031 // If the highlight layer is enabled, it will increase the size by 1.
1032 // We're interested in the third layer either way.
1033 EXPECT_GE(layers.size(), 3u);
1034 const auto blurSettings = layers[2];
1035 EXPECT_TRUE(blurSettings.skipContentDraw);
1036 EXPECT_EQ(half3(0.0f, 0.0f, 0.0f), blurSettings.source.solidColor);
1037 EXPECT_EQ(0.0f, blurSettings.alpha);
1038
1039 return ftl::yield<FenceResult>(Fence::NO_FENCE);
1040 };
1041
1042 EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _)).WillOnce(Invoke(drawLayers));
1043 cachedSet.render(mRenderEngine, mTexturePool, mOutputState, true);
1044 }
1045
1046 } // namespace
1047 } // namespace android::compositionengine
1048