diff options
| author | 2021-06-04 00:54:25 +0000 | |
|---|---|---|
| committer | 2021-06-04 00:54:25 +0000 | |
| commit | 6058403b714979f853e433212f083b64b3712be9 (patch) | |
| tree | 12c27754a9a30cb01a1521fd5a5418f62dfce241 | |
| parent | 020c3a4960179646b9471894f522a281e70a3df0 (diff) | |
| parent | 6909767e494fb797fb52534e4bc307ada513f0e5 (diff) | |
Merge "Improve blur caching heuristic" into sc-dev am: 6909767e49
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/native/+/14542233
Change-Id: If5307329be538fbf345b91526cbc037967b4ed21
14 files changed, 371 insertions, 50 deletions
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h index 791e7db75c..e51019ae99 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h @@ -78,6 +78,30 @@ public: virtual void prepareCompositionState(StateSubset) = 0; struct ClientCompositionTargetSettings { + enum class BlurSetting { + Disabled, + BackgroundBlurOnly, + BlurRegionsOnly, + Enabled, + }; + + friend std::string toString(BlurSetting blurSetting) { + switch (blurSetting) { + case BlurSetting::Enabled: + return "Enabled"; + case BlurSetting::BlurRegionsOnly: + return "BlurRegionsOnly"; + case BlurSetting::BackgroundBlurOnly: + return "BackgroundBlurOnly"; + case BlurSetting::Disabled: + return "Disabled"; + } + } + + friend std::ostream& operator<<(std::ostream& os, const BlurSetting& setting) { + return os << toString(setting); + } + // The clip region, or visible region that is being rendered to const Region& clip; @@ -110,8 +134,8 @@ public: // This may be requested by the HWC const bool clearContent; - // If set to true, change the layer settings to not use any blurs. - const bool disableBlurs; + // Configure layer settings for using blurs + BlurSetting blurSetting; }; // A superset of LayerSettings required by RenderEngine to compose a layer @@ -186,6 +210,7 @@ static inline void PrintTo(const LayerFE::ClientCompositionTargetSettings& setti PrintTo(settings.dataspace, os); *os << "\n .realContentIsVisible = " << settings.realContentIsVisible; *os << "\n .clearContent = " << settings.clearContent; + *os << "\n .blurSetting = " << settings.blurSetting; *os << "\n}"; } diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h index 3f670a1b32..7564c54218 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayerCompositionState.h @@ -103,6 +103,13 @@ struct OutputLayerCompositionState { // be visible through it. Unowned - the OutputLayer's lifetime will // outlast this.) compositionengine::OutputLayer* peekThroughLayer = nullptr; + // True when this layer's blur has been cached with a previous layer, so that this layer + // does not need to request blurring. + // TODO(b/188816867): support blur regions too, which are less likely to be common if a + // device supports cross-window blurs. Blur region support should be doable, but we would + // need to make sure that layer caching works well with the blur region transform passed + // into RenderEngine + bool disableBackgroundBlur = false; } overrideInfo; /* diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/CachedSet.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/CachedSet.h index fdcd6abe65..269ddd5956 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/CachedSet.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/CachedSet.h @@ -39,6 +39,7 @@ public: const LayerState* getState() const { return mState; } const std::string& getName() const { return mState->getName(); } + int32_t getBackgroundBlurRadius() const { return mState->getBackgroundBlurRadius(); } Rect getDisplayFrame() const { return mState->getDisplayFrame(); } const Region& getVisibleRegion() const { return mState->getVisibleRegion(); } const sp<GraphicBuffer>& getBuffer() const { @@ -91,6 +92,7 @@ public: mTexture = nullptr; mOutputDataspace = ui::Dataspace::UNKNOWN; mDrawFence = nullptr; + mBlurLayer = nullptr; mLayers.insert(mLayers.end(), other.mLayers.cbegin(), other.mLayers.cend()); Region boundingRegion; @@ -123,9 +125,13 @@ public: // nothing (besides the hole punch layer) will be drawn behind it. void addHolePunchLayerIfFeasible(const CachedSet&, bool isFirstLayer); + void addBackgroundBlurLayer(const CachedSet&); + // Retrieve the layer that will be drawn behind this one. compositionengine::OutputLayer* getHolePunchLayer() const; + compositionengine::OutputLayer* getBlurLayer() const; + private: CachedSet() = default; @@ -135,6 +141,7 @@ private: // Unowned. const LayerState* mHolePunchLayer = nullptr; + const LayerState* mBlurLayer = nullptr; Rect mBounds = Rect::EMPTY_RECT; Region mVisibleRegion; size_t mAge = 0; diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/Flattener.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/Flattener.h index 213c55e0ce..ca1d69d579 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/Flattener.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/Flattener.h @@ -51,6 +51,11 @@ public: void dump(std::string& result) const; void dumpLayers(std::string& result) const; + const std::optional<CachedSet>& getNewCachedSetForTesting() const { return mNewCachedSet; } + +protected: + std::optional<CachedSet> mNewCachedSet; + private: size_t calculateDisplayCost(const std::vector<const LayerState*>& layers) const; @@ -72,6 +77,7 @@ private: std::vector<CachedSet>::const_iterator mStart; std::vector<size_t> mLengths; const CachedSet* mHolePunchCandidate = nullptr; + const CachedSet* mBlurringLayer = nullptr; public: // Initializes a Builder a CachedSet to start from. @@ -90,6 +96,10 @@ private: mHolePunchCandidate = holePunchCandidate; } + void setBlurringLayer(const CachedSet* blurringLayer) { + mBlurringLayer = blurringLayer; + } + // Builds a Run instance, if a valid Run may be built. std::optional<Run> validateAndBuild() { if (mLengths.size() <= 1) { @@ -99,7 +109,7 @@ private: return Run(mStart, std::reduce(mLengths.cbegin(), mLengths.cend(), 0u, [](size_t left, size_t right) { return left + right; }), - mHolePunchCandidate); + mHolePunchCandidate, mBlurringLayer); } void reset() { *this = {}; } @@ -112,14 +122,19 @@ private: size_t getLayerLength() const { return mLength; } // Gets the hole punch candidate for this Run. const CachedSet* getHolePunchCandidate() const { return mHolePunchCandidate; } + const CachedSet* getBlurringLayer() const { return mBlurringLayer; } private: Run(std::vector<CachedSet>::const_iterator start, size_t length, - const CachedSet* holePunchCandidate) - : mStart(start), mLength(length), mHolePunchCandidate(holePunchCandidate) {} + const CachedSet* holePunchCandidate, const CachedSet* blurringLayer) + : mStart(start), + mLength(length), + mHolePunchCandidate(holePunchCandidate), + mBlurringLayer(blurringLayer) {} const std::vector<CachedSet>::const_iterator mStart; const size_t mLength; const CachedSet* const mHolePunchCandidate; + const CachedSet* const mBlurringLayer; friend class Builder; }; @@ -138,7 +153,6 @@ private: std::chrono::steady_clock::time_point mLastGeometryUpdate; std::vector<CachedSet> mLayers; - std::optional<CachedSet> mNewCachedSet; // Statistics size_t mUnflattenedDisplayCost = 0; diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/LayerState.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/LayerState.h index fef0dfb700..0b78cb8c0b 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/LayerState.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/planner/LayerState.h @@ -231,6 +231,7 @@ public: bool hasBlurBehind() const { return mBackgroundBlurRadius.get() > 0 || !mBlurRegions.get().empty(); } + int32_t getBackgroundBlurRadius() const { return mBackgroundBlurRadius.get(); } hardware::graphics::composer::hal::Composition getCompositionType() const { return mCompositionType.get(); } diff --git a/services/surfaceflinger/CompositionEngine/src/Output.cpp b/services/surfaceflinger/CompositionEngine/src/Output.cpp index 088a400877..e9a8b912f2 100644 --- a/services/surfaceflinger/CompositionEngine/src/Output.cpp +++ b/services/surfaceflinger/CompositionEngine/src/Output.cpp @@ -1188,19 +1188,6 @@ std::vector<LayerFE::LayerSettings> Output::generateClientCompositionRequests( !layerState.visibleRegion.subtract(layerState.shadowRegion).isEmpty(); if (clientComposition || clearClientComposition) { - compositionengine::LayerFE::ClientCompositionTargetSettings - targetSettings{.clip = clip, - .needsFiltering = - layer->needsFiltering() || outputState.needsFiltering, - .isSecure = outputState.isSecure, - .supportsProtectedContent = supportsProtectedContent, - .clearRegion = clientComposition ? clearRegion : stubRegion, - .viewport = outputState.layerStackSpace.content, - .dataspace = outputDataspace, - .realContentIsVisible = realContentIsVisible, - .clearContent = !clientComposition, - .disableBlurs = disableBlurs}; - std::vector<LayerFE::LayerSettings> results; if (layer->getState().overrideInfo.buffer != nullptr) { if (layer->getState().overrideInfo.buffer->getBuffer() != previousOverrideBuffer) { @@ -1212,6 +1199,25 @@ std::vector<LayerFE::LayerSettings> Output::generateClientCompositionRequests( layer->getLayerFE().getDebugName()); } } else { + LayerFE::ClientCompositionTargetSettings::BlurSetting blurSetting = disableBlurs + ? LayerFE::ClientCompositionTargetSettings::BlurSetting::Disabled + : (layer->getState().overrideInfo.disableBackgroundBlur + ? LayerFE::ClientCompositionTargetSettings::BlurSetting:: + BlurRegionsOnly + : LayerFE::ClientCompositionTargetSettings::BlurSetting:: + Enabled); + compositionengine::LayerFE::ClientCompositionTargetSettings + targetSettings{.clip = clip, + .needsFiltering = layer->needsFiltering() || + outputState.needsFiltering, + .isSecure = outputState.isSecure, + .supportsProtectedContent = supportsProtectedContent, + .clearRegion = clientComposition ? clearRegion : stubRegion, + .viewport = outputState.layerStackSpace.content, + .dataspace = outputDataspace, + .realContentIsVisible = realContentIsVisible, + .clearContent = !clientComposition, + .blurSetting = blurSetting}; results = layerFE.prepareClientCompositionList(targetSettings); if (realContentIsVisible && !results.empty()) { layer->editState().clientCompositionTimestamp = systemTime(); diff --git a/services/surfaceflinger/CompositionEngine/src/OutputLayerCompositionState.cpp b/services/surfaceflinger/CompositionEngine/src/OutputLayerCompositionState.cpp index b4c314c8d4..cfa740e251 100644 --- a/services/surfaceflinger/CompositionEngine/src/OutputLayerCompositionState.cpp +++ b/services/surfaceflinger/CompositionEngine/src/OutputLayerCompositionState.cpp @@ -78,6 +78,8 @@ void OutputLayerCompositionState::dump(std::string& out) const { std::string visibleRegionString; overrideInfo.visibleRegion.dump(visibleRegionString, ""); dumpVal(out, "override visible region", visibleRegionString); + dumpVal(out, "override peekThroughLayer", overrideInfo.peekThroughLayer); + dumpVal(out, "override disableBackgroundBlur", overrideInfo.disableBackgroundBlur); if (hwc) { dumpHwc(*hwc, out); diff --git a/services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp b/services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp index b61daeb7cd..3cfb211482 100644 --- a/services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp +++ b/services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp @@ -25,6 +25,7 @@ #include <math/HashCombine.h> #include <renderengine/DisplaySettings.h> #include <renderengine/RenderEngine.h> +#include <utils/Trace.h> #include <utils/Trace.h> @@ -184,7 +185,7 @@ void CachedSet::render(renderengine::RenderEngine& renderEngine, .dataspace = outputDataspace, .realContentIsVisible = true, .clearContent = false, - .disableBlurs = false, + .blurSetting = LayerFE::ClientCompositionTargetSettings::BlurSetting::Enabled, }; std::vector<renderengine::LayerSettings> layerSettings; @@ -201,6 +202,24 @@ void CachedSet::render(renderengine::RenderEngine& renderEngine, std::transform(layerSettings.cbegin(), layerSettings.cend(), std::back_inserter(layerSettingsPointers), [](const renderengine::LayerSettings& settings) { return &settings; }); + + renderengine::LayerSettings blurLayerSettings; + if (mBlurLayer) { + auto blurSettings = targetSettings; + blurSettings.blurSetting = + LayerFE::ClientCompositionTargetSettings::BlurSetting::BackgroundBlurOnly; + auto clientCompositionList = + mBlurLayer->getOutputLayer()->getLayerFE().prepareClientCompositionList( + blurSettings); + blurLayerSettings = clientCompositionList.back(); + // This mimics Layer::prepareClearClientComposition + blurLayerSettings.skipContentDraw = true; + blurLayerSettings.name = std::string("blur layer"); + // Clear out the shadow settings + blurLayerSettings.shadow = {}; + layerSettingsPointers.push_back(&blurLayerSettings); + } + renderengine::LayerSettings holePunchSettings; if (mHolePunchLayer) { auto clientCompositionList = @@ -315,10 +334,18 @@ void CachedSet::addHolePunchLayerIfFeasible(const CachedSet& holePunchLayer, boo } } +void CachedSet::addBackgroundBlurLayer(const CachedSet& blurLayer) { + mBlurLayer = blurLayer.getFirstLayer().getState(); +} + compositionengine::OutputLayer* CachedSet::getHolePunchLayer() const { return mHolePunchLayer ? mHolePunchLayer->getOutputLayer() : nullptr; } +compositionengine::OutputLayer* CachedSet::getBlurLayer() const { + return mBlurLayer ? mBlurLayer->getOutputLayer() : nullptr; +} + void CachedSet::dump(std::string& result) const { const auto now = std::chrono::steady_clock::now(); diff --git a/services/surfaceflinger/CompositionEngine/src/planner/Flattener.cpp b/services/surfaceflinger/CompositionEngine/src/planner/Flattener.cpp index 2def99d649..ef4633568c 100644 --- a/services/surfaceflinger/CompositionEngine/src/planner/Flattener.cpp +++ b/services/surfaceflinger/CompositionEngine/src/planner/Flattener.cpp @@ -245,6 +245,12 @@ bool Flattener::mergeWithCachedSets(const std::vector<const LayerState*>& layers auto currentLayerIter = mLayers.begin(); auto incomingLayerIter = layers.begin(); + + // If not null, this represents the layer that is blurring the layer before + // currentLayerIter. The blurring was stored in the override buffer, so the + // layer that requests the blur no longer needs to do any blurring. + compositionengine::OutputLayer* priorBlurLayer = nullptr; + while (incomingLayerIter != layers.end()) { if (mNewCachedSet && mNewCachedSet->getFirstLayer().getState()->getId() == (*incomingLayerIter)->getId()) { @@ -259,6 +265,8 @@ bool Flattener::mergeWithCachedSets(const std::vector<const LayerState*>& layers auto* peekThroughLayer = mNewCachedSet->getHolePunchLayer(); const size_t layerCount = currentLayerIter->getLayerCount(); for (size_t i = 0; i < layerCount; ++i) { + bool disableBlur = priorBlurLayer && + priorBlurLayer == (*incomingLayerIter)->getOutputLayer(); OutputLayer::CompositionState& state = (*incomingLayerIter)->getOutputLayer()->editState(); state.overrideInfo = { @@ -270,6 +278,7 @@ bool Flattener::mergeWithCachedSets(const std::vector<const LayerState*>& layers .damageRegion = Region::INVALID_REGION, .visibleRegion = mNewCachedSet->getVisibleRegion(), .peekThroughLayer = peekThroughLayer, + .disableBackgroundBlur = disableBlur, }; ++incomingLayerIter; } @@ -281,6 +290,7 @@ bool Flattener::mergeWithCachedSets(const std::vector<const LayerState*>& layers skipCount -= layerCount; } + priorBlurLayer = mNewCachedSet->getBlurLayer(); merged.emplace_back(std::move(*mNewCachedSet)); mNewCachedSet = std::nullopt; continue; @@ -295,6 +305,8 @@ bool Flattener::mergeWithCachedSets(const std::vector<const LayerState*>& layers const size_t layerCount = currentLayerIter->getLayerCount(); auto* peekThroughLayer = currentLayerIter->getHolePunchLayer(); for (size_t i = 0; i < layerCount; ++i) { + bool disableBlur = + priorBlurLayer && priorBlurLayer == (*incomingLayerIter)->getOutputLayer(); OutputLayer::CompositionState& state = (*incomingLayerIter)->getOutputLayer()->editState(); state.overrideInfo = { @@ -306,6 +318,7 @@ bool Flattener::mergeWithCachedSets(const std::vector<const LayerState*>& layers .damageRegion = Region(), .visibleRegion = currentLayerIter->getVisibleRegion(), .peekThroughLayer = peekThroughLayer, + .disableBackgroundBlur = disableBlur, }; ++incomingLayerIter; } @@ -313,15 +326,26 @@ bool Flattener::mergeWithCachedSets(const std::vector<const LayerState*>& layers // Break the current layer into its constituent layers ++mInvalidatedCachedSetAges[currentLayerIter->getAge()]; for (CachedSet& layer : currentLayerIter->decompose()) { + bool disableBlur = + priorBlurLayer && priorBlurLayer == (*incomingLayerIter)->getOutputLayer(); + OutputLayer::CompositionState& state = + (*incomingLayerIter)->getOutputLayer()->editState(); + state.overrideInfo.disableBackgroundBlur = disableBlur; layer.updateAge(now); merged.emplace_back(layer); ++incomingLayerIter; } } else { + bool disableBlur = + priorBlurLayer && priorBlurLayer == (*incomingLayerIter)->getOutputLayer(); + OutputLayer::CompositionState& state = + (*incomingLayerIter)->getOutputLayer()->editState(); + state.overrideInfo.disableBackgroundBlur = disableBlur; currentLayerIter->updateAge(now); merged.emplace_back(*currentLayerIter); ++incomingLayerIter; } + priorBlurLayer = currentLayerIter->getBlurLayer(); ++currentLayerIter; } @@ -361,6 +385,15 @@ std::vector<Flattener::Run> Flattener::findCandidateRuns(time_point now) const { } } else if (isPartOfRun) { builder.setHolePunchCandidate(&(*currentSet)); + + // If we're here then this blur layer recently had an active buffer updating, meaning + // that there is exactly one layer. Blur radius currently is part of layer stack + // geometry, so we're also guaranteed that the background blur radius hasn't changed for + // at least as long as this new inactive cached set. + if (runHasFirstLayer && layerHasBlur && + currentSet->getFirstLayer().getBackgroundBlurRadius() > 0) { + builder.setBlurringLayer(&(*currentSet)); + } if (auto run = builder.validateAndBuild(); run) { runs.push_back(*run); } @@ -422,6 +455,10 @@ void Flattener::buildCachedSets(time_point now) { mNewCachedSet->append(*currentSet); } + if (bestRun->getBlurringLayer()) { + mNewCachedSet->addBackgroundBlurLayer(*bestRun->getBlurringLayer()); + } + if (mEnableHolePunch && bestRun->getHolePunchCandidate() && bestRun->getHolePunchCandidate()->requiresHolePunch()) { // Add the pip layer to mNewCachedSet, but in a special way - it should diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp index 6677f408ad..52e042821a 100644 --- a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp @@ -3784,6 +3784,46 @@ TEST_F(GenerateClientCompositionRequestsTest_ThreeLayers, gathersClientCompositi EXPECT_TRUE(0 != mLayers[2].mOutputLayerState.clientCompositionTimestamp); } +MATCHER_P(ClientCompositionTargetSettingsBlurSettingsEq, expectedBlurSetting, "") { + *result_listener << "ClientCompositionTargetSettings' BlurSettings aren't equal \n"; + *result_listener << "expected " << expectedBlurSetting << "\n"; + *result_listener << "actual " << arg.blurSetting << "\n"; + + return expectedBlurSetting == arg.blurSetting; +} + +TEST_F(GenerateClientCompositionRequestsTest_ThreeLayers, overridesBlur) { + LayerFE::LayerSettings mShadowSettings; + mShadowSettings.source.solidColor = {0.1f, 0.1f, 0.1f}; + + mLayers[2].mOutputLayerState.overrideInfo.disableBackgroundBlur = true; + + EXPECT_CALL(*mLayers[0].mLayerFE, prepareClientCompositionList(_)) + .WillOnce(Return(std::vector<LayerFE::LayerSettings>())); + EXPECT_CALL(*mLayers[1].mLayerFE, prepareClientCompositionList(_)) + .WillOnce(Return(std::vector<LayerFE::LayerSettings>({mLayers[1].mLayerSettings}))); + EXPECT_CALL(*mLayers[2].mLayerFE, + prepareClientCompositionList(ClientCompositionTargetSettingsBlurSettingsEq( + LayerFE::ClientCompositionTargetSettings::BlurSetting::BlurRegionsOnly))) + .WillOnce(Return(std::vector<LayerFE::LayerSettings>( + {mShadowSettings, mLayers[2].mLayerSettings}))); + + Region accumClearRegion(Rect(10, 11, 12, 13)); + auto requests = mOutput.generateClientCompositionRequests(false /* supportsProtectedContent */, + accumClearRegion, kDisplayDataspace); + ASSERT_EQ(3u, requests.size()); + EXPECT_EQ(mLayers[1].mLayerSettings, requests[0]); + EXPECT_EQ(mShadowSettings, requests[1]); + EXPECT_EQ(mLayers[2].mLayerSettings, requests[2]); + + EXPECT_THAT(accumClearRegion, RegionEq(Region(Rect(10, 11, 12, 13)))); + + // Check that a timestamp was set for the layers that generated requests + EXPECT_TRUE(0 == mLayers[0].mOutputLayerState.clientCompositionTimestamp); + EXPECT_TRUE(0 != mLayers[1].mOutputLayerState.clientCompositionTimestamp); + EXPECT_TRUE(0 != mLayers[2].mOutputLayerState.clientCompositionTimestamp); +} + TEST_F(GenerateClientCompositionRequestsTest_ThreeLayers, onlyClientComposesClientComposedLayersIfNoClearingNeeded) { EXPECT_CALL(mLayers[0].mOutputLayer, requiresClientComposition()).WillOnce(Return(false)); @@ -3867,7 +3907,7 @@ TEST_F(GenerateClientCompositionRequestsTest_ThreeLayers, clearsHWCLayersIfOpaqu kDisplayDataspace, false /* realContentIsVisible */, true /* clearContent */, - false /* disabledBlurs */, + compositionengine::LayerFE::ClientCompositionTargetSettings::BlurSetting::Enabled, }; compositionengine::LayerFE::ClientCompositionTargetSettings layer2TargetSettings{ Region(kDisplayFrame), @@ -3879,7 +3919,7 @@ TEST_F(GenerateClientCompositionRequestsTest_ThreeLayers, clearsHWCLayersIfOpaqu kDisplayDataspace, true /* realContentIsVisible */, false /* clearContent */, - false /* disabledBlurs */, + compositionengine::LayerFE::ClientCompositionTargetSettings::BlurSetting::Enabled, }; LayerFE::LayerSettings mBlackoutSettings = mLayers[1].mLayerSettings; @@ -3923,7 +3963,7 @@ TEST_F(GenerateClientCompositionRequestsTest_ThreeLayers, kDisplayDataspace, true /* realContentIsVisible */, false /* clearContent */, - false /* disabledBlurs */, + compositionengine::LayerFE::ClientCompositionTargetSettings::BlurSetting::Enabled, }; compositionengine::LayerFE::ClientCompositionTargetSettings layer1TargetSettings{ Region(Rect(0, 0, 30, 30)), @@ -3935,7 +3975,7 @@ TEST_F(GenerateClientCompositionRequestsTest_ThreeLayers, kDisplayDataspace, true /* realContentIsVisible */, false /* clearContent */, - false /* disabledBlurs */, + compositionengine::LayerFE::ClientCompositionTargetSettings::BlurSetting::Enabled, }; compositionengine::LayerFE::ClientCompositionTargetSettings layer2TargetSettings{ Region(Rect(0, 0, 40, 201)), @@ -3947,7 +3987,7 @@ TEST_F(GenerateClientCompositionRequestsTest_ThreeLayers, kDisplayDataspace, true /* realContentIsVisible */, false /* clearContent */, - false /* disabledBlurs */, + compositionengine::LayerFE::ClientCompositionTargetSettings::BlurSetting::Enabled, }; EXPECT_CALL(*mLayers[0].mLayerFE, prepareClientCompositionList(Eq(ByRef(layer0TargetSettings)))) @@ -3979,7 +4019,7 @@ TEST_F(GenerateClientCompositionRequestsTest_ThreeLayers, kDisplayDataspace, true /* realContentIsVisible */, false /* clearContent */, - false /* disabledBlurs */, + compositionengine::LayerFE::ClientCompositionTargetSettings::BlurSetting::Enabled, }; compositionengine::LayerFE::ClientCompositionTargetSettings layer1TargetSettings{ Region(kDisplayFrame), @@ -3991,7 +4031,7 @@ TEST_F(GenerateClientCompositionRequestsTest_ThreeLayers, kDisplayDataspace, true /* realContentIsVisible */, false /* clearContent */, - false /* disabledBlurs */, + compositionengine::LayerFE::ClientCompositionTargetSettings::BlurSetting::Enabled, }; compositionengine::LayerFE::ClientCompositionTargetSettings layer2TargetSettings{ Region(kDisplayFrame), @@ -4003,7 +4043,7 @@ TEST_F(GenerateClientCompositionRequestsTest_ThreeLayers, kDisplayDataspace, true /* realContentIsVisible */, false /* clearContent */, - false /* disabledBlurs */, + compositionengine::LayerFE::ClientCompositionTargetSettings::BlurSetting::Enabled, }; EXPECT_CALL(*mLayers[0].mLayerFE, prepareClientCompositionList(Eq(ByRef(layer0TargetSettings)))) @@ -4035,7 +4075,7 @@ TEST_F(GenerateClientCompositionRequestsTest_ThreeLayers, kDisplayDataspace, true /* realContentIsVisible */, false /* clearContent */, - false /* disabledBlurs */, + compositionengine::LayerFE::ClientCompositionTargetSettings::BlurSetting::Enabled, }; compositionengine::LayerFE::ClientCompositionTargetSettings layer1TargetSettings{ @@ -4048,7 +4088,7 @@ TEST_F(GenerateClientCompositionRequestsTest_ThreeLayers, kDisplayDataspace, true /* realContentIsVisible */, false /* clearContent */, - false /* disabledBlurs */, + compositionengine::LayerFE::ClientCompositionTargetSettings::BlurSetting::Enabled, }; compositionengine::LayerFE::ClientCompositionTargetSettings layer2TargetSettings{ Region(kDisplayFrame), @@ -4060,7 +4100,7 @@ TEST_F(GenerateClientCompositionRequestsTest_ThreeLayers, kDisplayDataspace, true /* realContentIsVisible */, false /* clearContent */, - false /* disabledBlurs */, + compositionengine::LayerFE::ClientCompositionTargetSettings::BlurSetting::Enabled, }; EXPECT_CALL(*mLayers[0].mLayerFE, prepareClientCompositionList(Eq(ByRef(layer0TargetSettings)))) @@ -4091,7 +4131,7 @@ TEST_F(GenerateClientCompositionRequestsTest_ThreeLayers, kDisplayDataspace, true /* realContentIsVisible */, false /* clearContent */, - false /* disabledBlurs */, + compositionengine::LayerFE::ClientCompositionTargetSettings::BlurSetting::Enabled, }; compositionengine::LayerFE::ClientCompositionTargetSettings layer1TargetSettings{ Region(kDisplayFrame), @@ -4103,7 +4143,7 @@ TEST_F(GenerateClientCompositionRequestsTest_ThreeLayers, kDisplayDataspace, true /* realContentIsVisible */, false /* clearContent */, - false /* disabledBlurs */, + compositionengine::LayerFE::ClientCompositionTargetSettings::BlurSetting::Enabled, }; compositionengine::LayerFE::ClientCompositionTargetSettings layer2TargetSettings{ Region(kDisplayFrame), @@ -4115,7 +4155,7 @@ TEST_F(GenerateClientCompositionRequestsTest_ThreeLayers, kDisplayDataspace, true /* realContentIsVisible */, false /* clearContent */, - false /* disabledBlurs */, + compositionengine::LayerFE::ClientCompositionTargetSettings::BlurSetting::Enabled, }; EXPECT_CALL(*mLayers[0].mLayerFE, prepareClientCompositionList(Eq(ByRef(layer0TargetSettings)))) @@ -4144,7 +4184,7 @@ TEST_F(GenerateClientCompositionRequestsTest_ThreeLayers, kDisplayDataspace, true /* realContentIsVisible */, false /* clearContent */, - false /* disabledBlurs */, + compositionengine::LayerFE::ClientCompositionTargetSettings::BlurSetting::Enabled, }; compositionengine::LayerFE::ClientCompositionTargetSettings layer1TargetSettings{ Region(kDisplayFrame), @@ -4156,7 +4196,7 @@ TEST_F(GenerateClientCompositionRequestsTest_ThreeLayers, kDisplayDataspace, true /* realContentIsVisible */, false /* clearContent */, - false /* disabledBlurs */, + compositionengine::LayerFE::ClientCompositionTargetSettings::BlurSetting::Enabled, }; compositionengine::LayerFE::ClientCompositionTargetSettings layer2TargetSettings{ Region(kDisplayFrame), @@ -4168,7 +4208,7 @@ TEST_F(GenerateClientCompositionRequestsTest_ThreeLayers, kDisplayDataspace, true /* realContentIsVisible */, false /* clearContent */, - false /* disabledBlurs */, + compositionengine::LayerFE::ClientCompositionTargetSettings::BlurSetting::Enabled, }; EXPECT_CALL(*mLayers[0].mLayerFE, prepareClientCompositionList(Eq(ByRef(layer0TargetSettings)))) @@ -4306,7 +4346,7 @@ TEST_F(GenerateClientCompositionRequestsTest, handlesLandscapeModeSplitScreenReq kOutputDataspace, true /* realContentIsVisible */, false /* clearContent */, - false /* disabledBlurs */, + compositionengine::LayerFE::ClientCompositionTargetSettings::BlurSetting::Enabled, }; EXPECT_CALL(leftLayer.mOutputLayer, requiresClientComposition()).WillRepeatedly(Return(true)); @@ -4324,7 +4364,7 @@ TEST_F(GenerateClientCompositionRequestsTest, handlesLandscapeModeSplitScreenReq kOutputDataspace, true /* realContentIsVisible */, false /* clearContent */, - false /* disabledBlurs */, + compositionengine::LayerFE::ClientCompositionTargetSettings::BlurSetting::Enabled, }; EXPECT_CALL(rightLayer.mOutputLayer, requiresClientComposition()).WillRepeatedly(Return(true)); @@ -4358,7 +4398,7 @@ TEST_F(GenerateClientCompositionRequestsTest_ThreeLayers, kDisplayDataspace, false /* realContentIsVisible */, false /* clearContent */, - false /* disabledBlurs */, + compositionengine::LayerFE::ClientCompositionTargetSettings::BlurSetting::Enabled, }; LayerFE::LayerSettings mShadowSettings; @@ -4404,7 +4444,7 @@ TEST_F(GenerateClientCompositionRequestsTest_ThreeLayers, kDisplayDataspace, true /* realContentIsVisible */, false /* clearContent */, - false /* disabledBlurs */, + compositionengine::LayerFE::ClientCompositionTargetSettings::BlurSetting::Enabled, }; EXPECT_CALL(mLayers[0].mOutputLayer, requiresClientComposition()).WillOnce(Return(false)); diff --git a/services/surfaceflinger/CompositionEngine/tests/planner/CachedSetTest.cpp b/services/surfaceflinger/CompositionEngine/tests/planner/CachedSetTest.cpp index 8f44677676..591f9811ee 100644 --- a/services/surfaceflinger/CompositionEngine/tests/planner/CachedSetTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/planner/CachedSetTest.cpp @@ -24,6 +24,7 @@ #include <renderengine/ExternalTexture.h> #include <renderengine/mock/RenderEngine.h> #include <ui/GraphicTypes.h> +#include <utils/Errors.h> #include <memory> namespace android::compositionengine { @@ -42,6 +43,14 @@ using impl::planner::LayerStateField; namespace { +MATCHER_P(ClientCompositionTargetSettingsBlurSettingsEq, expectedBlurSetting, "") { + *result_listener << "ClientCompositionTargetSettings' BlurSettings aren't equal \n"; + *result_listener << "expected " << expectedBlurSetting << "\n"; + *result_listener << "actual " << arg.blurSetting << "\n"; + + return expectedBlurSetting == arg.blurSetting; +} + class CachedSetTest : public testing::Test { public: CachedSetTest() = default; @@ -593,5 +602,78 @@ TEST_F(CachedSetTest, hasBlurBehind) { EXPECT_TRUE(cachedSet4.hasBlurBehind()); } +TEST_F(CachedSetTest, addBackgroundBlurLayer) { + CachedSet::Layer& layer1 = *mTestLayers[0]->cachedSetLayer.get(); + CachedSet::Layer& layer2 = *mTestLayers[1]->cachedSetLayer.get(); + CachedSet cachedSet(layer1); + + EXPECT_EQ(nullptr, cachedSet.getBlurLayer()); + + cachedSet.addBackgroundBlurLayer(layer2); + EXPECT_EQ(layer2.getState()->getOutputLayer(), cachedSet.getBlurLayer()); +} + +TEST_F(CachedSetTest, addBlur) { + mTestLayers[0]->outputLayerCompositionState.displayFrame = Rect(0, 0, 5, 5); + CachedSet::Layer& layer1 = *mTestLayers[0]->cachedSetLayer.get(); + sp<mock::LayerFE> layerFE1 = mTestLayers[0]->layerFE; + + CachedSet::Layer& layer2 = *mTestLayers[1]->cachedSetLayer.get(); + sp<mock::LayerFE> layerFE2 = mTestLayers[1]->layerFE; + + CachedSet::Layer& layer3 = *mTestLayers[2]->cachedSetLayer.get(); + sp<mock::LayerFE> layerFE3 = mTestLayers[2]->layerFE; + + CachedSet cachedSet(layer1); + cachedSet.addLayer(layer2.getState(), kStartTime + 10ms); + + cachedSet.addBackgroundBlurLayer(layer3); + + std::vector<compositionengine::LayerFE::LayerSettings> clientCompList1; + clientCompList1.push_back({}); + std::vector<compositionengine::LayerFE::LayerSettings> clientCompList2; + clientCompList2.push_back({}); + std::vector<compositionengine::LayerFE::LayerSettings> clientCompList3; + clientCompList3.push_back({}); + + clientCompList3[0].source.buffer.buffer = std::make_shared< + renderengine::ExternalTexture>(sp<GraphicBuffer>::make(), mRenderEngine, + renderengine::ExternalTexture::READABLE); + + EXPECT_CALL(*layerFE1, + prepareClientCompositionList(ClientCompositionTargetSettingsBlurSettingsEq( + compositionengine::LayerFE::ClientCompositionTargetSettings::BlurSetting:: + Enabled))) + .WillOnce(Return(clientCompList1)); + EXPECT_CALL(*layerFE2, + prepareClientCompositionList(ClientCompositionTargetSettingsBlurSettingsEq( + compositionengine::LayerFE::ClientCompositionTargetSettings::BlurSetting:: + Enabled))) + .WillOnce(Return(clientCompList2)); + EXPECT_CALL(*layerFE3, + prepareClientCompositionList(ClientCompositionTargetSettingsBlurSettingsEq( + compositionengine::LayerFE::ClientCompositionTargetSettings::BlurSetting:: + BackgroundBlurOnly))) + .WillOnce(Return(clientCompList3)); + + const auto drawLayers = [&](const renderengine::DisplaySettings&, + const std::vector<const renderengine::LayerSettings*>& layers, + const std::shared_ptr<renderengine::ExternalTexture>&, const bool, + base::unique_fd&&, base::unique_fd*) -> int32_t { + // If the highlight layer is enabled, it will increase the size by 1. + // We're interested in the third layer either way. + EXPECT_GE(layers.size(), 3u); + const auto* blurSettings = layers[2]; + EXPECT_TRUE(blurSettings->skipContentDraw); + EXPECT_EQ(half3(0.0f, 0.0f, 0.0f), blurSettings->source.solidColor); + EXPECT_EQ(0.0f, blurSettings->alpha); + + return NO_ERROR; + }; + + EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _, _, _)).WillOnce(Invoke(drawLayers)); + cachedSet.render(mRenderEngine, mOutputState); +} + } // namespace } // namespace android::compositionengine diff --git a/services/surfaceflinger/CompositionEngine/tests/planner/FlattenerTest.cpp b/services/surfaceflinger/CompositionEngine/tests/planner/FlattenerTest.cpp index 7ec2c98bc1..8b03964ad2 100644 --- a/services/surfaceflinger/CompositionEngine/tests/planner/FlattenerTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/planner/FlattenerTest.cpp @@ -27,6 +27,7 @@ namespace android::compositionengine { using namespace std::chrono_literals; +using impl::planner::CachedSet; using impl::planner::Flattener; using impl::planner::LayerState; using impl::planner::NonBufferHash; @@ -43,9 +44,15 @@ using testing::SetArgPointee; namespace { +class TestableFlattener : public Flattener { +public: + TestableFlattener(bool enableHolePunch) : Flattener(enableHolePunch) {} + const std::optional<CachedSet>& getNewCachedSetForTesting() const { return mNewCachedSet; } +}; + class FlattenerTest : public testing::Test { public: - FlattenerTest() : mFlattener(std::make_unique<Flattener>(true)) {} + FlattenerTest() : mFlattener(std::make_unique<TestableFlattener>(true)) {} void SetUp() override; protected: @@ -55,7 +62,7 @@ protected: // mRenderEngine may be held as a pointer to mFlattener, so mFlattener must be destroyed first. renderengine::mock::RenderEngine mRenderEngine; - std::unique_ptr<Flattener> mFlattener; + std::unique_ptr<TestableFlattener> mFlattener; const std::chrono::steady_clock::time_point kStartTime = std::chrono::steady_clock::now(); std::chrono::steady_clock::time_point mTime = kStartTime; @@ -786,6 +793,56 @@ TEST_F(FlattenerTest, flattenLayers_flattenSkipsLayerWithBlurBehind) { EXPECT_EQ(overrideBuffer3, overrideBuffer4); } +TEST_F(FlattenerTest, flattenLayers_whenBlurLayerIsChanging_appliesBlurToInactiveBehindLayers) { + auto& layerState1 = mTestLayers[0]->layerState; + auto& layerState2 = mTestLayers[1]->layerState; + + auto& layerStateWithBlurBehind = mTestLayers[2]->layerState; + mTestLayers[2]->layerFECompositionState.backgroundBlurRadius = 1; + layerStateWithBlurBehind->update(&mTestLayers[2]->outputLayer); + const auto& overrideBuffer1 = layerState1->getOutputLayer()->getState().overrideInfo.buffer; + const auto& overrideBuffer2 = layerState2->getOutputLayer()->getState().overrideInfo.buffer; + const auto& blurOverrideBuffer = + layerStateWithBlurBehind->getOutputLayer()->getState().overrideInfo.buffer; + + const std::vector<const LayerState*> layers = { + layerState1.get(), + layerState2.get(), + layerStateWithBlurBehind.get(), + }; + + initializeFlattener(layers); + + // Mark the first two layers inactive, but update the blur layer + mTime += 200ms; + layerStateWithBlurBehind->resetFramesSinceBufferUpdate(); + + // layers would be flattened but the buffer would not be overridden + EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _, _, _)).WillOnce(Return(NO_ERROR)); + + initializeOverrideBuffer(layers); + EXPECT_EQ(getNonBufferHash(layers), + mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime)); + mFlattener->renderCachedSets(mRenderEngine, mOutputState); + + const auto& cachedSet = mFlattener->getNewCachedSetForTesting(); + ASSERT_NE(std::nullopt, cachedSet); + EXPECT_EQ(&mTestLayers[2]->outputLayer, cachedSet->getBlurLayer()); + + for (const auto layer : layers) { + EXPECT_EQ(nullptr, layer->getOutputLayer()->getState().overrideInfo.buffer); + } + + // the new flattened layer is replaced + initializeOverrideBuffer(layers); + EXPECT_NE(getNonBufferHash(layers), + mFlattener->flattenLayers(layers, getNonBufferHash(layers), mTime)); + mFlattener->renderCachedSets(mRenderEngine, mOutputState); + EXPECT_NE(nullptr, overrideBuffer1); + EXPECT_EQ(overrideBuffer2, overrideBuffer1); + EXPECT_EQ(nullptr, blurOverrideBuffer); +} + TEST_F(FlattenerTest, flattenLayers_renderCachedSets_doesNotRenderTwice) { auto& layerState1 = mTestLayers[0]->layerState; auto& layerState2 = mTestLayers[1]->layerState; diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index d720bcb20f..9fcc17c4b4 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -587,11 +587,24 @@ std::optional<compositionengine::LayerFE::LayerSettings> Layer::prepareClientCom layerSettings.alpha = alpha; layerSettings.sourceDataspace = getDataSpace(); - if (!targetSettings.disableBlurs) { - layerSettings.backgroundBlurRadius = getBackgroundBlurRadius(); - layerSettings.blurRegions = getBlurRegions(); - layerSettings.blurRegionTransform = - getActiveTransform(getDrawingState()).inverse().asMatrix4(); + switch (targetSettings.blurSetting) { + case LayerFE::ClientCompositionTargetSettings::BlurSetting::Enabled: + layerSettings.backgroundBlurRadius = getBackgroundBlurRadius(); + layerSettings.blurRegions = getBlurRegions(); + layerSettings.blurRegionTransform = + getActiveTransform(getDrawingState()).inverse().asMatrix4(); + break; + case LayerFE::ClientCompositionTargetSettings::BlurSetting::BackgroundBlurOnly: + layerSettings.backgroundBlurRadius = getBackgroundBlurRadius(); + break; + case LayerFE::ClientCompositionTargetSettings::BlurSetting::BlurRegionsOnly: + layerSettings.blurRegions = getBlurRegions(); + layerSettings.blurRegionTransform = + getActiveTransform(getDrawingState()).inverse().asMatrix4(); + break; + case LayerFE::ClientCompositionTargetSettings::BlurSetting::Disabled: + default: + break; } layerSettings.stretchEffect = getStretchEffect(); // Record the name of the layer for debugging further down the stack. diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index a86e0610fb..cef81997ea 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -6202,9 +6202,12 @@ status_t SurfaceFlinger::renderScreenImplLocked( clearRegion, layerStackSpaceRect, clientCompositionDisplay.outputDataspace, - true, /* realContentIsVisible */ + true, /* realContentIsVisible */ false, /* clearContent */ - disableBlurs, + disableBlurs ? compositionengine::LayerFE::ClientCompositionTargetSettings:: + BlurSetting::Disabled + : compositionengine::LayerFE::ClientCompositionTargetSettings:: + BlurSetting::Enabled, }; std::vector<compositionengine::LayerFE::LayerSettings> results = layer->prepareClientCompositionList(targetSettings); |