diff options
| author | 2021-06-25 23:56:53 +0000 | |
|---|---|---|
| committer | 2021-06-25 23:56:53 +0000 | |
| commit | 4e700e9119bc999d90d1742b9e10c759b9d5f44c (patch) | |
| tree | 29835585e5fbb105448912339e28ea867a610a60 | |
| parent | aabd53ca46eabbcb766eb2afbaac797bfa645c6b (diff) | |
| parent | a7e006b30bf5384b35b81dbd17399d13de4396e8 (diff) | |
Merge "SF caching: Skip BT601_625 layers for caching and hole-punch" into sc-dev
6 files changed, 180 insertions, 15 deletions
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/CachedSet.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/CachedSet.h index 7cb0f6b9f2..2bf931cb3d 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/CachedSet.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/CachedSet.h @@ -141,7 +141,7 @@ public: compositionengine::OutputLayer* getBlurLayer() const; - bool hasHdrLayers() const; + bool hasUnsupportedDataspace() const; bool hasProtectedLayers() const; diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/LayerState.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/LayerState.h index a20d7b3ce7..bce438fa13 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/LayerState.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/LayerState.h @@ -242,13 +242,6 @@ public: ui::Dataspace getDataspace() const { return mOutputDataspace.get(); } - bool isHdr() const { - const ui::Dataspace transfer = - static_cast<ui::Dataspace>(getDataspace() & ui::Dataspace::TRANSFER_MASK); - return (transfer == ui::Dataspace::TRANSFER_ST2084 || - transfer == ui::Dataspace::TRANSFER_HLG); - } - bool isProtected() const { return getOutputLayer()->getLayerFE().getCompositionState()->hasProtectedContent; } diff --git a/services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp b/services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp index 22d9dc6502..b24274e731 100644 --- a/services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp +++ b/services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp @@ -295,9 +295,7 @@ bool CachedSet::requiresHolePunch() const { return false; } - // Do not use a hole punch with an HDR layer; this should be done in client - // composition to properly mix HDR with SDR. - if (hasHdrLayers()) { + if (hasUnsupportedDataspace()) { return false; } @@ -352,9 +350,22 @@ compositionengine::OutputLayer* CachedSet::getBlurLayer() const { return mBlurLayer ? mBlurLayer->getOutputLayer() : nullptr; } -bool CachedSet::hasHdrLayers() const { - return std::any_of(mLayers.cbegin(), mLayers.cend(), - [](const Layer& layer) { return layer.getState()->isHdr(); }); +bool CachedSet::hasUnsupportedDataspace() const { + return std::any_of(mLayers.cbegin(), mLayers.cend(), [](const Layer& layer) { + auto dataspace = layer.getState()->getDataspace(); + const auto transfer = static_cast<ui::Dataspace>(dataspace & ui::Dataspace::TRANSFER_MASK); + if (transfer == ui::Dataspace::TRANSFER_ST2084 || transfer == ui::Dataspace::TRANSFER_HLG) { + // Skip HDR. + return true; + } + + if ((dataspace & HAL_DATASPACE_STANDARD_MASK) == HAL_DATASPACE_STANDARD_BT601_625) { + // RenderEngine does not match some DPUs, so skip + // to avoid flickering/color differences. + return true; + } + return false; + }); } bool CachedSet::hasProtectedLayers() const { diff --git a/services/surfaceflinger/CompositionEngine/src/planner/Flattener.cpp b/services/surfaceflinger/CompositionEngine/src/planner/Flattener.cpp index 153cee33a0..f033279caa 100644 --- a/services/surfaceflinger/CompositionEngine/src/planner/Flattener.cpp +++ b/services/surfaceflinger/CompositionEngine/src/planner/Flattener.cpp @@ -420,7 +420,7 @@ std::vector<Flattener::Run> Flattener::findCandidateRuns(time_point now) const { const bool layerIsInactive = now - currentSet->getLastUpdate() > mActiveLayerTimeout; const bool layerHasBlur = currentSet->hasBlurBehind(); if (layerIsInactive && (firstLayer || runHasFirstLayer || !layerHasBlur) && - !currentSet->hasHdrLayers()) { + !currentSet->hasUnsupportedDataspace()) { if (isPartOfRun) { builder.append(currentSet->getLayerCount()); } else { diff --git a/services/surfaceflinger/CompositionEngine/tests/planner/CachedSetTest.cpp b/services/surfaceflinger/CompositionEngine/tests/planner/CachedSetTest.cpp index 0acc31765a..7f0e186692 100644 --- a/services/surfaceflinger/CompositionEngine/tests/planner/CachedSetTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/planner/CachedSetTest.cpp @@ -457,6 +457,20 @@ TEST_F(CachedSetTest, holePunch_requiresNonHdr) { EXPECT_FALSE(cachedSet.requiresHolePunch()); } +TEST_F(CachedSetTest, holePunch_requiresNonBT601_625) { + mTestLayers[0]->outputLayerCompositionState.dataspace = ui::Dataspace::STANDARD_BT601_625; + mTestLayers[0]->layerState->update(&mTestLayers[0]->outputLayer); + + CachedSet::Layer& layer = *mTestLayers[0]->cachedSetLayer.get(); + mTestLayers[0]->layerFECompositionState.buffer = sp<GraphicBuffer>::make(); + sp<mock::LayerFE> layerFE = mTestLayers[0]->layerFE; + + CachedSet cachedSet(layer); + EXPECT_CALL(*layerFE, hasRoundedCorners()).WillRepeatedly(Return(true)); + + EXPECT_FALSE(cachedSet.requiresHolePunch()); +} + TEST_F(CachedSetTest, requiresHolePunch) { CachedSet::Layer& layer = *mTestLayers[0]->cachedSetLayer.get(); mTestLayers[0]->layerFECompositionState.buffer = sp<GraphicBuffer>::make(); diff --git a/services/surfaceflinger/CompositionEngine/tests/planner/FlattenerTest.cpp b/services/surfaceflinger/CompositionEngine/tests/planner/FlattenerTest.cpp index 334b855c22..f5cfd2f115 100644 --- a/services/surfaceflinger/CompositionEngine/tests/planner/FlattenerTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/planner/FlattenerTest.cpp @@ -937,5 +937,152 @@ TEST_F(FlattenerRenderSchedulingTest, flattenLayers_renderCachedSets_defersUpToM (kCachedSetRenderDuration + 10ms)); } +TEST_F(FlattenerTest, flattenLayers_skipsBT601_625) { + auto& layerState1 = mTestLayers[0]->layerState; + const auto& overrideBuffer1 = layerState1->getOutputLayer()->getState().overrideInfo.buffer; + + auto& layerState2 = mTestLayers[1]->layerState; + const auto& overrideBuffer2 = layerState2->getOutputLayer()->getState().overrideInfo.buffer; + + // The third layer uses a dataspace that will not be flattened due to + // possible mismatch with DPU rendering. + auto& layerState3 = mTestLayers[2]->layerState; + const auto& overrideBuffer3 = layerState3->getOutputLayer()->getState().overrideInfo.buffer; + mTestLayers[2]->outputLayerCompositionState.dataspace = ui::Dataspace::STANDARD_BT601_625; + mTestLayers[2]->layerState->update(&mTestLayers[2]->outputLayer); + + const std::vector<const LayerState*> layers = { + layerState1.get(), + layerState2.get(), + layerState3.get(), + }; + + initializeFlattener(layers); + + mTime += 200ms; + initializeOverrideBuffer(layers); + EXPECT_EQ(getNonBufferHash(layers), + mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime)); + + // This will render a CachedSet. + 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, overrideBuffer1); + EXPECT_EQ(nullptr, overrideBuffer2); + EXPECT_EQ(nullptr, overrideBuffer3); + + // This time we merge the CachedSet in, so we have a new hash, and we should + // only have two sets. + EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _, _, _)).Times(0); + initializeOverrideBuffer(layers); + EXPECT_NE(getNonBufferHash(layers), + mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime)); + mFlattener->renderCachedSets(mOutputState, std::nullopt); + + EXPECT_NE(nullptr, overrideBuffer1); + EXPECT_EQ(overrideBuffer1, overrideBuffer2); + EXPECT_EQ(nullptr, overrideBuffer3); +} + +TEST_F(FlattenerTest, flattenLayers_skipsHDR) { + auto& layerState1 = mTestLayers[0]->layerState; + const auto& overrideBuffer1 = layerState1->getOutputLayer()->getState().overrideInfo.buffer; + + auto& layerState2 = mTestLayers[1]->layerState; + const auto& overrideBuffer2 = layerState2->getOutputLayer()->getState().overrideInfo.buffer; + + // The third layer uses a dataspace that will not be flattened due to + // possible mismatch with DPU rendering. + auto& layerState3 = mTestLayers[2]->layerState; + const auto& overrideBuffer3 = layerState3->getOutputLayer()->getState().overrideInfo.buffer; + mTestLayers[2]->outputLayerCompositionState.dataspace = ui::Dataspace::BT2020_ITU_HLG; + mTestLayers[2]->layerState->update(&mTestLayers[2]->outputLayer); + + const std::vector<const LayerState*> layers = { + layerState1.get(), + layerState2.get(), + layerState3.get(), + }; + + initializeFlattener(layers); + + mTime += 200ms; + initializeOverrideBuffer(layers); + EXPECT_EQ(getNonBufferHash(layers), + mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime)); + + // This will render a CachedSet. + 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, overrideBuffer1); + EXPECT_EQ(nullptr, overrideBuffer2); + EXPECT_EQ(nullptr, overrideBuffer3); + + // This time we merge the CachedSet in, so we have a new hash, and we should + // only have two sets. + EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _, _, _)).Times(0); + initializeOverrideBuffer(layers); + EXPECT_NE(getNonBufferHash(layers), + mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime)); + mFlattener->renderCachedSets(mOutputState, std::nullopt); + + EXPECT_NE(nullptr, overrideBuffer1); + EXPECT_EQ(overrideBuffer1, overrideBuffer2); + EXPECT_EQ(nullptr, overrideBuffer3); +} + +TEST_F(FlattenerTest, flattenLayers_skipsHDR2) { + auto& layerState1 = mTestLayers[0]->layerState; + const auto& overrideBuffer1 = layerState1->getOutputLayer()->getState().overrideInfo.buffer; + + auto& layerState2 = mTestLayers[1]->layerState; + const auto& overrideBuffer2 = layerState2->getOutputLayer()->getState().overrideInfo.buffer; + + // The third layer uses a dataspace that will not be flattened due to + // possible mismatch with DPU rendering. + auto& layerState3 = mTestLayers[2]->layerState; + const auto& overrideBuffer3 = layerState3->getOutputLayer()->getState().overrideInfo.buffer; + mTestLayers[2]->outputLayerCompositionState.dataspace = ui::Dataspace::BT2020_PQ; + mTestLayers[2]->layerState->update(&mTestLayers[2]->outputLayer); + + const std::vector<const LayerState*> layers = { + layerState1.get(), + layerState2.get(), + layerState3.get(), + }; + + initializeFlattener(layers); + + mTime += 200ms; + initializeOverrideBuffer(layers); + EXPECT_EQ(getNonBufferHash(layers), + mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime)); + + // This will render a CachedSet. + 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, overrideBuffer1); + EXPECT_EQ(nullptr, overrideBuffer2); + EXPECT_EQ(nullptr, overrideBuffer3); + + // This time we merge the CachedSet in, so we have a new hash, and we should + // only have two sets. + EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _, _, _)).Times(0); + initializeOverrideBuffer(layers); + EXPECT_NE(getNonBufferHash(layers), + mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime)); + mFlattener->renderCachedSets(mOutputState, std::nullopt); + + EXPECT_NE(nullptr, overrideBuffer1); + EXPECT_EQ(overrideBuffer1, overrideBuffer2); + EXPECT_EQ(nullptr, overrideBuffer3); +} + } // namespace } // namespace android::compositionengine |