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

Commit 878166c9 authored by Ady Abraham's avatar Ady Abraham Committed by Android (Google) Code Review
Browse files

Merge "SurfaceFlinger: Layer::shouldPresentNow should consider early frames"

parents dbf31358 63a3e592
Loading
Loading
Loading
Loading
+37 −18
Original line number Diff line number Diff line
@@ -389,33 +389,58 @@ void BufferLayer::gatherBufferInfo() {
    mBufferInfo.mFrameLatencyNeeded = true;
}

bool BufferLayer::shouldPresentNow(nsecs_t expectedPresentTime) const {
    // If this is not a valid vsync for the layer's uid, return and try again later
    const bool isVsyncValidForUid =
            mFlinger->mScheduler->isVsyncValid(expectedPresentTime, mOwnerUid);
    if (!isVsyncValidForUid) {
        ATRACE_NAME("!isVsyncValidForUid");
        return false;
    }

    // AutoRefresh layers and sideband streams should always be presented
    if (getSidebandStreamChanged() || getAutoRefresh()) {
        return true;
    }

    // If the next planned present time is not current, return and try again later
    if (frameIsEarly(expectedPresentTime)) {
        ATRACE_NAME("frameIsEarly()");
        return false;
    }

    // If this layer doesn't have a frame is shouldn't be presented
    if (!hasFrameUpdate()) {
        return false;
    }

    // Defer to the derived class to decide whether the next buffer is due for
    // presentation.
    return isBufferDue(expectedPresentTime);
}

bool BufferLayer::frameIsEarly(nsecs_t expectedPresentTime) const {
    // TODO(b/169901895): kEarlyLatchVsyncThreshold should be based on the
    // vsync period. We can do this change as soon as ag/13100772 is merged.
    constexpr static std::chrono::nanoseconds kEarlyLatchVsyncThreshold = 5ms;

    const auto presentTime = nextPredictedPresentTime();
    if (std::abs(presentTime - expectedPresentTime) >= kEarlyLatchMaxThreshold.count()) {
    if (!presentTime.has_value()) {
        return false;
    }

    return presentTime >= expectedPresentTime &&
            presentTime - expectedPresentTime >= kEarlyLatchVsyncThreshold.count();
    if (std::abs(*presentTime - expectedPresentTime) >= kEarlyLatchMaxThreshold.count()) {
        return false;
    }

    return *presentTime >= expectedPresentTime &&
            *presentTime - expectedPresentTime >= kEarlyLatchVsyncThreshold.count();
}

bool BufferLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime,
                              nsecs_t expectedPresentTime) {
    ATRACE_CALL();

    // If this is not a valid vsync for the layer's uid, return and try again later
    const bool isVsyncValidForUid =
            mFlinger->mScheduler->isVsyncValid(expectedPresentTime, mOwnerUid);
    if (!isVsyncValidForUid) {
        ATRACE_NAME("!isVsyncValidForUid");
        mFlinger->setTransactionFlags(eTraversalNeeded);
        return false;
    }

    bool refreshRequired = latchSidebandStream(recomputeVisibleRegions);

    if (refreshRequired) {
@@ -435,12 +460,6 @@ bool BufferLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime,
        return false;
    }

    if (frameIsEarly(expectedPresentTime)) {
        ATRACE_NAME("frameIsEarly()");
        mFlinger->signalLayerUpdate();
        return false;
    }

    // If the head buffer's acquire fence hasn't signaled yet, return and
    // try again later
    if (!fenceHasSignaled()) {
+15 −8
Original line number Diff line number Diff line
@@ -175,12 +175,24 @@ protected:
    void setTransformHint(ui::Transform::RotationFlags displayTransformHint) override;

    // Transform hint provided to the producer. This must be accessed holding
    /// the mStateLock.
    // the mStateLock.
    ui::Transform::RotationFlags mTransformHint = ui::Transform::ROT_0;

    bool getAutoRefresh() const { return mAutoRefresh; }
    bool getSidebandStreamChanged() const { return mSidebandStreamChanged; }

    // Returns true if the next buffer should be presented at the expected present time
    bool shouldPresentNow(nsecs_t expectedPresentTime) const final;

    // Returns true if the next buffer should be presented at the expected present time,
    // overridden by BufferStateLayer and BufferQueueLayer for implementation
    // specific logic
    virtual bool isBufferDue(nsecs_t /*expectedPresentTime*/) const = 0;

    // Returns true if the next frame is considered too early to present
    // at the given expectedPresentTime
    bool frameIsEarly(nsecs_t expectedPresentTime) const;

    std::atomic<bool> mAutoRefresh{false};
    std::atomic<bool> mSidebandStreamChanged{false};

@@ -225,13 +237,8 @@ private:

    FloatRect computeSourceBounds(const FloatRect& parentBounds) const override;

    // Returns true if the next frame is considered too early to present
    // at the given expectedPresentTime
    bool frameIsEarly(nsecs_t expectedPresentTime) const;

    // Returns the predicted present time of the next frame if available or
    // 0 otherwise.
    virtual nsecs_t nextPredictedPresentTime() const = 0;
    // Returns the predicted present time of the next frame if available
    virtual std::optional<nsecs_t> nextPredictedPresentTime() const = 0;

    // The amount of time SF can delay a frame if it is considered early based
    // on the VsyncModulator::VsyncConfig::appWorkDuration
+4 −12
Original line number Diff line number Diff line
@@ -100,15 +100,7 @@ int32_t BufferQueueLayer::getQueuedFrameCount() const {
    return mQueuedFrames;
}

bool BufferQueueLayer::shouldPresentNow(nsecs_t expectedPresentTime) const {
    if (getSidebandStreamChanged() || getAutoRefresh()) {
        return true;
    }

    if (!hasFrameUpdate()) {
        return false;
    }

bool BufferQueueLayer::isBufferDue(nsecs_t expectedPresentTime) const {
    Mutex::Autolock lock(mQueueItemLock);

    const int64_t addedTime = mQueueItems[0].item.mTimestamp;
@@ -223,16 +215,16 @@ bool BufferQueueLayer::hasFrameUpdate() const {
    return mQueuedFrames > 0;
}

nsecs_t BufferQueueLayer::nextPredictedPresentTime() const {
std::optional<nsecs_t> BufferQueueLayer::nextPredictedPresentTime() const {
    Mutex::Autolock lock(mQueueItemLock);
    if (mQueueItems.empty()) {
        return 0;
        return std::nullopt;
    }

    const auto& bufferData = mQueueItems[0];

    if (!bufferData.item.mIsAutoTimestamp || !bufferData.surfaceFrame) {
        return 0;
        return std::nullopt;
    }

    return bufferData.surfaceFrame->getPredictions().presentTime;
+3 −2
Original line number Diff line number Diff line
@@ -53,7 +53,8 @@ public:

    int32_t getQueuedFrameCount() const override;

    bool shouldPresentNow(nsecs_t expectedPresentTime) const override;
    // Returns true if the next buffer should be presented at the expected present time
    bool isBufferDue(nsecs_t expectedPresentTime) const override;

    // Implements BufferLayer.
    bool fenceHasSignaled() const override;
@@ -116,7 +117,7 @@ private:
    // Temporary - Used only for LEGACY camera mode.
    uint32_t getProducerStickyTransform() const;

    nsecs_t nextPredictedPresentTime() const override;
    std::optional<nsecs_t> nextPredictedPresentTime() const override;

    sp<BufferLayerConsumer> mConsumer;
    sp<IGraphicBufferProducer> mProducer;
+2 −10
Original line number Diff line number Diff line
@@ -212,14 +212,6 @@ void BufferStateLayer::finalizeFrameEventHistory(const std::shared_ptr<FenceTime
    }
}

bool BufferStateLayer::shouldPresentNow(nsecs_t /*expectedPresentTime*/) const {
    if (getSidebandStreamChanged() || getAutoRefresh()) {
        return true;
    }

    return hasFrameUpdate();
}

bool BufferStateLayer::willPresentCurrentTransaction() const {
    // Returns true if the most recent Transaction applied to CurrentState will be presented.
    return (getSidebandStreamChanged() || getAutoRefresh() ||
@@ -602,9 +594,9 @@ bool BufferStateLayer::hasFrameUpdate() const {
    return mCurrentStateModified && (c.buffer != nullptr || c.bgColorLayer != nullptr);
}

nsecs_t BufferStateLayer::nextPredictedPresentTime() const {
std::optional<nsecs_t> BufferStateLayer::nextPredictedPresentTime() const {
    if (!getDrawingState().isAutoTimestamp || !mSurfaceFrame) {
        return 0;
        return std::nullopt;
    }

    return mSurfaceFrame->getPredictions().presentTime;
Loading