hwc: Avoid redoing GPU comp under certain conditions
* When the ambient light changes, pp-daemon will invoke multiple
screen-refresh cycles for LUT convergence needed for
PP algorithms.
* When this happens during static screen usecase, there would
be frequent switches from gpu-comp(due to idlescreen-fallback)
to mdpcomp and back. This results in increase in power numbers
due to increased composition cycles.
* To resolve this, do the following:
a) If frame 'n' is composed using GPU and frame 'n+1' is same
as frame 'n' in terms of input layers contents, avoid any
composition needed for frame 'n+1'. Mark the composition type
for all the layers as HWC_OVERLAY and push the GPU composed
content of frame 'n' for 'n+1' too.
b) Donot do (a) if the any of the incoming layers is marked as
skip or HWC_GEOMETRY_CHANGED flag is set in layer list.
c) Limit (a) to only primary and when secondary is not connected
so that display output expectations during secondary pause-resume
can be met.
* This saves ~10ma during static screen usecase when ambient
light is frequently changing.
Change-Id: I6ca4ab3bf194ffe71191cc661086a14d3e2c26b3
diff --git a/libhwcomposer/hwc_mdpcomp.cpp b/libhwcomposer/hwc_mdpcomp.cpp
index b130193..f6d8276 100644
--- a/libhwcomposer/hwc_mdpcomp.cpp
+++ b/libhwcomposer/hwc_mdpcomp.cpp
@@ -40,7 +40,6 @@
IdleInvalidator *MDPComp::sIdleInvalidator = NULL;
bool MDPComp::sIdleFallBack = false;
-bool MDPComp::sHandleTimeout = false;
bool MDPComp::sDebugLogs = false;
bool MDPComp::sEnabled = false;
bool MDPComp::sEnableMixedMode = true;
@@ -220,12 +219,13 @@
}
void MDPComp::reset() {
- sHandleTimeout = false;
+ mPrevModeOn = mModeOn;
mModeOn = false;
}
void MDPComp::timeout_handler(void *udata) {
struct hwc_context_t* ctx = (struct hwc_context_t*)(udata);
+ bool handleTimeout = false;
if(!ctx) {
ALOGE("%s: received empty data in timer callback", __FUNCTION__);
@@ -233,8 +233,16 @@
}
ctx->mDrawLock.lock();
- // Handle timeout event only if the previous composition is MDP or MIXED.
- if(!sHandleTimeout) {
+
+ /* Handle timeout event only if the previous composition
+ on any display is MDP or MIXED*/
+ for(int i = 0; i < HWC_NUM_DISPLAY_TYPES; i++) {
+ if(ctx->mMDPComp[i])
+ handleTimeout =
+ ctx->mMDPComp[i]->isMDPComp() || handleTimeout;
+ }
+
+ if(!handleTimeout) {
ALOGD_IF(isDebug(), "%s:Do not handle this timeout", __FUNCTION__);
ctx->mDrawLock.unlock();
return;
@@ -387,6 +395,25 @@
return true;
}
+bool MDPComp::LayerCache::isSameFrame(hwc_context_t *ctx, int dpy,
+ hwc_display_contents_1_t* list) {
+
+ if(layerCount != ctx->listStats[dpy].numAppLayers)
+ return false;
+
+ if((list->flags & HWC_GEOMETRY_CHANGED) ||
+ isSkipPresent(ctx, dpy)) {
+ return false;
+ }
+
+ for(int i = 0; i < layerCount; i++) {
+ if(hnd[i] != list->hwLayers[i].handle)
+ return false;
+ }
+
+ return true;
+}
+
bool MDPComp::isSupportedForMDPComp(hwc_context_t *ctx, hwc_layer_1_t* layer) {
private_handle_t *hnd = (private_handle_t *)layer->handle;
if((has90Transform(layer) and (not isRotationDoable(ctx, hnd))) ||
@@ -2036,6 +2063,20 @@
ctx->mAnimationState[mDpy] = ANIMATION_STOPPED;
}
+ if(!mDpy and !isSecondaryConnected(ctx) and !mPrevModeOn and
+ mCachedFrame.isSameFrame(ctx,mDpy,list)) {
+
+ ALOGD_IF(isDebug(),"%s: Avoid new composition",__FUNCTION__);
+ mCurrentFrame.needsRedraw = false;
+ setMDPCompLayerFlags(ctx, list);
+ mCachedFrame.updateCounts(mCurrentFrame);
+#ifdef DYNAMIC_FPS
+ setDynRefreshRate(ctx, list);
+#endif
+ return -1;
+
+ }
+
//Hard conditions, if not met, cannot do MDP comp
if(isFrameDoable(ctx)) {
generateROI(ctx, list);
@@ -2245,11 +2286,6 @@
return true;
}
- // Set the Handle timeout to true for MDP or MIXED composition.
- if(sIdleInvalidator && !sIdleFallBack && mCurrentFrame.mdpCount) {
- sHandleTimeout = true;
- }
-
overlay::Overlay& ov = *ctx->mOverlay;
LayerProp *layerProp = ctx->layerProp[mDpy];
@@ -2507,13 +2543,6 @@
return true;
}
- // Set the Handle timeout to true for MDP or MIXED composition.
- if(sIdleInvalidator && !sIdleFallBack && mCurrentFrame.mdpCount &&
- !(needs3DComposition(ctx, HWC_DISPLAY_PRIMARY) ||
- needs3DComposition(ctx, HWC_DISPLAY_EXTERNAL))) {
- sHandleTimeout = true;
- }
-
overlay::Overlay& ov = *ctx->mOverlay;
LayerProp *layerProp = ctx->layerProp[mDpy];