Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0faad6c2 authored by Rachel Lee's avatar Rachel Lee
Browse files

Logic for setFrameRateSelectionStrategy.

Use the frameRateSelectionStrategy value stored in Layer to inform the
frame rate propagation in the hierarchy.

Bug: 297418260
Test: atest CtsSurfaceControlTestsStaging
Test: atest libsurfaceflinger_unittest
Change-Id: I05a6a7effd17cefb01421bff10c9ff9dbcadf98a
parent 58cc90d3
Loading
Loading
Loading
Loading
+12 −4
Original line number Diff line number Diff line
@@ -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) {
+7 −1
Original line number Diff line number Diff line
@@ -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.
+1 −0
Original line number Diff line number Diff line
@@ -87,6 +87,7 @@ cc_test {
        "FramebufferSurfaceTest.cpp",
        "FrameRateOverrideMappingsTest.cpp",
        "FrameRateSelectionPriorityTest.cpp",
        "FrameRateSelectionStrategyTest.cpp",
        "FrameTimelineTest.cpp",
        "GameModeTest.cpp",
        "HWComposerTest.cpp",
+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