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

Commit d0010581 authored by Brian Anderson's avatar Brian Anderson
Browse files

Fix getFrameTimestamp test flakes.

This fixes both the dEQP CTS flakes relating to
compositor timing and the lib_gui test flakes that
don't initialize properly.

Test: adb shell /data/nativetest/libgui_test/libgui_test
  --gtest_filter=*GetFrameTimestamps*
Bug: 35995043

Change-Id: If8e59f0dc9a916bab28bd1a36190cef9a56cb64f
parent 46f224d1
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -105,7 +105,7 @@ struct FrameEvents {
struct CompositorTiming {
    nsecs_t deadline{0};
    nsecs_t interval{16666667};
    nsecs_t presentLatency{0};
    nsecs_t presentLatency{16666667};
};

// A short history of frames that are synchronized between the consumer and
+4 −4
Original line number Diff line number Diff line
@@ -52,6 +52,8 @@ protected:
        mComposerClient = new SurfaceComposerClient;
        ASSERT_EQ(NO_ERROR, mComposerClient->initCheck());

        // TODO(brianderson): The following sometimes fails and is a source of
        //   test flakiness.
        mSurfaceControl = mComposerClient->createSurface(
                String8("Test Surface"), 32, 32, PIXEL_FORMAT_RGBA_8888, 0);

@@ -526,7 +528,7 @@ public:
};


class GetFrameTimestampsTest : public SurfaceTest {
class GetFrameTimestampsTest : public ::testing::Test {
protected:
    struct FenceAndFenceTime {
        explicit FenceAndFenceTime(FenceToFenceTimeMap& fenceMap)
@@ -616,11 +618,9 @@ protected:
        RefreshEvents mRefreshes[3];
    };

    GetFrameTimestampsTest() : SurfaceTest() {}
    GetFrameTimestampsTest() {}

    virtual void SetUp() {
        SurfaceTest::SetUp();

        BufferQueue::createBufferQueue(&mProducer, &mConsumer);
        mFakeConsumer = new FakeConsumer;
        mCfeh = &mFakeConsumer->mFrameEventHistory;
+29 −20
Original line number Diff line number Diff line
@@ -1113,7 +1113,7 @@ void SurfaceFlinger::onVSyncReceived(HWComposer* composer, int32_t type,
}

void SurfaceFlinger::getCompositorTiming(CompositorTiming* compositorTiming) {
    std::lock_guard<std::mutex> lock(mCompositeTimingLock);
    std::lock_guard<std::mutex> lock(mCompositorTimingLock);
    *compositorTiming = mCompositorTiming;
}

@@ -1410,35 +1410,40 @@ void SurfaceFlinger::updateCompositorTiming(
        mCompositePresentTimes.pop();
    }

    setCompositorTimingSnapped(
            vsyncPhase, vsyncInterval, compositeToPresentLatency);
}

void SurfaceFlinger::setCompositorTimingSnapped(nsecs_t vsyncPhase,
        nsecs_t vsyncInterval, nsecs_t compositeToPresentLatency) {
    // Integer division and modulo round toward 0 not -inf, so we need to
    // treat negative and positive offsets differently.
    nsecs_t idealLatency = (sfVsyncPhaseOffsetNs >= 0) ?
    nsecs_t idealLatency = (sfVsyncPhaseOffsetNs > 0) ?
            (vsyncInterval - (sfVsyncPhaseOffsetNs % vsyncInterval)) :
            ((-sfVsyncPhaseOffsetNs) % vsyncInterval);

    // Just in case sfVsyncPhaseOffsetNs == -vsyncInterval.
    if (idealLatency <= 0) {
        idealLatency = vsyncInterval;
    }

    // Snap the latency to a value that removes scheduling jitter from the
    // composition and present times, which often have >1ms of jitter.
    // Reducing jitter is important if an app attempts to extrapolate
    // something (such as user input) to an accurate diasplay time.
    // Snapping also allows an app to precisely calculate sfVsyncPhaseOffsetNs
    // with (presentLatency % interval).
    nsecs_t snappedCompositeToPresentLatency = -1;
    if (compositeToPresentLatency >= 0) {
    nsecs_t bias = vsyncInterval / 2;
    int64_t extraVsyncs =
                (compositeToPresentLatency - idealLatency + bias) /
                vsyncInterval;
        nsecs_t extraLatency = extraVsyncs * vsyncInterval;
        snappedCompositeToPresentLatency = idealLatency + extraLatency;
    }
            (compositeToPresentLatency - idealLatency + bias) / vsyncInterval;
    nsecs_t snappedCompositeToPresentLatency = (extraVsyncs > 0) ?
            idealLatency + (extraVsyncs * vsyncInterval) : idealLatency;

    std::lock_guard<std::mutex> lock(mCompositeTimingLock);
    std::lock_guard<std::mutex> lock(mCompositorTimingLock);
    mCompositorTiming.deadline = vsyncPhase - idealLatency;
    mCompositorTiming.interval = vsyncInterval;
    if (snappedCompositeToPresentLatency >= 0) {
    mCompositorTiming.presentLatency = snappedCompositeToPresentLatency;
}
}

void SurfaceFlinger::postComposition(nsecs_t refreshStartTime)
{
@@ -1484,10 +1489,15 @@ void SurfaceFlinger::postComposition(nsecs_t refreshStartTime)
    // since updateCompositorTiming has snapping logic.
    updateCompositorTiming(
        vsyncPhase, vsyncInterval, refreshStartTime, displayFenceTime);
    CompositorTiming compositorTiming;
    {
        std::lock_guard<std::mutex> lock(mCompositorTimingLock);
        compositorTiming = mCompositorTiming;
    }

    mDrawingState.traverseInZOrder([&](Layer* layer) {
        bool frameLatched = layer->onPostComposition(glCompositionDoneFenceTime,
                *presentFenceTime, *retireFenceTime, mCompositorTiming);
                *presentFenceTime, *retireFenceTime, compositorTiming);
        if (frameLatched) {
            recordBufferingStats(layer->getName().string(),
                    layer->getOccupancyHistory(false));
@@ -2966,10 +2976,9 @@ void SurfaceFlinger::onInitializeDisplays() {
    const nsecs_t period = activeConfig->getVsyncPeriod();
    mAnimFrameTracker.setDisplayRefreshPeriod(period);

    {
        std::lock_guard<std::mutex> lock(mCompositeTimingLock);
        mCompositorTiming.interval = period;
    }
    // Use phase of 0 since phase is not known.
    // Use latency of 0, which will snap to the ideal latency.
    setCompositorTimingSnapped(0, period, 0);
}

void SurfaceFlinger::initializeDisplays() {
+4 −1
Original line number Diff line number Diff line
@@ -450,6 +450,9 @@ private:
    void updateCompositorTiming(
            nsecs_t vsyncPhase, nsecs_t vsyncInterval, nsecs_t compositeTime,
            std::shared_ptr<FenceTime>& presentFenceTime);
    void setCompositorTimingSnapped(
            nsecs_t vsyncPhase, nsecs_t vsyncInterval,
            nsecs_t compositeToPresentLatency);
    void rebuildLayerStacks();
    void setUpHWComposer();
    void doComposition();
@@ -620,7 +623,7 @@ private:
    bool mHWVsyncAvailable;

    // protected by mCompositorTimingLock;
    mutable std::mutex mCompositeTimingLock;
    mutable std::mutex mCompositorTimingLock;
    CompositorTiming mCompositorTiming;

    // Only accessed from the main thread.
+30 −16
Original line number Diff line number Diff line
@@ -1032,7 +1032,7 @@ void SurfaceFlinger::onVSyncReceived(HWComposer* /*composer*/, int type,
}

void SurfaceFlinger::getCompositorTiming(CompositorTiming* compositorTiming) {
    std::lock_guard<std::mutex> lock(mCompositeTimingLock);
    std::lock_guard<std::mutex> lock(mCompositorTimingLock);
    *compositorTiming = mCompositorTiming;
}

@@ -1195,35 +1195,40 @@ void SurfaceFlinger::updateCompositorTiming(
        mCompositePresentTimes.pop();
    }

    setCompositorTimingSnapped(
            vsyncPhase, vsyncInterval, compositeToPresentLatency);
}

void SurfaceFlinger::setCompositorTimingSnapped(nsecs_t vsyncPhase,
        nsecs_t vsyncInterval, nsecs_t compositeToPresentLatency) {
    // Integer division and modulo round toward 0 not -inf, so we need to
    // treat negative and positive offsets differently.
    nsecs_t idealLatency = (sfVsyncPhaseOffsetNs >= 0) ?
    nsecs_t idealLatency = (sfVsyncPhaseOffsetNs > 0) ?
            (vsyncInterval - (sfVsyncPhaseOffsetNs % vsyncInterval)) :
            ((-sfVsyncPhaseOffsetNs) % vsyncInterval);

    // Just in case sfVsyncPhaseOffsetNs == -vsyncInterval.
    if (idealLatency <= 0) {
        idealLatency = vsyncInterval;
    }

    // Snap the latency to a value that removes scheduling jitter from the
    // composition and present times, which often have >1ms of jitter.
    // Reducing jitter is important if an app attempts to extrapolate
    // something (such as user input) to an accurate diasplay time.
    // Snapping also allows an app to precisely calculate sfVsyncPhaseOffsetNs
    // with (presentLatency % interval).
    nsecs_t snappedCompositeToPresentLatency = -1;
    if (compositeToPresentLatency >= 0) {
    nsecs_t bias = vsyncInterval / 2;
    int64_t extraVsyncs =
                (compositeToPresentLatency - idealLatency + bias) /
                vsyncInterval;
        nsecs_t extraLatency = extraVsyncs * vsyncInterval;
        snappedCompositeToPresentLatency = idealLatency + extraLatency;
    }
            (compositeToPresentLatency - idealLatency + bias) / vsyncInterval;
    nsecs_t snappedCompositeToPresentLatency = (extraVsyncs > 0) ?
            idealLatency + (extraVsyncs * vsyncInterval) : idealLatency;

    std::lock_guard<std::mutex> lock(mCompositeTimingLock);
    std::lock_guard<std::mutex> lock(mCompositorTimingLock);
    mCompositorTiming.deadline = vsyncPhase - idealLatency;
    mCompositorTiming.interval = vsyncInterval;
    if (snappedCompositeToPresentLatency >= 0) {
    mCompositorTiming.presentLatency = snappedCompositeToPresentLatency;
}
}

void SurfaceFlinger::postComposition(nsecs_t refreshStartTime)
{
@@ -1254,10 +1259,15 @@ void SurfaceFlinger::postComposition(nsecs_t refreshStartTime)
    // since updateCompositorTiming has snapping logic.
    updateCompositorTiming(
        vsyncPhase, vsyncInterval, refreshStartTime, retireFenceTime);
    CompositorTiming compositorTiming;
    {
        std::lock_guard<std::mutex> lock(mCompositorTimingLock);
        compositorTiming = mCompositorTiming;
    }

    mDrawingState.traverseInZOrder([&](Layer* layer) {
        bool frameLatched = layer->onPostComposition(glCompositionDoneFenceTime,
                presentFenceTime, retireFenceTime, mCompositorTiming);
                presentFenceTime, retireFenceTime, compositorTiming);
        if (frameLatched) {
            recordBufferingStats(layer->getName().string(),
                    layer->getOccupancyHistory(false));
@@ -2742,6 +2752,10 @@ void SurfaceFlinger::onInitializeDisplays() {
    const nsecs_t period =
            getHwComposer().getRefreshPeriod(HWC_DISPLAY_PRIMARY);
    mAnimFrameTracker.setDisplayRefreshPeriod(period);

    // Use phase of 0 since phase is not known.
    // Use latency of 0, which will snap to the ideal latency.
    setCompositorTimingSnapped(0, period, 0);
}

void SurfaceFlinger::initializeDisplays() {