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 Diff line number Diff line
@@ -25,7 +25,7 @@
namespace android::scheduler {

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 kernelTimerChanged(bool expired) = 0;
    virtual void triggerOnFrameRateOverridesChanged() = 0;
+58 −23
Original line number Diff line number Diff line
@@ -114,8 +114,12 @@ void Scheduler::setPacesetterDisplay(std::optional<PhysicalDisplayId> pacesetter
}

void Scheduler::registerDisplay(PhysicalDisplayId displayId, RefreshRateSelectorPtr selectorPtr) {
    registerDisplayInternal(displayId, std::move(selectorPtr),
                            std::make_shared<VsyncSchedule>(displayId, mFeatures));
    auto schedulePtr = 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,
@@ -123,14 +127,22 @@ void Scheduler::registerDisplayInternal(PhysicalDisplayId displayId,
                                        VsyncSchedulePtr schedulePtr) {
    demotePacesetterDisplay();

    std::shared_ptr<VsyncSchedule> pacesetterVsyncSchedule;
    {
    auto [pacesetterVsyncSchedule, isNew] = [&]() FTL_FAKE_GUARD(kMainThreadContext) {
        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));

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

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

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

void Scheduler::resyncAllToHardwareVsync(bool allowToEnable) {
@@ -447,12 +459,32 @@ void Scheduler::resyncToHardwareVsyncLocked(PhysicalDisplayId id, bool allowToEn
            refreshRate = display.selectorPtr->getActiveMode().modePtr->getFps();
        }
        if (refreshRate->isValid()) {
            display.schedulePtr->startPeriodTransition(mSchedulerCallback, refreshRate->getPeriod(),
                                                       false /* force */);
            constexpr bool kForce = false;
            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) {
    std::scoped_lock lock(mDisplayLock);
    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());
        return false;
    }
    return schedule->addResyncSample(mSchedulerCallback, TimePoint::fromNs(timestamp),
                                     hwcVsyncPeriod);
    return schedule->addResyncSample(TimePoint::fromNs(timestamp), hwcVsyncPeriod);
}

void Scheduler::addPresentFence(PhysicalDisplayId id, std::shared_ptr<FenceTime> fence) {
    auto schedule = getVsyncSchedule(id);
    LOG_ALWAYS_FATAL_IF(!schedule);
    const bool needMoreSignals = schedule->getController().addPresentFence(std::move(fence));
    if (needMoreSignals) {
        schedule->enableHardwareVsync(mSchedulerCallback);
    if (const bool needMoreSignals = schedule->getController().addPresentFence(std::move(fence))) {
        schedule->enableHardwareVsync();
    } 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);
        auto vsyncSchedule = getVsyncScheduleLocked(id);
        LOG_ALWAYS_FATAL_IF(!vsyncSchedule);
        vsyncSchedule->getController().setDisplayPowerMode(powerMode);

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

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

@@ -633,7 +668,7 @@ void Scheduler::kernelIdleTimerCallback(TimerState state) {
        ftl::FakeGuard guard(kMainThreadContext);
        for (const auto& [_, display] : mDisplays) {
            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;

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

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

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

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

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

#include "VsyncSchedule.h"

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

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

VsyncSchedule::VsyncSchedule(PhysicalDisplayId id, TrackerPtr tracker, DispatchPtr dispatch,
                             ControllerPtr controller)
                             ControllerPtr controller, RequestHardwareVsync requestHardwareVsync)
      : mId(id),
        mRequestHardwareVsync(std::move(requestHardwareVsync)),
        mTracker(std::move(tracker)),
        mDispatch(std::move(dispatch)),
        mController(std::move(controller)) {}
@@ -135,14 +137,13 @@ VsyncSchedule::ControllerPtr VsyncSchedule::createController(PhysicalDisplayId i
    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);
    mController->startPeriodTransition(period.ns(), force);
    enableHardwareVsyncLocked(callback);
    enableHardwareVsyncLocked();
}

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

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

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

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

#pragma once

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

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

namespace android::scheduler {

struct ISchedulerCallback;

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

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

    // IVsyncSource overrides:
@@ -68,13 +69,12 @@ public:
    // \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
    //                      change.
    void startPeriodTransition(ISchedulerCallback&, Period period, bool force);
    void startPeriodTransition(Period period, bool force);

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

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

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

    // Disable hardware VSYNCs. If `disallow` is true, future calls to
    // enableHardwareVsync are ineffective until isHardwareVsyncAllowed is
    // 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
    // enabled). If false, enableHardwareVsync does nothing.
@@ -111,8 +111,11 @@ public:
protected:
    using ControllerPtr = std::unique_ptr<VsyncController>;

    static void NoOpRequestHardwareVsync(PhysicalDisplayId, bool) {}

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

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

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

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

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