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

Commit 010d2193 authored by Ana Krulec's avatar Ana Krulec
Browse files

SF: Stop passing DispSync around.

Instead of passing DispSync around, so that the functions can compute
next refresh time, compute the time in SurfaceFlinger, and pass around
the calculated value.

Test: SF tests pass.
Change-Id: I27f28257c866426bc871671eb57dd309b88b92be
parent adb29b0a
Loading
Loading
Loading
Loading
+2 −49
Original line number Diff line number Diff line
@@ -98,54 +98,7 @@ void BufferLayerConsumer::setContentsChangedListener(const wp<ContentsChangedLis
    mContentsChangedListener = listener;
}

// We need to determine the time when a buffer acquired now will be
// displayed.  This can be calculated:
//   time when previous buffer's actual-present fence was signaled
//    + current display refresh rate * HWC latency
//    + a little extra padding
//
// Buffer producers are expected to set their desired presentation time
// based on choreographer time stamps, which (coming from vsync events)
// will be slightly later then the actual-present timing.  If we get a
// desired-present time that is unintentionally a hair after the next
// vsync, we'll hold the frame when we really want to display it.  We
// need to take the offset between actual-present and reported-vsync
// into account.
//
// If the system is configured without a DispSync phase offset for the app,
// we also want to throw in a bit of padding to avoid edge cases where we
// just barely miss.  We want to do it here, not in every app.  A major
// source of trouble is the app's use of the display's ideal refresh time
// (via Display.getRefreshRate()), which could be off of the actual refresh
// by a few percent, with the error multiplied by the number of frames
// between now and when the buffer should be displayed.
//
// If the refresh reported to the app has a phase offset, we shouldn't need
// to tweak anything here.
nsecs_t BufferLayerConsumer::computeExpectedPresent(const DispSync& dispSync) {
    // The HWC doesn't currently have a way to report additional latency.
    // Assume that whatever we submit now will appear right after the flip.
    // For a smart panel this might be 1.  This is expressed in frames,
    // rather than time, because we expect to have a constant frame delay
    // regardless of the refresh rate.
    const uint32_t hwcLatency = 0;

    // Ask DispSync when the next refresh will be (CLOCK_MONOTONIC).
    const nsecs_t nextRefresh = dispSync.computeNextRefresh(hwcLatency);

    // The DispSync time is already adjusted for the difference between
    // vsync and reported-vsync (SurfaceFlinger::dispSyncPresentTimeOffset), so
    // we don't need to factor that in here.  Pad a little to avoid
    // weird effects if apps might be requesting times right on the edge.
    nsecs_t extraPadding = 0;
    if (SurfaceFlinger::vsyncPhaseOffsetNs == 0) {
        extraPadding = 1000000; // 1ms (6% of 60Hz)
    }

    return nextRefresh + extraPadding;
}

status_t BufferLayerConsumer::updateTexImage(BufferRejecter* rejecter, const DispSync& dispSync,
status_t BufferLayerConsumer::updateTexImage(BufferRejecter* rejecter, nsecs_t expectedPresentTime,
                                             bool* autoRefresh, bool* queuedBuffer,
                                             uint64_t maxFrameNumber,
                                             const sp<Fence>& releaseFence) {
@@ -169,7 +122,7 @@ status_t BufferLayerConsumer::updateTexImage(BufferRejecter* rejecter, const Dis
    // Acquire the next buffer.
    // In asynchronous mode the list is guaranteed to be one buffer
    // deep, while in synchronous mode we use the oldest buffer.
    status_t err = acquireBufferLocked(&item, computeExpectedPresent(dispSync), maxFrameNumber);
    status_t err = acquireBufferLocked(&item, expectedPresentTime, maxFrameNumber);
    if (err != NO_ERROR) {
        if (err == BufferQueue::NO_BUFFER_AVAILABLE) {
            err = NO_ERROR;
+2 −4
Original line number Diff line number Diff line
@@ -80,8 +80,6 @@ public:
    // ConsumerBase::setFrameAvailableListener().
    void setContentsChangedListener(const wp<ContentsChangedListener>& listener);

    nsecs_t computeExpectedPresent(const DispSync& dispSync);

    // updateTexImage acquires the most recently queued buffer, and sets the
    // image contents of the target texture to it.
    //
@@ -93,8 +91,8 @@ public:
    // Unlike the GLConsumer version, this version takes a functor that may be
    // used to reject the newly acquired buffer.  It also does not bind the
    // RenderEngine texture until bindTextureImage is called.
    status_t updateTexImage(BufferRejecter* rejecter, const DispSync& dispSync, bool* autoRefresh,
                            bool* queuedBuffer, uint64_t maxFrameNumber,
    status_t updateTexImage(BufferRejecter* rejecter, nsecs_t expectedPresentTime,
                            bool* autoRefresh, bool* queuedBuffer, uint64_t maxFrameNumber,
                            const sp<Fence>& releaseFence);

    // See BufferLayerConsumer::bindTextureImageLocked().
+4 −4
Original line number Diff line number Diff line
@@ -79,7 +79,7 @@ int32_t BufferQueueLayer::getQueuedFrameCount() const {
    return mQueuedFrames;
}

bool BufferQueueLayer::shouldPresentNow(const DispSync& dispSync) const {
bool BufferQueueLayer::shouldPresentNow(nsecs_t expectedPresentTime) const {
    if (getSidebandStreamChanged() || getAutoRefresh()) {
        return true;
    }
@@ -91,7 +91,6 @@ bool BufferQueueLayer::shouldPresentNow(const DispSync& dispSync) const {
    Mutex::Autolock lock(mQueueItemLock);

    const int64_t addedTime = mQueueItems[0].mTimestamp;
    const nsecs_t expectedPresentTime = mConsumer->computeExpectedPresent(dispSync);

    // Ignore timestamps more than a second in the future
    const bool isPlausible = addedTime < (expectedPresentTime + s2ns(1));
@@ -232,8 +231,9 @@ status_t BufferQueueLayer::updateTexImage(bool& recomputeVisibleRegions, nsecs_t
                    getProducerStickyTransform() != 0, mName.string(), mOverrideScalingMode,
                    getTransformToDisplayInverse(), mFreezeGeometryUpdates);
    status_t updateResult =
            mConsumer->updateTexImage(&r, *mFlinger->mPrimaryDispSync, &mAutoRefresh, &queuedBuffer,
                                      mLastFrameNumberReceived, releaseFence);
            mConsumer->updateTexImage(&r, mFlinger->mPrimaryDispSync->expectedPresentTime(),
                                      &mAutoRefresh, &queuedBuffer, mLastFrameNumberReceived,
                                      releaseFence);
    if (updateResult == BufferQueue::PRESENT_LATER) {
        // Producer doesn't want buffer to be displayed yet.  Signal a
        // layer update so we check again at the next opportunity.
+1 −1
Original line number Diff line number Diff line
@@ -55,7 +55,7 @@ public:

    int32_t getQueuedFrameCount() const override;

    bool shouldPresentNow(const DispSync& dispSync) const override;
    bool shouldPresentNow(nsecs_t expectedPresentTime) const override;
    // -----------------------------------------------------------------------

    // -----------------------------------------------------------------------
+1 −1
Original line number Diff line number Diff line
@@ -56,7 +56,7 @@ void BufferStateLayer::releasePendingBuffer(nsecs_t /*dequeueReadyTime*/) {
    return;
}

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