make sure to disable VSYNC while screen is off

Change-Id: If1894c43b0a39a2851e1280a35ae77bccd6d9abd
This commit is contained in:
Mathias Agopian 2012-04-10 21:04:02 -07:00
parent b60314a12f
commit 22ffb117b0
4 changed files with 57 additions and 22 deletions

View File

@ -205,6 +205,9 @@ status_t HWComposer::commit() const {
status_t HWComposer::release() const {
if (mHwc) {
if (mHwc->common.version >= HWC_DEVICE_API_VERSION_0_3) {
mHwc->methods->eventControl(mHwc, HWC_EVENT_VSYNC, 0);
}
int err = mHwc->set(mHwc, NULL, NULL, NULL);
return (status_t)err;
}

View File

@ -41,6 +41,7 @@ EventThread::EventThread(const sp<SurfaceFlinger>& flinger)
mHw(flinger->graphicPlane(0).editDisplayHardware()),
mLastVSyncTimestamp(0),
mVSyncTimestamp(0),
mUseSoftwareVSync(false),
mDeliveredEvents(0),
mDebugVsyncEnabled(false)
{
@ -55,16 +56,6 @@ sp<EventThread::Connection> EventThread::createEventConnection() const {
return new Connection(const_cast<EventThread*>(this));
}
nsecs_t EventThread::getLastVSyncTimestamp() const {
Mutex::Autolock _l(mLock);
return mLastVSyncTimestamp;
}
nsecs_t EventThread::getVSyncPeriod() const {
return mHw.getRefreshPeriod();
}
status_t EventThread::registerDisplayEventConnection(
const sp<EventThread::Connection>& connection) {
Mutex::Autolock _l(mLock);
@ -108,6 +99,24 @@ void EventThread::requestNextVsync(
}
}
void EventThread::onScreenReleased() {
Mutex::Autolock _l(mLock);
// wait for an eventual pending vsync to be serviced
if (!mUseSoftwareVSync) {
while (mVSyncTimestamp) {
mCondition.wait(mLock);
}
}
// disable reliance on h/w vsync
mUseSoftwareVSync = true;
}
void EventThread::onScreenAcquired() {
Mutex::Autolock _l(mLock);
mUseSoftwareVSync = false;
}
void EventThread::onVSyncReceived(int, nsecs_t timestamp) {
Mutex::Autolock _l(mLock);
mVSyncTimestamp = timestamp;
@ -121,7 +130,6 @@ bool EventThread::threadLoop() {
Vector< wp<EventThread::Connection> > displayEventConnections;
do {
Mutex::Autolock _l(mLock);
do {
// latch VSYNC event if any
@ -145,7 +153,7 @@ bool EventThread::threadLoop() {
if (!waitForNextVsync) {
// we received a VSYNC but we have no clients
// don't report it, and disable VSYNC events
disableVSync();
disableVSyncLocked();
} else {
// report VSYNC event
break;
@ -157,12 +165,21 @@ bool EventThread::threadLoop() {
// disable VSYNC events then.
if (waitForNextVsync) {
// enable
enableVSync();
enableVSyncLocked();
}
}
// wait for something to happen
mCondition.wait(mLock);
if (mUseSoftwareVSync == true) {
// 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) {
mVSyncTimestamp = systemTime(SYSTEM_TIME_MONOTONIC);
}
} else {
mCondition.wait(mLock);
}
} while(true);
// process vsync event
@ -233,12 +250,15 @@ bool EventThread::threadLoop() {
return true;
}
void EventThread::enableVSync() {
mHw.getHwComposer().eventControl(HWComposer::EVENT_VSYNC, true);
void EventThread::enableVSyncLocked() {
if (!mUseSoftwareVSync) {
// never enable h/w VSYNC when screen is off
mHw.getHwComposer().eventControl(HWComposer::EVENT_VSYNC, true);
}
mDebugVsyncEnabled = true;
}
void EventThread::disableVSync() {
void EventThread::disableVSyncLocked() {
mHw.getHwComposer().eventControl(HWComposer::EVENT_VSYNC, false);
mDebugVsyncEnabled = false;
}
@ -252,6 +272,8 @@ void EventThread::dump(String8& result, char* buffer, size_t SIZE) const {
Mutex::Autolock _l(mLock);
result.appendFormat("VSYNC state: %s\n",
mDebugVsyncEnabled?"enabled":"disabled");
result.appendFormat(" soft-vsync: %s\n",
mUseSoftwareVSync?"enabled":"disabled");
result.appendFormat(" numListeners=%u,\n events-delivered: %u\n",
mDisplayEventConnections.size(), mDeliveredEvents);
for (size_t i=0 ; i<mDisplayEventConnections.size() ; i++) {

View File

@ -72,8 +72,11 @@ public:
void setVsyncRate(uint32_t count, const sp<Connection>& connection);
void requestNextVsync(const sp<Connection>& connection);
nsecs_t getLastVSyncTimestamp() const;
nsecs_t getVSyncPeriod() const;
// called before the screen is turned off from main thread
void onScreenReleased();
// called after the screen is turned on from main thread
void onScreenAcquired();
void dump(String8& result, char* buffer, size_t SIZE) const;
@ -84,8 +87,8 @@ private:
virtual void onVSyncReceived(int, nsecs_t timestamp);
void removeDisplayEventConnection(const wp<Connection>& connection);
void enableVSync();
void disableVSync();
void enableVSyncLocked();
void disableVSyncLocked();
// constants
sp<SurfaceFlinger> mFlinger;
@ -98,6 +101,7 @@ private:
SortedVector< wp<Connection> > mDisplayEventConnections;
nsecs_t mLastVSyncTimestamp;
nsecs_t mVSyncTimestamp;
bool mUseSoftwareVSync;
// main thread only
size_t mDeliveredEvents;

View File

@ -1467,16 +1467,18 @@ uint32_t SurfaceFlinger::setClientStateLocked(
void SurfaceFlinger::onScreenAcquired() {
const DisplayHardware& hw(graphicPlane(0).displayHardware());
hw.acquireScreen();
mEventThread->onScreenAcquired();
// this is a temporary work-around, eventually this should be called
// by the power-manager
SurfaceFlinger::turnElectronBeamOn(mElectronBeamAnimationMode);
mDirtyRegion.set(hw.bounds());
// from this point on, SF will priocess updates again
// from this point on, SF will process updates again
}
void SurfaceFlinger::onScreenReleased() {
const DisplayHardware& hw(graphicPlane(0).displayHardware());
if (hw.isScreenAcquired()) {
mEventThread->onScreenReleased();
mDirtyRegion.set(hw.bounds());
hw.releaseScreen();
// from this point on, SF will stop drawing
@ -1883,6 +1885,8 @@ status_t SurfaceFlinger::renderScreenToTexture(DisplayID dpy,
status_t SurfaceFlinger::renderScreenToTextureLocked(DisplayID dpy,
GLuint* textureName, GLfloat* uOut, GLfloat* vOut)
{
ATRACE_CALL();
if (!GLExtensions::getInstance().haveFramebufferObject())
return INVALID_OPERATION;
@ -2263,6 +2267,8 @@ status_t SurfaceFlinger::electronBeamOnAnimationImplLocked()
status_t SurfaceFlinger::turnElectronBeamOffImplLocked(int32_t mode)
{
ATRACE_CALL();
DisplayHardware& hw(graphicPlane(0).editDisplayHardware());
if (!hw.canDraw()) {
// we're already off