summaryrefslogtreecommitdiff
path: root/services/surfaceflinger/EventThread.cpp
diff options
context:
space:
mode:
author Mathias Agopian <mathias@google.com> 2012-04-03 22:09:52 -0700
committer Mathias Agopian <mathias@google.com> 2012-04-04 19:01:20 -0700
commit3eb38cb33e41ce40dd1094bdec850f0fca9f8a53 (patch)
tree3f8cc9dc54f314fc53e50b579ab2d903cdb09d5c /services/surfaceflinger/EventThread.cpp
parent9d61b955db7ccd00d1e5b33e75f37dfd5ac2a456 (diff)
SurfaceFlinger now uses the new VSYNC HAL API.
If h/w composer doesn't support vsync (version < 0.3) we "fake" it with a timer. Change-Id: I1e3be79f43c9631d1293ad7d6cf52f9bfc42d65b
Diffstat (limited to 'services/surfaceflinger/EventThread.cpp')
-rw-r--r--services/surfaceflinger/EventThread.cpp125
1 files changed, 70 insertions, 55 deletions
diff --git a/services/surfaceflinger/EventThread.cpp b/services/surfaceflinger/EventThread.cpp
index 97afb5fa37..b05b7c281b 100644
--- a/services/surfaceflinger/EventThread.cpp
+++ b/services/surfaceflinger/EventThread.cpp
@@ -38,13 +38,15 @@ namespace android {
EventThread::EventThread(const sp<SurfaceFlinger>& flinger)
: mFlinger(flinger),
- mHw(flinger->graphicPlane(0).displayHardware()),
+ mHw(flinger->graphicPlane(0).editDisplayHardware()),
mLastVSyncTimestamp(0),
+ mVSyncTimestamp(0),
mDeliveredEvents(0)
{
}
void EventThread::onFirstRef() {
+ mHw.setVSyncHandler(this);
run("EventThread", PRIORITY_URGENT_DISPLAY + PRIORITY_MORE_FAVORABLE);
}
@@ -105,76 +107,89 @@ void EventThread::requestNextVsync(
}
}
+void EventThread::onVSyncReceived(int, nsecs_t timestamp) {
+ Mutex::Autolock _l(mLock);
+ mVSyncTimestamp = timestamp;
+ mCondition.signal();
+}
+
bool EventThread::threadLoop() {
nsecs_t timestamp;
DisplayEventReceiver::Event vsync;
Vector< wp<EventThread::Connection> > displayEventConnections;
- { // scope for the lock
+ do {
+
Mutex::Autolock _l(mLock);
do {
- // 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++) {
- sp<Connection> connection =
- mDisplayEventConnections.itemAt(i).promote();
- if (connection!=0 && connection->count >= 0) {
- // at least one continuous mode or active one-shot event
- waitForNextVsync = true;
- break;
- }
- }
-
- if (waitForNextVsync)
- break;
-
- mCondition.wait(mLock);
- } while(true);
-
- // at least one listener requested VSYNC
- mLock.unlock();
- timestamp = mHw.waitForRefresh();
- ATRACE_INT("VSYNC", mDeliveredEvents&1);
- mLock.lock();
- mDeliveredEvents++;
- mLastVSyncTimestamp = timestamp;
+ // check if we have received a VSYNC event
+ if (mVSyncTimestamp) {
+ // we have a VSYNC event pending
+ timestamp = mVSyncTimestamp;
+ mVSyncTimestamp = 0;
+ break;
+ }
- // now see if we still need to report this VSYNC event
- const size_t count = mDisplayEventConnections.size();
+ // check if we should be waiting for VSYNC events
+ bool waitForNextVsync = false;
+ size_t count = mDisplayEventConnections.size();
for (size_t i=0 ; i<count ; i++) {
- bool reportVsync = false;
sp<Connection> connection =
mDisplayEventConnections.itemAt(i).promote();
- if (connection == 0)
- continue;
-
- const int32_t count = connection->count;
- if (count >= 1) {
- if (count==1 || (mDeliveredEvents % count) == 0) {
- // continuous event, and time to report it
- reportVsync = true;
- }
- } else if (count >= -1) {
- if (count == 0) {
- // fired this time around
- reportVsync = true;
- }
- connection->count--;
+ if (connection!=0 && connection->count >= 0) {
+ // at least one continuous mode or active one-shot event
+ waitForNextVsync = true;
+ break;
}
- if (reportVsync) {
- displayEventConnections.add(connection);
+ }
+
+ // enable or disable VSYNC events
+ mHw.getHwComposer().eventControl(
+ HWComposer::EVENT_VSYNC, waitForNextVsync);
+
+ // wait for something to happen
+ mCondition.wait(mLock);
+ } while(true);
+
+ // process vsync event
+
+ ATRACE_INT("VSYNC", mDeliveredEvents&1);
+ mDeliveredEvents++;
+ mLastVSyncTimestamp = timestamp;
+
+ // now see if we still need to report this VSYNC event
+ const size_t count = mDisplayEventConnections.size();
+ for (size_t i=0 ; i<count ; i++) {
+ bool reportVsync = false;
+ sp<Connection> connection =
+ mDisplayEventConnections.itemAt(i).promote();
+ if (connection == 0)
+ continue;
+
+ const int32_t count = connection->count;
+ if (count >= 1) {
+ if (count==1 || (mDeliveredEvents % count) == 0) {
+ // continuous event, and time to report it
+ reportVsync = true;
}
+ } else if (count >= -1) {
+ if (count == 0) {
+ // fired this time around
+ reportVsync = true;
+ }
+ connection->count--;
+ }
+ if (reportVsync) {
+ displayEventConnections.add(connection);
}
- } while (!displayEventConnections.size());
+ }
+ } while (!displayEventConnections.size());
- // dispatch vsync events to listeners...
- vsync.header.type = DisplayEventReceiver::DISPLAY_EVENT_VSYNC;
- vsync.header.timestamp = timestamp;
- vsync.vsync.count = mDeliveredEvents;
- }
+ // dispatch vsync events to listeners...
+ vsync.header.type = DisplayEventReceiver::DISPLAY_EVENT_VSYNC;
+ vsync.header.timestamp = timestamp;
+ vsync.vsync.count = mDeliveredEvents;
const size_t count = displayEventConnections.size();
for (size_t i=0 ; i<count ; i++) {