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

Commit 67388625 authored by Leon Scroggins III's avatar Leon Scroggins III
Browse files

Reland "Create a VsyncSchedule per display"

In order to determine the vsync offsets between displays, keep track of
a VsyncSchedule for each display.

Store the VsyncSchedules in a SmallMap. Update getVsyncSchedule with a
parameter to choose the display. The default parameter uses the leader's
display, which is what many current callers want.

Update VsyncDispatches when the leader changes, so that they are always
listening to the leader.

Enable and disable vsync callbacks per display. Earlier attempts to turn
them on and off together could leave a secondary display on a bad
schedule. Add a method for resyncing all displays at once.

Use std::shared_ptrs for VsyncDispatches. This prevents lifetime issues
if a VsyncSchedule gets removed while its VsyncDispatch is still in use.
Same for VsyncTracker, which is referenced by VsyncDispatch.

When the leader VsyncSchedule changes, call cancel on
VsyncCallbackRegistrations and replace them with new ones using the new
VsyncDispatches. If a callback was scheduled, schedule a new one.

Update VsyncSchedule's members' traces so that there is a separate track
for each display.

For refresh rate changes, modulate vsync config based on the leader
display. When switching leaders, force a period transition to ensure
that a potential refresh rate change is completed.

This reverts commit db16a2be aka
I0757a7df540fad316b2db42e4c77f1c73bc49420, which reverted the original
CL, If60218e85292c786b9fa70ecb33ee374d3a385e0. Notable differences from
the original CL:
- Logical pieces have been separated and landed in the following CLs:
  - I21be76e20776d8a3f49e5bd295a0042de9e2dde9
  - I062002245db8fd817e145a3aaf197bb874b00636
  - I54a1304a3428968134cc707b24d5b325927c31df
- Remove IEventThreadCallback changes. These are ultimately orthogonal
  to the motivation of this CL.
- Store the ID instead of the name and use ftl::Concat, as tracked in
  b/266817103.
- Rename MessageQueue::updateVsyncRegistration to onNewVsyncSchedule, to
  match the name in EventThread. These methods do essentially the same
  thing, so use the same name.
- Crucially, I54a1304a3428968134cc707b24d5b325927c31df restores the
  pending HWC Vsync state, which was originally removed in
  If60218e85292c786b9fa70ecb33ee374d3a385e0. The removal seems to have
  been responsible for b/267562341.

Bug: 255601557
Bug: 256196556
Bug: 241285473
Bug: 241286146
Bug: 268366385
Fixes: 266817103
Test: libsurfaceflinger_unittest
Test: manual (look at perfetto traces)
Change-Id: Icdb80253436b4d0034fc20fcae8583efb7c30292
parent ba9323ad
Loading
Loading
Loading
Loading
+25 −10
Original line number Diff line number Diff line
@@ -238,7 +238,7 @@ EventThread::~EventThread() = default;

namespace impl {

EventThread::EventThread(const char* name, scheduler::VsyncSchedule& vsyncSchedule,
EventThread::EventThread(const char* name, std::shared_ptr<scheduler::VsyncSchedule> vsyncSchedule,
                         android::frametimeline::TokenManager* tokenManager,
                         ThrottleVsyncCallback throttleVsyncCallback,
                         GetVsyncPeriodFunction getVsyncPeriodFunction,
@@ -248,13 +248,8 @@ EventThread::EventThread(const char* name, scheduler::VsyncSchedule& vsyncSchedu
        mVsyncTracer(base::StringPrintf("VSYNC-%s", name), 0),
        mWorkDuration(base::StringPrintf("VsyncWorkDuration-%s", name), workDuration),
        mReadyDuration(readyDuration),
        mVsyncSchedule(vsyncSchedule),
        mVsyncRegistration(
                vsyncSchedule.getDispatch(),
                [this](nsecs_t vsyncTime, nsecs_t wakeupTime, nsecs_t readyTime) {
                    onVsync(vsyncTime, wakeupTime, readyTime);
                },
                name),
        mVsyncSchedule(std::move(vsyncSchedule)),
        mVsyncRegistration(mVsyncSchedule->getDispatch(), createDispatchCallback(), name),
        mTokenManager(tokenManager),
        mThrottleVsyncCallback(std::move(throttleVsyncCallback)),
        mGetVsyncPeriodFunction(std::move(getVsyncPeriodFunction)) {
@@ -375,7 +370,7 @@ VsyncEventData EventThread::getLatestVsyncEventData(
    vsyncEventData.frameInterval = frameInterval;
    const auto [presentTime, deadline] = [&]() -> std::pair<nsecs_t, nsecs_t> {
        std::lock_guard<std::mutex> lock(mMutex);
        const auto vsyncTime = mVsyncSchedule.getTracker().nextAnticipatedVSyncTimeFrom(
        const auto vsyncTime = mVsyncSchedule->getTracker().nextAnticipatedVSyncTimeFrom(
                systemTime() + mWorkDuration.get().count() + mReadyDuration.count());
        return {vsyncTime, vsyncTime - mReadyDuration.count()};
    }();
@@ -533,7 +528,7 @@ bool EventThread::shouldConsumeEvent(const DisplayEventReceiver::Event& event,
    const auto throttleVsync = [&] {
        const auto& vsyncData = event.vsync.vsyncData;
        if (connection->frameRate.isValid()) {
            return !mVsyncSchedule.getTracker()
            return !mVsyncSchedule->getTracker()
                            .isVSyncInPhase(vsyncData.preferredExpectedPresentationTime(),
                                            connection->frameRate);
        }
@@ -696,6 +691,26 @@ const char* EventThread::toCString(State state) {
    }
}

void EventThread::onNewVsyncSchedule(std::shared_ptr<scheduler::VsyncSchedule> schedule) {
    std::lock_guard<std::mutex> lock(mMutex);
    const bool reschedule = mVsyncRegistration.cancel() == scheduler::CancelResult::Cancelled;
    mVsyncSchedule = std::move(schedule);
    mVsyncRegistration =
            scheduler::VSyncCallbackRegistration(mVsyncSchedule->getDispatch(),
                                                 createDispatchCallback(), mThreadName);
    if (reschedule) {
        mVsyncRegistration.schedule({.workDuration = mWorkDuration.get().count(),
                                     .readyDuration = mReadyDuration.count(),
                                     .earliestVsync = mLastVsyncCallbackTime.ns()});
    }
}

scheduler::VSyncDispatch::Callback EventThread::createDispatchCallback() {
    return [this](nsecs_t vsyncTime, nsecs_t wakeupTime, nsecs_t readyTime) {
        onVsync(vsyncTime, wakeupTime, readyTime);
    };
}

} // namespace impl
} // namespace android

+9 −3
Original line number Diff line number Diff line
@@ -133,6 +133,8 @@ public:

    // Retrieves the number of event connections tracked by this EventThread.
    virtual size_t getEventThreadConnectionCount() = 0;

    virtual void onNewVsyncSchedule(std::shared_ptr<scheduler::VsyncSchedule>) = 0;
};

namespace impl {
@@ -142,8 +144,8 @@ public:
    using ThrottleVsyncCallback = std::function<bool(nsecs_t, uid_t)>;
    using GetVsyncPeriodFunction = std::function<nsecs_t(uid_t)>;

    EventThread(const char* name, scheduler::VsyncSchedule&, frametimeline::TokenManager*,
                ThrottleVsyncCallback, GetVsyncPeriodFunction,
    EventThread(const char* name, std::shared_ptr<scheduler::VsyncSchedule>,
                frametimeline::TokenManager*, ThrottleVsyncCallback, GetVsyncPeriodFunction,
                std::chrono::nanoseconds workDuration, std::chrono::nanoseconds readyDuration);
    ~EventThread();

@@ -172,6 +174,8 @@ public:

    size_t getEventThreadConnectionCount() override;

    void onNewVsyncSchedule(std::shared_ptr<scheduler::VsyncSchedule>) override;

private:
    friend EventThreadTest;

@@ -195,11 +199,13 @@ private:
                               nsecs_t timestamp, nsecs_t preferredExpectedPresentationTime,
                               nsecs_t preferredDeadlineTimestamp) const;

    scheduler::VSyncDispatch::Callback createDispatchCallback();

    const char* const mThreadName;
    TracedOrdinal<int> mVsyncTracer;
    TracedOrdinal<std::chrono::nanoseconds> mWorkDuration GUARDED_BY(mMutex);
    std::chrono::nanoseconds mReadyDuration GUARDED_BY(mMutex);
    scheduler::VsyncSchedule& mVsyncSchedule;
    std::shared_ptr<scheduler::VsyncSchedule> mVsyncSchedule;
    TimePoint mLastVsyncCallbackTime GUARDED_BY(mMutex) = TimePoint::now();
    scheduler::VSyncCallbackRegistration mVsyncRegistration GUARDED_BY(mMutex);
    frametimeline::TokenManager* const mTokenManager;
+3 −1
Original line number Diff line number Diff line
@@ -18,12 +18,14 @@

#include <vector>

#include <ui/DisplayId.h>

#include "Display/DisplayModeRequest.h"

namespace android::scheduler {

struct ISchedulerCallback {
    virtual void setVsyncEnabled(bool) = 0;
    virtual void setVsyncEnabled(PhysicalDisplayId, bool) = 0;
    virtual void requestDisplayModes(std::vector<display::DisplayModeRequest>) = 0;
    virtual void kernelTimerChanged(bool expired) = 0;
    virtual void triggerOnFrameRateOverridesChanged() = 0;
+19 −2
Original line number Diff line number Diff line
@@ -75,19 +75,36 @@ void MessageQueue::vsyncCallback(nsecs_t vsyncTime, nsecs_t targetWakeupTime, ns
    mHandler->dispatchFrame(vsyncId, expectedVsyncTime);
}

void MessageQueue::initVsync(scheduler::VSyncDispatch& dispatch,
void MessageQueue::initVsync(std::shared_ptr<scheduler::VSyncDispatch> dispatch,
                             frametimeline::TokenManager& tokenManager,
                             std::chrono::nanoseconds workDuration) {
    std::lock_guard lock(mVsync.mutex);
    mVsync.workDuration = workDuration;
    mVsync.tokenManager = &tokenManager;
    onNewVsyncScheduleLocked(std::move(dispatch));
}

void MessageQueue::onNewVsyncSchedule(std::shared_ptr<scheduler::VSyncDispatch> dispatch) {
    std::lock_guard lock(mVsync.mutex);
    onNewVsyncScheduleLocked(std::move(dispatch));
}

void MessageQueue::onNewVsyncScheduleLocked(std::shared_ptr<scheduler::VSyncDispatch> dispatch) {
    const bool reschedule = mVsync.registration &&
            mVsync.registration->cancel() == scheduler::CancelResult::Cancelled;
    mVsync.registration = std::make_unique<
            scheduler::VSyncCallbackRegistration>(dispatch,
            scheduler::VSyncCallbackRegistration>(std::move(dispatch),
                                                  std::bind(&MessageQueue::vsyncCallback, this,
                                                            std::placeholders::_1,
                                                            std::placeholders::_2,
                                                            std::placeholders::_3),
                                                  "sf");
    if (reschedule) {
        mVsync.scheduledFrameTime =
                mVsync.registration->schedule({.workDuration = mVsync.workDuration.get().count(),
                                               .readyDuration = 0,
                                               .earliestVsync = mVsync.lastCallbackTime.ns()});
    }
}

void MessageQueue::destroyVsync() {
+6 −2
Original line number Diff line number Diff line
@@ -65,7 +65,7 @@ class MessageQueue {
public:
    virtual ~MessageQueue() = default;

    virtual void initVsync(scheduler::VSyncDispatch&, frametimeline::TokenManager&,
    virtual void initVsync(std::shared_ptr<scheduler::VSyncDispatch>, frametimeline::TokenManager&,
                           std::chrono::nanoseconds workDuration) = 0;
    virtual void destroyVsync() = 0;
    virtual void setDuration(std::chrono::nanoseconds workDuration) = 0;
@@ -106,6 +106,8 @@ protected:

    void vsyncCallback(nsecs_t vsyncTime, nsecs_t targetWakeupTime, nsecs_t readyTime);

    void onNewVsyncSchedule(std::shared_ptr<scheduler::VSyncDispatch>) EXCLUDES(mVsync.mutex);

private:
    virtual void onFrameSignal(ICompositor&, VsyncId, TimePoint expectedVsyncTime) = 0;

@@ -127,10 +129,12 @@ private:

    Vsync mVsync;

    void onNewVsyncScheduleLocked(std::shared_ptr<scheduler::VSyncDispatch>) REQUIRES(mVsync.mutex);

public:
    explicit MessageQueue(ICompositor&);

    void initVsync(scheduler::VSyncDispatch&, frametimeline::TokenManager&,
    void initVsync(std::shared_ptr<scheduler::VSyncDispatch>, frametimeline::TokenManager&,
                   std::chrono::nanoseconds workDuration) override;
    void destroyVsync() override;
    void setDuration(std::chrono::nanoseconds workDuration) override;
Loading