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 {
|
status_t HWComposer::release() const {
|
||||||
if (mHwc) {
|
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);
|
int err = mHwc->set(mHwc, NULL, NULL, NULL);
|
||||||
return (status_t)err;
|
return (status_t)err;
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,6 +41,7 @@ EventThread::EventThread(const sp<SurfaceFlinger>& flinger)
|
||||||
mHw(flinger->graphicPlane(0).editDisplayHardware()),
|
mHw(flinger->graphicPlane(0).editDisplayHardware()),
|
||||||
mLastVSyncTimestamp(0),
|
mLastVSyncTimestamp(0),
|
||||||
mVSyncTimestamp(0),
|
mVSyncTimestamp(0),
|
||||||
|
mUseSoftwareVSync(false),
|
||||||
mDeliveredEvents(0),
|
mDeliveredEvents(0),
|
||||||
mDebugVsyncEnabled(false)
|
mDebugVsyncEnabled(false)
|
||||||
{
|
{
|
||||||
|
@ -55,16 +56,6 @@ sp<EventThread::Connection> EventThread::createEventConnection() const {
|
||||||
return new Connection(const_cast<EventThread*>(this));
|
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(
|
status_t EventThread::registerDisplayEventConnection(
|
||||||
const sp<EventThread::Connection>& connection) {
|
const sp<EventThread::Connection>& connection) {
|
||||||
Mutex::Autolock _l(mLock);
|
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) {
|
void EventThread::onVSyncReceived(int, nsecs_t timestamp) {
|
||||||
Mutex::Autolock _l(mLock);
|
Mutex::Autolock _l(mLock);
|
||||||
mVSyncTimestamp = timestamp;
|
mVSyncTimestamp = timestamp;
|
||||||
|
@ -121,7 +130,6 @@ bool EventThread::threadLoop() {
|
||||||
Vector< wp<EventThread::Connection> > displayEventConnections;
|
Vector< wp<EventThread::Connection> > displayEventConnections;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
|
|
||||||
Mutex::Autolock _l(mLock);
|
Mutex::Autolock _l(mLock);
|
||||||
do {
|
do {
|
||||||
// latch VSYNC event if any
|
// latch VSYNC event if any
|
||||||
|
@ -145,7 +153,7 @@ bool EventThread::threadLoop() {
|
||||||
if (!waitForNextVsync) {
|
if (!waitForNextVsync) {
|
||||||
// we received a VSYNC but we have no clients
|
// we received a VSYNC but we have no clients
|
||||||
// don't report it, and disable VSYNC events
|
// don't report it, and disable VSYNC events
|
||||||
disableVSync();
|
disableVSyncLocked();
|
||||||
} else {
|
} else {
|
||||||
// report VSYNC event
|
// report VSYNC event
|
||||||
break;
|
break;
|
||||||
|
@ -157,12 +165,21 @@ bool EventThread::threadLoop() {
|
||||||
// disable VSYNC events then.
|
// disable VSYNC events then.
|
||||||
if (waitForNextVsync) {
|
if (waitForNextVsync) {
|
||||||
// enable
|
// enable
|
||||||
enableVSync();
|
enableVSyncLocked();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// wait for something to happen
|
// 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);
|
} while(true);
|
||||||
|
|
||||||
// process vsync event
|
// process vsync event
|
||||||
|
@ -233,12 +250,15 @@ bool EventThread::threadLoop() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void EventThread::enableVSync() {
|
void EventThread::enableVSyncLocked() {
|
||||||
mHw.getHwComposer().eventControl(HWComposer::EVENT_VSYNC, true);
|
if (!mUseSoftwareVSync) {
|
||||||
|
// never enable h/w VSYNC when screen is off
|
||||||
|
mHw.getHwComposer().eventControl(HWComposer::EVENT_VSYNC, true);
|
||||||
|
}
|
||||||
mDebugVsyncEnabled = true;
|
mDebugVsyncEnabled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void EventThread::disableVSync() {
|
void EventThread::disableVSyncLocked() {
|
||||||
mHw.getHwComposer().eventControl(HWComposer::EVENT_VSYNC, false);
|
mHw.getHwComposer().eventControl(HWComposer::EVENT_VSYNC, false);
|
||||||
mDebugVsyncEnabled = false;
|
mDebugVsyncEnabled = false;
|
||||||
}
|
}
|
||||||
|
@ -252,6 +272,8 @@ void EventThread::dump(String8& result, char* buffer, size_t SIZE) const {
|
||||||
Mutex::Autolock _l(mLock);
|
Mutex::Autolock _l(mLock);
|
||||||
result.appendFormat("VSYNC state: %s\n",
|
result.appendFormat("VSYNC state: %s\n",
|
||||||
mDebugVsyncEnabled?"enabled":"disabled");
|
mDebugVsyncEnabled?"enabled":"disabled");
|
||||||
|
result.appendFormat(" soft-vsync: %s\n",
|
||||||
|
mUseSoftwareVSync?"enabled":"disabled");
|
||||||
result.appendFormat(" numListeners=%u,\n events-delivered: %u\n",
|
result.appendFormat(" numListeners=%u,\n events-delivered: %u\n",
|
||||||
mDisplayEventConnections.size(), mDeliveredEvents);
|
mDisplayEventConnections.size(), mDeliveredEvents);
|
||||||
for (size_t i=0 ; i<mDisplayEventConnections.size() ; i++) {
|
for (size_t i=0 ; i<mDisplayEventConnections.size() ; i++) {
|
||||||
|
|
|
@ -72,8 +72,11 @@ public:
|
||||||
void setVsyncRate(uint32_t count, const sp<Connection>& connection);
|
void setVsyncRate(uint32_t count, const sp<Connection>& connection);
|
||||||
void requestNextVsync(const sp<Connection>& connection);
|
void requestNextVsync(const sp<Connection>& connection);
|
||||||
|
|
||||||
nsecs_t getLastVSyncTimestamp() const;
|
// called before the screen is turned off from main thread
|
||||||
nsecs_t getVSyncPeriod() const;
|
void onScreenReleased();
|
||||||
|
|
||||||
|
// called after the screen is turned on from main thread
|
||||||
|
void onScreenAcquired();
|
||||||
|
|
||||||
void dump(String8& result, char* buffer, size_t SIZE) const;
|
void dump(String8& result, char* buffer, size_t SIZE) const;
|
||||||
|
|
||||||
|
@ -84,8 +87,8 @@ private:
|
||||||
virtual void onVSyncReceived(int, nsecs_t timestamp);
|
virtual void onVSyncReceived(int, nsecs_t timestamp);
|
||||||
|
|
||||||
void removeDisplayEventConnection(const wp<Connection>& connection);
|
void removeDisplayEventConnection(const wp<Connection>& connection);
|
||||||
void enableVSync();
|
void enableVSyncLocked();
|
||||||
void disableVSync();
|
void disableVSyncLocked();
|
||||||
|
|
||||||
// constants
|
// constants
|
||||||
sp<SurfaceFlinger> mFlinger;
|
sp<SurfaceFlinger> mFlinger;
|
||||||
|
@ -98,6 +101,7 @@ private:
|
||||||
SortedVector< wp<Connection> > mDisplayEventConnections;
|
SortedVector< wp<Connection> > mDisplayEventConnections;
|
||||||
nsecs_t mLastVSyncTimestamp;
|
nsecs_t mLastVSyncTimestamp;
|
||||||
nsecs_t mVSyncTimestamp;
|
nsecs_t mVSyncTimestamp;
|
||||||
|
bool mUseSoftwareVSync;
|
||||||
|
|
||||||
// main thread only
|
// main thread only
|
||||||
size_t mDeliveredEvents;
|
size_t mDeliveredEvents;
|
||||||
|
|
|
@ -1467,16 +1467,18 @@ uint32_t SurfaceFlinger::setClientStateLocked(
|
||||||
void SurfaceFlinger::onScreenAcquired() {
|
void SurfaceFlinger::onScreenAcquired() {
|
||||||
const DisplayHardware& hw(graphicPlane(0).displayHardware());
|
const DisplayHardware& hw(graphicPlane(0).displayHardware());
|
||||||
hw.acquireScreen();
|
hw.acquireScreen();
|
||||||
|
mEventThread->onScreenAcquired();
|
||||||
// this is a temporary work-around, eventually this should be called
|
// this is a temporary work-around, eventually this should be called
|
||||||
// by the power-manager
|
// by the power-manager
|
||||||
SurfaceFlinger::turnElectronBeamOn(mElectronBeamAnimationMode);
|
SurfaceFlinger::turnElectronBeamOn(mElectronBeamAnimationMode);
|
||||||
mDirtyRegion.set(hw.bounds());
|
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() {
|
void SurfaceFlinger::onScreenReleased() {
|
||||||
const DisplayHardware& hw(graphicPlane(0).displayHardware());
|
const DisplayHardware& hw(graphicPlane(0).displayHardware());
|
||||||
if (hw.isScreenAcquired()) {
|
if (hw.isScreenAcquired()) {
|
||||||
|
mEventThread->onScreenReleased();
|
||||||
mDirtyRegion.set(hw.bounds());
|
mDirtyRegion.set(hw.bounds());
|
||||||
hw.releaseScreen();
|
hw.releaseScreen();
|
||||||
// from this point on, SF will stop drawing
|
// from this point on, SF will stop drawing
|
||||||
|
@ -1883,6 +1885,8 @@ status_t SurfaceFlinger::renderScreenToTexture(DisplayID dpy,
|
||||||
status_t SurfaceFlinger::renderScreenToTextureLocked(DisplayID dpy,
|
status_t SurfaceFlinger::renderScreenToTextureLocked(DisplayID dpy,
|
||||||
GLuint* textureName, GLfloat* uOut, GLfloat* vOut)
|
GLuint* textureName, GLfloat* uOut, GLfloat* vOut)
|
||||||
{
|
{
|
||||||
|
ATRACE_CALL();
|
||||||
|
|
||||||
if (!GLExtensions::getInstance().haveFramebufferObject())
|
if (!GLExtensions::getInstance().haveFramebufferObject())
|
||||||
return INVALID_OPERATION;
|
return INVALID_OPERATION;
|
||||||
|
|
||||||
|
@ -2263,6 +2267,8 @@ status_t SurfaceFlinger::electronBeamOnAnimationImplLocked()
|
||||||
|
|
||||||
status_t SurfaceFlinger::turnElectronBeamOffImplLocked(int32_t mode)
|
status_t SurfaceFlinger::turnElectronBeamOffImplLocked(int32_t mode)
|
||||||
{
|
{
|
||||||
|
ATRACE_CALL();
|
||||||
|
|
||||||
DisplayHardware& hw(graphicPlane(0).editDisplayHardware());
|
DisplayHardware& hw(graphicPlane(0).editDisplayHardware());
|
||||||
if (!hw.canDraw()) {
|
if (!hw.canDraw()) {
|
||||||
// we're already off
|
// we're already off
|
||||||
|
|
Loading…
Reference in New Issue