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

Commit 0bd0d4c6 authored by Leon Scroggins III's avatar Leon Scroggins III
Browse files

SF: Move present timing to FrameTargeter

Split out from I2c27dc709afd1f33bddbf9c2ca1cd61dd335f66c.

Store earliestPresentTime on the FrameTarget, like expectedPresentTime,
so it can be stored per display.

Add FrameTargeter::computeEarliestPresentTime. This calculation was
previously done in SurfaceFlinger, using data mostly contained in the
FrameTargeter. This will simplify computing this per display.

Move computation of the earliestPresentTime to
FrameTargeter::beginFrame. Add a scheduler::Feature to track whether
ExpectedPresentTime is supported.

Make previousFrameVsyncTime and wouldPresentEarly protected, now that
they are only called by FrameTargeter (subclass) and tests.

Make the test a friend of FrameTarget for accessing the above methods.

Bug: 255601557
Bug: 256196556
Bug: 259132483
Test: atest libscheduler_test:FrameTargeterTest
Test: atest
        libscheduler_test:FrameTargeterWithExpectedPresentSupportTest

Change-Id: Ib927935de6ba2b7b8d5037b42eb635ae92019634
parent 823d4ca5
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -192,7 +192,8 @@ void Scheduler::onFrameSignal(ICompositor& compositor, VsyncId vsyncId,
             .vsyncId = vsyncId,
             // TODO(b/255601557): Calculate per display.
             .expectedVsyncTime = expectedVsyncTime,
             .sfWorkDuration = mVsyncModulator->getVsyncConfig().sfWorkDuration};
             .sfWorkDuration = mVsyncModulator->getVsyncConfig().sfWorkDuration,
             .hwcMinWorkDuration = mVsyncConfiguration->getCurrentConfigs().hwcMinWorkDuration};

    ftl::NonNull<const Display*> pacesetterPtr = pacesetterPtrLocked();
    pacesetterPtr->targeterPtr->beginFrame(beginFrameArgs, *pacesetterPtr->schedulePtr);
+1 −3
Original line number Diff line number Diff line
@@ -514,9 +514,7 @@ private:
              : displayId(displayId),
                selectorPtr(std::move(selectorPtr)),
                schedulePtr(std::move(schedulePtr)),
                targeterPtr(std::make_unique<
                            FrameTargeter>(displayId,
                                           features.test(Feature::kBackpressureGpuComposition))) {}
                targeterPtr(std::make_unique<FrameTargeter>(displayId, features)) {}

        const PhysicalDisplayId displayId;

+1 −0
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@ enum class Feature : std::uint8_t {
    kTracePredictedVsync = 1 << 3,
    kBackpressureGpuComposition = 1 << 4,
    kSmallDirtyContentDetection = 1 << 5,
    kExpectedPresentTime = 1 << 6,
};

using FeatureFlags = ftl::Flags<Feature>;
+23 −10
Original line number Diff line number Diff line
@@ -19,11 +19,13 @@
#include <array>
#include <atomic>
#include <memory>
#include <optional>

#include <ui/DisplayId.h>
#include <ui/Fence.h>
#include <ui/FenceTime.h>

#include <scheduler/Features.h>
#include <scheduler/Time.h>
#include <scheduler/VsyncId.h>
#include <scheduler/interface/CompositeResult.h>
@@ -49,14 +51,11 @@ public:

    TimePoint expectedPresentTime() const { return mExpectedPresentTime; }

    std::optional<TimePoint> earliestPresentTime() const { return mEarliestPresentTime; }

    // The time of the VSYNC that preceded this frame. See `presentFenceForPastVsync` for details.
    TimePoint pastVsyncTime(Period minFramePeriod) const;

    // Equivalent to `pastVsyncTime` unless running N VSYNCs ahead.
    TimePoint previousFrameVsyncTime(Period minFramePeriod) const {
        return mExpectedPresentTime - minFramePeriod;
    }

    // The present fence for the frame that had targeted the most recent VSYNC before this frame.
    // If the target VSYNC for any given frame is more than `vsyncPeriod` in the future, then the
    // VSYNC of at least one previous frame has not yet passed. In other words, this is NOT the
@@ -69,8 +68,6 @@ public:
        return mPresentFences.front().fenceTime;
    }

    bool wouldPresentEarly(Period minFramePeriod) const;

    bool isFramePending() const { return mFramePending; }
    bool didMissFrame() const { return mFrameMissed; }
    bool didMissHwcFrame() const { return mHwcFrameMissed && !mGpuFrameMissed; }
@@ -79,9 +76,17 @@ protected:
    explicit FrameTarget(const std::string& displayLabel);
    ~FrameTarget() = default;

    bool wouldPresentEarly(Period minFramePeriod) const;

    // Equivalent to `pastVsyncTime` unless running N VSYNCs ahead.
    TimePoint previousFrameVsyncTime(Period minFramePeriod) const {
        return mExpectedPresentTime - minFramePeriod;
    }

    VsyncId mVsyncId;
    TimePoint mFrameBeginTime;
    TimePoint mExpectedPresentTime;
    std::optional<TimePoint> mEarliestPresentTime;

    TracedOrdinal<bool> mFramePending;
    TracedOrdinal<bool> mFrameMissed;
@@ -95,6 +100,8 @@ protected:
    std::array<FenceWithFenceTime, 2> mPresentFences;

private:
    friend class FrameTargeterTestBase;

    template <int N>
    inline bool targetsVsyncsAhead(Period minFramePeriod) const {
        static_assert(N > 1);
@@ -105,9 +112,10 @@ private:
// Computes a display's per-frame metrics about past/upcoming targeting of present deadlines.
class FrameTargeter final : private FrameTarget {
public:
    FrameTargeter(PhysicalDisplayId displayId, bool backpressureGpuComposition)
    FrameTargeter(PhysicalDisplayId displayId, FeatureFlags flags)
          : FrameTarget(to_string(displayId)),
            mBackpressureGpuComposition(backpressureGpuComposition) {}
            mBackpressureGpuComposition(flags.test(Feature::kBackpressureGpuComposition)),
            mSupportsExpectedPresentTime(flags.test(Feature::kExpectedPresentTime)) {}

    const FrameTarget& target() const { return *this; }

@@ -116,10 +124,14 @@ public:
        VsyncId vsyncId;
        TimePoint expectedVsyncTime;
        Duration sfWorkDuration;
        Duration hwcMinWorkDuration;
    };

    void beginFrame(const BeginFrameArgs&, const IVsyncSource&);

    std::optional<TimePoint> computeEarliestPresentTime(Period minFramePeriod,
                                                        Duration hwcMinWorkDuration);

    // TODO(b/241285191): Merge with FrameTargeter::endFrame.
    FenceTimePtr setPresentFence(sp<Fence>);

@@ -128,7 +140,7 @@ public:
    void dump(utils::Dumper&) const;

private:
    friend class FrameTargeterTest;
    friend class FrameTargeterTestBase;

    // For tests.
    using IsFencePendingFuncPtr = bool (*)(const FenceTimePtr&, int graceTimeMs);
@@ -138,6 +150,7 @@ private:
    static bool isFencePending(const FenceTimePtr&, int graceTimeMs);

    const bool mBackpressureGpuComposition;
    const bool mSupportsExpectedPresentTime;

    TimePoint mScheduledPresentTime;
    CompositionCoverageFlags mCompositionCoverage;
+12 −0
Original line number Diff line number Diff line
@@ -82,6 +82,10 @@ void FrameTargeter::beginFrame(const BeginFrameArgs& args, const IVsyncSource& v
        }
    }

    if (!mSupportsExpectedPresentTime) {
        mEarliestPresentTime = computeEarliestPresentTime(minFramePeriod, args.hwcMinWorkDuration);
    }

    ATRACE_FORMAT("%s %" PRId64 " vsyncIn %.2fms%s", __func__, ftl::to_underlying(args.vsyncId),
                  ticks<std::milli, float>(mExpectedPresentTime - TimePoint::now()),
                  mExpectedPresentTime == args.expectedVsyncTime ? "" : " (adjusted)");
@@ -121,6 +125,14 @@ void FrameTargeter::beginFrame(const BeginFrameArgs& args, const IVsyncSource& v
    if (mGpuFrameMissed) mGpuFrameMissedCount++;
}

std::optional<TimePoint> FrameTargeter::computeEarliestPresentTime(Period minFramePeriod,
                                                                   Duration hwcMinWorkDuration) {
    if (wouldPresentEarly(minFramePeriod)) {
        return previousFrameVsyncTime(minFramePeriod) - hwcMinWorkDuration;
    }
    return {};
}

void FrameTargeter::endFrame(const CompositeResult& result) {
    mCompositionCoverage = result.compositionCoverage;
}
Loading