summaryrefslogtreecommitdiffstats
path: root/services/surfaceflinger
diff options
context:
space:
mode:
authorPrashant Malani <pmalani@google.com>2014-05-25 01:36:31 -0700
committerPrashant Malani <pmalani@google.com>2014-06-05 16:35:52 -0700
commit2c9b11f0291210c9b9513a1a0cce6afebd361b3b (patch)
tree47ba276853c591e558553ee5e0eefabbc7db4625 /services/surfaceflinger
parentedcf7f4d3ac452500d68e254d367f559d538695d (diff)
downloadframeworks_native-2c9b11f0291210c9b9513a1a0cce6afebd361b3b.zip
frameworks_native-2c9b11f0291210c9b9513a1a0cce6afebd361b3b.tar.gz
frameworks_native-2c9b11f0291210c9b9513a1a0cce6afebd361b3b.tar.bz2
surfaceflinger: Replace blank/unblank with setPowerMode
We replace the blank/unblank calls in surfaceFlinger with a more generic setPowerMode() routine. Some displays support different power modes (for example, with reduced color palettes). Depending on the use case we should be able to toggle these modes, so as to achieve incremental power savings. Initially, three power modes will be supported: - HWC_POWER_MODE_OFF - HWC_POWER_MODE_DOZE - HWC_POWER_MODE_NORMAL HWC_POWER_MODE_OFF will correspond to blanking the display, while HWC_POWER_MODE_NORMAL will correspond to unblanking. HWC_POWER_MODE_DOZE will put the display into a low power setting, if it is supported in hardware. If such a low power mode is not supported, it should be treated as a call to set the mode to HWC_POWER_MODE_NORMAL. As a consequence of adding the mPowerMode field, the mScreenAcquired is no longer required, and thus references to it are removed and replaced equivalent references to mPowerMode. We also add the glue code to connect the services invocation of setting a power mode and the HAL implementation in HWComposer. Bug: 13472578 Change-Id: I431595ecf16d2f2c94259272db3dd42f29636204 Signed-off-by: Prashant Malani <pmalani@google.com>
Diffstat (limited to 'services/surfaceflinger')
-rw-r--r--services/surfaceflinger/DisplayDevice.cpp28
-rw-r--r--services/surfaceflinger/DisplayDevice.h14
-rw-r--r--services/surfaceflinger/DisplayHardware/HWComposer.cpp21
-rw-r--r--services/surfaceflinger/DisplayHardware/HWComposer.h7
-rw-r--r--services/surfaceflinger/SurfaceFlinger.cpp116
-rw-r--r--services/surfaceflinger/SurfaceFlinger.h11
6 files changed, 78 insertions, 119 deletions
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index 4ebe291..71377ed 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -70,9 +70,9 @@ DisplayDevice::DisplayDevice(
mPageFlipCount(),
mIsSecure(isSecure),
mSecureLayerVisible(false),
- mScreenAcquired(false),
mLayerStack(NO_LAYER_STACK),
- mOrientation()
+ mOrientation(),
+ mPowerMode(HWC_POWER_MODE_OFF)
{
mNativeWindow = new Surface(producer, false);
ANativeWindow* const window = mNativeWindow.get();
@@ -109,7 +109,8 @@ DisplayDevice::DisplayDevice(
mFrame.makeInvalid();
// virtual displays are always considered enabled
- mScreenAcquired = (mType >= DisplayDevice::DISPLAY_VIRTUAL);
+ mPowerMode = (mType >= DisplayDevice::DISPLAY_VIRTUAL) ?
+ HWC_POWER_MODE_NORMAL : HWC_POWER_MODE_OFF;
// Name the display. The name will be replaced shortly if the display
// was created with createDisplay().
@@ -322,21 +323,16 @@ Region DisplayDevice::getDirtyRegion(bool repaintEverything) const {
}
// ----------------------------------------------------------------------------
-
-bool DisplayDevice::canDraw() const {
- return mScreenAcquired;
-}
-
-void DisplayDevice::releaseScreen() const {
- mScreenAcquired = false;
+void DisplayDevice::setPowerMode(int mode) {
+ mPowerMode = mode;
}
-void DisplayDevice::acquireScreen() const {
- mScreenAcquired = true;
+int DisplayDevice::getPowerMode() const {
+ return mPowerMode;
}
-bool DisplayDevice::isScreenAcquired() const {
- return mScreenAcquired;
+bool DisplayDevice::isDisplayOn() const {
+ return (mPowerMode != HWC_POWER_MODE_OFF);
}
// ----------------------------------------------------------------------------
@@ -465,13 +461,13 @@ void DisplayDevice::dump(String8& result) const {
result.appendFormat(
"+ DisplayDevice: %s\n"
" type=%x, hwcId=%d, layerStack=%u, (%4dx%4d), ANativeWindow=%p, orient=%2d (type=%08x), "
- "flips=%u, isSecure=%d, secureVis=%d, acquired=%d, numLayers=%zu\n"
+ "flips=%u, isSecure=%d, secureVis=%d, powerMode=%d, numLayers=%zu\n"
" v:[%d,%d,%d,%d], f:[%d,%d,%d,%d], s:[%d,%d,%d,%d],"
"transform:[[%0.3f,%0.3f,%0.3f][%0.3f,%0.3f,%0.3f][%0.3f,%0.3f,%0.3f]]\n",
mDisplayName.string(), mType, mHwcDisplayId,
mLayerStack, mDisplayWidth, mDisplayHeight, mNativeWindow.get(),
mOrientation, tr.getType(), getPageFlipCount(),
- mIsSecure, mSecureLayerVisible, mScreenAcquired, mVisibleLayersSortedByZ.size(),
+ mIsSecure, mSecureLayerVisible, mPowerMode, mVisibleLayersSortedByZ.size(),
mViewport.left, mViewport.top, mViewport.right, mViewport.bottom,
mFrame.left, mFrame.top, mFrame.right, mFrame.bottom,
mScissor.left, mScissor.top, mScissor.right, mScissor.bottom,
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index f750c6c..4c8ef02 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -147,12 +147,11 @@ public:
void setViewportAndProjection() const;
/* ------------------------------------------------------------------------
- * blank / unblank management
+ * Display power mode management.
*/
- void releaseScreen() const;
- void acquireScreen() const;
- bool isScreenAcquired() const;
- bool canDraw() const;
+ int getPowerMode() const;
+ void setPowerMode(int mode);
+ bool isDisplayOn() const;
// release HWC resources (if any) for removable displays
void disconnect(HWComposer& hwc);
@@ -197,9 +196,6 @@ private:
// Whether we have a visible secure layer on this display
bool mSecureLayerVisible;
- // Whether the screen is blanked;
- mutable int mScreenAcquired;
-
/*
* Transaction state
@@ -217,6 +213,8 @@ private:
Rect mScissor;
Transform mGlobalTransform;
bool mNeedsFiltering;
+ // Current power mode
+ int mPowerMode;
};
}; // namespace android
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index c3b2159..185dab2 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -759,19 +759,18 @@ status_t HWComposer::commit() {
return (status_t)err;
}
-status_t HWComposer::release(int disp) {
+status_t HWComposer::setPowerMode(int disp, int mode) {
LOG_FATAL_IF(disp >= VIRTUAL_DISPLAY_ID_BASE);
if (mHwc) {
- eventControl(disp, HWC_EVENT_VSYNC, 0);
- return (status_t)mHwc->blank(mHwc, disp, 1);
- }
- return NO_ERROR;
-}
-
-status_t HWComposer::acquire(int disp) {
- LOG_FATAL_IF(disp >= VIRTUAL_DISPLAY_ID_BASE);
- if (mHwc) {
- return (status_t)mHwc->blank(mHwc, disp, 0);
+ if (mode == HWC_POWER_MODE_OFF) {
+ eventControl(disp, HWC_EVENT_VSYNC, 0);
+ }
+ if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_4)) {
+ return (status_t)mHwc->setPowerMode(mHwc, disp, mode);
+ } else {
+ return (status_t)mHwc->blank(mHwc, disp,
+ mode == HWC_POWER_MODE_OFF ? 1 : 0);
+ }
}
return NO_ERROR;
}
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index 2f92672..c62b924 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -97,11 +97,8 @@ public:
// commits the list
status_t commit();
- // release hardware resources and blank screen
- status_t release(int disp);
-
- // acquire hardware resources and unblank screen
- status_t acquire(int disp);
+ // set power mode
+ status_t setPowerMode(int disp, int mode);
// reset state when an external, non-virtual display is disconnected
void disconnectDisplay(int disp);
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 7152f93..06435ab 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -437,7 +437,7 @@ void SurfaceFlinger::init() {
// for displays other than the main display, so we always
// assume a connected display is unblanked.
ALOGD("marking display %zu as acquired/unblanked", i);
- hw->acquireScreen();
+ hw->setPowerMode(HWC_POWER_MODE_NORMAL);
}
mDisplays.add(token, hw);
}
@@ -793,7 +793,7 @@ void SurfaceFlinger::doDebugFlashRegions()
const bool repaintEverything = mRepaintEverything;
for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
const sp<DisplayDevice>& hw(mDisplays[dpy]);
- if (hw->canDraw()) {
+ if (hw->isDisplayOn()) {
// transform the dirty region into this screen's coordinate space
const Region dirtyRegion(hw->getDirtyRegion(repaintEverything));
if (!dirtyRegion.isEmpty()) {
@@ -860,7 +860,7 @@ void SurfaceFlinger::postComposition()
if (runningWithoutSyncFramework) {
const sp<const DisplayDevice> hw(getDefaultDisplayDevice());
- if (hw->isScreenAcquired()) {
+ if (hw->isDisplayOn()) {
enableHardwareVsync();
}
}
@@ -895,7 +895,7 @@ void SurfaceFlinger::rebuildLayerStacks() {
const sp<DisplayDevice>& hw(mDisplays[dpy]);
const Transform& tr(hw->getTransform());
const Rect bounds(hw->getBounds());
- if (hw->canDraw()) {
+ if (hw->isDisplayOn()) {
SurfaceFlinger::computeVisibleRegions(layers,
hw->getLayerStack(), dirtyRegion, opaqueRegion);
@@ -991,7 +991,7 @@ void SurfaceFlinger::doComposition() {
const bool repaintEverything = android_atomic_and(0, &mRepaintEverything);
for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) {
const sp<DisplayDevice>& hw(mDisplays[dpy]);
- if (hw->canDraw()) {
+ if (hw->isDisplayOn()) {
// transform the dirty region into this screen's coordinate space
const Region dirtyRegion(hw->getDirtyRegion(repaintEverything));
@@ -2082,7 +2082,7 @@ void SurfaceFlinger::onInitializeDisplays() {
d.viewport.makeInvalid();
displays.add(d);
setTransactionState(state, displays, 0);
- onScreenAcquired(getDefaultDisplayDevice());
+ setPowerModeInternal(getDisplayDevice(d.token), HWC_POWER_MODE_NORMAL);
const nsecs_t period =
getHwComposer().getRefreshPeriod(HWC_DISPLAY_PRIMARY);
@@ -2103,42 +2103,35 @@ void SurfaceFlinger::initializeDisplays() {
postMessageAsync(msg); // we may be called from main thread, use async message
}
+void SurfaceFlinger::setPowerModeInternal(const sp<DisplayDevice>& hw,
+ int mode) {
+ ALOGD("Set power mode=%d, type=%d flinger=%p", mode, hw->getDisplayType(),
+ this);
+ int32_t type = hw->getDisplayType();
+ int currentMode = hw->getPowerMode();
-void SurfaceFlinger::onScreenAcquired(const sp<const DisplayDevice>& hw) {
- ALOGD("Screen acquired, type=%d flinger=%p", hw->getDisplayType(), this);
- if (hw->isScreenAcquired()) {
- // this is expected, e.g. when power manager wakes up during boot
- ALOGD(" screen was previously acquired");
+ if (mode == currentMode) {
+ ALOGD("Screen type=%d is already mode=%d", hw->getDisplayType(), mode);
return;
}
- hw->acquireScreen();
- int32_t type = hw->getDisplayType();
- if (type < DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES) {
- // built-in display, tell the HWC
- getHwComposer().acquire(type);
+ hw->setPowerMode(mode);
+ if (type >= DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES) {
+ ALOGW("Trying to set power mode for virtual display");
+ return;
+ }
+ if (currentMode == HWC_POWER_MODE_OFF) {
+ getHwComposer().setPowerMode(type, mode);
if (type == DisplayDevice::DISPLAY_PRIMARY) {
// FIXME: eventthread only knows about the main display right now
mEventThread->onScreenAcquired();
-
resyncToHardwareVsync(true);
}
- }
- mVisibleRegionsDirty = true;
- repaintEverything();
-}
-void SurfaceFlinger::onScreenReleased(const sp<const DisplayDevice>& hw) {
- ALOGD("Screen released, type=%d flinger=%p", hw->getDisplayType(), this);
- if (!hw->isScreenAcquired()) {
- ALOGD(" screen was previously released");
- return;
- }
-
- hw->releaseScreen();
- int32_t type = hw->getDisplayType();
- if (type < DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES) {
+ mVisibleRegionsDirty = true;
+ repaintEverything();
+ } else if (mode == HWC_POWER_MODE_OFF) {
if (type == DisplayDevice::DISPLAY_PRIMARY) {
disableHardwareVsync(true); // also cancels any in-progress resync
@@ -2146,56 +2139,38 @@ void SurfaceFlinger::onScreenReleased(const sp<const DisplayDevice>& hw) {
mEventThread->onScreenReleased();
}
- // built-in display, tell the HWC
- getHwComposer().release(type);
+ getHwComposer().setPowerMode(type, mode);
+ mVisibleRegionsDirty = true;
+ // from this point on, SF will stop drawing on this display
+ } else {
+ getHwComposer().setPowerMode(type, mode);
}
- mVisibleRegionsDirty = true;
- // from this point on, SF will stop drawing on this display
-}
-
-void SurfaceFlinger::unblank(const sp<IBinder>& display) {
- class MessageScreenAcquired : public MessageBase {
- SurfaceFlinger& mFlinger;
- sp<IBinder> mDisplay;
- public:
- MessageScreenAcquired(SurfaceFlinger& flinger,
- const sp<IBinder>& disp) : mFlinger(flinger), mDisplay(disp) { }
- virtual bool handler() {
- const sp<DisplayDevice> hw(mFlinger.getDisplayDevice(mDisplay));
- if (hw == NULL) {
- ALOGE("Attempt to unblank null display %p", mDisplay.get());
- } else if (hw->getDisplayType() >= DisplayDevice::DISPLAY_VIRTUAL) {
- ALOGW("Attempt to unblank virtual display");
- } else {
- mFlinger.onScreenAcquired(hw);
- }
- return true;
- }
- };
- sp<MessageBase> msg = new MessageScreenAcquired(*this, display);
- postMessageSync(msg);
}
-void SurfaceFlinger::blank(const sp<IBinder>& display) {
- class MessageScreenReleased : public MessageBase {
+void SurfaceFlinger::setPowerMode(const sp<IBinder>& display, int mode) {
+ class MessageSetPowerMode: public MessageBase {
SurfaceFlinger& mFlinger;
sp<IBinder> mDisplay;
+ int mMode;
public:
- MessageScreenReleased(SurfaceFlinger& flinger,
- const sp<IBinder>& disp) : mFlinger(flinger), mDisplay(disp) { }
+ MessageSetPowerMode(SurfaceFlinger& flinger,
+ const sp<IBinder>& disp, int mode) : mFlinger(flinger),
+ mDisplay(disp) { mMode = mode; }
virtual bool handler() {
- const sp<DisplayDevice> hw(mFlinger.getDisplayDevice(mDisplay));
+ sp<DisplayDevice> hw(mFlinger.getDisplayDevice(mDisplay));
if (hw == NULL) {
- ALOGE("Attempt to blank null display %p", mDisplay.get());
+ ALOGE("Attempt to set power mode = %d for null display %p",
+ mDisplay.get(), mMode);
} else if (hw->getDisplayType() >= DisplayDevice::DISPLAY_VIRTUAL) {
- ALOGW("Attempt to blank virtual display");
+ ALOGW("Attempt to set power mode = %d for virtual display",
+ mMode);
} else {
- mFlinger.onScreenReleased(hw);
+ mFlinger.setPowerModeInternal(hw, mMode);
}
return true;
}
};
- sp<MessageBase> msg = new MessageScreenReleased(*this, display);
+ sp<MessageBase> msg = new MessageSetPowerMode(*this, display, mode);
postMessageSync(msg);
}
@@ -2456,8 +2431,8 @@ void SurfaceFlinger::dumpAllLocked(const Vector<String16>& args, size_t& index,
mRenderEngine->dump(result);
hw->undefinedRegion.dump(result, "undefinedRegion");
- result.appendFormat(" orientation=%d, canDraw=%d\n",
- hw->getOrientation(), hw->canDraw());
+ result.appendFormat(" orientation=%d, isDisplayOn=%d\n",
+ hw->getOrientation(), hw->isDisplayOn());
result.appendFormat(
" last eglSwapBuffers() time: %f us\n"
" last transaction time : %f us\n"
@@ -2549,10 +2524,9 @@ status_t SurfaceFlinger::onTransact(
case CREATE_DISPLAY:
case SET_TRANSACTION_STATE:
case BOOT_FINISHED:
- case BLANK:
- case UNBLANK:
case CLEAR_ANIMATION_FRAME_STATS:
case GET_ANIMATION_FRAME_STATS:
+ case SET_POWER_MODE:
{
// codes that require permission check
IPCThreadState* ipc = IPCThreadState::self();
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index cc01eb3..996a795 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -205,13 +205,10 @@ private:
Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
uint32_t minLayerZ, uint32_t maxLayerZ,
bool useIdentityTransform);
- // called when screen needs to turn off
- virtual void blank(const sp<IBinder>& display);
- // called when screen is turning back on
- virtual void unblank(const sp<IBinder>& display);
virtual status_t getDisplayConfigs(const sp<IBinder>& display,
Vector<DisplayInfo>* configs);
virtual int getActiveConfig(const sp<IBinder>& display);
+ virtual void setPowerMode(const sp<IBinder>& display, int mode);
virtual status_t setActiveConfig(const sp<IBinder>& display, int id);
virtual status_t clearAnimationFrameStats();
virtual status_t getAnimationFrameStats(FrameStats* outStats) const;
@@ -242,10 +239,8 @@ private:
// called on the main thread in response to initializeDisplays()
void onInitializeDisplays();
- // called on the main thread in response to blank()
- void onScreenReleased(const sp<const DisplayDevice>& hw);
- // called on the main thread in response to unblank()
- void onScreenAcquired(const sp<const DisplayDevice>& hw);
+ // called on the main thread in response to setPowerMode()
+ void setPowerModeInternal(const sp<DisplayDevice>& hw, int mode);
void handleMessageTransaction();
void handleMessageInvalidate();