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

Commit c106457a authored by Ram Indani's avatar Ram Indani Committed by Android (Google) Code Review
Browse files

Merge changes I4b43ff1a,I9d769fc3 into main

* changes:
  [SF] setRenderRate to freeze old timeline at a sequence that aligns with all the FrameRateOverrides
  [SF] Add a flag to align FrameRateOverrides for setRenderRate
parents 566e93a9 afbbd90b
Loading
Loading
Loading
Loading
+3 −2
Original line number Diff line number Diff line
@@ -643,8 +643,9 @@ void Scheduler::setRenderRate(PhysicalDisplayId id, Fps renderFrameRate, bool ap

    ALOGV("%s %s (%s)", __func__, to_string(mode.fps).c_str(),
          to_string(mode.modePtr->getVsyncRate()).c_str());

    display.schedulePtr->getTracker().setRenderRate(renderFrameRate, applyImmediately);
    std::vector<FrameRateOverride> overrides = mFrameRateOverrideMappings.getAllFrameRateOverrides(
            display.selectorPtr->supportsAppFrameRateOverrideByContent());
    display.schedulePtr->getTracker().setRenderRate(renderFrameRate, applyImmediately, overrides);
}

Fps Scheduler::getNextFrameInterval(PhysicalDisplayId id,
+38 −8
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@

#include <algorithm>
#include <chrono>
#include <numeric>
#include <sstream>

#include <android-base/logging.h>
@@ -383,7 +384,8 @@ bool VSyncPredictor::isVSyncInPhase(nsecs_t timePoint, Fps frameRate) {
    return mTimelines.back().isVSyncInPhase(model, vsync, frameRate);
}

void VSyncPredictor::setRenderRate(Fps renderRate, bool applyImmediately) {
void VSyncPredictor::setRenderRate(Fps renderRate, bool applyImmediately,
                                   std::vector<FrameRateOverride> frameRateOverrides) {
    SFTRACE_FORMAT("%s %s", __func__, to_string(renderRate).c_str());
    ALOGV("%s %s: RenderRate %s ", __func__, to_string(mId).c_str(), to_string(renderRate).c_str());
    std::lock_guard lock(mMutex);
@@ -407,14 +409,12 @@ void VSyncPredictor::setRenderRate(Fps renderRate, bool applyImmediately) {
        SFTRACE_FORMAT_INSTANT("newRenderRateIsHigher");
        mTimelines.clear();
        mLastCommittedVsync = TimePoint::fromNs(0);

        mTimelines.emplace_back(mLastCommittedVsync, mIdealPeriod, renderRate);
    } else {
        // We need to freeze the timeline at the committed vsync, and
        // then use with threshold adjustments when required to avoid
        // marginal errors when checking the vsync on the timeline.
        mTimelines.back().freeze(mLastCommittedVsync);
        mTimelines.back().freeze(getVSyncPredictionModelLocked(), mLastCommittedVsync,
                                 frameRateOverrides);
        mTimelines.emplace_back(*(mTimelines.back().validUntil()), mIdealPeriod, renderRate);
    }
    mTimelines.emplace_back(mLastCommittedVsync, mIdealPeriod, renderRate);
    purgeTimelines(TimePoint::fromNs(mClock->now()));
}

@@ -659,14 +659,44 @@ VSyncPredictor::VsyncTimeline::VsyncTimeline(TimePoint knownVsync, Period idealP
        mRenderRateOpt(renderRateOpt),
        mLastVsyncSequence(makeVsyncSequence(knownVsync)) {}

void VSyncPredictor::VsyncTimeline::freeze(TimePoint lastVsync) {
void VSyncPredictor::VsyncTimeline::freeze(Model model, TimePoint lastVsync,
                                           std::vector<FrameRateOverride> frameRateOverrides) {
    LOG_ALWAYS_FATAL_IF(mValidUntil.has_value());
    if (FlagManager::getInstance().vsync_predictor_rate_change_with_aligned_sequence() &&
        !frameRateOverrides.empty() && mLastVsyncSequence) {
        const int64_t renderRatePhase =
                getFreezeSequencePhase(model, lastVsync, std::move(frameRateOverrides));
        lastVsync = TimePoint::fromNs(lastVsync.ns() + model.slope * renderRatePhase);
    }

    SFTRACE_FORMAT_INSTANT("renderRate %s valid for %.2f",
                           mRenderRateOpt ? to_string(*mRenderRateOpt).c_str() : "NA",
                           float(lastVsync.ns() - TimePoint::now().ns()) / 1e6f);
    mValidUntil = lastVsync;
}

int64_t VSyncPredictor::VsyncTimeline::getFreezeSequencePhase(
        Model model, TimePoint lastVsync, std::vector<FrameRateOverride> frameRateOverrides) {
    static constexpr uint32_t kCapacity = 10;
    ftl::SmallMap<Fps, ftl::Unit, kCapacity, FpsApproxEqual> overridesSet;
    for (auto [_, frameRateHz] : frameRateOverrides) {
        overridesSet.emplace_or_replace(Fps::fromValue(frameRateHz));
    }

    const auto idealPeriodFps = Fps::fromPeriodNsecs(mIdealPeriod.ns());

    int64_t divisor = 1;
    for (auto [fps, _] : overridesSet) {
        auto frameRateDivisor = RefreshRateSelector::getFrameRateDivisor(idealPeriodFps, fps);
        if (frameRateDivisor <= 0) continue;
        divisor = std::lcm(divisor, frameRateDivisor);
    }

    const auto lastVsyncSequence = getVsyncSequenceLocked(model, lastVsync.ns());
    auto seq = static_cast<int64_t>(std::ceil(lastVsyncSequence.seq / divisor)) * divisor;
    return seq - lastVsyncSequence.seq;
}

std::optional<TimePoint> VSyncPredictor::VsyncTimeline::nextAnticipatedVSyncTimeFrom(
        Model model, std::optional<Period> minFramePeriodOpt, nsecs_t vsync,
        MissedVsync missedVsync, std::optional<nsecs_t> lastVsyncOpt) {
+7 −2
Original line number Diff line number Diff line
@@ -76,7 +76,8 @@ public:
                mRateMap.find(idealPeriod())->second.slope;
    }

    void setRenderRate(Fps, bool applyImmediately) final EXCLUDES(mMutex);
    void setRenderRate(Fps, bool applyImmediately, std::vector<FrameRateOverride>) final
            EXCLUDES(mMutex);

    void onFrameBegin(TimePoint expectedPresentTime, FrameTime lastSignaledFrameTime) final
            EXCLUDES(mMutex);
@@ -101,7 +102,7 @@ private:
        std::optional<TimePoint> nextAnticipatedVSyncTimeFrom(
                Model model, std::optional<Period> minFramePeriodOpt, nsecs_t vsyncTime,
                MissedVsync lastMissedVsync, std::optional<nsecs_t> lastVsyncOpt = {});
        void freeze(TimePoint lastVsync);
        void freeze(Model, TimePoint lastVsync, std::vector<FrameRateOverride>);
        std::optional<TimePoint> validUntil() const { return mValidUntil; }
        bool isVSyncInPhase(Model, nsecs_t vsync, Fps frameRate);
        void shiftVsyncSequence(Duration phase, Period minFramePeriod);
@@ -118,6 +119,10 @@ private:
        nsecs_t snapToVsyncAlignedWithRenderRate(Model model, nsecs_t vsync);
        VsyncSequence getVsyncSequenceLocked(Model, nsecs_t vsync);
        std::optional<VsyncSequence> makeVsyncSequence(TimePoint knownVsync);
        // Get the phase for vsync sequence where all the provided frameRateOverrides align
        // from the vsync provided.
        int64_t getFreezeSequencePhase(Model, TimePoint vsync,
                                       std::vector<FrameRateOverride> frameRateOverrides);

        const Period mIdealPeriod = Duration::fromNs(0);
        std::optional<Fps> mRenderRateOpt;
+11 −4
Original line number Diff line number Diff line
@@ -23,9 +23,12 @@
#include <scheduler/FrameRateMode.h>
#include <scheduler/FrameTime.h>

#include <gui/DisplayEventReceiver.h>

#include "VSyncDispatch.h"

namespace android::scheduler {
using FrameRateOverride = DisplayEventReceiver::Event::FrameRateOverride;

/*
 * VSyncTracker is an interface for providing estimates on future Vsync signal times based on
@@ -103,15 +106,19 @@ public:
     * Sets a render rate on the tracker. If the render rate is not a divisor
     * of the period, the render rate is ignored until the period changes.
     * The tracker will continue to track the vsync timeline and expect it
     * to match the current period, however, nextAnticipatedVSyncTimeFrom will
     * return vsyncs according to the render rate set. Setting a render rate is useful
     * when a display is running at 120Hz but the render frame rate is 60Hz.
     * to match the current period.
     * nextAnticipatedVSyncTimeFrom will return vsyncs according to the new render rate
     * set only after the point where all the frame rate overrides align.
     * Setting a render rate is useful when a display is running at 120Hz but
     * the render frame rate is 60Hz.
     *
     * \param [in] Fps   The render rate the tracker should operate at.
     * \param [in] applyImmediately Whether to apply the new render rate immediately regardless of
     *                              already committed vsyncs.
     * \param [in] std::vector<FrameRateOverride> list of all the frame rate overrides currently
     *                                            active with the old render rate.
     */
    virtual void setRenderRate(Fps, bool applyImmediately) = 0;
    virtual void setRenderRate(Fps, bool applyImmediately, std::vector<FrameRateOverride>) = 0;

    virtual void onFrameBegin(TimePoint expectedPresentTime, FrameTime lastSignaledFrameTime) = 0;

+2 −0
Original line number Diff line number Diff line
@@ -131,6 +131,7 @@ void FlagManager::dump(std::string& result) const {
    DUMP_ACONFIG_FLAG(increase_missed_frame_jank_threshold);
    DUMP_ACONFIG_FLAG(monitor_buffer_fences);
    DUMP_ACONFIG_FLAG(refresh_rate_overlay_on_external_display);
    DUMP_ACONFIG_FLAG(vsync_predictor_rate_change_with_aligned_sequence);
    DUMP_ACONFIG_FLAG(vsync_predictor_recovery);

    /// Trunk stable readonly flags ///
@@ -306,6 +307,7 @@ FLAG_MANAGER_ACONFIG_FLAG(adpf_native_session_manager, "");
FLAG_MANAGER_ACONFIG_FLAG(graphite_renderengine_preview_rollout, "");
FLAG_MANAGER_ACONFIG_FLAG(increase_missed_frame_jank_threshold, "");
FLAG_MANAGER_ACONFIG_FLAG(monitor_buffer_fences, "");
FLAG_MANAGER_ACONFIG_FLAG(vsync_predictor_rate_change_with_aligned_sequence, "")
FLAG_MANAGER_ACONFIG_FLAG(vsync_predictor_recovery, "");

/// Trunk stable server (R/W) flags from outside SurfaceFlinger ///
Loading