make sure to disable VSYNC while screen is off
Change-Id: If1894c43b0a39a2851e1280a35ae77bccd6d9abd
This commit is contained in:
parent
b60314a12f
commit
22ffb117b0
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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++) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue