Loading services/surfaceflinger/Layer.cpp +12 −4 Original line number Diff line number Diff line Loading @@ -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; } Loading @@ -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 Loading Loading @@ -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) { Loading services/surfaceflinger/Layer.h +7 −1 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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. Loading services/surfaceflinger/tests/unittests/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -87,6 +87,7 @@ cc_test { "FramebufferSurfaceTest.cpp", "FrameRateOverrideMappingsTest.cpp", "FrameRateSelectionPriorityTest.cpp", "FrameRateSelectionStrategyTest.cpp", "FrameTimelineTest.cpp", "GameModeTest.cpp", "HWComposerTest.cpp", Loading services/surfaceflinger/tests/unittests/FrameRateSelectionStrategyTest.cpp 0 → 100644 +159 −0 Original line number Diff line number Diff line /* * 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 Loading
services/surfaceflinger/Layer.cpp +12 −4 Original line number Diff line number Diff line Loading @@ -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; } Loading @@ -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 Loading Loading @@ -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) { Loading
services/surfaceflinger/Layer.h +7 −1 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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. Loading
services/surfaceflinger/tests/unittests/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -87,6 +87,7 @@ cc_test { "FramebufferSurfaceTest.cpp", "FrameRateOverrideMappingsTest.cpp", "FrameRateSelectionPriorityTest.cpp", "FrameRateSelectionStrategyTest.cpp", "FrameTimelineTest.cpp", "GameModeTest.cpp", "HWComposerTest.cpp", Loading
services/surfaceflinger/tests/unittests/FrameRateSelectionStrategyTest.cpp 0 → 100644 +159 −0 Original line number Diff line number Diff line /* * 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