diff options
| author | 2012-08-30 16:34:41 -0700 | |
|---|---|---|
| committer | 2012-08-31 16:47:44 -0700 | |
| commit | 6bf552ee02f8540a36cde7be90ffd840b2f6cd5c (patch) | |
| tree | 21c471344d4e40ec0cc7f25866f3a7c010570b7d /services/surfaceflinger/EventThread.cpp | |
| parent | 72f096fb1ad0a0deadbfac5f88627461905d38e8 (diff) | |
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
Diffstat (limited to 'services/surfaceflinger/EventThread.cpp')
| -rw-r--r-- | services/surfaceflinger/EventThread.cpp | 43 | 
1 files changed, 34 insertions, 9 deletions
| diff --git a/services/surfaceflinger/EventThread.cpp b/services/surfaceflinger/EventThread.cpp index dcda67ef18..ade9f751f0 100644 --- a/services/surfaceflinger/EventThread.cpp +++ b/services/surfaceflinger/EventThread.cpp @@ -140,6 +140,8 @@ bool EventThread::threadLoop() {      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(          DisplayEventReceiver::Event* event)  { @@ -193,31 +195,54 @@ Vector< sp<EventThread::Connection> > EventThread::waitForEvent(              // don't report it, and disable VSYNC events              disableVSyncLocked();          } 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();          } -        // note: !timestamp implies signalConnections.isEmpty() +        // note: !timestamp implies signalConnections.isEmpty(), because we +        // don't populate signalConnections if there's no vsync pending          if (!timestamp) {              // wait for something to happen -            if (CC_UNLIKELY(mUseSoftwareVSync && waitForVSync)) { -                // h/w vsync cannot be used (screen is off), so we use -                // a  timeout instead. it doesn't matter how imprecise this -                // is, we just need to make sure to serve the clients -                if (mCondition.waitRelative(mLock, ms2ns(16)) == TIMED_OUT) { +            if (waitForVSync) { +                // This is where we spend most of our time, waiting +                // for vsync events and new client registrations. +                // +                // 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);                      mVSyncCount++;                  }              } else { -                // This is where we spend most of our time, waiting -                // for a vsync events and registered clients +                // Nobody is interested in vsync, so we just want to sleep. +                // 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);              }          }      } while (signalConnections.isEmpty());      // 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.timestamp = timestamp;      event->vsync.count = vsyncCount; |