Loading services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/Flattener.h +9 −3 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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; } Loading services/surfaceflinger/CompositionEngine/tests/planner/FlattenerTest.cpp +67 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading
services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/Flattener.h +9 −3 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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; } Loading
services/surfaceflinger/CompositionEngine/tests/planner/FlattenerTest.cpp +67 −0 Original line number Diff line number Diff line Loading @@ -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; Loading