diff options
-rw-r--r-- | services/surfaceflinger/Layer.cpp | 16 | ||||
-rw-r--r-- | services/surfaceflinger/Layer.h | 8 | ||||
-rw-r--r-- | services/surfaceflinger/tests/unittests/Android.bp | 1 | ||||
-rw-r--r-- | services/surfaceflinger/tests/unittests/FrameRateSelectionStrategyTest.cpp | 159 |
4 files changed, 179 insertions, 5 deletions
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 31b5e28e4e..e780a1e8f7 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -1252,9 +1252,14 @@ const half4& Layer::getBorderColor() { return mBorderColor; } -bool Layer::propagateFrameRateForLayerTree(FrameRate parentFrameRate, bool* transactionNeeded) { - // The frame rate for layer tree is this layer's frame rate if present, or the parent frame rate +bool Layer::propagateFrameRateForLayerTree(FrameRate parentFrameRate, bool overrideChildren, + bool* transactionNeeded) { + // Gets the frame rate to propagate to children. const auto frameRate = [&] { + if (overrideChildren && parentFrameRate.isValid()) { + return parentFrameRate; + } + if (mDrawingState.frameRate.isValid()) { return mDrawingState.frameRate; } @@ -1268,7 +1273,10 @@ bool Layer::propagateFrameRateForLayerTree(FrameRate parentFrameRate, bool* tran bool childrenHaveFrameRate = false; for (const sp<Layer>& child : mCurrentChildren) { childrenHaveFrameRate |= - child->propagateFrameRateForLayerTree(frameRate, transactionNeeded); + child->propagateFrameRateForLayerTree(frameRate, + overrideChildren || + shouldOverrideChildrenFrameRate(), + transactionNeeded); } // If we don't have a valid frame rate specification, but the children do, we set this @@ -1301,7 +1309,7 @@ void Layer::updateTreeHasFrameRateVote() { }(); bool transactionNeeded = false; - root->propagateFrameRateForLayerTree({}, &transactionNeeded); + root->propagateFrameRateForLayerTree({}, false, &transactionNeeded); // TODO(b/195668952): we probably don't need eTraversalNeeded here if (transactionNeeded) { diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index d5e2185a5e..40882f442c 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -1102,7 +1102,8 @@ private: const std::vector<Layer*>& layersInTree); void updateTreeHasFrameRateVote(); - bool propagateFrameRateForLayerTree(FrameRate parentFrameRate, bool* transactionNeeded); + bool propagateFrameRateForLayerTree(FrameRate parentFrameRate, bool overrideChildren, + bool* transactionNeeded); void setZOrderRelativeOf(const wp<Layer>& relativeOf); bool isTrustedOverlay() const; gui::DropInputMode getDropInputMode() const; @@ -1164,6 +1165,11 @@ private: void transferAvailableJankData(const std::deque<sp<CallbackHandle>>& handles, std::vector<JankData>& jankData); + bool shouldOverrideChildrenFrameRate() const { + return getDrawingState().frameRateSelectionStrategy == + FrameRateSelectionStrategy::OverrideChildren; + } + // Cached properties computed from drawing state // Effective transform taking into account parent transforms and any parent scaling, which is // a transform from the current layer coordinate space to display(screen) coordinate space. diff --git a/services/surfaceflinger/tests/unittests/Android.bp b/services/surfaceflinger/tests/unittests/Android.bp index 8deff85118..f4516c7635 100644 --- a/services/surfaceflinger/tests/unittests/Android.bp +++ b/services/surfaceflinger/tests/unittests/Android.bp @@ -87,6 +87,7 @@ cc_test { "FramebufferSurfaceTest.cpp", "FrameRateOverrideMappingsTest.cpp", "FrameRateSelectionPriorityTest.cpp", + "FrameRateSelectionStrategyTest.cpp", "FrameTimelineTest.cpp", "GameModeTest.cpp", "HWComposerTest.cpp", diff --git a/services/surfaceflinger/tests/unittests/FrameRateSelectionStrategyTest.cpp b/services/surfaceflinger/tests/unittests/FrameRateSelectionStrategyTest.cpp new file mode 100644 index 0000000000..ffe6f245b5 --- /dev/null +++ b/services/surfaceflinger/tests/unittests/FrameRateSelectionStrategyTest.cpp @@ -0,0 +1,159 @@ +/* + * Copyright 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#undef LOG_TAG +#define LOG_TAG "LibSurfaceFlingerUnittests" + +#include <gmock/gmock.h> +#include <gtest/gtest.h> +#include <gui/LayerMetadata.h> + +#include "Layer.h" +#include "LayerTestUtils.h" +#include "TestableSurfaceFlinger.h" +#include "mock/DisplayHardware/MockComposer.h" + +namespace android { + +using testing::DoAll; +using testing::Mock; +using testing::SetArgPointee; + +using android::Hwc2::IComposer; +using android::Hwc2::IComposerClient; + +using scheduler::LayerHistory; + +using FrameRate = Layer::FrameRate; +using FrameRateCompatibility = Layer::FrameRateCompatibility; +using FrameRateSelectionStrategy = scheduler::LayerInfo::FrameRateSelectionStrategy; + +/** + * This class tests the behaviour of Layer::setFrameRateSelectionStrategy. + */ +class FrameRateSelectionStrategyTest : public BaseLayerTest { +protected: + const FrameRate FRAME_RATE_VOTE1 = FrameRate(11_Hz, FrameRateCompatibility::Default); + const FrameRate FRAME_RATE_VOTE2 = FrameRate(22_Hz, FrameRateCompatibility::Default); + const FrameRate FRAME_RATE_VOTE3 = FrameRate(33_Hz, FrameRateCompatibility::Default); + const FrameRate FRAME_RATE_TREE = FrameRate(Fps(), FrameRateCompatibility::NoVote); + + FrameRateSelectionStrategyTest(); + + void addChild(sp<Layer> layer, sp<Layer> child); + void removeChild(sp<Layer> layer, sp<Layer> child); + void commitTransaction(); + + std::vector<sp<Layer>> mLayers; +}; + +FrameRateSelectionStrategyTest::FrameRateSelectionStrategyTest() { + const ::testing::TestInfo* const test_info = + ::testing::UnitTest::GetInstance()->current_test_info(); + ALOGD("**** Setting up for %s.%s\n", test_info->test_case_name(), test_info->name()); + + mFlinger.setupComposer(std::make_unique<Hwc2::mock::Composer>()); +} + +void FrameRateSelectionStrategyTest::addChild(sp<Layer> layer, sp<Layer> child) { + layer->addChild(child); +} + +void FrameRateSelectionStrategyTest::removeChild(sp<Layer> layer, sp<Layer> child) { + layer->removeChild(child); +} + +void FrameRateSelectionStrategyTest::commitTransaction() { + for (auto layer : mLayers) { + layer->commitTransaction(); + } +} + +namespace { + +INSTANTIATE_TEST_SUITE_P(PerLayerType, FrameRateSelectionStrategyTest, + testing::Values(std::make_shared<BufferStateLayerFactory>(), + std::make_shared<EffectLayerFactory>()), + PrintToStringParamName); + +TEST_P(FrameRateSelectionStrategyTest, SetAndGet) { + EXPECT_CALL(*mFlinger.scheduler(), scheduleFrame()).Times(1); + + const auto& layerFactory = GetParam(); + auto layer = mLayers.emplace_back(layerFactory->createLayer(mFlinger)); + layer->setFrameRate(FRAME_RATE_VOTE1.vote); + layer->setFrameRateSelectionStrategy(FrameRateSelectionStrategy::OverrideChildren); + commitTransaction(); + EXPECT_EQ(FRAME_RATE_VOTE1, layer->getFrameRateForLayerTree()); + EXPECT_EQ(FrameRateSelectionStrategy::OverrideChildren, + layer->getDrawingState().frameRateSelectionStrategy); +} + +TEST_P(FrameRateSelectionStrategyTest, SetChildAndGetParent) { + EXPECT_CALL(*mFlinger.scheduler(), scheduleFrame()).Times(1); + + const auto& layerFactory = GetParam(); + auto parent = mLayers.emplace_back(layerFactory->createLayer(mFlinger)); + auto child1 = mLayers.emplace_back(layerFactory->createLayer(mFlinger)); + auto child2 = mLayers.emplace_back(layerFactory->createLayer(mFlinger)); + addChild(parent, child1); + addChild(child1, child2); + + child2->setFrameRate(FRAME_RATE_VOTE1.vote); + child2->setFrameRateSelectionStrategy(FrameRateSelectionStrategy::OverrideChildren); + commitTransaction(); + EXPECT_EQ(FRAME_RATE_TREE, parent->getFrameRateForLayerTree()); + EXPECT_EQ(FrameRateSelectionStrategy::Self, + parent->getDrawingState().frameRateSelectionStrategy); + EXPECT_EQ(FRAME_RATE_TREE, child1->getFrameRateForLayerTree()); + EXPECT_EQ(FrameRateSelectionStrategy::Self, + child1->getDrawingState().frameRateSelectionStrategy); + EXPECT_EQ(FRAME_RATE_VOTE1, child2->getFrameRateForLayerTree()); + EXPECT_EQ(FrameRateSelectionStrategy::OverrideChildren, + child2->getDrawingState().frameRateSelectionStrategy); +} + +TEST_P(FrameRateSelectionStrategyTest, SetParentAndGet) { + EXPECT_CALL(*mFlinger.scheduler(), scheduleFrame()).Times(1); + + const auto& layerFactory = GetParam(); + auto layer1 = mLayers.emplace_back(layerFactory->createLayer(mFlinger)); + auto layer2 = mLayers.emplace_back(layerFactory->createLayer(mFlinger)); + auto layer3 = mLayers.emplace_back(layerFactory->createLayer(mFlinger)); + addChild(layer1, layer2); + addChild(layer2, layer3); + + layer1->setFrameRate(FRAME_RATE_VOTE1.vote); + layer1->setFrameRate(FRAME_RATE_VOTE1.vote); + layer1->setFrameRateSelectionStrategy(FrameRateSelectionStrategy::OverrideChildren); + layer2->setFrameRate(FRAME_RATE_VOTE2.vote); + layer2->setFrameRateSelectionStrategy(FrameRateSelectionStrategy::OverrideChildren); + layer3->setFrameRate(FRAME_RATE_VOTE3.vote); + commitTransaction(); + + EXPECT_EQ(FRAME_RATE_VOTE1, layer1->getFrameRateForLayerTree()); + EXPECT_EQ(FrameRateSelectionStrategy::OverrideChildren, + layer1->getDrawingState().frameRateSelectionStrategy); + EXPECT_EQ(FRAME_RATE_VOTE1, layer2->getFrameRateForLayerTree()); + EXPECT_EQ(FrameRateSelectionStrategy::OverrideChildren, + layer2->getDrawingState().frameRateSelectionStrategy); + EXPECT_EQ(FRAME_RATE_VOTE1, layer3->getFrameRateForLayerTree()); + EXPECT_EQ(FrameRateSelectionStrategy::Self, + layer3->getDrawingState().frameRateSelectionStrategy); +} + +} // namespace +} // namespace android
\ No newline at end of file |