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

Commit 04eb8e0b authored by Jerry Chang's avatar Jerry Chang
Browse files

SF: update consistent criteria for heuristic refresh rate calculation

Enlarge the consistent criteria to apply heuristic logic for more cases.
To prevent introducing oscillation, this makes sure to only select a
valid know refresh rate if all the frametime in the layer history have
the same nearest known refresh rate.

Bug: 299201319
Test: presubmit
Change-Id: Ie317f7fe337c84c2c7314069cba1bd02a147bf6b
parent 43881b0f
Loading
Loading
Loading
Loading
+23 −12
Original line number Diff line number Diff line
@@ -276,17 +276,16 @@ std::optional<Fps> LayerInfo::calculateRefreshRateIfPossible(const RefreshRateSe

    if (const auto averageFrameTime = calculateAverageFrameTime()) {
        const auto refreshRate = Fps::fromPeriodNsecs(*averageFrameTime);
        const bool refreshRateConsistent = mRefreshRateHistory.add(refreshRate, now);
        if (refreshRateConsistent) {
            const auto knownRefreshRate = selector.findClosestKnownFrameRate(refreshRate);
        const auto closestKnownRefreshRate = mRefreshRateHistory.add(refreshRate, now, selector);
        if (closestKnownRefreshRate.isValid()) {
            using fps_approx_ops::operator!=;

            // To avoid oscillation, use the last calculated refresh rate if it is close enough.
            if (std::abs(mLastRefreshRate.calculated.getValue() - refreshRate.getValue()) >
                        MARGIN &&
                mLastRefreshRate.reported != knownRefreshRate) {
                mLastRefreshRate.reported != closestKnownRefreshRate) {
                mLastRefreshRate.calculated = refreshRate;
                mLastRefreshRate.reported = knownRefreshRate;
                mLastRefreshRate.reported = closestKnownRefreshRate;
            }

            ALOGV("%s %s rounded to nearest known frame rate %s", mName.c_str(),
@@ -432,7 +431,8 @@ void LayerInfo::RefreshRateHistory::clear() {
    mRefreshRates.clear();
}

bool LayerInfo::RefreshRateHistory::add(Fps refreshRate, nsecs_t now) {
Fps LayerInfo::RefreshRateHistory::add(Fps refreshRate, nsecs_t now,
                                       const RefreshRateSelector& selector) {
    mRefreshRates.push_back({refreshRate, now});
    while (mRefreshRates.size() >= HISTORY_SIZE ||
           now - mRefreshRates.front().timestamp > HISTORY_DURATION.count()) {
@@ -447,11 +447,11 @@ bool LayerInfo::RefreshRateHistory::add(Fps refreshRate, nsecs_t now) {
        ATRACE_INT(mHeuristicTraceTagData->average.c_str(), refreshRate.getIntValue());
    }

    return isConsistent();
    return selectRefreshRate(selector);
}

bool LayerInfo::RefreshRateHistory::isConsistent() const {
    if (mRefreshRates.empty()) return true;
Fps LayerInfo::RefreshRateHistory::selectRefreshRate(const RefreshRateSelector& selector) const {
    if (mRefreshRates.empty()) return Fps();

    const auto [min, max] =
            std::minmax_element(mRefreshRates.begin(), mRefreshRates.end(),
@@ -459,8 +459,19 @@ bool LayerInfo::RefreshRateHistory::isConsistent() const {
                                    return isStrictlyLess(lhs.refreshRate, rhs.refreshRate);
                                });

    const bool consistent =
            max->refreshRate.getValue() - min->refreshRate.getValue() < MARGIN_CONSISTENT_FPS;
    const auto maxClosestRate = selector.findClosestKnownFrameRate(max->refreshRate);
    const bool consistent = [&](Fps maxFps, Fps minFps) {
        if (FlagManager::getInstance().use_known_refresh_rate_for_fps_consistency()) {
            if (maxFps.getValue() - minFps.getValue() <
                MARGIN_CONSISTENT_FPS_FOR_CLOSEST_REFRESH_RATE) {
                const auto minClosestRate = selector.findClosestKnownFrameRate(minFps);
                using fps_approx_ops::operator==;
                return maxClosestRate == minClosestRate;
            }
            return false;
        }
        return maxFps.getValue() - minFps.getValue() < MARGIN_CONSISTENT_FPS;
    }(max->refreshRate, min->refreshRate);

    if (CC_UNLIKELY(sTraceEnabled)) {
        if (!mHeuristicTraceTagData.has_value()) {
@@ -472,7 +483,7 @@ bool LayerInfo::RefreshRateHistory::isConsistent() const {
        ATRACE_INT(mHeuristicTraceTagData->consistent.c_str(), consistent);
    }

    return consistent;
    return consistent ? maxClosestRate : Fps();
}

FrameRateCompatibility LayerInfo::FrameRate::convertCompatibility(int8_t compatibility) {
+4 −3
Original line number Diff line number Diff line
@@ -264,8 +264,8 @@ private:
        // Clears History
        void clear();

        // Adds a new refresh rate and returns true if it is consistent
        bool add(Fps refreshRate, nsecs_t now);
        // Adds a new refresh rate and returns valid refresh rate if it is consistent enough
        Fps add(Fps refreshRate, nsecs_t now, const RefreshRateSelector&);

    private:
        friend class LayerHistoryTest;
@@ -285,13 +285,14 @@ private:
            std::string average;
        };

        bool isConsistent() const;
        Fps selectRefreshRate(const RefreshRateSelector&) const;
        HeuristicTraceTagData makeHeuristicTraceTagData() const;

        const std::string mName;
        mutable std::optional<HeuristicTraceTagData> mHeuristicTraceTagData;
        std::deque<RefreshRateData> mRefreshRates;
        static constexpr float MARGIN_CONSISTENT_FPS = 1.0;
        static constexpr float MARGIN_CONSISTENT_FPS_FOR_CLOSEST_REFRESH_RATE = 5.0;
    };

    // Represents whether we were able to determine either layer is frequent or infrequent
+2 −0
Original line number Diff line number Diff line
@@ -121,6 +121,7 @@ void FlagManager::dump(std::string& result) const {
    DUMP_READ_ONLY_FLAG(hdcp_level_hal);
    DUMP_READ_ONLY_FLAG(multithreaded_present);
    DUMP_READ_ONLY_FLAG(add_sf_skipped_frames_to_trace);
    DUMP_READ_ONLY_FLAG(use_known_refresh_rate_for_fps_consistency);

#undef DUMP_READ_ONLY_FLAG
#undef DUMP_SERVER_FLAG
@@ -190,6 +191,7 @@ FLAG_MANAGER_READ_ONLY_FLAG(hotplug2, "")
FLAG_MANAGER_READ_ONLY_FLAG(hdcp_level_hal, "")
FLAG_MANAGER_READ_ONLY_FLAG(multithreaded_present, "debug.sf.multithreaded_present")
FLAG_MANAGER_READ_ONLY_FLAG(add_sf_skipped_frames_to_trace, "")
FLAG_MANAGER_READ_ONLY_FLAG(use_known_refresh_rate_for_fps_consistency, "")

/// Trunk stable server flags ///
FLAG_MANAGER_SERVER_FLAG(late_boot_misc2, "")
+1 −0
Original line number Diff line number Diff line
@@ -60,6 +60,7 @@ public:
    bool hdcp_level_hal() const;
    bool multithreaded_present() const;
    bool add_sf_skipped_frames_to_trace() const;
    bool use_known_refresh_rate_for_fps_consistency() const;

protected:
    // overridden for unit tests
+8 −0
Original line number Diff line number Diff line
@@ -84,3 +84,11 @@ flag {
  description: "enable refresh rate indicator on the external display"
  bug: "301647974"
}

flag {
  name: "use_known_refresh_rate_for_fps_consistency"
  namespace: "core_graphics"
  description: "Whether to use the closest known refresh rate to determine the fps consistency."
  bug: "299201319"
  is_fixed_read_only: true
}
Loading