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

Commit 08fbd85f authored by Dominik Laskowski's avatar Dominik Laskowski
Browse files

SF: Delegate ICompositor interfacing to Scheduler

Factor out MessageQueue's calls to commit/composite/sample into an
onFrameSignal delegate that Scheduler implements, since the policy
for ICompositor interfacing (e.g. whether to composite displays
sequentially or concurrently) will be the latter's responsibility.

Improve type correctness by replacing more nsecs_t with TimePoint/
Duration, and int64_t with a new VsyncId type.

Bug: 241285191
Test: Boot
Change-Id: I5039894038b62a562c1f93b7cea41751f7f76ca6
parent e4a23a99
Loading
Loading
Loading
Loading
+17 −23
Original line number Diff line number Diff line
@@ -30,7 +30,7 @@

namespace android::impl {

void MessageQueue::Handler::dispatchFrame(int64_t vsyncId, nsecs_t expectedVsyncTime) {
void MessageQueue::Handler::dispatchFrame(VsyncId vsyncId, TimePoint expectedVsyncTime) {
    if (!mFramePending.exchange(true)) {
        mVsyncId = vsyncId;
        mExpectedVsyncTime = expectedVsyncTime;
@@ -44,16 +44,7 @@ bool MessageQueue::Handler::isFramePending() const {

void MessageQueue::Handler::handleMessage(const Message&) {
    mFramePending.store(false);

    const nsecs_t frameTime = systemTime();
    auto& compositor = mQueue.mCompositor;

    if (!compositor.commit(frameTime, mVsyncId, mExpectedVsyncTime)) {
        return;
    }

    compositor.composite(frameTime, mVsyncId);
    compositor.sample();
    mQueue.onFrameSignal(mQueue.mCompositor, mVsyncId, mExpectedVsyncTime);
}

MessageQueue::MessageQueue(ICompositor& compositor)
@@ -102,16 +93,17 @@ void MessageQueue::vsyncCallback(nsecs_t vsyncTime, nsecs_t targetWakeupTime, ns
    // Trace VSYNC-sf
    mVsync.value = (mVsync.value + 1) % 2;

    const auto expectedVsyncTime = TimePoint::fromNs(vsyncTime);
    {
        std::lock_guard lock(mVsync.mutex);
        mVsync.lastCallbackTime = std::chrono::nanoseconds(vsyncTime);
        mVsync.lastCallbackTime = expectedVsyncTime;
        mVsync.scheduledFrameTime.reset();
    }

    const auto vsyncId = mVsync.tokenManager->generateTokenForPredictions(
            {targetWakeupTime, readyTime, vsyncTime});
    const auto vsyncId = VsyncId{mVsync.tokenManager->generateTokenForPredictions(
            {targetWakeupTime, readyTime, vsyncTime})};

    mHandler->dispatchFrame(vsyncId, vsyncTime);
    mHandler->dispatchFrame(vsyncId, expectedVsyncTime);
}

void MessageQueue::initVsync(scheduler::VSyncDispatch& dispatch,
@@ -133,9 +125,10 @@ void MessageQueue::setDuration(std::chrono::nanoseconds workDuration) {
    std::lock_guard lock(mVsync.mutex);
    mVsync.workDuration = workDuration;
    if (mVsync.scheduledFrameTime) {
        mVsync.scheduledFrameTime = mVsync.registration->schedule(
                {mVsync.workDuration.get().count(),
                 /*readyDuration=*/0, mVsync.lastCallbackTime.count()});
        mVsync.scheduledFrameTime =
                mVsync.registration->schedule({.workDuration = mVsync.workDuration.get().count(),
                                               .readyDuration = 0,
                                               .earliestVsync = mVsync.lastCallbackTime.ns()});
    }
}

@@ -171,7 +164,7 @@ void MessageQueue::scheduleFrame() {
    {
        std::lock_guard lock(mInjector.mutex);
        if (CC_UNLIKELY(mInjector.connection)) {
            ALOGD("%s while injecting VSYNC", __FUNCTION__);
            ALOGD("%s while injecting VSYNC", __func__);
            mInjector.connection->requestNextVsync();
            return;
        }
@@ -181,7 +174,7 @@ void MessageQueue::scheduleFrame() {
    mVsync.scheduledFrameTime =
            mVsync.registration->schedule({.workDuration = mVsync.workDuration.get().count(),
                                           .readyDuration = 0,
                                           .earliestVsync = mVsync.lastCallbackTime.count()});
                                           .earliestVsync = mVsync.lastCallbackTime.ns()});
}

void MessageQueue::injectorCallback() {
@@ -190,9 +183,10 @@ void MessageQueue::injectorCallback() {
    while ((n = DisplayEventReceiver::getEvents(&mInjector.tube, buffer, 8)) > 0) {
        for (int i = 0; i < n; i++) {
            if (buffer[i].header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC) {
                auto& vsync = buffer[i].vsync;
                mHandler->dispatchFrame(vsync.vsyncData.preferredVsyncId(),
                                        vsync.vsyncData.preferredExpectedPresentationTime());
                auto& vsync = buffer[i].vsync.vsyncData;
                mHandler->dispatchFrame(VsyncId{vsync.preferredVsyncId()},
                                        TimePoint::fromNs(
                                                vsync.preferredExpectedPresentationTime()));
                break;
            }
        }
+12 −6
Original line number Diff line number Diff line
@@ -28,6 +28,9 @@
#include <utils/StrongPointer.h>
#include <utils/Timers.h>

#include <scheduler/Time.h>
#include <scheduler/VsyncId.h>

#include "EventThread.h"
#include "TracedOrdinal.h"
#include "VSyncDispatch.h"
@@ -35,8 +38,8 @@
namespace android {

struct ICompositor {
    virtual bool commit(nsecs_t frameTime, int64_t vsyncId, nsecs_t expectedVsyncTime) = 0;
    virtual void composite(nsecs_t frameTime, int64_t vsyncId) = 0;
    virtual bool commit(TimePoint frameTime, VsyncId, TimePoint expectedVsyncTime) = 0;
    virtual void composite(TimePoint frameTime, VsyncId) = 0;
    virtual void sample() = 0;

protected:
@@ -88,8 +91,9 @@ protected:
    class Handler : public MessageHandler {
        MessageQueue& mQueue;
        std::atomic_bool mFramePending = false;
        std::atomic<int64_t> mVsyncId = 0;
        std::atomic<nsecs_t> mExpectedVsyncTime = 0;

        std::atomic<VsyncId> mVsyncId;
        std::atomic<TimePoint> mExpectedVsyncTime;

    public:
        explicit Handler(MessageQueue& queue) : mQueue(queue) {}
@@ -97,7 +101,7 @@ protected:

        bool isFramePending() const;

        virtual void dispatchFrame(int64_t vsyncId, nsecs_t expectedVsyncTime);
        virtual void dispatchFrame(VsyncId, TimePoint expectedVsyncTime);
    };

    friend class Handler;
@@ -108,6 +112,8 @@ protected:
    void vsyncCallback(nsecs_t vsyncTime, nsecs_t targetWakeupTime, nsecs_t readyTime);

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

    ICompositor& mCompositor;
    const sp<Looper> mLooper;
    const sp<Handler> mHandler;
@@ -119,7 +125,7 @@ private:
        mutable std::mutex mutex;
        TracedOrdinal<std::chrono::nanoseconds> workDuration
                GUARDED_BY(mutex) = {"VsyncWorkDuration-sf", std::chrono::nanoseconds(0)};
        std::chrono::nanoseconds lastCallbackTime GUARDED_BY(mutex) = std::chrono::nanoseconds{0};
        TimePoint lastCallbackTime GUARDED_BY(mutex);
        std::optional<nsecs_t> scheduledFrameTime GUARDED_BY(mutex);
        TracedOrdinal<int> value = {"VSYNC-sf", 0};
    };
+15 −3
Original line number Diff line number Diff line
@@ -131,6 +131,18 @@ void Scheduler::run() {
    }
}

void Scheduler::onFrameSignal(ICompositor& compositor, VsyncId vsyncId,
                              TimePoint expectedVsyncTime) {
    const TimePoint frameTime = SchedulerClock::now();

    if (!compositor.commit(frameTime, vsyncId, expectedVsyncTime)) {
        return;
    }

    compositor.composite(frameTime, vsyncId);
    compositor.sample();
}

void Scheduler::createVsyncSchedule(FeatureFlags features) {
    mVsyncSchedule.emplace(features);
}
@@ -151,20 +163,20 @@ std::optional<Fps> Scheduler::getFrameRateOverride(uid_t uid) const {
            .getFrameRateOverrideForUid(uid, supportsFrameRateOverrideByContent);
}

bool Scheduler::isVsyncValid(nsecs_t expectedVsyncTimestamp, uid_t uid) const {
bool Scheduler::isVsyncValid(TimePoint expectedVsyncTimestamp, uid_t uid) const {
    const auto frameRate = getFrameRateOverride(uid);
    if (!frameRate.has_value()) {
        return true;
    }

    return mVsyncSchedule->getTracker().isVSyncInPhase(expectedVsyncTimestamp, *frameRate);
    return mVsyncSchedule->getTracker().isVSyncInPhase(expectedVsyncTimestamp.ns(), *frameRate);
}

impl::EventThread::ThrottleVsyncCallback Scheduler::makeThrottleVsyncCallback() const {
    std::scoped_lock lock(mRefreshRateConfigsLock);

    return [this](nsecs_t expectedVsyncTimestamp, uid_t uid) {
        return !isVsyncValid(expectedVsyncTimestamp, uid);
        return !isVsyncValid(TimePoint::fromNs(expectedVsyncTimestamp), uid);
    };
}

+4 −1
Original line number Diff line number Diff line
@@ -192,7 +192,7 @@ public:

    // Returns true if a given vsync timestamp is considered valid vsync
    // for a given uid
    bool isVsyncValid(nsecs_t expectedVsyncTimestamp, uid_t uid) const;
    bool isVsyncValid(TimePoint expectedVsyncTimestamp, uid_t uid) const;

    void dump(std::string&) const;
    void dump(ConnectionHandle, std::string&) const;
@@ -243,6 +243,9 @@ private:
    enum class TimerState { Reset, Expired };
    enum class TouchState { Inactive, Active };

    // impl::MessageQueue overrides:
    void onFrameSignal(ICompositor&, VsyncId, TimePoint expectedVsyncTime) override;

    // Create a connection on the given EventThread.
    ConnectionHandle createConnection(std::unique_ptr<EventThread>);
    sp<EventThreadConnection> createConnectionInternal(
+13 −1
Original line number Diff line number Diff line
@@ -46,7 +46,8 @@ struct TimePoint : scheduler::SchedulerClock::time_point {

struct Duration : TimePoint::duration {
    // Implicit conversion from std::chrono counterpart.
    constexpr Duration(TimePoint::duration d) : TimePoint::duration(d) {}
    template <typename R, typename P>
    constexpr Duration(std::chrono::duration<R, P> d) : TimePoint::duration(d) {}

    static constexpr Duration fromNs(nsecs_t ns) { return {std::chrono::nanoseconds(ns)}; }

@@ -65,4 +66,15 @@ inline nsecs_t TimePoint::ns() const {
    return Duration(time_since_epoch()).ns();
}

// Shorthand to convert the tick count of a Duration to Period and Rep. For example:
//
//     const auto i = ticks<std::ratio<1>>(d);      // Integer seconds.
//     const auto f = ticks<std::milli, float>(d);  // Floating-point milliseconds.
//
template <typename Period, typename Rep = Duration::rep>
constexpr Rep ticks(Duration d) {
    using D = std::chrono::duration<Rep, Period>;
    return std::chrono::duration_cast<D>(d).count();
}

} // namespace android
Loading