Fix an issue with VSYNC

one-shot VSYNC listeners could miss a VSYNC event if
scheduled while in waitForVsync().

Change-Id: I720485784aecfea6cc7a23c77081d7af3c9c71db
This commit is contained in:
Mathias Agopian 2012-01-09 18:19:18 -08:00
parent 1556662f95
commit a72d0db292
1 changed files with 31 additions and 38 deletions

View File

@ -107,27 +107,17 @@ bool EventThread::threadLoop() {
{ // scope for the lock
Mutex::Autolock _l(mLock);
do {
// wait for listeners
// see if we need to wait for the VSYNC at all
do {
bool waitForNextVsync = false;
size_t count = mDisplayEventConnections.size();
for (size_t i=0 ; i<count ; i++) {
const ConnectionInfo& info(
mDisplayEventConnections.valueAt(i));
if (info.count >= 1) {
// continuous mode
if (info.count >= 0) {
// at least one continuous mode or active one-shot event
waitForNextVsync = true;
} else {
// one-shot event
if (info.count >= -1) {
ConnectionInfo& info(
mDisplayEventConnections.editValueAt(i));
info.count--;
if (info.count == -1) {
// fired this time around
waitForNextVsync = true;
}
}
break;
}
}
@ -137,14 +127,38 @@ bool EventThread::threadLoop() {
mCondition.wait(mLock);
} while(true);
// wait for vsync
// at least one listener requested VSYNC
mLock.unlock();
timestamp = mHw.waitForVSync();
mLock.lock();
mDeliveredEvents++;
// make sure we still have some listeners
} while (!mDisplayEventConnections.size());
// now see if we still need to report this VSYNC event
bool reportVsync = false;
size_t count = mDisplayEventConnections.size();
for (size_t i=0 ; i<count ; i++) {
const ConnectionInfo& info(
mDisplayEventConnections.valueAt(i));
if (info.count >= 1) {
if (info.count==1 || (mDeliveredEvents % info.count) == 0) {
// continuous event, and time to report it
reportVsync = true;
}
} else if (info.count >= -1) {
ConnectionInfo& info(
mDisplayEventConnections.editValueAt(i));
if (info.count == 0) {
// fired this time around
reportVsync = true;
}
info.count--;
}
}
if (reportVsync) {
break;
}
} while (true);
// dispatch vsync events to listeners...
vsync.header.type = DisplayEventReceiver::DISPLAY_EVENT_VSYNC;
@ -161,27 +175,6 @@ bool EventThread::threadLoop() {
sp<DisplayEventConnection> conn(displayEventConnections.keyAt(i).promote());
// make sure the connection didn't die
if (conn != NULL) {
const ConnectionInfo& info(
displayEventConnections.valueAt(i));
if ((info.count > 1) && (mDeliveredEvents % info.count)) {
// continuous event, but not time to send this event yet
continue;
} else if (info.count < -1) {
// disabled event
continue;
} else if (info.count == 0) {
// impossible by construction. but we prefer to be safe.
continue;
}
// here, either:
// count = -1 : one-shot scheduled this time around
// count = 1 : continuous not rate-limited
// count > 1 : continuous, rate-limited
// Note: count == 0 is not possible by construction
status_t err = conn->postEvent(vsync);
if (err == -EAGAIN || err == -EWOULDBLOCK) {
// The destination doesn't accept events anymore, it's probably