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