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

Commit ee9806ad authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Reduce number of Fence syscalls made."

parents f7664393 fbc80aef
Loading
Loading
Loading
Loading
+39 −33
Original line number Diff line number Diff line
@@ -30,7 +30,7 @@
#include <utils/Trace.h>
#include <utils/Vector.h>

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

#include "DispSync.h"
#include "SurfaceFlinger.h"
@@ -419,25 +419,13 @@ void DispSync::reset() {
    resetErrorLocked();
}

bool DispSync::addPresentFence(const sp<Fence>& fence) {
bool DispSync::addPresentFence(const std::shared_ptr<FenceTime>& fenceTime) {
    Mutex::Autolock lock(mMutex);

    mPresentFences[mPresentSampleOffset] = fence;
    mPresentTimes[mPresentSampleOffset] = 0;
    mPresentFences[mPresentSampleOffset] = fenceTime;
    mPresentSampleOffset = (mPresentSampleOffset + 1) % NUM_PRESENT_SAMPLES;
    mNumResyncSamplesSincePresent = 0;

    for (size_t i = 0; i < NUM_PRESENT_SAMPLES; i++) {
        const sp<Fence>& f(mPresentFences[i]);
        if (f != NULL) {
            nsecs_t t = f->getSignalTime();
            if (t < INT64_MAX) {
                mPresentFences[i].clear();
                mPresentTimes[i] = t + mPresentTimeOffset;
            }
        }
    }

    updateErrorLocked();

    return !mModelUpdated || mError > kErrorThreshold;
@@ -602,8 +590,21 @@ void DispSync::updateErrorLocked() {
    nsecs_t sqErrSum = 0;

    for (size_t i = 0; i < NUM_PRESENT_SAMPLES; i++) {
        nsecs_t sample = mPresentTimes[i] - mReferenceTime;
        if (sample > mPhase) {
        // Only check for the cached value of signal time to avoid unecessary
        // syscalls. It is the responsibility of the DispSync owner to
        // call getSignalTime() periodically so the cache is updated when the
        // fence signals.
        nsecs_t time = mPresentFences[i]->getCachedSignalTime();
        if (time == Fence::SIGNAL_TIME_PENDING ||
                time == Fence::SIGNAL_TIME_INVALID) {
            continue;
        }

        nsecs_t sample = time - mReferenceTime;
        if (sample <= mPhase) {
            continue;
        }

        nsecs_t sampleErr = (sample - mPhase) % period;
        if (sampleErr > period / 2) {
            sampleErr -= period;
@@ -611,12 +612,17 @@ void DispSync::updateErrorLocked() {
        sqErrSum += sampleErr * sampleErr;
        numErrSamples++;
    }
    }

    if (numErrSamples > 0) {
        mError = sqErrSum / numErrSamples;
        mZeroErrSamplesCount = 0;
    } else {
        mError = 0;
        // Use mod ACCEPTABLE_ZERO_ERR_SAMPLES_COUNT to avoid log spam.
        mZeroErrSamplesCount++;
        ALOGE_IF(
                (mZeroErrSamplesCount % ACCEPTABLE_ZERO_ERR_SAMPLES_COUNT) == 0,
                "No present times for model error.");
    }

    if (kTraceDetailedInfo) {
@@ -627,9 +633,9 @@ void DispSync::updateErrorLocked() {
void DispSync::resetErrorLocked() {
    mPresentSampleOffset = 0;
    mError = 0;
    mZeroErrSamplesCount = 0;
    for (size_t i = 0; i < NUM_PRESENT_SAMPLES; i++) {
        mPresentFences[i].clear();
        mPresentTimes[i] = 0;
        mPresentFences[i] = FenceTime::NO_FENCE;
    }
}

@@ -668,19 +674,19 @@ void DispSync::dump(String8& result) const {
        previous = sampleTime;
    }

    result.appendFormat("mPresentFences / mPresentTimes [%d]:\n",
    result.appendFormat("mPresentFences [%d]:\n",
            NUM_PRESENT_SAMPLES);
    nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
    previous = 0;
    previous = Fence::SIGNAL_TIME_INVALID;
    for (size_t i = 0; i < NUM_PRESENT_SAMPLES; i++) {
        size_t idx = (i + mPresentSampleOffset) % NUM_PRESENT_SAMPLES;
        bool signaled = mPresentFences[idx] == NULL;
        nsecs_t presentTime = mPresentTimes[idx];
        if (!signaled) {
        nsecs_t presentTime = mPresentFences[idx]->getSignalTime();
        if (presentTime == Fence::SIGNAL_TIME_PENDING) {
            result.appendFormat("  [unsignaled fence]\n");
        } else if (presentTime == 0) {
            result.appendFormat("  0\n");
        } else if (previous == 0) {
        } else if(presentTime == Fence::SIGNAL_TIME_INVALID) {
            result.appendFormat("  [invalid fence]\n");
        } else if (previous == Fence::SIGNAL_TIME_PENDING ||
                previous == Fence::SIGNAL_TIME_INVALID) {
            result.appendFormat("  %" PRId64 "  (%.3f ms ago)\n", presentTime,
                    (now - presentTime) / 1000000.0);
        } else {
+15 −5
Original line number Diff line number Diff line
@@ -23,10 +23,14 @@
#include <utils/Timers.h>
#include <utils/RefBase.h>

#include <ui/FenceTime.h>

#include <memory>

namespace android {

class String8;
class Fence;
class FenceTime;
class DispSyncThread;

// DispSync maintains a model of the periodic hardware-based vsync events of a
@@ -67,7 +71,7 @@ public:
    //
    // This method should be called with the retire fence from each HWComposer
    // set call that affects the display.
    bool addPresentFence(const sp<Fence>& fence);
    bool addPresentFence(const std::shared_ptr<FenceTime>& fenceTime);

    // The beginResync, addResyncSample, and endResync methods are used to re-
    // synchronize the DispSync's model to the hardware vsync events.  The re-
@@ -129,6 +133,7 @@ private:
    enum { MIN_RESYNC_SAMPLES_FOR_UPDATE = 6 };
    enum { NUM_PRESENT_SAMPLES = 8 };
    enum { MAX_RESYNC_SAMPLES_WITHOUT_PRESENT = 4 };
    enum { ACCEPTABLE_ZERO_ERR_SAMPLES_COUNT = 64 };

    const char* const mName;

@@ -146,9 +151,14 @@ private:

    // mError is the computed model error.  It is based on the difference
    // between the estimated vsync event times and those observed in the
    // mPresentTimes array.
    // mPresentFences array.
    nsecs_t mError;

    // mZeroErrSamplesCount keeps track of how many times in a row there were
    // zero timestamps available in the mPresentFences array.
    // Used to sanity check that we are able to calculate the model error.
    size_t mZeroErrSamplesCount;

    // Whether we have updated the vsync event model since the last resync.
    bool mModelUpdated;

@@ -162,8 +172,8 @@ private:

    // These member variables store information about the present fences used
    // to validate the currently computed model.
    sp<Fence> mPresentFences[NUM_PRESENT_SAMPLES];
    nsecs_t mPresentTimes[NUM_PRESENT_SAMPLES];
    std::shared_ptr<FenceTime>
            mPresentFences[NUM_PRESENT_SAMPLES] {FenceTime::NO_FENCE};
    size_t mPresentSampleOffset;

    int mRefreshSkipCount;
+10 −4
Original line number Diff line number Diff line
@@ -1309,7 +1309,8 @@ bool Layer::headFenceHasSignaled() const {
        // able to be latched. To avoid this, grab this buffer anyway.
        return true;
    }
    return mQueueItems[0].mFence->getSignalTime() != INT64_MAX;
    return mQueueItems[0].mFenceTime->getSignalTime() !=
            Fence::SIGNAL_TIME_PENDING;
#else
    return true;
#endif
@@ -2012,9 +2013,6 @@ bool Layer::onPreComposition(nsecs_t refreshStartTime) {
bool Layer::onPostComposition(const std::shared_ptr<FenceTime>& glDoneFence,
        const std::shared_ptr<FenceTime>& presentFence,
        const CompositorTiming& compositorTiming) {
    mAcquireTimeline.updateSignalTimes();
    mReleaseTimeline.updateSignalTimes();

    // mFrameLatencyNeeded is true when a new frame was latched for the
    // composition.
    if (!mFrameLatencyNeeded)
@@ -2065,6 +2063,7 @@ void Layer::releasePendingBuffer(nsecs_t dequeueReadyTime) {

    auto releaseFenceTime = std::make_shared<FenceTime>(
            mSurfaceFlingerConsumer->getPrevFinalReleaseFence());
    mReleaseTimeline.updateSignalTimes();
    mReleaseTimeline.push(releaseFenceTime);

    Mutex::Autolock lock(mFrameEventHistoryMutex);
@@ -2255,6 +2254,7 @@ Region Layer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime)
#ifndef USE_HWC2
        auto releaseFenceTime = std::make_shared<FenceTime>(
                mSurfaceFlingerConsumer->getPrevFinalReleaseFence());
        mReleaseTimeline.updateSignalTimes();
        mReleaseTimeline.push(releaseFenceTime);
        if (mPreviousFrameNumber != 0) {
            mFrameEventHistory.addRelease(mPreviousFrameNumber,
@@ -2510,6 +2510,12 @@ void Layer::addAndGetFrameTimestamps(const NewFrameEventsEntry* newTimestamps,
        FrameEventHistoryDelta *outDelta) {
    Mutex::Autolock lock(mFrameEventHistoryMutex);
    if (newTimestamps) {
        // If there are any unsignaled fences in the aquire timeline at this
        // point, the previously queued frame hasn't been latched yet. Go ahead
        // and try to get the signal time here so the syscall is taken out of
        // the main thread's critical path.
        mAcquireTimeline.updateSignalTimes();
        // Push the new fence after updating since it's likely still pending.
        mAcquireTimeline.push(newTimestamps->acquireFence);
        mFrameEventHistory.addQueue(*newTimestamps);
    }
+4 −4
Original line number Diff line number Diff line
@@ -1553,6 +1553,7 @@ void SurfaceFlinger::postComposition(nsecs_t refreshStartTime)
    // |mStateLock| not needed as we are on the main thread
    const sp<const DisplayDevice> hw(getDefaultDisplayDeviceLocked());

    mGlCompositionDoneTimeline.updateSignalTimes();
    std::shared_ptr<FenceTime> glCompositionDoneFenceTime;
    if (mHwc->hasClientComposition(HWC_DISPLAY_PRIMARY)) {
        glCompositionDoneFenceTime =
@@ -1561,12 +1562,11 @@ void SurfaceFlinger::postComposition(nsecs_t refreshStartTime)
    } else {
        glCompositionDoneFenceTime = FenceTime::NO_FENCE;
    }
    mGlCompositionDoneTimeline.updateSignalTimes();

    mDisplayTimeline.updateSignalTimes();
    sp<Fence> presentFence = mHwc->getPresentFence(HWC_DISPLAY_PRIMARY);
    auto presentFenceTime = std::make_shared<FenceTime>(presentFence);
    mDisplayTimeline.push(presentFenceTime);
    mDisplayTimeline.updateSignalTimes();

    nsecs_t vsyncPhase = mPrimaryDispSync.computeNextRefresh(0);
    nsecs_t vsyncInterval = mPrimaryDispSync.getPeriod();
@@ -1591,8 +1591,8 @@ void SurfaceFlinger::postComposition(nsecs_t refreshStartTime)
        }
    });

    if (presentFence->isValid()) {
        if (mPrimaryDispSync.addPresentFence(presentFence)) {
    if (presentFenceTime->isValid()) {
        if (mPrimaryDispSync.addPresentFence(presentFenceTime)) {
            enableHardwareVsync();
        } else {
            disableHardwareVsync(false);
+3 −3
Original line number Diff line number Diff line
@@ -1257,6 +1257,7 @@ void SurfaceFlinger::postComposition(nsecs_t refreshStartTime)
    const HWComposer& hwc = getHwComposer();
    const sp<const DisplayDevice> hw(getDefaultDisplayDevice());

    mGlCompositionDoneTimeline.updateSignalTimes();
    std::shared_ptr<FenceTime> glCompositionDoneFenceTime;
    if (getHwComposer().hasGlesComposition(hw->getHwcDisplayId())) {
        glCompositionDoneFenceTime =
@@ -1265,12 +1266,11 @@ void SurfaceFlinger::postComposition(nsecs_t refreshStartTime)
    } else {
        glCompositionDoneFenceTime = FenceTime::NO_FENCE;
    }
    mGlCompositionDoneTimeline.updateSignalTimes();

    mDisplayTimeline.updateSignalTimes();
    sp<Fence> retireFence = mHwc->getDisplayFence(HWC_DISPLAY_PRIMARY);
    auto retireFenceTime = std::make_shared<FenceTime>(retireFence);
    mDisplayTimeline.push(retireFenceTime);
    mDisplayTimeline.updateSignalTimes();

    nsecs_t vsyncPhase = mPrimaryDispSync.computeNextRefresh(0);
    nsecs_t vsyncInterval = mPrimaryDispSync.getPeriod();
@@ -1298,7 +1298,7 @@ void SurfaceFlinger::postComposition(nsecs_t refreshStartTime)
    });

    if (retireFence->isValid()) {
        if (mPrimaryDispSync.addPresentFence(retireFence)) {
        if (mPrimaryDispSync.addPresentFence(retireFenceTime)) {
            enableHardwareVsync();
        } else {
            disableHardwareVsync(false);