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

Commit 7c24a551 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "SurfaceFlinger: Consider resolution when switching refresh rate" into rvc-dev

parents 696b6c83 abc2760c
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -170,7 +170,7 @@ bool RefreshRateOverlay::createLayer() {
void RefreshRateOverlay::primeCache() {
    auto& allRefreshRates = mFlinger.mRefreshRateConfigs->getAllRefreshRates();
    if (allRefreshRates.size() == 1) {
        auto fps = allRefreshRates.begin()->second->fps;
        auto fps = allRefreshRates.begin()->second->getFps();
        half4 color = {LOW_FPS_COLOR, ALPHA};
        mBufferCache.emplace(fps, SevenSegmentDrawer::drawNumber(fps, color));
        return;
@@ -179,7 +179,7 @@ void RefreshRateOverlay::primeCache() {
    std::vector<uint32_t> supportedFps;
    supportedFps.reserve(allRefreshRates.size());
    for (auto& [ignored, refreshRate] : allRefreshRates) {
        supportedFps.push_back(refreshRate->fps);
        supportedFps.push_back(refreshRate->getFps());
    }

    std::sort(supportedFps.begin(), supportedFps.end());
@@ -207,7 +207,7 @@ void RefreshRateOverlay::changeRefreshRate(const RefreshRate& refreshRate) {
    const int32_t right = left + display->getWidth() / 8;
    const int32_t buttom = top + display->getHeight() / 32;

    auto buffer = mBufferCache[refreshRate.fps];
    auto buffer = mBufferCache[refreshRate.getFps()];
    mLayer->setBuffer(buffer, Fence::NO_FENCE, 0, 0, {});

    mLayer->setFrame(Rect(left, top, right, buttom));
+0 −1
Original line number Diff line number Diff line
@@ -22,6 +22,5 @@ namespace android {

// Strong types for the different indexes as they are referring to a different base.
using HwcConfigIndexType = StrongTyping<int, struct HwcConfigIndexTypeTag, Compare, Add, Hash>;
using HwcConfigGroupType = StrongTyping<int, struct HwcConfigGroupTypeTag, Compare>;

} // namespace android
 No newline at end of file
+3 −3
Original line number Diff line number Diff line
@@ -43,7 +43,7 @@ std::vector<float> getRefreshRatesFromConfigs(
    refreshRates.reserve(allRefreshRates.size());

    for (const auto& [ignored, refreshRate] : allRefreshRates) {
        refreshRates.emplace_back(refreshRate->fps);
        refreshRates.emplace_back(refreshRate->getFps());
    }

    return refreshRates;
@@ -59,7 +59,7 @@ namespace impl {

PhaseOffsets::PhaseOffsets(const scheduler::RefreshRateConfigs& refreshRateConfigs)
      : PhaseOffsets(getRefreshRatesFromConfigs(refreshRateConfigs),
                     refreshRateConfigs.getCurrentRefreshRate().fps,
                     refreshRateConfigs.getCurrentRefreshRate().getFps(),
                     // Below defines the threshold when an offset is considered to be negative,
                     // i.e. targeting for the N+2 vsync instead of N+1. This means that: For offset
                     // < threshold, SF wake up (vsync_duration - offset) before HW vsync. For
@@ -275,7 +275,7 @@ std::unordered_map<float, PhaseDurations::Offsets> PhaseDurations::initializeOff

PhaseDurations::PhaseDurations(const scheduler::RefreshRateConfigs& refreshRateConfigs)
      : PhaseDurations(getRefreshRatesFromConfigs(refreshRateConfigs),
                       refreshRateConfigs.getCurrentRefreshRate().fps,
                       refreshRateConfigs.getCurrentRefreshRate().getFps(),
                       getProperty("debug.sf.late.sf.duration").value_or(-1),
                       getProperty("debug.sf.late.app.duration").value_or(-1),
                       getProperty("debug.sf.early.sf.duration").value_or(mSfDuration),
+38 −45
Original line number Diff line number Diff line
@@ -53,7 +53,7 @@ const RefreshRate& RefreshRateConfigs::getRefreshRateForContent(
    if (explicitContentFramerate != 0) {
        contentFramerate = explicitContentFramerate;
    } else if (contentFramerate == 0) {
        contentFramerate = round<int>(mMaxSupportedRefreshRate->fps);
        contentFramerate = round<int>(mMaxSupportedRefreshRate->getFps());
    }
    ATRACE_INT("ContentFPS", contentFramerate);

@@ -177,7 +177,7 @@ const RefreshRate& RefreshRateConfigs::getRefreshRateForContentV2(
                continue;
            }

            const auto displayPeriod = scores[i].first->vsyncPeriod;
            const auto displayPeriod = scores[i].first->hwcConfig->getVsyncPeriod();
            const auto layerPeriod = round<nsecs_t>(1e9f / layer.desiredRefreshRate);
            if (layer.vote == LayerVoteType::ExplicitDefault) {
                const auto layerScore = [&]() {
@@ -309,21 +309,30 @@ void RefreshRateConfigs::setCurrentConfigId(HwcConfigIndexType configId) {
    mCurrentRefreshRate = mRefreshRates.at(configId).get();
}

RefreshRateConfigs::RefreshRateConfigs(const std::vector<InputConfig>& configs,
                                       HwcConfigIndexType currentHwcConfig) {
    init(configs, currentHwcConfig);
}

RefreshRateConfigs::RefreshRateConfigs(
        const std::vector<std::shared_ptr<const HWC2::Display::Config>>& configs,
        HwcConfigIndexType currentConfigId) {
    std::vector<InputConfig> inputConfigs;
    for (size_t configId = 0; configId < configs.size(); ++configId) {
        auto configGroup = HwcConfigGroupType(configs[configId]->getConfigGroup());
        inputConfigs.push_back({HwcConfigIndexType(static_cast<int>(configId)), configGroup,
                                configs[configId]->getVsyncPeriod()});
    LOG_ALWAYS_FATAL_IF(configs.empty());
    LOG_ALWAYS_FATAL_IF(currentConfigId.value() >= configs.size());

    for (auto configId = HwcConfigIndexType(0); configId.value() < configs.size(); configId++) {
        const auto& config = configs.at(static_cast<size_t>(configId.value()));
        const float fps = 1e9f / config->getVsyncPeriod();
        mRefreshRates.emplace(configId,
                              std::make_unique<RefreshRate>(configId, config,
                                                            base::StringPrintf("%2.ffps", fps), fps,
                                                            RefreshRate::ConstructorTag(0)));
        if (configId == currentConfigId) {
            mCurrentRefreshRate = mRefreshRates.at(configId).get();
        }
    }
    init(inputConfigs, currentConfigId);

    std::vector<const RefreshRate*> sortedConfigs;
    getSortedRefreshRateList([](const RefreshRate&) { return true; }, &sortedConfigs);
    mDisplayManagerPolicy.defaultConfig = currentConfigId;
    mMinSupportedRefreshRate = sortedConfigs.front();
    mMaxSupportedRefreshRate = sortedConfigs.back();
    constructAvailableRefreshRates();
}

bool RefreshRateConfigs::isPolicyValid(const Policy& policy) {
@@ -406,10 +415,13 @@ void RefreshRateConfigs::getSortedRefreshRateList(

    std::sort(outRefreshRates->begin(), outRefreshRates->end(),
              [](const auto refreshRate1, const auto refreshRate2) {
                  if (refreshRate1->vsyncPeriod != refreshRate2->vsyncPeriod) {
                      return refreshRate1->vsyncPeriod > refreshRate2->vsyncPeriod;
                  if (refreshRate1->hwcConfig->getVsyncPeriod() !=
                      refreshRate2->hwcConfig->getVsyncPeriod()) {
                      return refreshRate1->hwcConfig->getVsyncPeriod() >
                              refreshRate2->hwcConfig->getVsyncPeriod();
                  } else {
                      return refreshRate1->configGroup > refreshRate2->configGroup;
                      return refreshRate1->hwcConfig->getConfigGroup() >
                              refreshRate2->hwcConfig->getConfigGroup();
                  }
              });
}
@@ -417,13 +429,20 @@ void RefreshRateConfigs::getSortedRefreshRateList(
void RefreshRateConfigs::constructAvailableRefreshRates() {
    // Filter configs based on current policy and sort based on vsync period
    const Policy* policy = getCurrentPolicyLocked();
    HwcConfigGroupType group = mRefreshRates.at(policy->defaultConfig)->configGroup;
    const auto& defaultConfig = mRefreshRates.at(policy->defaultConfig)->hwcConfig;
    ALOGV("constructAvailableRefreshRates: default %d group %d min %.2f max %.2f",
          policy->defaultConfig.value(), group.value(), policy->minRefreshRate,
          policy->defaultConfig.value(), defaultConfig->getConfigGroup(), policy->minRefreshRate,
          policy->maxRefreshRate);
    getSortedRefreshRateList(
            [&](const RefreshRate& refreshRate) REQUIRES(mLock) {
                return (policy->allowGroupSwitching || refreshRate.configGroup == group) &&
                const auto& hwcConfig = refreshRate.hwcConfig;

                return hwcConfig->getHeight() == defaultConfig->getHeight() &&
                        hwcConfig->getWidth() == defaultConfig->getWidth() &&
                        hwcConfig->getDpiX() == defaultConfig->getDpiX() &&
                        hwcConfig->getDpiY() == defaultConfig->getDpiY() &&
                        (policy->allowGroupSwitching ||
                         hwcConfig->getConfigGroup() == defaultConfig->getConfigGroup()) &&
                        refreshRate.inPolicy(policy->minRefreshRate, policy->maxRefreshRate);
            },
            &mAvailableRefreshRates);
@@ -440,30 +459,4 @@ void RefreshRateConfigs::constructAvailableRefreshRates() {
                        policy->maxRefreshRate);
}

// NO_THREAD_SAFETY_ANALYSIS since this is called from the constructor
void RefreshRateConfigs::init(const std::vector<InputConfig>& configs,
                              HwcConfigIndexType currentHwcConfig) NO_THREAD_SAFETY_ANALYSIS {
    LOG_ALWAYS_FATAL_IF(configs.empty());
    LOG_ALWAYS_FATAL_IF(currentHwcConfig.value() >= configs.size());

    for (const auto& config : configs) {
        const float fps = 1e9f / config.vsyncPeriod;
        mRefreshRates.emplace(config.configId,
                              std::make_unique<RefreshRate>(config.configId, config.vsyncPeriod,
                                                            config.configGroup,
                                                            base::StringPrintf("%2.ffps", fps),
                                                            fps));
        if (config.configId == currentHwcConfig) {
            mCurrentRefreshRate = mRefreshRates.at(config.configId).get();
        }
    }

    std::vector<const RefreshRate*> sortedConfigs;
    getSortedRefreshRateList([](const RefreshRate&) { return true; }, &sortedConfigs);
    mDisplayManagerPolicy.defaultConfig = currentHwcConfig;
    mMinSupportedRefreshRate = sortedConfigs.front();
    mMaxSupportedRefreshRate = sortedConfigs.back();
    constructAvailableRefreshRates();
}

} // namespace android::scheduler
+38 −33
Original line number Diff line number Diff line
@@ -29,6 +29,8 @@
#include "Scheduler/StrongTyping.h"

namespace android::scheduler {
class RefreshRateConfigsTest;

using namespace std::chrono_literals;

enum class RefreshRateConfigEvent : unsigned { None = 0b0, Changed = 0b1 };
@@ -49,30 +51,27 @@ public:
    static constexpr nsecs_t MARGIN_FOR_PERIOD_CALCULATION =
        std::chrono::nanoseconds(800us).count();

    struct RefreshRate {
        // The tolerance within which we consider FPS approximately equals.
        static constexpr float FPS_EPSILON = 0.001f;
    class RefreshRate {
    private:
        // Effectively making the constructor private while allowing
        // std::make_unique to create the object
        struct ConstructorTag {
            explicit ConstructorTag(int) {}
        };

        RefreshRate(HwcConfigIndexType configId, nsecs_t vsyncPeriod,
                    HwcConfigGroupType configGroup, std::string name, float fps)
              : configId(configId),
                vsyncPeriod(vsyncPeriod),
                configGroup(configGroup),
                name(std::move(name)),
                fps(fps) {}
    public:
        RefreshRate(HwcConfigIndexType configId,
                    std::shared_ptr<const HWC2::Display::Config> config, std::string name,
                    float fps, ConstructorTag)
              : configId(configId), hwcConfig(config), name(std::move(name)), fps(fps) {}

        RefreshRate(const RefreshRate&) = delete;
        // This config ID corresponds to the position of the config in the vector that is stored
        // on the device.
        const HwcConfigIndexType configId;
        // Vsync period in nanoseconds.
        const nsecs_t vsyncPeriod;
        // This configGroup for the config.
        const HwcConfigGroupType configGroup;
        // Human readable name of the refresh rate.
        const std::string name;
        // Refresh rate in frames per second
        const float fps = 0;

        HwcConfigIndexType getConfigId() const { return configId; }
        nsecs_t getVsyncPeriod() const { return hwcConfig->getVsyncPeriod(); }
        int32_t getConfigGroup() const { return hwcConfig->getConfigGroup(); }
        const std::string& getName() const { return name; }
        float getFps() const { return fps; }

        // Checks whether the fps of this RefreshRate struct is within a given min and max refresh
        // rate passed in. FPS_EPSILON is applied to the boundaries for approximation.
@@ -81,11 +80,27 @@ public:
        }

        bool operator!=(const RefreshRate& other) const {
            return configId != other.configId || vsyncPeriod != other.vsyncPeriod ||
                    configGroup != other.configGroup;
            return configId != other.configId || hwcConfig != other.hwcConfig;
        }

        bool operator==(const RefreshRate& other) const { return !(*this != other); }

    private:
        friend RefreshRateConfigs;
        friend RefreshRateConfigsTest;

        // The tolerance within which we consider FPS approximately equals.
        static constexpr float FPS_EPSILON = 0.001f;

        // This config ID corresponds to the position of the config in the vector that is stored
        // on the device.
        const HwcConfigIndexType configId;
        // The config itself
        std::shared_ptr<const HWC2::Display::Config> hwcConfig;
        // Human readable name of the refresh rate.
        const std::string name;
        // Refresh rate in frames per second
        const float fps = 0;
    };

    using AllRefreshRatesMapType =
@@ -208,20 +223,10 @@ public:
    // Stores the current configId the device operates at
    void setCurrentConfigId(HwcConfigIndexType configId) EXCLUDES(mLock);

    struct InputConfig {
        HwcConfigIndexType configId = HwcConfigIndexType(0);
        HwcConfigGroupType configGroup = HwcConfigGroupType(0);
        nsecs_t vsyncPeriod = 0;
    };

    RefreshRateConfigs(const std::vector<InputConfig>& configs,
                       HwcConfigIndexType currentHwcConfig);
    RefreshRateConfigs(const std::vector<std::shared_ptr<const HWC2::Display::Config>>& configs,
                       HwcConfigIndexType currentConfigId);

private:
    void init(const std::vector<InputConfig>& configs, HwcConfigIndexType currentHwcConfig);

    void constructAvailableRefreshRates() REQUIRES(mLock);

    void getSortedRefreshRateList(
Loading