diff options
author | 2021-08-10 16:13:24 -0400 | |
---|---|---|
committer | 2021-08-16 10:35:44 -0400 | |
commit | 1e69253c5fdf738fc50af06bff7a249d66303cbd (patch) | |
tree | 1845ac12604dc1ca89db2e8aaa71b93ebd04741d | |
parent | 9cf612f12d429fc23ed9e68d3a7fa9fe823d79da (diff) |
Allow single inactive layers to be cached if they would be used for a hole punch.
Test: atest libcompositionengine_test
Bug: b/195448126
Change-Id: I2eb19397990d76a835fd842b33c627be91135e2f
-rw-r--r-- | services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/Flattener.h | 12 | ||||
-rw-r--r-- | services/surfaceflinger/CompositionEngine/tests/planner/FlattenerTest.cpp | 67 |
2 files changed, 76 insertions, 3 deletions
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/Flattener.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/Flattener.h index 8ec15edf12..7c2700ce91 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/Flattener.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/Flattener.h @@ -98,8 +98,8 @@ private: std::chrono::steady_clock::time_point now); // A Run is a sequence of CachedSets, which is a candidate for flattening into a single - // CachedSet. Because it is wasteful to flatten 1 CachedSet, a Run must contain more than 1 - // CachedSet + // CachedSet. Because it is wasteful to flatten 1 CachedSet, a run must contain more than + // 1 CachedSet or be used for a hole punch. class Run { public: // A builder for a Run, to aid in construction @@ -133,7 +133,13 @@ private: // Builds a Run instance, if a valid Run may be built. std::optional<Run> validateAndBuild() { - if (mLengths.size() <= 1) { + if (mLengths.size() == 0) { + return std::nullopt; + } + // Runs of length 1 which are hole punch candidates are allowed if the candidate is + // going to be used. + if (mLengths.size() == 1 && + (!mHolePunchCandidate || !(mHolePunchCandidate->requiresHolePunch()))) { return std::nullopt; } diff --git a/services/surfaceflinger/CompositionEngine/tests/planner/FlattenerTest.cpp b/services/surfaceflinger/CompositionEngine/tests/planner/FlattenerTest.cpp index f5cfd2f115..fc9d0ddf3d 100644 --- a/services/surfaceflinger/CompositionEngine/tests/planner/FlattenerTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/planner/FlattenerTest.cpp @@ -659,6 +659,73 @@ TEST_F(FlattenerTest, flattenLayers_pip) { EXPECT_EQ(peekThroughLayer1, peekThroughLayer2); } +// A test that verifies the hole puch optimization can be done on a single layer. +TEST_F(FlattenerTest, flattenLayers_holePunchSingleLayer) { + mTestLayers[0]->outputLayerCompositionState.displayFrame = Rect(0, 0, 5, 5); + + // An opaque static background + auto& layerState0 = mTestLayers[0]->layerState; + const auto& overrideBuffer0 = layerState0->getOutputLayer()->getState().overrideInfo.buffer; + + // a rounded updating layer + auto& layerState1 = mTestLayers[1]->layerState; + const auto& overrideBuffer1 = layerState1->getOutputLayer()->getState().overrideInfo.buffer; + + EXPECT_CALL(*mTestLayers[1]->layerFE, hasRoundedCorners()).WillRepeatedly(Return(true)); + + std::vector<LayerFE::LayerSettings> clientCompositionList = { + LayerFE::LayerSettings{}, + }; + clientCompositionList[0].source.buffer.buffer = std::make_shared< + renderengine::ExternalTexture>(mTestLayers[1]->layerFECompositionState.buffer, + mRenderEngine, + renderengine::ExternalTexture::Usage::READABLE); + EXPECT_CALL(*mTestLayers[1]->layerFE, prepareClientCompositionList(_)) + .WillOnce(Return(clientCompositionList)); + + const std::vector<const LayerState*> layers = { + layerState0.get(), + layerState1.get(), + }; + + initializeFlattener(layers); + + // layer 1 satisfies every condition in CachedSet::requiresHolePunch() + mTime += 200ms; + layerState1->resetFramesSinceBufferUpdate(); // it is updating + + initializeOverrideBuffer(layers); + // Expect no cache invalidation the first time (there's no cache yet) + EXPECT_EQ(getNonBufferHash(layers), + mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime)); + + // This will render a CachedSet of layer 0. Though it is just one layer, it satisfies the + // exception that there would be a hole punch above it. + EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _, _, _)).WillOnce(Return(NO_ERROR)); + mFlattener->renderCachedSets(mOutputState, std::nullopt); + + // We've rendered a CachedSet, but we haven't merged it in. + EXPECT_EQ(nullptr, overrideBuffer0); + + // This time we merge the CachedSet in and we should still have only two sets. + EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _, _, _)).Times(0); + initializeOverrideBuffer(layers); + EXPECT_EQ(getNonBufferHash(layers), + mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime)); + mFlattener->renderCachedSets(mOutputState, std::nullopt); + + EXPECT_NE(nullptr, overrideBuffer0); // got overridden + EXPECT_EQ(nullptr, overrideBuffer1); // did not + + // expect 0's peek though layer to be 1's output layer + const auto* peekThroughLayer0 = + layerState0->getOutputLayer()->getState().overrideInfo.peekThroughLayer; + const auto* peekThroughLayer1 = + layerState1->getOutputLayer()->getState().overrideInfo.peekThroughLayer; + EXPECT_EQ(&mTestLayers[1]->outputLayer, peekThroughLayer0); + EXPECT_EQ(nullptr, peekThroughLayer1); +} + TEST_F(FlattenerTest, flattenLayers_flattensBlurBehindRunIfFirstRun) { auto& layerState1 = mTestLayers[0]->layerState; |