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

Commit 16dec1f6 authored by Matt Buckley's avatar Matt Buckley
Browse files

Rename hwc-specific methods and properties for readability

In hint session timing code, "present" is used to refer to:

1) The CompositionEngine present method called in SF
2) The present method in Output called separately per-display
3) The present call made to the actual vendor HWC
4) The place where the frame actually starts to display on the screen
   eg: expectedPresentTime

The distinctions is important in a timing context because they behave
differently and happen at different points in the frame, but they are
currently referred to interchangeably. This patch aims to remove some
of that ambiguity by prefixing hwc-specific methods + properties with
"hwc" as well as making fence naming more specific.

Bug: b/195990840
Test: atest libsurfaceflinger_unittest:libsurfaceflinger_unittest.AidlPowerHalWrapperTest
Change-Id: I138e197431a5f1af05031e1180483433009c333d
parent a09e6780
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -261,7 +261,7 @@ bool Display::chooseCompositionStrategy(
    }

    if (isPowerHintSessionEnabled()) {
        mPowerAdvisor->setValidateTiming(mId, startTime, systemTime());
        mPowerAdvisor->setHwcValidateTiming(mId, startTime, systemTime());
        mPowerAdvisor->setRequiresClientComposition(mId, requiresClientComposition);
    }

@@ -371,7 +371,7 @@ compositionengine::Output::FrameFences Display::presentAndGetFrameFences() {
        if (!getCompositionEngine().getHwComposer().getComposer()->isSupported(
                    Hwc2::Composer::OptionalFeature::ExpectedPresentTime) &&
            getState().previousPresentFence->getSignalTime() != Fence::SIGNAL_TIME_PENDING) {
            mPowerAdvisor->setPresentDelayedTime(mId, getState().earliestPresentTime);
            mPowerAdvisor->setHwcPresentDelayedTime(mId, getState().earliestPresentTime);
        }
    }

@@ -379,7 +379,7 @@ compositionengine::Output::FrameFences Display::presentAndGetFrameFences() {
                                   getState().previousPresentFence);

    if (isPowerHintSessionEnabled()) {
        mPowerAdvisor->setPresentTiming(mId, startTime, systemTime());
        mPowerAdvisor->setHwcPresentTiming(mId, startTime, systemTime());
    }

    fences.presentFence = hwc.getPresentFence(*halDisplayIdOpt);
+3 −3
Original line number Diff line number Diff line
@@ -45,17 +45,17 @@ public:
    MOCK_METHOD(bool, startPowerHintSession, (const std::vector<int32_t>& threadIds), (override));
    MOCK_METHOD(void, setGpuFenceTime,
                (DisplayId displayId, std::unique_ptr<FenceTime>&& fenceTime), (override));
    MOCK_METHOD(void, setValidateTiming,
    MOCK_METHOD(void, setHwcValidateTiming,
                (DisplayId displayId, nsecs_t valiateStartTime, nsecs_t validateEndTime),
                (override));
    MOCK_METHOD(void, setPresentTiming,
    MOCK_METHOD(void, setHwcPresentTiming,
                (DisplayId displayId, nsecs_t presentStartTime, nsecs_t presentEndTime),
                (override));
    MOCK_METHOD(void, setSkippedValidate, (DisplayId displayId, bool skipped), (override));
    MOCK_METHOD(void, setRequiresClientComposition,
                (DisplayId displayId, bool requiresClientComposition), (override));
    MOCK_METHOD(void, setExpectedPresentTime, (nsecs_t expectedPresentTime), (override));
    MOCK_METHOD(void, setPresentDelayedTime,
    MOCK_METHOD(void, setHwcPresentDelayedTime,
                (DisplayId displayId,
                 std::chrono::steady_clock::time_point earliestFrameStartTime));
    MOCK_METHOD(void, setFrameDelay, (nsecs_t frameDelayDuration), (override));
+57 −50
Original line number Diff line number Diff line
@@ -287,18 +287,18 @@ void PowerAdvisor::setGpuFenceTime(DisplayId displayId, std::unique_ptr<FenceTim
    displayData.gpuStartTime = systemTime();
}

void PowerAdvisor::setValidateTiming(DisplayId displayId, nsecs_t validateStartTime,
void PowerAdvisor::setHwcValidateTiming(DisplayId displayId, nsecs_t validateStartTime,
                                        nsecs_t validateEndTime) {
    DisplayTimingData& displayData = mDisplayTimingData[displayId];
    displayData.validateStartTime = validateStartTime;
    displayData.validateEndTime = validateEndTime;
    displayData.hwcValidateStartTime = validateStartTime;
    displayData.hwcValidateEndTime = validateEndTime;
}

void PowerAdvisor::setPresentTiming(DisplayId displayId, nsecs_t presentStartTime,
void PowerAdvisor::setHwcPresentTiming(DisplayId displayId, nsecs_t presentStartTime,
                                       nsecs_t presentEndTime) {
    DisplayTimingData& displayData = mDisplayTimingData[displayId];
    displayData.presentStartTime = presentStartTime;
    displayData.presentEndTime = presentEndTime;
    displayData.hwcPresentStartTime = presentStartTime;
    displayData.hwcPresentEndTime = presentEndTime;
}

void PowerAdvisor::setSkippedValidate(DisplayId displayId, bool skipped) {
@@ -318,9 +318,9 @@ void PowerAdvisor::setFrameDelay(nsecs_t frameDelayDuration) {
    mFrameDelayDuration = frameDelayDuration;
}

void PowerAdvisor::setPresentDelayedTime(
void PowerAdvisor::setHwcPresentDelayedTime(
        DisplayId displayId, std::chrono::steady_clock::time_point earliestFrameStartTime) {
    mDisplayTimingData[displayId].presentDelayedTime =
    mDisplayTimingData[displayId].hwcPresentDelayedTime =
            (earliestFrameStartTime - std::chrono::steady_clock::now()).count() + systemTime();
}

@@ -331,10 +331,11 @@ void PowerAdvisor::setCommitStart(nsecs_t commitStartTime) {
void PowerAdvisor::setCompositeEnd(nsecs_t compositeEnd) {
    mLastCompositeEndTime = compositeEnd;
    // calculate the postcomp time here as well
    std::vector<DisplayId>&& displays = getOrderedDisplayIds(&DisplayTimingData::presentEndTime);
    std::vector<DisplayId>&& displays = getOrderedDisplayIds(&DisplayTimingData::hwcPresentEndTime);
    DisplayTimingData& timingData = mDisplayTimingData[displays.back()];
    mLastPostcompDuration = compositeEnd -
            (timingData.skippedValidate ? *timingData.validateEndTime : *timingData.presentEndTime);
            (timingData.skippedValidate ? *timingData.hwcValidateEndTime
                                        : *timingData.hwcPresentEndTime);
}

void PowerAdvisor::setDisplays(std::vector<DisplayId>& displayIds) {
@@ -390,7 +391,7 @@ std::optional<nsecs_t> PowerAdvisor::estimateWorkDuration(bool earlyHint) {
    // The timing info for the previously calculated display, if there was one
    std::optional<DisplayTimeline> previousDisplayReferenceTiming;
    std::vector<DisplayId>&& displayIds =
            getOrderedDisplayIds(&DisplayTimingData::presentStartTime);
            getOrderedDisplayIds(&DisplayTimingData::hwcPresentStartTime);
    DisplayTimeline referenceTiming, estimatedTiming;

    // Iterate over the displays in the same order they are presented
@@ -402,27 +403,26 @@ std::optional<nsecs_t> PowerAdvisor::estimateWorkDuration(bool earlyHint) {
        auto& displayData = mDisplayTimingData.at(displayId);
        referenceTiming = displayData.calculateDisplayTimeline(referenceFenceTime);

        // If this is the first display, add the pre-present time to the total
        // If this is the first display, include the duration before hwc present starts
        if (!previousDisplayReferenceTiming.has_value()) {
            estimatedEndTime += referenceTiming.prePresentTime - referenceFrameStartTime;
        } else { // Otherwise add last display's postprocessing time to the total
            estimatedEndTime += referenceTiming.prePresentTime -
                    previousDisplayReferenceTiming->postPresentTime;
            estimatedEndTime += referenceTiming.hwcPresentStartTime - referenceFrameStartTime;
        } else { // Otherwise add the time since last display's hwc present finished
            estimatedEndTime += referenceTiming.hwcPresentStartTime -
                    previousDisplayReferenceTiming->hwcPresentEndTime;
        }

        estimatedTiming = referenceTiming.estimateTimelineFromReference(mExpectedPresentTimes[-1],
                                                                        estimatedEndTime);
        // Update predicted present finish time with this display's present time
        estimatedEndTime = estimatedTiming.postPresentTime;
        estimatedEndTime = estimatedTiming.hwcPresentEndTime;

        // Track how long we spent waiting for the fence, can be excluded from the timing estimate
        idleDuration += estimatedTiming.probablyWaitsForFence
                ? mExpectedPresentTimes[-1] - estimatedTiming.preFenceWaitTime
        idleDuration += estimatedTiming.probablyWaitsForReleaseFence
                ? mExpectedPresentTimes[-1] - estimatedTiming.releaseFenceWaitStartTime
                : 0;

        // Track how long we spent waiting to present, can be excluded from the timing estimate
        idleDuration +=
                !earlyHint ? referenceTiming.presentStartTime - referenceTiming.prePresentTime : 0;
        idleDuration += earlyHint ? 0 : referenceTiming.hwcPresentDelayDuration;

        // Estimate the reference frame's gpu timing
        auto gpuTiming = displayData.estimateGpuTiming(previousValidGpuEndTime);
@@ -431,7 +431,7 @@ std::optional<nsecs_t> PowerAdvisor::estimateWorkDuration(bool earlyHint) {

            // Estimate the prediction frame's gpu end time from the reference frame
            estimatedGpuEndTime =
                    std::max(estimatedTiming.prePresentTime, estimatedGpuEndTime.value_or(0)) +
                    std::max(estimatedTiming.hwcPresentStartTime, estimatedGpuEndTime.value_or(0)) +
                    gpuTiming->duration;
        }
        previousDisplayReferenceTiming = referenceTiming;
@@ -470,48 +470,55 @@ nsecs_t PowerAdvisor::combineTimingEstimates(nsecs_t totalDuration, nsecs_t flin
PowerAdvisor::DisplayTimeline PowerAdvisor::DisplayTimeline::estimateTimelineFromReference(
        nsecs_t fenceTime, nsecs_t displayStartTime) {
    DisplayTimeline estimated;
    estimated.prePresentTime = displayStartTime;
    estimated.hwcPresentStartTime = displayStartTime;

    // We don't predict waiting for vsync alignment yet
    estimated.presentStartTime = estimated.prePresentTime;
    estimated.hwcPresentDelayDuration = 0;

    // For now just re-use last frame's post-present duration and assume it will not change much
    // How long we expect to run before we start waiting for the fence
    estimated.preFenceWaitTime = estimated.presentStartTime + (preFenceWaitTime - presentStartTime);
    estimated.probablyWaitsForFence = fenceTime > estimated.preFenceWaitTime;
    estimated.postPresentTime = postFenceDuration +
            (estimated.probablyWaitsForFence ? fenceTime : estimated.preFenceWaitTime);
    // If it's the early hint we exclude time we spent waiting for a vsync, otherwise don't
    estimated.releaseFenceWaitStartTime = estimated.hwcPresentStartTime +
            (releaseFenceWaitStartTime - (hwcPresentStartTime + hwcPresentDelayDuration));
    estimated.probablyWaitsForReleaseFence = fenceTime > estimated.releaseFenceWaitStartTime;
    estimated.hwcPresentEndTime = postReleaseFenceHwcPresentDuration +
            (estimated.probablyWaitsForReleaseFence ? fenceTime
                                                    : estimated.releaseFenceWaitStartTime);
    return estimated;
}

PowerAdvisor::DisplayTimeline PowerAdvisor::DisplayTimingData::calculateDisplayTimeline(
        nsecs_t fenceTime) {
    DisplayTimeline timeline;
    // How long between calling present from flinger and trying to wait on the fence in HWC
    const nsecs_t preFenceWaitDelay =
            (skippedValidate ? kPrefenceDelaySkippedValidate : kPrefenceDelayValidated).count();
    // How long between calling hwc present and trying to wait on the fence
    const nsecs_t fenceWaitStartDelay =
            (skippedValidate ? kFenceWaitStartDelaySkippedValidate : kFenceWaitStartDelayValidated)
                    .count();

    // Did our reference frame wait for an earliest present time before calling the HWC
    const bool waitedOnPresentTime = presentDelayedTime.has_value() &&
            *presentDelayedTime > *presentStartTime && *presentDelayedTime < *presentEndTime;
    // Did our reference frame wait for an appropriate vsync before calling into hwc
    const bool waitedOnHwcPresentTime = hwcPresentDelayedTime.has_value() &&
            *hwcPresentDelayedTime > *hwcPresentStartTime &&
            *hwcPresentDelayedTime < *hwcPresentEndTime;

    // Use validate start here if we skipped it because we did validate + present together
    timeline.prePresentTime = skippedValidate ? *validateStartTime : *presentStartTime;
    timeline.hwcPresentStartTime = skippedValidate ? *hwcValidateStartTime : *hwcPresentStartTime;

    // Use validate end here if we skipped it because we did validate + present together
    timeline.postPresentTime = skippedValidate ? *validateEndTime : *presentEndTime;

    // When we think we started waiting for the fence after calling into present
    // This is after any time spent waiting for the earliest present time
    timeline.presentStartTime =
            (waitedOnPresentTime ? *presentDelayedTime : timeline.prePresentTime);
    timeline.preFenceWaitTime = timeline.presentStartTime + preFenceWaitDelay;
    timeline.probablyWaitsForFence =
            fenceTime > timeline.preFenceWaitTime && fenceTime < timeline.postPresentTime;

    // How long we ran after we finished waiting for the fence but before present happened
    timeline.postFenceDuration = timeline.postPresentTime -
            (timeline.probablyWaitsForFence ? fenceTime : timeline.preFenceWaitTime);
    timeline.hwcPresentEndTime = skippedValidate ? *hwcValidateEndTime : *hwcPresentEndTime;

    // How long hwc present was delayed waiting for the next appropriate vsync
    timeline.hwcPresentDelayDuration =
            (waitedOnHwcPresentTime ? *hwcPresentDelayedTime - *hwcPresentStartTime : 0);
    // When we started waiting for the release fence after calling into hwc present
    timeline.releaseFenceWaitStartTime =
            timeline.hwcPresentStartTime + timeline.hwcPresentDelayDuration + fenceWaitStartDelay;
    timeline.probablyWaitsForReleaseFence = fenceTime > timeline.releaseFenceWaitStartTime &&
            fenceTime < timeline.hwcPresentEndTime;

    // How long we ran after we finished waiting for the fence but before hwc present finished
    timeline.postReleaseFenceHwcPresentDuration = timeline.hwcPresentEndTime -
            (timeline.probablyWaitsForReleaseFence ? fenceTime
                                                   : timeline.releaseFenceWaitStartTime);
    return timeline;
}

+32 −30
Original line number Diff line number Diff line
@@ -64,11 +64,11 @@ public:
    virtual bool startPowerHintSession(const std::vector<int32_t>& threadIds) = 0;
    // Provides PowerAdvisor with a copy of the gpu fence so it can determine the gpu end time
    virtual void setGpuFenceTime(DisplayId displayId, std::unique_ptr<FenceTime>&& fenceTime) = 0;
    // Reports the start and end times of a present call this frame for a given display
    virtual void setValidateTiming(DisplayId displayId, nsecs_t validateStartTime,
    // Reports the start and end times of a hwc validate call this frame for a given display
    virtual void setHwcValidateTiming(DisplayId displayId, nsecs_t validateStartTime,
                                      nsecs_t validateEndTime) = 0;
    // Reports the start and end times of a present call this frame for a given display
    virtual void setPresentTiming(DisplayId displayId, nsecs_t presentStartTime,
    // Reports the start and end times of a hwc present call this frame for a given display
    virtual void setHwcPresentTiming(DisplayId displayId, nsecs_t presentStartTime,
                                     nsecs_t presentEndTime) = 0;
    virtual void setExpectedPresentTime(nsecs_t expectedPresentTime) = 0;
    // Reports whether a display used client composition this frame
@@ -76,8 +76,8 @@ public:
                                              bool requiresClientComposition) = 0;
    // Reports whether a given display skipped validation this frame
    virtual void setSkippedValidate(DisplayId displayId, bool skipped) = 0;
    // Reports how much a given display delayed its present call this frame
    virtual void setPresentDelayedTime(
    // Reports when a hwc present is delayed, and the time that it will resume
    virtual void setHwcPresentDelayedTime(
            DisplayId displayId, std::chrono::steady_clock::time_point earliestFrameStartTime) = 0;
    // Reports the start delay for SurfaceFlinger this frame
    virtual void setFrameDelay(nsecs_t frameDelayDuration) = 0;
@@ -132,14 +132,14 @@ public:
    void enablePowerHint(bool enabled) override;
    bool startPowerHintSession(const std::vector<int32_t>& threadIds) override;
    void setGpuFenceTime(DisplayId displayId, std::unique_ptr<FenceTime>&& fenceTime);
    void setValidateTiming(DisplayId displayId, nsecs_t valiateStartTime,
    void setHwcValidateTiming(DisplayId displayId, nsecs_t valiateStartTime,
                              nsecs_t validateEndTime) override;
    void setPresentTiming(DisplayId displayId, nsecs_t presentStartTime,
    void setHwcPresentTiming(DisplayId displayId, nsecs_t presentStartTime,
                             nsecs_t presentEndTime) override;
    void setSkippedValidate(DisplayId displayId, bool skipped) override;
    void setRequiresClientComposition(DisplayId displayId, bool requiresClientComposition) override;
    void setExpectedPresentTime(nsecs_t expectedPresentTime) override;
    void setPresentDelayedTime(
    void setHwcPresentDelayedTime(
            DisplayId displayId,
            std::chrono::steady_clock::time_point earliestFrameStartTime) override;

@@ -166,17 +166,19 @@ private:

    // Higher-level timing data used for estimation
    struct DisplayTimeline {
        nsecs_t prePresentTime = -1;
        nsecs_t postPresentTime = -1;
        // Usually equals prePresentTime but can be delayed if we wait for the next valid vsync
        nsecs_t presentStartTime = -1;
        // When we think we started waiting for the fence after calling into present and
        // The start of hwc present, or the start of validate if it happened there instead
        nsecs_t hwcPresentStartTime = -1;
        // The end of hwc present or validate, whichever one actually presented
        nsecs_t hwcPresentEndTime = -1;
        // How long the actual hwc present was delayed after hwcPresentStartTime
        nsecs_t hwcPresentDelayDuration = 0;
        // When we think we started waiting for the release fence after calling into hwc present and
        // after potentially waiting for the earliest present time
        nsecs_t preFenceWaitTime = -1;
        // How long we ran after we finished waiting for the fence but before present happened
        nsecs_t postFenceDuration = 0;
        nsecs_t releaseFenceWaitStartTime = -1;
        // How long we ran after we finished waiting for the fence but before hwc present finished
        nsecs_t postReleaseFenceHwcPresentDuration = 0;
        // Are we likely to have waited for the present fence during composition
        bool probablyWaitsForFence = false;
        bool probablyWaitsForReleaseFence = false;
        // Estimate one frame's timeline from that of a previous frame
        DisplayTimeline estimateTimelineFromReference(nsecs_t fenceTime, nsecs_t displayStartTime);
    };
@@ -192,11 +194,11 @@ private:
        std::optional<nsecs_t> gpuStartTime;
        std::optional<nsecs_t> lastValidGpuEndTime;
        std::optional<nsecs_t> lastValidGpuStartTime;
        std::optional<nsecs_t> presentStartTime;
        std::optional<nsecs_t> presentEndTime;
        std::optional<nsecs_t> validateStartTime;
        std::optional<nsecs_t> validateEndTime;
        std::optional<nsecs_t> presentDelayedTime;
        std::optional<nsecs_t> hwcPresentStartTime;
        std::optional<nsecs_t> hwcPresentEndTime;
        std::optional<nsecs_t> hwcValidateStartTime;
        std::optional<nsecs_t> hwcValidateEndTime;
        std::optional<nsecs_t> hwcPresentDelayedTime;
        bool usedClientComposition = false;
        bool skippedValidate = false;
        // Calculate high-level timing milestones from more granular display timing data
@@ -258,13 +260,13 @@ private:

    // An adjustable safety margin which moves the "target" earlier to allow flinger to
    // go a bit over without dropping a frame, especially since we can't measure
    // the exact time HWC finishes composition so "actual" durations are measured
    // the exact time hwc finishes composition so "actual" durations are measured
    // from the end of present() instead, which is a bit later.
    static constexpr const std::chrono::nanoseconds kTargetSafetyMargin = 1ms;

    // How long we expect hwc to run after the present call until it waits for the fence
    static constexpr const std::chrono::nanoseconds kPrefenceDelayValidated = 150us;
    static constexpr const std::chrono::nanoseconds kPrefenceDelaySkippedValidate = 250us;
    static constexpr const std::chrono::nanoseconds kFenceWaitStartDelayValidated = 150us;
    static constexpr const std::chrono::nanoseconds kFenceWaitStartDelaySkippedValidate = 250us;
};

class AidlPowerHalWrapper : public PowerAdvisor::HalWrapper {
+3 −3
Original line number Diff line number Diff line
@@ -43,17 +43,17 @@ public:
    MOCK_METHOD(bool, startPowerHintSession, (const std::vector<int32_t>& threadIds), (override));
    MOCK_METHOD(void, setGpuFenceTime,
                (DisplayId displayId, std::unique_ptr<FenceTime>&& fenceTime), (override));
    MOCK_METHOD(void, setValidateTiming,
    MOCK_METHOD(void, setHwcValidateTiming,
                (DisplayId displayId, nsecs_t valiateStartTime, nsecs_t validateEndTime),
                (override));
    MOCK_METHOD(void, setPresentTiming,
    MOCK_METHOD(void, setHwcPresentTiming,
                (DisplayId displayId, nsecs_t presentStartTime, nsecs_t presentEndTime),
                (override));
    MOCK_METHOD(void, setSkippedValidate, (DisplayId displayId, bool skipped), (override));
    MOCK_METHOD(void, setRequiresClientComposition,
                (DisplayId displayId, bool requiresClientComposition), (override));
    MOCK_METHOD(void, setExpectedPresentTime, (nsecs_t expectedPresentTime), (override));
    MOCK_METHOD(void, setPresentDelayedTime,
    MOCK_METHOD(void, setHwcPresentDelayedTime,
                (DisplayId displayId,
                 std::chrono::steady_clock::time_point earliestFrameStartTime));
    MOCK_METHOD(void, setFrameDelay, (nsecs_t frameDelayDuration), (override));