am 81cd5d3b: make sure we don\'t call into the HWC HAL when not needed

* commit '81cd5d3b94d21253a0be925f4ae58cc7f4afeef7':
  make sure we don't call into the HWC HAL when not needed
This commit is contained in:
Mathias Agopian 2012-10-04 15:29:22 -07:00 committed by Android Git Automerger
commit 64a224236d
5 changed files with 47 additions and 24 deletions

View File

@ -147,7 +147,7 @@ HWComposer::HWComposer(
// don't need a vsync thread if we have a hardware composer // don't need a vsync thread if we have a hardware composer
needVSyncThread = false; needVSyncThread = false;
// always turn vsync off when we start // always turn vsync off when we start
mHwc->eventControl(mHwc, HWC_DISPLAY_PRIMARY, HWC_EVENT_VSYNC, 0); eventControl(HWC_DISPLAY_PRIMARY, HWC_EVENT_VSYNC, 0);
// these IDs are always reserved // these IDs are always reserved
for (size_t i=0 ; i<HWC_NUM_DISPLAY_TYPES ; i++) { for (size_t i=0 ; i<HWC_NUM_DISPLAY_TYPES ; i++) {
@ -202,7 +202,7 @@ HWComposer::HWComposer(
HWComposer::~HWComposer() { HWComposer::~HWComposer() {
if (mHwc) { if (mHwc) {
mHwc->eventControl(mHwc, HWC_DISPLAY_PRIMARY, HWC_EVENT_VSYNC, 0); eventControl(HWC_DISPLAY_PRIMARY, HWC_EVENT_VSYNC, 0);
} }
if (mVSyncThread != NULL) { if (mVSyncThread != NULL) {
mVSyncThread->requestExitAndWait(); mVSyncThread->requestExitAndWait();
@ -443,16 +443,32 @@ bool HWComposer::isConnected(int disp) const {
return mDisplayData[disp].connected; return mDisplayData[disp].connected;
} }
void HWComposer::eventControl(int event, int enabled) { void HWComposer::eventControl(int disp, int event, int enabled) {
if (uint32_t(disp)>31 || !mAllocatedDisplayIDs.hasBit(disp)) {
return;
}
status_t err = NO_ERROR; status_t err = NO_ERROR;
if (mHwc) { if (mHwc && !mDebugForceFakeVSync) {
if (!mDebugForceFakeVSync) { // NOTE: we use our own internal lock here because we have to call
err = mHwc->eventControl(mHwc, 0, event, enabled); // into the HWC with the lock held, and we want to make sure
// error here should not happen -- not sure what we should // that even if HWC blocks (which it shouldn't), it won't
// do if it does. // affect other threads.
ALOGE_IF(err, "eventControl(%d, %d) failed %s", Mutex::Autolock _l(mEventControlLock);
event, enabled, strerror(-err)); const int32_t eventBit = 1UL << event;
const int32_t newValue = enabled ? eventBit : 0;
const int32_t oldValue = mDisplayData[disp].events & eventBit;
if (newValue != oldValue) {
ATRACE_CALL();
err = mHwc->eventControl(mHwc, disp, event, enabled);
if (!err) {
int32_t& events(mDisplayData[disp].events);
events = (events & ~eventBit) | newValue;
}
} }
// error here should not happen -- not sure what we should
// do if it does.
ALOGE_IF(err, "eventControl(%d, %d) failed %s",
event, enabled, strerror(-err));
} }
if (err == NO_ERROR && mVSyncThread != NULL) { if (err == NO_ERROR && mVSyncThread != NULL) {
@ -652,16 +668,16 @@ status_t HWComposer::commit() {
return (status_t)err; return (status_t)err;
} }
status_t HWComposer::release(int disp) const { status_t HWComposer::release(int disp) {
LOG_FATAL_IF(disp >= HWC_NUM_DISPLAY_TYPES); LOG_FATAL_IF(disp >= HWC_NUM_DISPLAY_TYPES);
if (mHwc) { if (mHwc) {
mHwc->eventControl(mHwc, disp, HWC_EVENT_VSYNC, 0); eventControl(disp, HWC_EVENT_VSYNC, 0);
return (status_t)mHwc->blank(mHwc, disp, 1); return (status_t)mHwc->blank(mHwc, disp, 1);
} }
return NO_ERROR; return NO_ERROR;
} }
status_t HWComposer::acquire(int disp) const { status_t HWComposer::acquire(int disp) {
LOG_FATAL_IF(disp >= HWC_NUM_DISPLAY_TYPES); LOG_FATAL_IF(disp >= HWC_NUM_DISPLAY_TYPES);
if (mHwc) { if (mHwc) {
return (status_t)mHwc->blank(mHwc, disp, 0); return (status_t)mHwc->blank(mHwc, disp, 0);
@ -965,8 +981,10 @@ HWComposer::VSyncThread::VSyncThread(HWComposer& hwc)
void HWComposer::VSyncThread::setEnabled(bool enabled) { void HWComposer::VSyncThread::setEnabled(bool enabled) {
Mutex::Autolock _l(mLock); Mutex::Autolock _l(mLock);
mEnabled = enabled; if (mEnabled != enabled) {
mCondition.signal(); mEnabled = enabled;
mCondition.signal();
}
} }
void HWComposer::VSyncThread::onFirstRef() { void HWComposer::VSyncThread::onFirstRef() {

View File

@ -92,10 +92,10 @@ public:
status_t commit(); status_t commit();
// release hardware resources and blank screen // release hardware resources and blank screen
status_t release(int disp) const; status_t release(int disp);
// acquire hardware resources and unblank screen // acquire hardware resources and unblank screen
status_t acquire(int disp) const; status_t acquire(int disp);
// reset state when an external, non-virtual display is disconnected // reset state when an external, non-virtual display is disconnected
void disconnectDisplay(int disp); void disconnectDisplay(int disp);
@ -226,7 +226,7 @@ public:
EVENT_VSYNC = HWC_EVENT_VSYNC EVENT_VSYNC = HWC_EVENT_VSYNC
}; };
void eventControl(int event, int enabled); void eventControl(int disp, int event, int enabled);
// Query display parameters. Pass in a display index (e.g. // Query display parameters. Pass in a display index (e.g.
// HWC_DISPLAY_PRIMARY). // HWC_DISPLAY_PRIMARY).
@ -289,7 +289,7 @@ private:
DisplayData() : xdpi(0), ydpi(0), refresh(0), DisplayData() : xdpi(0), ydpi(0), refresh(0),
connected(false), hasFbComp(false), hasOvComp(false), connected(false), hasFbComp(false), hasOvComp(false),
capacity(0), list(NULL), capacity(0), list(NULL),
framebufferTarget(NULL), fbTargetHandle(NULL) { } framebufferTarget(NULL), fbTargetHandle(NULL), events(0) { }
~DisplayData() { ~DisplayData() {
free(list); free(list);
} }
@ -306,6 +306,8 @@ private:
hwc_display_contents_1* list; hwc_display_contents_1* list;
hwc_layer_1* framebufferTarget; hwc_layer_1* framebufferTarget;
buffer_handle_t fbTargetHandle; buffer_handle_t fbTargetHandle;
// protected by mEventControlLock
int32_t events;
}; };
sp<SurfaceFlinger> mFlinger; sp<SurfaceFlinger> mFlinger;
@ -327,6 +329,9 @@ private:
// protected by mLock // protected by mLock
mutable Mutex mLock; mutable Mutex mLock;
mutable nsecs_t mLastHwVSync; mutable nsecs_t mLastHwVSync;
// thread-safe
mutable Mutex mEventControlLock;
}; };
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------

View File

@ -308,14 +308,14 @@ Vector< sp<EventThread::Connection> > EventThread::waitForEvent(
void EventThread::enableVSyncLocked() { void EventThread::enableVSyncLocked() {
if (!mUseSoftwareVSync) { if (!mUseSoftwareVSync) {
// never enable h/w VSYNC when screen is off // never enable h/w VSYNC when screen is off
mFlinger->eventControl(SurfaceFlinger::EVENT_VSYNC, true); mFlinger->eventControl(HWC_DISPLAY_PRIMARY, SurfaceFlinger::EVENT_VSYNC, true);
mPowerHAL.vsyncHint(true); mPowerHAL.vsyncHint(true);
} }
mDebugVsyncEnabled = true; mDebugVsyncEnabled = true;
} }
void EventThread::disableVSyncLocked() { void EventThread::disableVSyncLocked() {
mFlinger->eventControl(SurfaceFlinger::EVENT_VSYNC, false); mFlinger->eventControl(HWC_DISPLAY_PRIMARY, SurfaceFlinger::EVENT_VSYNC, false);
mPowerHAL.vsyncHint(false); mPowerHAL.vsyncHint(false);
mDebugVsyncEnabled = false; mDebugVsyncEnabled = false;
} }

View File

@ -777,8 +777,8 @@ void SurfaceFlinger::onHotplugReceived(int type, bool connected) {
} }
} }
void SurfaceFlinger::eventControl(int event, int enabled) { void SurfaceFlinger::eventControl(int disp, int event, int enabled) {
getHwComposer().eventControl(event, enabled); getHwComposer().eventControl(disp, event, enabled);
} }
void SurfaceFlinger::onMessageReceived(int32_t what) { void SurfaceFlinger::onMessageReceived(int32_t what) {

View File

@ -123,7 +123,7 @@ public:
// enable/disable h/w composer event // enable/disable h/w composer event
// TODO: this should be made accessible only to EventThread // TODO: this should be made accessible only to EventThread
void eventControl(int event, int enabled); void eventControl(int disp, int event, int enabled);
// called on the main thread by MessageQueue when an internal message // called on the main thread by MessageQueue when an internal message
// is received // is received