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

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

Merge "[SF] Adds callback from the VsyncPredictor" into main

parents b85ff981 d4354a9d
Loading
Loading
Loading
Loading
+20 −7
Original line number Diff line number Diff line
@@ -67,11 +67,12 @@
namespace android::scheduler {

Scheduler::Scheduler(ICompositor& compositor, ISchedulerCallback& callback, FeatureFlags features,
                     sp<VsyncModulator> modulatorPtr)
                     sp<VsyncModulator> modulatorPtr, IVsyncTrackerCallback& vsyncTrackerCallback)
      : impl::MessageQueue(compositor),
        mFeatures(features),
        mVsyncModulator(std::move(modulatorPtr)),
        mSchedulerCallback(callback) {}
        mSchedulerCallback(callback),
        mVsyncTrackerCallback(vsyncTrackerCallback) {}

Scheduler::~Scheduler() {
    // MessageQueue depends on VsyncSchedule, so first destroy it.
@@ -116,10 +117,10 @@ void Scheduler::setPacesetterDisplay(std::optional<PhysicalDisplayId> pacesetter
}

void Scheduler::registerDisplay(PhysicalDisplayId displayId, RefreshRateSelectorPtr selectorPtr) {
    auto schedulePtr = std::make_shared<VsyncSchedule>(displayId, mFeatures,
                                                       [this](PhysicalDisplayId id, bool enable) {
                                                           onHardwareVsyncRequest(id, enable);
                                                       });
    auto schedulePtr = std::make_shared<VsyncSchedule>(
            displayId, mFeatures,
            [this](PhysicalDisplayId id, bool enable) { onHardwareVsyncRequest(id, enable); },
            mVsyncTrackerCallback);

    registerDisplayInternal(displayId, std::move(selectorPtr), std::move(schedulePtr));
}
@@ -562,7 +563,19 @@ void Scheduler::setRenderRate(PhysicalDisplayId id, Fps renderFrameRate) {
    ALOGV("%s %s (%s)", __func__, to_string(mode.fps).c_str(),
          to_string(mode.modePtr->getVsyncRate()).c_str());

    display.schedulePtr->getTracker().setRenderRate(renderFrameRate);
    display.schedulePtr->getTracker().setDisplayModeData(
            {.renderRate = renderFrameRate,
             .notifyExpectedPresentTimeoutOpt = getNotifyExpectedPresentTimeout(mode)});
}

std::optional<Period> Scheduler::getNotifyExpectedPresentTimeout(const FrameRateMode& mode) {
    if (mode.modePtr->getVrrConfig() && mode.modePtr->getVrrConfig()->notifyExpectedPresentConfig) {
        return Period::fromNs(
                mode.modePtr->getVrrConfig()
                        ->notifyExpectedPresentConfig->notifyExpectedPresentTimeoutNs);
    } else {
        return std::nullopt;
    }
}

void Scheduler::resync() {
+7 −1
Original line number Diff line number Diff line
@@ -102,7 +102,8 @@ class Scheduler : public IEventThreadCallback, android::impl::MessageQueue {
    using Impl = android::impl::MessageQueue;

public:
    Scheduler(ICompositor&, ISchedulerCallback&, FeatureFlags, sp<VsyncModulator>);
    Scheduler(ICompositor&, ISchedulerCallback&, FeatureFlags, sp<VsyncModulator>,
              IVsyncTrackerCallback&);
    virtual ~Scheduler();

    void startTimers();
@@ -429,6 +430,9 @@ private:
    Period getVsyncPeriod(uid_t) override EXCLUDES(mDisplayLock);
    void resync() override EXCLUDES(mDisplayLock);

    std::optional<Period> getNotifyExpectedPresentTimeout(const FrameRateMode&)
            REQUIRES(mDisplayLock);

    // Stores EventThread associated with a given VSyncSource, and an initial EventThreadConnection.
    struct Connection {
        sp<EventThreadConnection> connection;
@@ -462,6 +466,8 @@ private:

    ISchedulerCallback& mSchedulerCallback;

    IVsyncTrackerCallback& mVsyncTrackerCallback;

    // mDisplayLock may be locked while under mPolicyLock.
    mutable std::mutex mPolicyLock;

+28 −8
Original line number Diff line number Diff line
@@ -35,6 +35,7 @@
#include <gui/TraceUtils.h>
#include <utils/Log.h>

#include "FlagManager.h"
#include "RefreshRateSelector.h"
#include "VSyncPredictor.h"

@@ -47,12 +48,14 @@ static auto constexpr kMaxPercent = 100u;
VSyncPredictor::~VSyncPredictor() = default;

VSyncPredictor::VSyncPredictor(PhysicalDisplayId id, nsecs_t idealPeriod, size_t historySize,
                               size_t minimumSamplesForPrediction, uint32_t outlierTolerancePercent)
                               size_t minimumSamplesForPrediction, uint32_t outlierTolerancePercent,
                               IVsyncTrackerCallback& callback)
      : mId(id),
        mTraceOn(property_get_bool("debug.sf.vsp_trace", false)),
        kHistorySize(historySize),
        kMinimumSamplesForPrediction(minimumSamplesForPrediction),
        kOutlierTolerancePercent(std::min(outlierTolerancePercent, kMaxPercent)),
        mVsyncTrackerCallback(callback),
        mIdealPeriod(idealPeriod) {
    resetModel();
}
@@ -275,11 +278,11 @@ nsecs_t VSyncPredictor::nextAnticipatedVSyncTimeFrom(nsecs_t timePoint) const {
    mLastVsyncSequence = getVsyncSequenceLocked(timePoint);

    const auto renderRatePhase = [&]() REQUIRES(mMutex) -> int {
        if (!mRenderRate) return 0;
        if (!mDisplayModeDataOpt) return 0;

        const auto divisor =
                RefreshRateSelector::getFrameRateDivisor(Fps::fromPeriodNsecs(mIdealPeriod),
                                                         *mRenderRate);
                                                         mDisplayModeDataOpt->renderRate);
        if (divisor <= 1) return 0;

        const int mod = mLastVsyncSequence->seq % divisor;
@@ -289,12 +292,24 @@ nsecs_t VSyncPredictor::nextAnticipatedVSyncTimeFrom(nsecs_t timePoint) const {
    }();

    if (renderRatePhase == 0) {
        return mLastVsyncSequence->vsyncTime;
        const auto vsyncTime = mLastVsyncSequence->vsyncTime;
        if (FlagManager::getInstance().vrr_config() && mDisplayModeDataOpt) {
            mVsyncTrackerCallback.onVsyncGenerated(mId, TimePoint::fromNs(vsyncTime),
                                                   *mDisplayModeDataOpt,
                                                   Period::fromNs(mIdealPeriod));
        }
        return vsyncTime;
    }

    auto const [slope, intercept] = getVSyncPredictionModelLocked();
    const auto approximateNextVsync = mLastVsyncSequence->vsyncTime + slope * renderRatePhase;
    return nextAnticipatedVSyncTimeFromLocked(approximateNextVsync - slope / 2);
    const auto nextAnticipatedVsyncTime =
            nextAnticipatedVSyncTimeFromLocked(approximateNextVsync - slope / 2);
    if (FlagManager::getInstance().vrr_config() && mDisplayModeDataOpt) {
        mVsyncTrackerCallback.onVsyncGenerated(mId, TimePoint::fromNs(nextAnticipatedVsyncTime),
                                               *mDisplayModeDataOpt, Period::fromNs(mIdealPeriod));
    }
    return nextAnticipatedVsyncTime;
}

/*
@@ -332,10 +347,14 @@ bool VSyncPredictor::isVSyncInPhaseLocked(nsecs_t timePoint, unsigned divisor) c
    return vsyncSequence.seq % divisor == 0;
}

void VSyncPredictor::setRenderRate(Fps fps) {
    ALOGV("%s %s: %s", __func__, to_string(mId).c_str(), to_string(fps).c_str());
void VSyncPredictor::setDisplayModeData(const DisplayModeData& displayModeData) {
    ALOGV("%s %s: RenderRate %s notifyExpectedPresentTimeout %s", __func__, to_string(mId).c_str(),
          to_string(displayModeData.renderRate).c_str(),
          displayModeData.notifyExpectedPresentTimeoutOpt
                  ? std::to_string(displayModeData.notifyExpectedPresentTimeoutOpt->ns()).c_str()
                  : "N/A");
    std::lock_guard lock(mMutex);
    mRenderRate = fps;
    mDisplayModeDataOpt = displayModeData;
}

VSyncPredictor::Model VSyncPredictor::getVSyncPredictionModel() const {
@@ -358,6 +377,7 @@ void VSyncPredictor::setPeriod(nsecs_t period) {
        mRateMap.erase(mRateMap.begin());
    }

    // TODO(b/308610306) mIdealPeriod to be updated with setDisplayModeData
    mIdealPeriod = period;
    if (mRateMap.find(period) == mRateMap.end()) {
        mRateMap[mIdealPeriod] = {period, 0};
+6 −3
Original line number Diff line number Diff line
@@ -36,9 +36,11 @@ public:
     * \param [in] minimumSamplesForPrediction The minimum number of samples to collect before
     * predicting. \param [in] outlierTolerancePercent a number 0 to 100 that will be used to filter
     * samples that fall outlierTolerancePercent from an anticipated vsync event.
     * \param [in] IVsyncTrackerCallback The callback for the VSyncTracker.
     */
    VSyncPredictor(PhysicalDisplayId, nsecs_t idealPeriod, size_t historySize,
                   size_t minimumSamplesForPrediction, uint32_t outlierTolerancePercent);
                   size_t minimumSamplesForPrediction, uint32_t outlierTolerancePercent,
                   IVsyncTrackerCallback&);
    ~VSyncPredictor();

    bool addVsyncTimestamp(nsecs_t timestamp) final EXCLUDES(mMutex);
@@ -69,7 +71,7 @@ public:

    bool isVSyncInPhase(nsecs_t timePoint, Fps frameRate) const final EXCLUDES(mMutex);

    void setRenderRate(Fps) final EXCLUDES(mMutex);
    void setDisplayModeData(const DisplayModeData&) final EXCLUDES(mMutex);

    void dump(std::string& result) const final EXCLUDES(mMutex);

@@ -99,6 +101,7 @@ private:
    size_t const kHistorySize;
    size_t const kMinimumSamplesForPrediction;
    size_t const kOutlierTolerancePercent;
    IVsyncTrackerCallback& mVsyncTrackerCallback;
    std::mutex mutable mMutex;

    nsecs_t mIdealPeriod GUARDED_BY(mMutex);
@@ -110,7 +113,7 @@ private:
    size_t mLastTimestampIndex GUARDED_BY(mMutex) = 0;
    std::vector<nsecs_t> mTimestamps GUARDED_BY(mMutex);

    std::optional<Fps> mRenderRate GUARDED_BY(mMutex);
    std::optional<DisplayModeData> mDisplayModeDataOpt GUARDED_BY(mMutex);

    mutable std::optional<VsyncSequence> mLastVsyncSequence GUARDED_BY(mMutex);
};
+26 −4
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

#pragma once

#include <ui/DisplayId.h>
#include <utils/Timers.h>

#include <scheduler/Fps.h>
@@ -23,6 +24,23 @@
#include "VSyncDispatch.h"

namespace android::scheduler {

struct DisplayModeData {
    Fps renderRate;
    std::optional<Period> notifyExpectedPresentTimeoutOpt;

    bool operator==(const DisplayModeData& other) const {
        return isApproxEqual(renderRate, other.renderRate) &&
                notifyExpectedPresentTimeoutOpt == other.notifyExpectedPresentTimeoutOpt;
    }
};

struct IVsyncTrackerCallback {
    virtual ~IVsyncTrackerCallback() = default;
    virtual void onVsyncGenerated(PhysicalDisplayId, TimePoint expectedPresentTime,
                                  const DisplayModeData&, Period vsyncPeriod) = 0;
};

/*
 * VSyncTracker is an interface for providing estimates on future Vsync signal times based on
 * historical vsync timing data.
@@ -80,16 +98,20 @@ public:
    virtual bool isVSyncInPhase(nsecs_t timePoint, Fps frameRate) const = 0;

    /*
     * 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.
     * Sets the metadata about the currently active display mode such as VRR
     * timeout period, vsyncPeriod and framework property such as render rate.
     * 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.
     * When IVsyncTrackerCallback::onVsyncGenerated callback is made we will pass along
     * the vsyncPeriod, render rate and timeoutNs.
     *
     * \param [in] Fps   The render rate the tracker should operate at.
     * \param [in] DisplayModeData The DisplayModeData the tracker will use.
     */
    virtual void setRenderRate(Fps) = 0;
    virtual void setDisplayModeData(const DisplayModeData&) = 0;

    virtual void dump(std::string& result) const = 0;

Loading