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

Commit 9900c7e6 authored by Dominik Laskowski's avatar Dominik Laskowski Committed by Android (Google) Code Review
Browse files

Merge changes I157b0895,I5c858522 into udc-qpr-dev

* changes:
  SF: Simplify Scheduler's hardware VSYNC delegate
  SF: Disable hardware VSYNC for any new display
parents ca7b3dc7 66295432
Loading
Loading
Loading
Loading
+1 −1
Original line number Original line Diff line number Diff line
@@ -25,7 +25,7 @@
namespace android::scheduler {
namespace android::scheduler {


struct ISchedulerCallback {
struct ISchedulerCallback {
    virtual void setVsyncEnabled(PhysicalDisplayId, bool) = 0;
    virtual void requestHardwareVsync(PhysicalDisplayId, bool enabled) = 0;
    virtual void requestDisplayModes(std::vector<display::DisplayModeRequest>) = 0;
    virtual void requestDisplayModes(std::vector<display::DisplayModeRequest>) = 0;
    virtual void kernelTimerChanged(bool expired) = 0;
    virtual void kernelTimerChanged(bool expired) = 0;
    virtual void triggerOnFrameRateOverridesChanged() = 0;
    virtual void triggerOnFrameRateOverridesChanged() = 0;
+58 −23
Original line number Original line Diff line number Diff line
@@ -114,8 +114,12 @@ void Scheduler::setPacesetterDisplay(std::optional<PhysicalDisplayId> pacesetter
}
}


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

    registerDisplayInternal(displayId, std::move(selectorPtr), std::move(schedulePtr));
}
}


void Scheduler::registerDisplayInternal(PhysicalDisplayId displayId,
void Scheduler::registerDisplayInternal(PhysicalDisplayId displayId,
@@ -123,14 +127,22 @@ void Scheduler::registerDisplayInternal(PhysicalDisplayId displayId,
                                        VsyncSchedulePtr schedulePtr) {
                                        VsyncSchedulePtr schedulePtr) {
    demotePacesetterDisplay();
    demotePacesetterDisplay();


    std::shared_ptr<VsyncSchedule> pacesetterVsyncSchedule;
    auto [pacesetterVsyncSchedule, isNew] = [&]() FTL_FAKE_GUARD(kMainThreadContext) {
    {
        std::scoped_lock lock(mDisplayLock);
        std::scoped_lock lock(mDisplayLock);
        mDisplays.emplace_or_replace(displayId, std::move(selectorPtr), std::move(schedulePtr));
        const bool isNew = mDisplays
                                   .emplace_or_replace(displayId, std::move(selectorPtr),
                                                       std::move(schedulePtr))
                                   .second;

        return std::make_pair(promotePacesetterDisplayLocked(), isNew);
    }();


        pacesetterVsyncSchedule = promotePacesetterDisplayLocked();
    }
    applyNewVsyncSchedule(std::move(pacesetterVsyncSchedule));
    applyNewVsyncSchedule(std::move(pacesetterVsyncSchedule));

    // Disable hardware VSYNC if the registration is new, as opposed to a renewal.
    if (isNew) {
        onHardwareVsyncRequest(displayId, false);
    }
}
}


void Scheduler::unregisterDisplay(PhysicalDisplayId displayId) {
void Scheduler::unregisterDisplay(PhysicalDisplayId displayId) {
@@ -414,13 +426,13 @@ void Scheduler::setVsyncConfig(const VsyncConfig& config, Period vsyncPeriod) {
void Scheduler::enableHardwareVsync(PhysicalDisplayId id) {
void Scheduler::enableHardwareVsync(PhysicalDisplayId id) {
    auto schedule = getVsyncSchedule(id);
    auto schedule = getVsyncSchedule(id);
    LOG_ALWAYS_FATAL_IF(!schedule);
    LOG_ALWAYS_FATAL_IF(!schedule);
    schedule->enableHardwareVsync(mSchedulerCallback);
    schedule->enableHardwareVsync();
}
}


void Scheduler::disableHardwareVsync(PhysicalDisplayId id, bool disallow) {
void Scheduler::disableHardwareVsync(PhysicalDisplayId id, bool disallow) {
    auto schedule = getVsyncSchedule(id);
    auto schedule = getVsyncSchedule(id);
    LOG_ALWAYS_FATAL_IF(!schedule);
    LOG_ALWAYS_FATAL_IF(!schedule);
    schedule->disableHardwareVsync(mSchedulerCallback, disallow);
    schedule->disableHardwareVsync(disallow);
}
}


void Scheduler::resyncAllToHardwareVsync(bool allowToEnable) {
void Scheduler::resyncAllToHardwareVsync(bool allowToEnable) {
@@ -447,12 +459,32 @@ void Scheduler::resyncToHardwareVsyncLocked(PhysicalDisplayId id, bool allowToEn
            refreshRate = display.selectorPtr->getActiveMode().modePtr->getFps();
            refreshRate = display.selectorPtr->getActiveMode().modePtr->getFps();
        }
        }
        if (refreshRate->isValid()) {
        if (refreshRate->isValid()) {
            display.schedulePtr->startPeriodTransition(mSchedulerCallback, refreshRate->getPeriod(),
            constexpr bool kForce = false;
                                                       false /* force */);
            display.schedulePtr->startPeriodTransition(refreshRate->getPeriod(), kForce);
        }
        }
    }
    }
}
}


void Scheduler::onHardwareVsyncRequest(PhysicalDisplayId id, bool enabled) {
    static const auto& whence = __func__;
    ATRACE_NAME(ftl::Concat(whence, ' ', id.value, ' ', enabled).c_str());

    // On main thread to serialize reads/writes of pending hardware VSYNC state.
    static_cast<void>(
            schedule([=]() FTL_FAKE_GUARD(mDisplayLock) FTL_FAKE_GUARD(kMainThreadContext) {
                ATRACE_NAME(ftl::Concat(whence, ' ', id.value, ' ', enabled).c_str());

                if (const auto displayOpt = mDisplays.get(id)) {
                    auto& display = displayOpt->get();
                    display.schedulePtr->setPendingHardwareVsyncState(enabled);

                    if (display.powerMode != hal::PowerMode::OFF) {
                        mSchedulerCallback.requestHardwareVsync(id, enabled);
                    }
                }
            }));
}

void Scheduler::setRenderRate(PhysicalDisplayId id, Fps renderFrameRate) {
void Scheduler::setRenderRate(PhysicalDisplayId id, Fps renderFrameRate) {
    std::scoped_lock lock(mDisplayLock);
    std::scoped_lock lock(mDisplayLock);
    ftl::FakeGuard guard(kMainThreadContext);
    ftl::FakeGuard guard(kMainThreadContext);
@@ -498,18 +530,17 @@ bool Scheduler::addResyncSample(PhysicalDisplayId id, nsecs_t timestamp,
        ALOGW("%s: Invalid display %s!", __func__, to_string(id).c_str());
        ALOGW("%s: Invalid display %s!", __func__, to_string(id).c_str());
        return false;
        return false;
    }
    }
    return schedule->addResyncSample(mSchedulerCallback, TimePoint::fromNs(timestamp),
    return schedule->addResyncSample(TimePoint::fromNs(timestamp), hwcVsyncPeriod);
                                     hwcVsyncPeriod);
}
}


void Scheduler::addPresentFence(PhysicalDisplayId id, std::shared_ptr<FenceTime> fence) {
void Scheduler::addPresentFence(PhysicalDisplayId id, std::shared_ptr<FenceTime> fence) {
    auto schedule = getVsyncSchedule(id);
    auto schedule = getVsyncSchedule(id);
    LOG_ALWAYS_FATAL_IF(!schedule);
    LOG_ALWAYS_FATAL_IF(!schedule);
    const bool needMoreSignals = schedule->getController().addPresentFence(std::move(fence));
    if (const bool needMoreSignals = schedule->getController().addPresentFence(std::move(fence))) {
    if (needMoreSignals) {
        schedule->enableHardwareVsync();
        schedule->enableHardwareVsync(mSchedulerCallback);
    } else {
    } else {
        schedule->disableHardwareVsync(mSchedulerCallback, false /* disallow */);
        constexpr bool kDisallow = false;
        schedule->disableHardwareVsync(kDisallow);
    }
    }
}
}


@@ -573,9 +604,13 @@ void Scheduler::setDisplayPowerMode(PhysicalDisplayId id, hal::PowerMode powerMo
    }
    }
    {
    {
        std::scoped_lock lock(mDisplayLock);
        std::scoped_lock lock(mDisplayLock);
        auto vsyncSchedule = getVsyncScheduleLocked(id);

        LOG_ALWAYS_FATAL_IF(!vsyncSchedule);
        const auto displayOpt = mDisplays.get(id);
        vsyncSchedule->getController().setDisplayPowerMode(powerMode);
        LOG_ALWAYS_FATAL_IF(!displayOpt);
        auto& display = displayOpt->get();

        display.powerMode = powerMode;
        display.schedulePtr->getController().setDisplayPowerMode(powerMode);
    }
    }
    if (!isPacesetter) return;
    if (!isPacesetter) return;


@@ -633,7 +668,7 @@ void Scheduler::kernelIdleTimerCallback(TimerState state) {
        ftl::FakeGuard guard(kMainThreadContext);
        ftl::FakeGuard guard(kMainThreadContext);
        for (const auto& [_, display] : mDisplays) {
        for (const auto& [_, display] : mDisplays) {
            constexpr bool kDisallow = false;
            constexpr bool kDisallow = false;
            display.schedulePtr->disableHardwareVsync(mSchedulerCallback, kDisallow);
            display.schedulePtr->disableHardwareVsync(kDisallow);
        }
        }
    }
    }


@@ -754,8 +789,8 @@ std::shared_ptr<VsyncSchedule> Scheduler::promotePacesetterDisplayLocked(
        newVsyncSchedulePtr = pacesetter.schedulePtr;
        newVsyncSchedulePtr = pacesetter.schedulePtr;


        const Fps refreshRate = pacesetter.selectorPtr->getActiveMode().modePtr->getFps();
        const Fps refreshRate = pacesetter.selectorPtr->getActiveMode().modePtr->getFps();
        newVsyncSchedulePtr->startPeriodTransition(mSchedulerCallback, refreshRate.getPeriod(),
        constexpr bool kForce = true;
                                                   true /* force */);
        newVsyncSchedulePtr->startPeriodTransition(refreshRate.getPeriod(), kForce);
    }
    }
    return newVsyncSchedulePtr;
    return newVsyncSchedulePtr;
}
}
+5 −0
Original line number Original line Diff line number Diff line
@@ -320,6 +320,9 @@ private:
    void touchTimerCallback(TimerState);
    void touchTimerCallback(TimerState);
    void displayPowerTimerCallback(TimerState);
    void displayPowerTimerCallback(TimerState);


    // VsyncSchedule delegate.
    void onHardwareVsyncRequest(PhysicalDisplayId, bool enable);

    void resyncToHardwareVsyncLocked(PhysicalDisplayId, bool allowToEnable,
    void resyncToHardwareVsyncLocked(PhysicalDisplayId, bool allowToEnable,
                                     std::optional<Fps> refreshRate = std::nullopt)
                                     std::optional<Fps> refreshRate = std::nullopt)
            REQUIRES(kMainThreadContext, mDisplayLock);
            REQUIRES(kMainThreadContext, mDisplayLock);
@@ -433,6 +436,8 @@ private:
        // Effectively const except in move constructor.
        // Effectively const except in move constructor.
        RefreshRateSelectorPtr selectorPtr;
        RefreshRateSelectorPtr selectorPtr;
        VsyncSchedulePtr schedulePtr;
        VsyncSchedulePtr schedulePtr;

        hal::PowerMode powerMode = hal::PowerMode::OFF;
    };
    };


    using DisplayRef = std::reference_wrapper<Display>;
    using DisplayRef = std::reference_wrapper<Display>;
+17 −15
Original line number Original line Diff line number Diff line
@@ -22,7 +22,6 @@


#include "VsyncSchedule.h"
#include "VsyncSchedule.h"


#include "ISchedulerCallback.h"
#include "Utils/Dumper.h"
#include "Utils/Dumper.h"
#include "VSyncDispatchTimerQueue.h"
#include "VSyncDispatchTimerQueue.h"
#include "VSyncPredictor.h"
#include "VSyncPredictor.h"
@@ -54,8 +53,10 @@ private:
    VSyncCallbackRegistration mRegistration;
    VSyncCallbackRegistration mRegistration;
};
};


VsyncSchedule::VsyncSchedule(PhysicalDisplayId id, FeatureFlags features)
VsyncSchedule::VsyncSchedule(PhysicalDisplayId id, FeatureFlags features,
                             RequestHardwareVsync requestHardwareVsync)
      : mId(id),
      : mId(id),
        mRequestHardwareVsync(std::move(requestHardwareVsync)),
        mTracker(createTracker(id)),
        mTracker(createTracker(id)),
        mDispatch(createDispatch(mTracker)),
        mDispatch(createDispatch(mTracker)),
        mController(createController(id, *mTracker, features)),
        mController(createController(id, *mTracker, features)),
@@ -64,8 +65,9 @@ VsyncSchedule::VsyncSchedule(PhysicalDisplayId id, FeatureFlags features)
                        : nullptr) {}
                        : nullptr) {}


VsyncSchedule::VsyncSchedule(PhysicalDisplayId id, TrackerPtr tracker, DispatchPtr dispatch,
VsyncSchedule::VsyncSchedule(PhysicalDisplayId id, TrackerPtr tracker, DispatchPtr dispatch,
                             ControllerPtr controller)
                             ControllerPtr controller, RequestHardwareVsync requestHardwareVsync)
      : mId(id),
      : mId(id),
        mRequestHardwareVsync(std::move(requestHardwareVsync)),
        mTracker(std::move(tracker)),
        mTracker(std::move(tracker)),
        mDispatch(std::move(dispatch)),
        mDispatch(std::move(dispatch)),
        mController(std::move(controller)) {}
        mController(std::move(controller)) {}
@@ -135,14 +137,13 @@ VsyncSchedule::ControllerPtr VsyncSchedule::createController(PhysicalDisplayId i
    return reactor;
    return reactor;
}
}


void VsyncSchedule::startPeriodTransition(ISchedulerCallback& callback, Period period, bool force) {
void VsyncSchedule::startPeriodTransition(Period period, bool force) {
    std::lock_guard<std::mutex> lock(mHwVsyncLock);
    std::lock_guard<std::mutex> lock(mHwVsyncLock);
    mController->startPeriodTransition(period.ns(), force);
    mController->startPeriodTransition(period.ns(), force);
    enableHardwareVsyncLocked(callback);
    enableHardwareVsyncLocked();
}
}


bool VsyncSchedule::addResyncSample(ISchedulerCallback& callback, TimePoint timestamp,
bool VsyncSchedule::addResyncSample(TimePoint timestamp, ftl::Optional<Period> hwcVsyncPeriod) {
                                    ftl::Optional<Period> hwcVsyncPeriod) {
    bool needsHwVsync = false;
    bool needsHwVsync = false;
    bool periodFlushed = false;
    bool periodFlushed = false;
    {
    {
@@ -154,31 +155,32 @@ bool VsyncSchedule::addResyncSample(ISchedulerCallback& callback, TimePoint time
        }
        }
    }
    }
    if (needsHwVsync) {
    if (needsHwVsync) {
        enableHardwareVsync(callback);
        enableHardwareVsync();
    } else {
    } else {
        disableHardwareVsync(callback, false /* disallow */);
        constexpr bool kDisallow = false;
        disableHardwareVsync(kDisallow);
    }
    }
    return periodFlushed;
    return periodFlushed;
}
}


void VsyncSchedule::enableHardwareVsync(ISchedulerCallback& callback) {
void VsyncSchedule::enableHardwareVsync() {
    std::lock_guard<std::mutex> lock(mHwVsyncLock);
    std::lock_guard<std::mutex> lock(mHwVsyncLock);
    enableHardwareVsyncLocked(callback);
    enableHardwareVsyncLocked();
}
}


void VsyncSchedule::enableHardwareVsyncLocked(ISchedulerCallback& callback) {
void VsyncSchedule::enableHardwareVsyncLocked() {
    if (mHwVsyncState == HwVsyncState::Disabled) {
    if (mHwVsyncState == HwVsyncState::Disabled) {
        getTracker().resetModel();
        getTracker().resetModel();
        callback.setVsyncEnabled(mId, true);
        mRequestHardwareVsync(mId, true);
        mHwVsyncState = HwVsyncState::Enabled;
        mHwVsyncState = HwVsyncState::Enabled;
    }
    }
}
}


void VsyncSchedule::disableHardwareVsync(ISchedulerCallback& callback, bool disallow) {
void VsyncSchedule::disableHardwareVsync(bool disallow) {
    std::lock_guard<std::mutex> lock(mHwVsyncLock);
    std::lock_guard<std::mutex> lock(mHwVsyncLock);
    switch (mHwVsyncState) {
    switch (mHwVsyncState) {
        case HwVsyncState::Enabled:
        case HwVsyncState::Enabled:
            callback.setVsyncEnabled(mId, false);
            mRequestHardwareVsync(mId, false);
            [[fallthrough]];
            [[fallthrough]];
        case HwVsyncState::Disabled:
        case HwVsyncState::Disabled:
            mHwVsyncState = disallow ? HwVsyncState::Disallowed : HwVsyncState::Disabled;
            mHwVsyncState = disallow ? HwVsyncState::Disallowed : HwVsyncState::Disabled;
+14 −10
Original line number Original line Diff line number Diff line
@@ -16,6 +16,7 @@


#pragma once
#pragma once


#include <functional>
#include <memory>
#include <memory>
#include <string>
#include <string>


@@ -41,8 +42,6 @@ class SchedulerFuzzer;


namespace android::scheduler {
namespace android::scheduler {


struct ISchedulerCallback;

// TODO(b/185535769): Rename classes, and remove aliases.
// TODO(b/185535769): Rename classes, and remove aliases.
class VSyncDispatch;
class VSyncDispatch;
class VSyncTracker;
class VSyncTracker;
@@ -54,7 +53,9 @@ using VsyncTracker = VSyncTracker;
// Schedule that synchronizes to hardware VSYNC of a physical display.
// Schedule that synchronizes to hardware VSYNC of a physical display.
class VsyncSchedule final : public IVsyncSource {
class VsyncSchedule final : public IVsyncSource {
public:
public:
    VsyncSchedule(PhysicalDisplayId, FeatureFlags);
    using RequestHardwareVsync = std::function<void(PhysicalDisplayId, bool enabled)>;

    VsyncSchedule(PhysicalDisplayId, FeatureFlags, RequestHardwareVsync);
    ~VsyncSchedule();
    ~VsyncSchedule();


    // IVsyncSource overrides:
    // IVsyncSource overrides:
@@ -68,13 +69,12 @@ public:
    // \param [in] period   The period that the system is changing into.
    // \param [in] period   The period that the system is changing into.
    // \param [in] force    True to force a transition even if it is not a
    // \param [in] force    True to force a transition even if it is not a
    //                      change.
    //                      change.
    void startPeriodTransition(ISchedulerCallback&, Period period, bool force);
    void startPeriodTransition(Period period, bool force);


    // Pass a VSYNC sample to VsyncController. Return true if
    // Pass a VSYNC sample to VsyncController. Return true if
    // VsyncController detected that the VSYNC period changed. Enable or disable
    // VsyncController detected that the VSYNC period changed. Enable or disable
    // hardware VSYNCs depending on whether more samples are needed.
    // hardware VSYNCs depending on whether more samples are needed.
    bool addResyncSample(ISchedulerCallback&, TimePoint timestamp,
    bool addResyncSample(TimePoint timestamp, ftl::Optional<Period> hwcVsyncPeriod);
                         ftl::Optional<Period> hwcVsyncPeriod);


    // TODO(b/185535769): Hide behind API.
    // TODO(b/185535769): Hide behind API.
    const VsyncTracker& getTracker() const { return *mTracker; }
    const VsyncTracker& getTracker() const { return *mTracker; }
@@ -93,12 +93,12 @@ public:


    // Turn on hardware VSYNCs, unless mHwVsyncState is Disallowed, in which
    // Turn on hardware VSYNCs, unless mHwVsyncState is Disallowed, in which
    // case this call is ignored.
    // case this call is ignored.
    void enableHardwareVsync(ISchedulerCallback&) EXCLUDES(mHwVsyncLock);
    void enableHardwareVsync() EXCLUDES(mHwVsyncLock);


    // Disable hardware VSYNCs. If `disallow` is true, future calls to
    // Disable hardware VSYNCs. If `disallow` is true, future calls to
    // enableHardwareVsync are ineffective until isHardwareVsyncAllowed is
    // enableHardwareVsync are ineffective until isHardwareVsyncAllowed is
    // called with `makeAllowed` set to true.
    // called with `makeAllowed` set to true.
    void disableHardwareVsync(ISchedulerCallback&, bool disallow) EXCLUDES(mHwVsyncLock);
    void disableHardwareVsync(bool disallow) EXCLUDES(mHwVsyncLock);


    // If true, enableHardwareVsync can enable hardware VSYNC (if not already
    // If true, enableHardwareVsync can enable hardware VSYNC (if not already
    // enabled). If false, enableHardwareVsync does nothing.
    // enabled). If false, enableHardwareVsync does nothing.
@@ -111,8 +111,11 @@ public:
protected:
protected:
    using ControllerPtr = std::unique_ptr<VsyncController>;
    using ControllerPtr = std::unique_ptr<VsyncController>;


    static void NoOpRequestHardwareVsync(PhysicalDisplayId, bool) {}

    // For tests.
    // For tests.
    VsyncSchedule(PhysicalDisplayId, TrackerPtr, DispatchPtr, ControllerPtr);
    VsyncSchedule(PhysicalDisplayId, TrackerPtr, DispatchPtr, ControllerPtr,
                  RequestHardwareVsync = NoOpRequestHardwareVsync);


private:
private:
    friend class TestableScheduler;
    friend class TestableScheduler;
@@ -124,7 +127,7 @@ private:
    static DispatchPtr createDispatch(TrackerPtr);
    static DispatchPtr createDispatch(TrackerPtr);
    static ControllerPtr createController(PhysicalDisplayId, VsyncTracker&, FeatureFlags);
    static ControllerPtr createController(PhysicalDisplayId, VsyncTracker&, FeatureFlags);


    void enableHardwareVsyncLocked(ISchedulerCallback&) REQUIRES(mHwVsyncLock);
    void enableHardwareVsyncLocked() REQUIRES(mHwVsyncLock);


    mutable std::mutex mHwVsyncLock;
    mutable std::mutex mHwVsyncLock;
    enum class HwVsyncState {
    enum class HwVsyncState {
@@ -151,6 +154,7 @@ private:
    using TracerPtr = std::unique_ptr<PredictedVsyncTracer>;
    using TracerPtr = std::unique_ptr<PredictedVsyncTracer>;


    const PhysicalDisplayId mId;
    const PhysicalDisplayId mId;
    const RequestHardwareVsync mRequestHardwareVsync;
    const TrackerPtr mTracker;
    const TrackerPtr mTracker;
    const DispatchPtr mDispatch;
    const DispatchPtr mDispatch;
    const ControllerPtr mController;
    const ControllerPtr mController;
Loading