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

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

Merge "SF: Avoid adjusting Vsync Timeline when minFramePeriod isn't violated" into main

parents 0f499e82 3614e0b2
Loading
Loading
Loading
Loading
+12 −5
Original line number Diff line number Diff line
@@ -452,7 +452,7 @@ Duration VSyncPredictor::ensureMinFrameDurationIsKept(TimePoint expectedPresentT

    const auto currentPeriod = mRateMap.find(idealPeriod())->second.slope;
    const auto threshold = currentPeriod / 2;
    const auto minFramePeriod = minFramePeriodLocked().ns();
    const auto minFramePeriod = minFramePeriodLocked();

    auto prev = lastConfirmedPresentTime.ns();
    for (auto& current : mPastExpectedPresentTimes) {
@@ -463,10 +463,10 @@ Duration VSyncPredictor::ensureMinFrameDurationIsKept(TimePoint expectedPresentT
                                           1e6f);
        }

        const auto minPeriodViolation = current.ns() - prev + threshold < minFramePeriod;
        const auto minPeriodViolation = current.ns() - prev + threshold < minFramePeriod.ns();
        if (minPeriodViolation) {
            SFTRACE_NAME("minPeriodViolation");
            current = TimePoint::fromNs(prev + minFramePeriod);
            current = TimePoint::fromNs(prev + minFramePeriod.ns());
            prev = current.ns();
        } else {
            break;
@@ -477,7 +477,7 @@ Duration VSyncPredictor::ensureMinFrameDurationIsKept(TimePoint expectedPresentT
        const auto phase = Duration(mPastExpectedPresentTimes.back() - expectedPresentTime);
        if (phase > 0ns) {
            for (auto& timeline : mTimelines) {
                timeline.shiftVsyncSequence(phase);
                timeline.shiftVsyncSequence(phase, minFramePeriod);
            }
            mPastExpectedPresentTimes.clear();
            return phase;
@@ -778,8 +778,15 @@ bool VSyncPredictor::VsyncTimeline::isVSyncInPhase(Model model, nsecs_t vsync, F
    return vsyncSequence.seq % divisor == 0;
}

void VSyncPredictor::VsyncTimeline::shiftVsyncSequence(Duration phase) {
void VSyncPredictor::VsyncTimeline::shiftVsyncSequence(Duration phase, Period minFramePeriod) {
    if (mLastVsyncSequence) {
        const auto renderRate = mRenderRateOpt.value_or(Fps::fromPeriodNsecs(mIdealPeriod.ns()));
        const auto threshold = mIdealPeriod.ns() / 2;
        if (renderRate.getPeriodNsecs() - phase.ns() + threshold >= minFramePeriod.ns()) {
            SFTRACE_FORMAT_INSTANT("Not-Adjusting vsync by %.2f",
                                   static_cast<float>(phase.ns()) / 1e6f);
            return;
        }
        SFTRACE_FORMAT_INSTANT("adjusting vsync by %.2f", static_cast<float>(phase.ns()) / 1e6f);
        mLastVsyncSequence->vsyncTime += phase.ns();
    }
+1 −1
Original line number Diff line number Diff line
@@ -104,7 +104,7 @@ private:
        void freeze(TimePoint lastVsync);
        std::optional<TimePoint> validUntil() const { return mValidUntil; }
        bool isVSyncInPhase(Model, nsecs_t vsync, Fps frameRate);
        void shiftVsyncSequence(Duration phase);
        void shiftVsyncSequence(Duration phase, Period minFramePeriod);
        void setRenderRate(std::optional<Fps> renderRateOpt) { mRenderRateOpt = renderRateOpt; }

        enum class VsyncOnTimeline {
+30 −0
Original line number Diff line number Diff line
@@ -1055,6 +1055,36 @@ TEST_F(VSyncPredictorTest, timelineNotAdjustedForEarlyPresent) {
    EXPECT_EQ(2000, vrrTracker.nextAnticipatedVSyncTimeFrom(1400, 1000));
    EXPECT_EQ(3000, vrrTracker.nextAnticipatedVSyncTimeFrom(2000, 1000));
}

TEST_F(VSyncPredictorTest, adjustsOnlyMinFrameViolatingVrrTimeline) {
    const auto refreshRate = Fps::fromPeriodNsecs(500);
    auto minFrameRate = Fps::fromPeriodNsecs(1000);
    hal::VrrConfig vrrConfig{.minFrameIntervalNs =
                                     static_cast<int32_t>(minFrameRate.getPeriodNsecs())};
    ftl::NonNull<DisplayModePtr> mode =
            ftl::as_non_null(createVrrDisplayMode(DisplayModeId(0), refreshRate, vrrConfig));
    VSyncPredictor vrrTracker{std::make_unique<ClockWrapper>(mClock), mode, kHistorySize,
                              kMinimumSamplesForPrediction, kOutlierTolerancePercent};
    vrrTracker.setRenderRate(minFrameRate, /*applyImmediately*/ false);
    vrrTracker.addVsyncTimestamp(0);

    EXPECT_EQ(1000, vrrTracker.nextAnticipatedVSyncTimeFrom(700));
    EXPECT_EQ(2000, vrrTracker.nextAnticipatedVSyncTimeFrom(1000));
    auto lastConfirmedSignalTime = TimePoint::fromNs(1500);
    auto lastConfirmedExpectedPresentTime = TimePoint::fromNs(1000);
    vrrTracker.onFrameBegin(TimePoint::fromNs(2000),
                            {lastConfirmedSignalTime, lastConfirmedExpectedPresentTime});
    EXPECT_EQ(3500, vrrTracker.nextAnticipatedVSyncTimeFrom(3000, 1500));

    minFrameRate = Fps::fromPeriodNsecs(2000);
    vrrTracker.setRenderRate(minFrameRate, /*applyImmediately*/ false);
    lastConfirmedSignalTime = TimePoint::fromNs(2500);
    lastConfirmedExpectedPresentTime = TimePoint::fromNs(2500);
    vrrTracker.onFrameBegin(TimePoint::fromNs(3000),
                            {lastConfirmedSignalTime, lastConfirmedExpectedPresentTime});
    // Enough time without adjusting vsync to present with new rate on time, no need of adjustment
    EXPECT_EQ(5500, vrrTracker.nextAnticipatedVSyncTimeFrom(4000, 3500));
}
} // namespace android::scheduler

// TODO(b/129481165): remove the #pragma below and fix conversion issues