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

Commit 05dacfb6 authored by Dan Stoza's avatar Dan Stoza
Browse files

HWC2: Backpressure missed vsyncs into apps

Adds a mechanism to detect whether the prior frame SurfaceFlinger
presented to hardware composer was actually picked up or not. We then
use this mechanism to avoid pushing two frames in the same vsync.
This backpressure is passed back to applications by not latching any
buffers, which will manifest as dequeueBuffer stalling until
SurfaceFlinger releases a buffer on the following vsync.

Also makes the former INVALIDATE_ON_VSYNC behavior the only behavior
so that this functionality works correctly.

Bug: 29413700
Change-Id: Ibde358e45423ee6fea7b5e09ff65e49c4ad67baa
parent 1ce6581a
Loading
Loading
Loading
Loading
+0 −23
Original line number Diff line number Diff line
@@ -134,31 +134,12 @@ status_t MessageQueue::postMessage(
}


/* when INVALIDATE_ON_VSYNC is set SF only processes
 * buffer updates on VSYNC and performs a refresh immediately
 * after.
 *
 * when INVALIDATE_ON_VSYNC is set to false, SF will instead
 * perform the buffer updates immediately, but the refresh only
 * at the next VSYNC.
 * THIS MODE IS BUGGY ON GALAXY NEXUS AND WILL CAUSE HANGS
 */
#define INVALIDATE_ON_VSYNC 1

void MessageQueue::invalidate() {
#if INVALIDATE_ON_VSYNC
    mEvents->requestNextVsync();
#else
    mHandler->dispatchInvalidate();
#endif
}

void MessageQueue::refresh() {
#if INVALIDATE_ON_VSYNC
    mHandler->dispatchRefresh();
#else
    mEvents->requestNextVsync();
#endif
}

int MessageQueue::cb_eventReceiver(int fd, int events, void* data) {
@@ -172,11 +153,7 @@ int MessageQueue::eventReceiver(int /*fd*/, int /*events*/) {
    while ((n = DisplayEventReceiver::getEvents(mEventTube, buffer, 8)) > 0) {
        for (int i=0 ; i<n ; i++) {
            if (buffer[i].header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC) {
#if INVALIDATE_ON_VSYNC
                mHandler->dispatchInvalidate();
#else
                mHandler->dispatchRefresh();
#endif
                break;
            }
        }
+18 −27
Original line number Diff line number Diff line
@@ -167,9 +167,6 @@ SurfaceFlinger::SurfaceFlinger()
    property_get("ro.bq.gpu_to_cpu_unsupported", value, "0");
    mGpuToCpuSupported = !atoi(value);

    property_get("debug.sf.drop_missed_frames", value, "0");
    mDropMissedFrames = atoi(value);

    property_get("debug.sf.showupdates", value, "0");
    mDebugRegion = atoi(value);

@@ -933,6 +930,14 @@ bool SurfaceFlinger::handleMessageTransaction() {

bool SurfaceFlinger::handleMessageInvalidate() {
    ATRACE_CALL();
    bool frameMissed = !mHadClientComposition &&
            mPreviousPresentFence != Fence::NO_FENCE &&
            mPreviousPresentFence->getSignalTime() == INT64_MAX;
    ATRACE_INT("FrameMissed", static_cast<int>(frameMissed));
    if (frameMissed) {
        signalLayerUpdate();
        return false;
    }
    return handlePageFlip();
}

@@ -940,36 +945,22 @@ void SurfaceFlinger::handleMessageRefresh() {
    ATRACE_CALL();

    nsecs_t refreshStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
    static nsecs_t previousExpectedPresent = 0;
    nsecs_t expectedPresent = mPrimaryDispSync.computeNextRefresh(0);
    static bool previousFrameMissed = false;
    bool frameMissed = (expectedPresent == previousExpectedPresent);
    if (frameMissed != previousFrameMissed) {
        ATRACE_INT("FrameMissed", static_cast<int>(frameMissed));
    }
    previousFrameMissed = frameMissed;

    if (CC_UNLIKELY(mDropMissedFrames && frameMissed)) {
        // Latch buffers, but don't send anything to HWC, then signal another
        // wakeup for the next vsync
        preComposition();
        repaintEverything();
    } else {
    preComposition();
    rebuildLayerStacks();
    setUpHWComposer();
    doDebugFlashRegions();
    doComposition();
    postComposition(refreshStartTime);
    }

    mPreviousPresentFence = mHwc->getRetireFence(HWC_DISPLAY_PRIMARY);
    mHadClientComposition = mHwc->hasClientComposition(HWC_DISPLAY_PRIMARY);

    // Release any buffers which were replaced this frame
    for (auto& layer : mLayersWithQueuedFrames) {
        layer->releasePendingBuffer();
    }
    mLayersWithQueuedFrames.clear();

    previousExpectedPresent = mPrimaryDispSync.computeNextRefresh(0);
}

void SurfaceFlinger::doDebugFlashRegions()
+2 −1
Original line number Diff line number Diff line
@@ -468,7 +468,6 @@ private:
    RenderEngine* mRenderEngine;
    nsecs_t mBootTime;
    bool mGpuToCpuSupported;
    bool mDropMissedFrames;
    sp<EventThread> mEventThread;
    sp<EventThread> mSFEventThread;
    sp<EventControlThread> mEventControlThread;
@@ -488,6 +487,8 @@ private:
    bool mAnimCompositionPending;
#ifdef USE_HWC2
    std::vector<sp<Layer>> mLayersWithQueuedFrames;
    sp<Fence> mPreviousPresentFence = Fence::NO_FENCE;
    bool mHadClientComposition = false;
#endif

    // this may only be written from the main thread with mStateLock held
+6 −26
Original line number Diff line number Diff line
@@ -166,9 +166,6 @@ SurfaceFlinger::SurfaceFlinger()
    property_get("ro.bq.gpu_to_cpu_unsupported", value, "0");
    mGpuToCpuSupported = !atoi(value);

    property_get("debug.sf.drop_missed_frames", value, "0");
    mDropMissedFrames = atoi(value);

    property_get("debug.sf.showupdates", value, "0");
    mDebugRegion = atoi(value);

@@ -944,21 +941,7 @@ void SurfaceFlinger::handleMessageRefresh() {
    ATRACE_CALL();

    nsecs_t refreshStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
    static nsecs_t previousExpectedPresent = 0;
    nsecs_t expectedPresent = mPrimaryDispSync.computeNextRefresh(0);
    static bool previousFrameMissed = false;
    bool frameMissed = (expectedPresent == previousExpectedPresent);
    if (frameMissed != previousFrameMissed) {
        ATRACE_INT("FrameMissed", static_cast<int>(frameMissed));
    }
    previousFrameMissed = frameMissed;

    if (CC_UNLIKELY(mDropMissedFrames && frameMissed)) {
        // Latch buffers, but don't send anything to HWC, then signal another
        // wakeup for the next vsync
        preComposition();
        repaintEverything();
    } else {

    preComposition();
    rebuildLayerStacks();
    setUpHWComposer();
@@ -967,9 +950,6 @@ void SurfaceFlinger::handleMessageRefresh() {
    postComposition(refreshStartTime);
}

    previousExpectedPresent = mPrimaryDispSync.computeNextRefresh(0);
}

void SurfaceFlinger::doDebugFlashRegions()
{
    // is debugging enabled