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

Commit 50c44062 authored by Matt Buckley's avatar Matt Buckley
Browse files

Change SF power hints to use early frame predictions

Currently we issue hints at the end of the frame reporting what happened
that frame. However, this is often too late anyway and lacks critical
information not known until after the frame completes, like gpu timing.
By waiting until the next frame start and using those timings along with
information about gpu duration, the new expected present time, and the
new wakeup time, we can instead use those timings to predict the
duration of the upcoming frame and signal in advance of a frame drop.
This patch also changes how and where frame timing is done and measures
gpu duration so we can predict if a cpu speedup can help gpu composition
happen earlier, preventing a drop that way.

Bug: b/195990840
Test: manual

Change-Id: I5f0ae796198631fced503dce8e6c495885fb256a
parent 7b2bea28
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@
#include <compositionengine/LayerFE.h>
#include <renderengine/LayerSettings.h>
#include <ui/Fence.h>
#include <ui/FenceTime.h>
#include <ui/GraphicTypes.h>
#include <ui/LayerStack.h>
#include <ui/Region.h>
@@ -311,6 +312,8 @@ protected:
            const Region& flashRegion,
            std::vector<LayerFE::LayerSettings>& clientCompositionLayers) = 0;
    virtual void setExpensiveRenderingExpected(bool enabled) = 0;
    virtual void setHintSessionGpuFence(std::unique_ptr<FenceTime>&& gpuFence) = 0;
    virtual bool isPowerHintSessionEnabled() = 0;
    virtual void cacheClientCompositionRequests(uint32_t cacheSize) = 0;
    virtual bool canPredictCompositionStrategy(const CompositionRefreshArgs&) = 0;
};
+2 −0
Original line number Diff line number Diff line
@@ -89,6 +89,8 @@ public:
    std::unique_ptr<compositionengine::OutputLayer> createOutputLayer(const sp<LayerFE>&) const;

private:
    bool isPowerHintSessionEnabled() override;
    void setHintSessionGpuFence(std::unique_ptr<FenceTime>&& gpuFence) override;
    DisplayId mId;
    bool mIsDisconnected = false;
    Hwc2::PowerAdvisor* mPowerAdvisor = nullptr;
+2 −0
Original line number Diff line number Diff line
@@ -140,6 +140,8 @@ protected:
          std::vector<LayerFE*> &outLayerFEs) override;
    void appendRegionFlashRequests(const Region&, std::vector<LayerFE::LayerSettings>&) override;
    void setExpensiveRenderingExpected(bool enabled) override;
    void setHintSessionGpuFence(std::unique_ptr<FenceTime>&& gpuFence) override;
    bool isPowerHintSessionEnabled() override;
    void dumpBase(std::string&) const;

    // Implemented by the final implementation for the final state it uses.
+2 −0
Original line number Diff line number Diff line
@@ -133,6 +133,8 @@ public:
    MOCK_METHOD1(canPredictCompositionStrategy, bool(const CompositionRefreshArgs&));
    MOCK_METHOD1(setPredictCompositionStrategy, void(bool));
    MOCK_METHOD1(setTreat170mAsSrgb, void(bool));
    MOCK_METHOD(void, setHintSessionGpuFence, (std::unique_ptr<FenceTime> && gpuFence));
    MOCK_METHOD(bool, isPowerHintSessionEnabled, ());
};

} // namespace android::compositionengine::mock
+39 −1
Original line number Diff line number Diff line
@@ -243,11 +243,14 @@ bool Display::chooseCompositionStrategy(
        return false;
    }

    const nsecs_t startTime = systemTime();

    // Get any composition changes requested by the HWC device, and apply them.
    std::optional<android::HWComposer::DeviceRequestedChanges> changes;
    auto& hwc = getCompositionEngine().getHwComposer();
    const bool requiresClientComposition = anyLayersRequireClientComposition();
    if (status_t result =
                hwc.getDeviceCompositionChanges(*halDisplayId, anyLayersRequireClientComposition(),
                hwc.getDeviceCompositionChanges(*halDisplayId, requiresClientComposition,
                                                getState().earliestPresentTime,
                                                getState().previousPresentFence,
                                                getState().expectedPresentTime, outChanges);
@@ -257,6 +260,11 @@ bool Display::chooseCompositionStrategy(
        return false;
    }

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

    return true;
}

@@ -356,9 +364,24 @@ compositionengine::Output::FrameFences Display::presentAndGetFrameFences() {
    }

    auto& hwc = getCompositionEngine().getHwComposer();

    const nsecs_t startTime = systemTime();

    if (isPowerHintSessionEnabled()) {
        if (!getCompositionEngine().getHwComposer().getComposer()->isSupported(
                    Hwc2::Composer::OptionalFeature::ExpectedPresentTime) &&
            getState().previousPresentFence->getSignalTime() != Fence::SIGNAL_TIME_PENDING) {
            mPowerAdvisor->setPresentDelayedTime(mId, getState().earliestPresentTime);
        }
    }

    hwc.presentAndGetReleaseFences(*halDisplayIdOpt, getState().earliestPresentTime,
                                   getState().previousPresentFence);

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

    fences.presentFence = hwc.getPresentFence(*halDisplayIdOpt);

    // TODO(b/121291683): Change HWComposer call to return entire map
@@ -384,6 +407,14 @@ void Display::setExpensiveRenderingExpected(bool enabled) {
    }
}

bool Display::isPowerHintSessionEnabled() {
    return mPowerAdvisor != nullptr && mPowerAdvisor->usePowerHintSession();
}

void Display::setHintSessionGpuFence(std::unique_ptr<FenceTime>&& gpuFence) {
    mPowerAdvisor->setGpuFenceTime(mId, std::move(gpuFence));
}

void Display::finishFrame(const compositionengine::CompositionRefreshArgs& refreshArgs,
                          GpuCompositionResult&& result) {
    // We only need to actually compose the display if:
@@ -396,6 +427,13 @@ void Display::finishFrame(const compositionengine::CompositionRefreshArgs& refre
    }

    impl::Output::finishFrame(refreshArgs, std::move(result));

    if (isPowerHintSessionEnabled()) {
        auto& hwc = getCompositionEngine().getHwComposer();
        if (auto halDisplayId = HalDisplayId::tryCast(mId)) {
            mPowerAdvisor->setSkippedValidate(mId, hwc.getValidateSkipped(*halDisplayId));
        }
    }
}

} // namespace android::compositionengine::impl
Loading