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

Commit 6bf552ee authored by Andy McFadden's avatar Andy McFadden
Browse files

Add timeout when waiting for HW vsync

This way we don't get stuck if, say, the driver decides not
to send us vsync events.

Change-Id: I4af6358b3a1f304eaae5fd926ed3403fa1091827
parent 72f096fb
Loading
Loading
Loading
Loading
+34 −9
Original line number Original line Diff line number Diff line
@@ -140,6 +140,8 @@ bool EventThread::threadLoop() {
    return true;
    return true;
}
}


// This will return when (1) a vsync event has been received, and (2) there was
// at least one connection interested in receiving it when we started waiting.
Vector< sp<EventThread::Connection> > EventThread::waitForEvent(
Vector< sp<EventThread::Connection> > EventThread::waitForEvent(
        DisplayEventReceiver::Event* event)
        DisplayEventReceiver::Event* event)
{
{
@@ -193,31 +195,54 @@ Vector< sp<EventThread::Connection> > EventThread::waitForEvent(
            // don't report it, and disable VSYNC events
            // don't report it, and disable VSYNC events
            disableVSyncLocked();
            disableVSyncLocked();
        } else if (!timestamp && waitForVSync) {
        } else if (!timestamp && waitForVSync) {
            // we have at least one client, so we want vsync enabled
            // (TODO: this function is called right after we finish
            // notifying clients of a vsync, so this call will be made
            // at the vsync rate, e.g. 60fps.  If we can accurately
            // track the current state we could avoid making this call
            // so often.)
            enableVSyncLocked();
            enableVSyncLocked();
        }
        }


        // note: !timestamp implies signalConnections.isEmpty()
        // note: !timestamp implies signalConnections.isEmpty(), because we
        // don't populate signalConnections if there's no vsync pending
        if (!timestamp) {
        if (!timestamp) {
            // wait for something to happen
            // wait for something to happen
            if (CC_UNLIKELY(mUseSoftwareVSync && waitForVSync)) {
            if (waitForVSync) {
                // h/w vsync cannot be used (screen is off), so we use
                // This is where we spend most of our time, waiting
                // a  timeout instead. it doesn't matter how imprecise this
                // for vsync events and new client registrations.
                // is, we just need to make sure to serve the clients
                //
                if (mCondition.waitRelative(mLock, ms2ns(16)) == TIMED_OUT) {
                // If the screen is off, we can't use h/w vsync, so we
                // use a 16ms timeout instead.  It doesn't need to be
                // precise, we just need to keep feeding our clients.
                //
                // We don't want to stall if there's a driver bug, so we
                // use a (long) timeout when waiting for h/w vsync, and
                // generate fake events when necessary.
                bool softwareSync = mUseSoftwareVSync;
                nsecs_t timeout = softwareSync ? ms2ns(16) : ms2ns(1000);
                if (mCondition.waitRelative(mLock, timeout) == TIMED_OUT) {
                    if (!softwareSync) {
                        ALOGW("Timed out waiting for hw vsync; faking it");
                    }
                    mVSyncTimestamp = systemTime(SYSTEM_TIME_MONOTONIC);
                    mVSyncTimestamp = systemTime(SYSTEM_TIME_MONOTONIC);
                    mVSyncCount++;
                    mVSyncCount++;
                }
                }
            } else {
            } else {
                // This is where we spend most of our time, waiting
                // Nobody is interested in vsync, so we just want to sleep.
                // for a vsync events and registered clients
                // h/w vsync should be disabled, so this will wait until we
                // get a new connection, or an existing connection becomes
                // interested in receiving vsync again.
                mCondition.wait(mLock);
                mCondition.wait(mLock);
            }
            }
        }
        }
    } while (signalConnections.isEmpty());
    } while (signalConnections.isEmpty());


    // here we're guaranteed to have a timestamp and some connections to signal
    // here we're guaranteed to have a timestamp and some connections to signal
    // (The connections might have dropped out of mDisplayEventConnections
    // while we were asleep, but we'll still have strong references to them.)


    // dispatch vsync events to listeners...
    // fill in vsync event info
    event->header.type = DisplayEventReceiver::DISPLAY_EVENT_VSYNC;
    event->header.type = DisplayEventReceiver::DISPLAY_EVENT_VSYNC;
    event->header.timestamp = timestamp;
    event->header.timestamp = timestamp;
    event->vsync.count = vsyncCount;
    event->vsync.count = vsyncCount;