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

Commit 5a85855b authored by Ady Abraham's avatar Ady Abraham
Browse files

SF: move VSyncTracker and VSyncDispatch ownership to Scheduler

This is a first change towards removing the old DispSync interface
for VSyncReactor. This change allows Scheduler to use VSyncTracker and
VSyncDispatch directly to schedule work-based vsync callback rather than
periodic, to get better control on scheduling app / sf vsync callbacks.

Test: adb shell /data/nativetest64/libsurfaceflinger_unittest/libsurfaceflinger_unittest
Change-Id: I81637bf458337b03489faa580a79afa05f47c6c8
parent 1abf04d8
Loading
Loading
Loading
Loading
+41 −26
Original line number Original line Diff line number Diff line
@@ -61,36 +61,46 @@
    } while (false)
    } while (false)


namespace android {
namespace android {

namespace {
namespace {


std::unique_ptr<DispSync> createDispSync(bool supportKernelTimer) {
std::unique_ptr<scheduler::VSyncTracker> createVSyncTracker() {
    // TODO (140302863) remove this and use the vsync_reactor system.
    if (property_get_bool("debug.sf.vsync_reactor", true)) {
    // TODO (144707443) tune Predictor tunables.
    // TODO (144707443) tune Predictor tunables.
        static constexpr int defaultRate = 60;
    static constexpr int default_rate = 60;
        static constexpr auto initialPeriod =
    static constexpr auto initial_period =
                std::chrono::duration<nsecs_t, std::ratio<1, defaultRate>>(1);
            std::chrono::duration<nsecs_t, std::ratio<1, default_rate>>(1);
    static constexpr size_t vsyncTimestampHistorySize = 20;
    static constexpr size_t vsyncTimestampHistorySize = 20;
    static constexpr size_t minimumSamplesForPrediction = 6;
    static constexpr size_t minimumSamplesForPrediction = 6;
    static constexpr uint32_t discardOutlierPercent = 20;
    static constexpr uint32_t discardOutlierPercent = 20;
        auto tracker = std::make_unique<
    return std::make_unique<
            scheduler::VSyncPredictor>(std::chrono::duration_cast<std::chrono::nanoseconds>(
            scheduler::VSyncPredictor>(std::chrono::duration_cast<std::chrono::nanoseconds>(
                                                   initialPeriod)
                                               initial_period)
                                               .count(),
                                               .count(),
                                       vsyncTimestampHistorySize, minimumSamplesForPrediction,
                                       vsyncTimestampHistorySize, minimumSamplesForPrediction,
                                       discardOutlierPercent);
                                       discardOutlierPercent);
}

std::unique_ptr<scheduler::VSyncDispatch> createVSyncDispatch(
        const std::unique_ptr<scheduler::VSyncTracker>& vSyncTracker) {
    if (!vSyncTracker) return {};


    // TODO (144707443) tune Predictor tunables.
    static constexpr auto vsyncMoveThreshold =
    static constexpr auto vsyncMoveThreshold =
            std::chrono::duration_cast<std::chrono::nanoseconds>(3ms);
            std::chrono::duration_cast<std::chrono::nanoseconds>(3ms);
        static constexpr auto timerSlack =
    static constexpr auto timerSlack = std::chrono::duration_cast<std::chrono::nanoseconds>(500us);
                std::chrono::duration_cast<std::chrono::nanoseconds>(500us);
    return std::make_unique<
        auto dispatch = std::make_unique<
            scheduler::VSyncDispatchTimerQueue>(std::make_unique<scheduler::Timer>(), *vSyncTracker,
                scheduler::VSyncDispatchTimerQueue>(std::make_unique<scheduler::Timer>(), *tracker,
                                                timerSlack.count(), vsyncMoveThreshold.count());
                                                timerSlack.count(), vsyncMoveThreshold.count());
}


std::unique_ptr<DispSync> createDispSync(
        const std::unique_ptr<scheduler::VSyncTracker>& vSyncTracker,
        const std::unique_ptr<scheduler::VSyncDispatch>& vSyncDispatch, bool supportKernelTimer) {
    if (vSyncTracker && vSyncDispatch) {
        // TODO (144707443) tune Predictor tunables.
        static constexpr size_t pendingFenceLimit = 20;
        static constexpr size_t pendingFenceLimit = 20;
        return std::make_unique<scheduler::VSyncReactor>(std::make_unique<scheduler::SystemClock>(),
        return std::make_unique<scheduler::VSyncReactor>(std::make_unique<scheduler::SystemClock>(),
                                                         std::move(dispatch), std::move(tracker),
                                                         *vSyncDispatch, *vSyncTracker,
                                                         pendingFenceLimit, supportKernelTimer);
                                                         pendingFenceLimit, supportKernelTimer);
    } else {
    } else {
        return std::make_unique<impl::DispSync>("SchedulerDispSync",
        return std::make_unique<impl::DispSync>("SchedulerDispSync",
@@ -110,7 +120,11 @@ Scheduler::Scheduler(impl::EventControlThread::SetVSyncEnabledFunction function,
                     ISchedulerCallback& schedulerCallback, bool useContentDetectionV2,
                     ISchedulerCallback& schedulerCallback, bool useContentDetectionV2,
                     bool useContentDetection)
                     bool useContentDetection)
      : mSupportKernelTimer(sysprop::support_kernel_idle_timer(false)),
      : mSupportKernelTimer(sysprop::support_kernel_idle_timer(false)),
        mPrimaryDispSync(createDispSync(mSupportKernelTimer)),
        // TODO (140302863) remove this and use the vsync_reactor system.
        mUseVsyncPredictor(property_get_bool("debug.sf.vsync_reactor", true)),
        mVSyncTracker(mUseVsyncPredictor ? createVSyncTracker() : nullptr),
        mVSyncDispatch(createVSyncDispatch(mVSyncTracker)),
        mPrimaryDispSync(createDispSync(mVSyncTracker, mVSyncDispatch, mSupportKernelTimer)),
        mEventControlThread(new impl::EventControlThread(std::move(function))),
        mEventControlThread(new impl::EventControlThread(std::move(function))),
        mLayerHistory(createLayerHistory(refreshRateConfigs, useContentDetectionV2)),
        mLayerHistory(createLayerHistory(refreshRateConfigs, useContentDetectionV2)),
        mSchedulerCallback(schedulerCallback),
        mSchedulerCallback(schedulerCallback),
@@ -156,6 +170,7 @@ Scheduler::Scheduler(std::unique_ptr<DispSync> primaryDispSync,
                     std::unique_ptr<LayerHistory> layerHistory, bool useContentDetectionV2,
                     std::unique_ptr<LayerHistory> layerHistory, bool useContentDetectionV2,
                     bool useContentDetection)
                     bool useContentDetection)
      : mSupportKernelTimer(false),
      : mSupportKernelTimer(false),
        mUseVsyncPredictor(true),
        mPrimaryDispSync(std::move(primaryDispSync)),
        mPrimaryDispSync(std::move(primaryDispSync)),
        mEventControlThread(std::move(eventControlThread)),
        mEventControlThread(std::move(eventControlThread)),
        mLayerHistory(std::move(layerHistory)),
        mLayerHistory(std::move(layerHistory)),
+8 −1
Original line number Original line Diff line number Diff line
@@ -44,7 +44,11 @@ using scheduler::LayerHistory;
class DispSync;
class DispSync;
class FenceTime;
class FenceTime;
class InjectVSyncSource;
class InjectVSyncSource;
struct DisplayStateInfo;

namespace scheduler {
class VSyncDispatch;
class VSyncTracker;
} // namespace scheduler


class ISchedulerCallback {
class ISchedulerCallback {
public:
public:
@@ -230,6 +234,9 @@ private:
    // Whether to use idle timer callbacks that support the kernel timer.
    // Whether to use idle timer callbacks that support the kernel timer.
    const bool mSupportKernelTimer;
    const bool mSupportKernelTimer;


    const bool mUseVsyncPredictor;
    const std::unique_ptr<scheduler::VSyncTracker> mVSyncTracker;
    const std::unique_ptr<scheduler::VSyncDispatch> mVSyncDispatch;
    std::unique_ptr<DispSync> mPrimaryDispSync;
    std::unique_ptr<DispSync> mPrimaryDispSync;
    std::unique_ptr<EventControlThread> mEventControlThread;
    std::unique_ptr<EventControlThread> mEventControlThread;


+23 −23
Original line number Original line Diff line number Diff line
@@ -55,15 +55,15 @@ private:
    }
    }
};
};


VSyncReactor::VSyncReactor(std::unique_ptr<Clock> clock, std::unique_ptr<VSyncDispatch> dispatch,
VSyncReactor::VSyncReactor(std::unique_ptr<Clock> clock, VSyncDispatch& dispatch,
                           std::unique_ptr<VSyncTracker> tracker, size_t pendingFenceLimit,
                           VSyncTracker& tracker, size_t pendingFenceLimit,
                           bool supportKernelIdleTimer)
                           bool supportKernelIdleTimer)
      : mClock(std::move(clock)),
      : mClock(std::move(clock)),
        mTracker(std::move(tracker)),
        mTracker(tracker),
        mDispatch(std::move(dispatch)),
        mDispatch(dispatch),
        mPendingLimit(pendingFenceLimit),
        mPendingLimit(pendingFenceLimit),
        mPredictedVsyncTracer(property_get_bool("debug.sf.show_predicted_vsync", false)
        mPredictedVsyncTracer(property_get_bool("debug.sf.show_predicted_vsync", false)
                                      ? std::make_unique<PredictedVsyncTracer>(*mDispatch)
                                      ? std::make_unique<PredictedVsyncTracer>(mDispatch)
                                      : nullptr),
                                      : nullptr),
        mSupportKernelIdleTimer(supportKernelIdleTimer) {}
        mSupportKernelIdleTimer(supportKernelIdleTimer) {}


@@ -182,7 +182,7 @@ bool VSyncReactor::addPresentFence(const std::shared_ptr<FenceTime>& fence) {
        } else if (time == Fence::SIGNAL_TIME_INVALID) {
        } else if (time == Fence::SIGNAL_TIME_INVALID) {
            it = mUnfiredFences.erase(it);
            it = mUnfiredFences.erase(it);
        } else {
        } else {
            timestampAccepted &= mTracker->addVsyncTimestamp(time);
            timestampAccepted &= mTracker.addVsyncTimestamp(time);


            it = mUnfiredFences.erase(it);
            it = mUnfiredFences.erase(it);
        }
        }
@@ -194,7 +194,7 @@ bool VSyncReactor::addPresentFence(const std::shared_ptr<FenceTime>& fence) {
        }
        }
        mUnfiredFences.push_back(fence);
        mUnfiredFences.push_back(fence);
    } else {
    } else {
        timestampAccepted &= mTracker->addVsyncTimestamp(signalTime);
        timestampAccepted &= mTracker.addVsyncTimestamp(signalTime);
    }
    }


    if (!timestampAccepted) {
    if (!timestampAccepted) {
@@ -224,12 +224,12 @@ void VSyncReactor::updateIgnorePresentFencesInternal() {
}
}


nsecs_t VSyncReactor::computeNextRefresh(int periodOffset, nsecs_t now) const {
nsecs_t VSyncReactor::computeNextRefresh(int periodOffset, nsecs_t now) const {
    auto const currentPeriod = periodOffset ? mTracker->currentPeriod() : 0;
    auto const currentPeriod = periodOffset ? mTracker.currentPeriod() : 0;
    return mTracker->nextAnticipatedVSyncTimeFrom(now + periodOffset * currentPeriod);
    return mTracker.nextAnticipatedVSyncTimeFrom(now + periodOffset * currentPeriod);
}
}


nsecs_t VSyncReactor::expectedPresentTime(nsecs_t now) {
nsecs_t VSyncReactor::expectedPresentTime(nsecs_t now) {
    return mTracker->nextAnticipatedVSyncTimeFrom(now);
    return mTracker.nextAnticipatedVSyncTimeFrom(now);
}
}


void VSyncReactor::startPeriodTransition(nsecs_t newPeriod) {
void VSyncReactor::startPeriodTransition(nsecs_t newPeriod) {
@@ -262,11 +262,11 @@ void VSyncReactor::setPeriod(nsecs_t period) {
}
}


nsecs_t VSyncReactor::getPeriod() {
nsecs_t VSyncReactor::getPeriod() {
    return mTracker->currentPeriod();
    return mTracker.currentPeriod();
}
}


void VSyncReactor::beginResync() {
void VSyncReactor::beginResync() {
    mTracker->resetModel();
    mTracker.resetModel();
}
}


void VSyncReactor::endResync() {}
void VSyncReactor::endResync() {}
@@ -307,7 +307,7 @@ bool VSyncReactor::addResyncSample(nsecs_t timestamp, std::optional<nsecs_t> hwc
    if (periodConfirmed(timestamp, hwcVsyncPeriod)) {
    if (periodConfirmed(timestamp, hwcVsyncPeriod)) {
        ATRACE_NAME("VSR: period confirmed");
        ATRACE_NAME("VSR: period confirmed");
        if (mPeriodTransitioningTo) {
        if (mPeriodTransitioningTo) {
            mTracker->setPeriod(*mPeriodTransitioningTo);
            mTracker.setPeriod(*mPeriodTransitioningTo);
            for (auto& entry : mCallbacks) {
            for (auto& entry : mCallbacks) {
                entry.second->setPeriod(*mPeriodTransitioningTo);
                entry.second->setPeriod(*mPeriodTransitioningTo);
            }
            }
@@ -315,12 +315,12 @@ bool VSyncReactor::addResyncSample(nsecs_t timestamp, std::optional<nsecs_t> hwc
        }
        }


        if (mLastHwVsync) {
        if (mLastHwVsync) {
            mTracker->addVsyncTimestamp(*mLastHwVsync);
            mTracker.addVsyncTimestamp(*mLastHwVsync);
        }
        }
        mTracker->addVsyncTimestamp(timestamp);
        mTracker.addVsyncTimestamp(timestamp);


        endPeriodTransition();
        endPeriodTransition();
        mMoreSamplesNeeded = mTracker->needsMoreSamples();
        mMoreSamplesNeeded = mTracker.needsMoreSamples();
    } else if (mPeriodConfirmationInProgress) {
    } else if (mPeriodConfirmationInProgress) {
        ATRACE_NAME("VSR: still confirming period");
        ATRACE_NAME("VSR: still confirming period");
        mLastHwVsync = timestamp;
        mLastHwVsync = timestamp;
@@ -329,8 +329,8 @@ bool VSyncReactor::addResyncSample(nsecs_t timestamp, std::optional<nsecs_t> hwc
    } else {
    } else {
        ATRACE_NAME("VSR: adding sample");
        ATRACE_NAME("VSR: adding sample");
        *periodFlushed = false;
        *periodFlushed = false;
        mTracker->addVsyncTimestamp(timestamp);
        mTracker.addVsyncTimestamp(timestamp);
        mMoreSamplesNeeded = mTracker->needsMoreSamples();
        mMoreSamplesNeeded = mTracker.needsMoreSamples();
    }
    }


    if (!mMoreSamplesNeeded) {
    if (!mMoreSamplesNeeded) {
@@ -353,9 +353,9 @@ status_t VSyncReactor::addEventListener(const char* name, nsecs_t phase,
            return NO_MEMORY;
            return NO_MEMORY;
        }
        }


        auto const period = mTracker->currentPeriod();
        auto const period = mTracker.currentPeriod();
        auto repeater = std::make_unique<CallbackRepeater>(*mDispatch, callback, name, period,
        auto repeater = std::make_unique<CallbackRepeater>(mDispatch, callback, name, period, phase,
                                                           phase, mClock->now());
                                                           mClock->now());
        it = mCallbacks.emplace(std::pair(callback, std::move(repeater))).first;
        it = mCallbacks.emplace(std::pair(callback, std::move(repeater))).first;
    }
    }


@@ -409,9 +409,9 @@ void VSyncReactor::dump(std::string& result) const {
    }
    }


    StringAppendF(&result, "VSyncTracker:\n");
    StringAppendF(&result, "VSyncTracker:\n");
    mTracker->dump(result);
    mTracker.dump(result);
    StringAppendF(&result, "VSyncDispatch:\n");
    StringAppendF(&result, "VSyncDispatch:\n");
    mDispatch->dump(result);
    mDispatch.dump(result);
}
}


void VSyncReactor::reset() {}
void VSyncReactor::reset() {}
+4 −5
Original line number Original line Diff line number Diff line
@@ -35,9 +35,8 @@ class PredictedVsyncTracer;
// TODO (b/145217110): consider renaming.
// TODO (b/145217110): consider renaming.
class VSyncReactor : public android::DispSync {
class VSyncReactor : public android::DispSync {
public:
public:
    VSyncReactor(std::unique_ptr<Clock> clock, std::unique_ptr<VSyncDispatch> dispatch,
    VSyncReactor(std::unique_ptr<Clock> clock, VSyncDispatch& dispatch, VSyncTracker& tracker,
                 std::unique_ptr<VSyncTracker> tracker, size_t pendingFenceLimit,
                 size_t pendingFenceLimit, bool supportKernelIdleTimer);
                 bool supportKernelIdleTimer);
    ~VSyncReactor();
    ~VSyncReactor();


    bool addPresentFence(const std::shared_ptr<FenceTime>& fence) final;
    bool addPresentFence(const std::shared_ptr<FenceTime>& fence) final;
@@ -72,8 +71,8 @@ private:
            REQUIRES(mMutex);
            REQUIRES(mMutex);


    std::unique_ptr<Clock> const mClock;
    std::unique_ptr<Clock> const mClock;
    std::unique_ptr<VSyncTracker> const mTracker;
    VSyncTracker& mTracker;
    std::unique_ptr<VSyncDispatch> const mDispatch;
    VSyncDispatch& mDispatch;
    size_t const mPendingLimit;
    size_t const mPendingLimit;


    mutable std::mutex mMutex;
    mutable std::mutex mMutex;
+5 −51
Original line number Original line Diff line number Diff line
@@ -45,26 +45,6 @@ public:
    MOCK_CONST_METHOD1(dump, void(std::string&));
    MOCK_CONST_METHOD1(dump, void(std::string&));
};
};


class VSyncTrackerWrapper : public VSyncTracker {
public:
    VSyncTrackerWrapper(std::shared_ptr<VSyncTracker> const& tracker) : mTracker(tracker) {}

    bool addVsyncTimestamp(nsecs_t timestamp) final {
        return mTracker->addVsyncTimestamp(timestamp);
    }
    nsecs_t nextAnticipatedVSyncTimeFrom(nsecs_t timePoint) const final {
        return mTracker->nextAnticipatedVSyncTimeFrom(timePoint);
    }
    nsecs_t currentPeriod() const final { return mTracker->currentPeriod(); }
    void setPeriod(nsecs_t period) final { mTracker->setPeriod(period); }
    void resetModel() final { mTracker->resetModel(); }
    bool needsMoreSamples() const final { return mTracker->needsMoreSamples(); }
    void dump(std::string& result) const final { mTracker->dump(result); }

private:
    std::shared_ptr<VSyncTracker> const mTracker;
};

class MockClock : public Clock {
class MockClock : public Clock {
public:
public:
    MOCK_CONST_METHOD0(now, nsecs_t());
    MOCK_CONST_METHOD0(now, nsecs_t());
@@ -90,29 +70,6 @@ public:
    MOCK_CONST_METHOD1(dump, void(std::string&));
    MOCK_CONST_METHOD1(dump, void(std::string&));
};
};


class VSyncDispatchWrapper : public VSyncDispatch {
public:
    VSyncDispatchWrapper(std::shared_ptr<VSyncDispatch> const& dispatch) : mDispatch(dispatch) {}
    CallbackToken registerCallback(std::function<void(nsecs_t, nsecs_t)> const& callbackFn,
                                   std::string callbackName) final {
        return mDispatch->registerCallback(callbackFn, callbackName);
    }

    void unregisterCallback(CallbackToken token) final { mDispatch->unregisterCallback(token); }

    ScheduleResult schedule(CallbackToken token, nsecs_t workDuration,
                            nsecs_t earliestVsync) final {
        return mDispatch->schedule(token, workDuration, earliestVsync);
    }

    CancelResult cancel(CallbackToken token) final { return mDispatch->cancel(token); }

    void dump(std::string& result) const final { return mDispatch->dump(result); }

private:
    std::shared_ptr<VSyncDispatch> const mDispatch;
};

std::shared_ptr<FenceTime> generateInvalidFence() {
std::shared_ptr<FenceTime> generateInvalidFence() {
    sp<Fence> fence = new Fence();
    sp<Fence> fence = new Fence();
    return std::make_shared<FenceTime>(fence);
    return std::make_shared<FenceTime>(fence);
@@ -157,10 +114,8 @@ protected:
          : mMockDispatch(std::make_shared<NiceMock<MockVSyncDispatch>>()),
          : mMockDispatch(std::make_shared<NiceMock<MockVSyncDispatch>>()),
            mMockTracker(std::make_shared<NiceMock<MockVSyncTracker>>()),
            mMockTracker(std::make_shared<NiceMock<MockVSyncTracker>>()),
            mMockClock(std::make_shared<NiceMock<MockClock>>()),
            mMockClock(std::make_shared<NiceMock<MockClock>>()),
            mReactor(std::make_unique<ClockWrapper>(mMockClock),
            mReactor(std::make_unique<ClockWrapper>(mMockClock), *mMockDispatch, *mMockTracker,
                     std::make_unique<VSyncDispatchWrapper>(mMockDispatch),
                     kPendingLimit, false /* supportKernelIdleTimer */) {
                     std::make_unique<VSyncTrackerWrapper>(mMockTracker), kPendingLimit,
                     false /* supportKernelIdleTimer */) {
        ON_CALL(*mMockClock, now()).WillByDefault(Return(mFakeNow));
        ON_CALL(*mMockClock, now()).WillByDefault(Return(mFakeNow));
        ON_CALL(*mMockTracker, currentPeriod()).WillByDefault(Return(period));
        ON_CALL(*mMockTracker, currentPeriod()).WillByDefault(Return(period));
    }
    }
@@ -745,9 +700,8 @@ TEST_F(VSyncReactorTest, periodChangeWithGivenVsyncPeriod) {


TEST_F(VSyncReactorTest, periodIsMeasuredIfIgnoringComposer) {
TEST_F(VSyncReactorTest, periodIsMeasuredIfIgnoringComposer) {
    // Create a reactor which supports the kernel idle timer
    // Create a reactor which supports the kernel idle timer
    auto idleReactor = VSyncReactor(std::make_unique<ClockWrapper>(mMockClock),
    auto idleReactor =
                                    std::make_unique<VSyncDispatchWrapper>(mMockDispatch),
            VSyncReactor(std::make_unique<ClockWrapper>(mMockClock), *mMockDispatch, *mMockTracker,
                                    std::make_unique<VSyncTrackerWrapper>(mMockTracker),
                         kPendingLimit, true /* supportKernelIdleTimer */);
                         kPendingLimit, true /* supportKernelIdleTimer */);


    bool periodFlushed = true;
    bool periodFlushed = true;