hwc: mdpcomp: Use other compositions if programming MDP fails

Currently, if programming MDP fails from a certain composition
strategy we fall back to GPU. This change, redesigns so that
composition types can have a chain of fall back strategies if
programming MDP fails. This happens currently only if resource
checks fail.

Change-Id: Ia7fb71788e595e59a91e95b1fb4eac3faea9451e
diff --git a/libhwcomposer/hwc_mdpcomp.cpp b/libhwcomposer/hwc_mdpcomp.cpp
index 63b4aa5..8048d71 100644
--- a/libhwcomposer/hwc_mdpcomp.cpp
+++ b/libhwcomposer/hwc_mdpcomp.cpp
@@ -157,10 +157,11 @@
     return true;
 }
 
-void MDPComp::reset(const int& numLayers, hwc_display_contents_1_t* list) {
+void MDPComp::reset(hwc_context_t *ctx) {
+    const int numLayers = ctx->listStats[mDpy].numAppLayers;
     mCurrentFrame.reset(numLayers);
-    mCachedFrame.cacheAll(list);
-    mCachedFrame.updateCounts(mCurrentFrame);
+    ctx->mOverlay->clear(mDpy);
+    ctx->mLayerRotMap[mDpy]->clear();
 }
 
 void MDPComp::timeout_handler(void *udata) {
@@ -200,6 +201,16 @@
     }
 }
 
+void MDPComp::setRedraw(hwc_context_t *ctx,
+        hwc_display_contents_1_t* list) {
+    mCurrentFrame.needsRedraw = false;
+    if(!mCachedFrame.isSameFrame(mCurrentFrame, list) ||
+            (list->flags & HWC_GEOMETRY_CHANGED) ||
+            isSkipPresent(ctx, mDpy)) {
+        mCurrentFrame.needsRedraw = true;
+    }
+}
+
 MDPComp::FrameInfo::FrameInfo() {
     reset(0);
 }
@@ -513,7 +524,7 @@
 
 /* Checks for conditions where all the layers marked for MDP comp cannot be
  * bypassed. On such conditions we try to bypass atleast YUV layers */
-bool MDPComp::isFullFrameDoable(hwc_context_t *ctx,
+bool MDPComp::tryFullFrame(hwc_context_t *ctx,
                                 hwc_display_contents_1_t* list){
 
     const int numAppLayers = ctx->listStats[mDpy].numAppLayers;
@@ -563,11 +574,6 @@
         ret = true;
     }
 
-    if(!hwLimitationsCheck(ctx, list)) {
-        ALOGD_IF(isDebug(), "%s: HW limitations",__FUNCTION__);
-        return false;
-    }
-
     return ret;
 }
 
@@ -596,6 +602,7 @@
                                 qhwc::needsScaling(layer))
             return false;
     }
+
     mCurrentFrame.fbCount = 0;
     mCurrentFrame.fbZ = -1;
     memcpy(&mCurrentFrame.isFBComposed, &mCurrentFrame.drop,
@@ -607,8 +614,9 @@
         adjustForSourceSplit(ctx, list);
     }
 
-    if(!resourceCheck(ctx, list)) {
-        ALOGD_IF(isDebug(), "%s: resource check failed", __FUNCTION__);
+    if(!postHeuristicsHandling(ctx, list)) {
+        ALOGD_IF(isDebug(), "post heuristic handling failed");
+        reset(ctx);
         return false;
     }
 
@@ -649,6 +657,7 @@
             if(not isSupportedForMDPComp(ctx, layer)) {
                 ALOGD_IF(isDebug(), "%s: Unsupported layer in list",
                         __FUNCTION__);
+                reset(ctx);
                 return false;
             }
         }
@@ -658,6 +667,7 @@
     bool ret = markLayersForCaching(ctx, list); //sets up fbZ also
     if(!ret) {
         ALOGD_IF(isDebug(),"%s: batching failed, dpy %d",__FUNCTION__, mDpy);
+        reset(ctx);
         return false;
     }
 
@@ -671,11 +681,13 @@
     if((mDpy > HWC_DISPLAY_PRIMARY) and
             (mdpCount > MAX_SEC_LAYERS)) {
         ALOGD_IF(isDebug(), "%s: Exceeds max secondary pipes",__FUNCTION__);
+        reset(ctx);
         return false;
     }
 
-    if(!resourceCheck(ctx, list)) {
-        ALOGD_IF(isDebug(), "%s: resource check failed", __FUNCTION__);
+    if(!postHeuristicsHandling(ctx, list)) {
+        ALOGD_IF(isDebug(), "post heuristic handling failed");
+        reset(ctx);
         return false;
     }
 
@@ -731,6 +743,7 @@
             if(not isSupportedForMDPComp(ctx, layer)) {
                 ALOGD_IF(isDebug(), "%s: MDP unsupported layer found at %d",
                         __FUNCTION__, i);
+                reset(ctx);
                 return false;
             }
             mCurrentFrame.isFBComposed[i] = false;
@@ -741,17 +754,19 @@
     mCurrentFrame.fbCount = batchSize;
     mCurrentFrame.mdpCount = mCurrentFrame.layerCount - batchSize;
 
+    ALOGD_IF(isDebug(), "%s: fbZ %d batchSize %d",
+                __FUNCTION__, mCurrentFrame.fbZ, batchSize);
+
     if(sEnable4k2kYUVSplit){
         adjustForSourceSplit(ctx, list);
     }
 
-    if(!resourceCheck(ctx, list)) {
-        ALOGD_IF(isDebug(), "%s: resource check failed", __FUNCTION__);
+    if(!postHeuristicsHandling(ctx, list)) {
+        ALOGD_IF(isDebug(), "post heuristic handling failed");
+        reset(ctx);
         return false;
     }
 
-    ALOGD_IF(isDebug(), "%s: fbZ %d batchSize %d",
-                __FUNCTION__, mCurrentFrame.fbZ, batchSize);
     return true;
 }
 
@@ -792,6 +807,7 @@
         if(not isSupportedForMDPComp(ctx, layer)) {
             ALOGD_IF(isDebug(), "%s: MDP unsupported layer found at %d",
                     __FUNCTION__, i);
+            reset(ctx);
             return false;
         }
         mCurrentFrame.isFBComposed[i] = false;
@@ -801,19 +817,20 @@
     mCurrentFrame.fbCount = fbBatchSize;
     mCurrentFrame.mdpCount = mCurrentFrame.layerCount - fbBatchSize;
 
+    ALOGD_IF(isDebug(), "%s: FB Z %d, num app layers %d, MDP Batch Size %d",
+                __FUNCTION__, mCurrentFrame.fbZ, numAppLayers,
+                numAppLayers - fbBatchSize);
+
     if(sEnable4k2kYUVSplit){
         adjustForSourceSplit(ctx, list);
     }
 
-    if(!resourceCheck(ctx, list)) {
-        ALOGD_IF(isDebug(), "%s: resource check failed", __FUNCTION__);
+    if(!postHeuristicsHandling(ctx, list)) {
+        ALOGD_IF(isDebug(), "post heuristic handling failed");
+        reset(ctx);
         return false;
     }
 
-    ALOGD_IF(isDebug(), "%s: FB Z %d, num app layers %d, MDP Batch Size %d",
-                __FUNCTION__, mCurrentFrame.fbZ, numAppLayers,
-                numAppLayers - fbBatchSize);
-
     return true;
 }
 
@@ -825,7 +842,14 @@
     return true;
 }
 
-bool MDPComp::isOnlyVideoDoable(hwc_context_t *ctx,
+bool MDPComp::tryVideoOnly(hwc_context_t *ctx,
+        hwc_display_contents_1_t* list) {
+    const bool secureOnly = true;
+    return videoOnlyComp(ctx, list, not secureOnly) or
+            videoOnlyComp(ctx, list, secureOnly);
+}
+
+bool MDPComp::videoOnlyComp(hwc_context_t *ctx,
         hwc_display_contents_1_t* list, bool secureOnly) {
     int numAppLayers = ctx->listStats[mDpy].numAppLayers;
 
@@ -833,21 +857,28 @@
     updateYUV(ctx, list, secureOnly);
     int mdpCount = mCurrentFrame.mdpCount;
 
-    if(!isYuvPresent(ctx, mDpy)) {
+    if(!isYuvPresent(ctx, mDpy) or (mdpCount == 0)) {
+        reset(ctx);
         return false;
     }
 
     /* Bail out if we are processing only secured video layers
      * and we dont have any */
     if(!isSecurePresent(ctx, mDpy) && secureOnly){
+        reset(ctx);
         return false;
     }
 
-    if(!mdpCount)
-        return false;
+    if(mCurrentFrame.fbCount)
+        mCurrentFrame.fbZ = mCurrentFrame.mdpCount;
 
-    if(!resourceCheck(ctx, list)) {
-        ALOGD_IF(isDebug(), "%s: resource check failed", __FUNCTION__);
+    if(sEnable4k2kYUVSplit){
+        adjustForSourceSplit(ctx, list);
+    }
+
+    if(!postHeuristicsHandling(ctx, list)) {
+        ALOGD_IF(isDebug(), "post heuristic handling failed");
+        reset(ctx);
         return false;
     }
 
@@ -1102,7 +1133,21 @@
              mCurrentFrame.fbCount);
 }
 
-bool MDPComp::programMDP(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
+bool MDPComp::postHeuristicsHandling(hwc_context_t *ctx,
+        hwc_display_contents_1_t* list) {
+
+    //Capability checks
+    if(!resourceCheck(ctx, list)) {
+        ALOGD_IF(isDebug(), "%s: resource check failed", __FUNCTION__);
+        return false;
+    }
+
+    //Limitations checks
+    if(!hwLimitationsCheck(ctx, list)) {
+        ALOGD_IF(isDebug(), "%s: HW limitations",__FUNCTION__);
+        return false;
+    }
+
     //Configure framebuffer first if applicable
     if(mCurrentFrame.fbZ >= 0) {
         if(!ctx->mFBUpdate[mDpy]->prepare(ctx, list, mCurrentFrame.fbZ)) {
@@ -1112,6 +1157,8 @@
         }
     }
 
+    mCurrentFrame.map();
+
     if(!allocLayerPipes(ctx, list)) {
         ALOGD_IF(isDebug(), "%s: Unable to allocate MDP pipes", __FUNCTION__);
         return false;
@@ -1152,6 +1199,7 @@
         }
     }
 
+    setRedraw(ctx, list);
     return true;
 }
 
@@ -1276,21 +1324,20 @@
     const int numLayers = ctx->listStats[mDpy].numAppLayers;
     MDPVersion& mdpVersion = qdutils::MDPVersion::getInstance();
 
+    //number of app layers exceeds MAX_NUM_APP_LAYERS fall back to GPU
+    //do not cache the information for next draw cycle.
+    if(numLayers > MAX_NUM_APP_LAYERS) {
+        ALOGI("%s: Number of App layers exceeded the limit ",
+        __FUNCTION__);
+        mCachedFrame.reset();
+        return -1;
+    }
+
     //reset old data
     mCurrentFrame.reset(numLayers);
     memset(&mCurrentFrame.drop, 0, sizeof(mCurrentFrame.drop));
     mCurrentFrame.dropCount = 0;
 
-    //number of app layers exceeds MAX_NUM_APP_LAYERS fall back to GPU
-    //do not cache the information for next draw cycle.
-    if(numLayers > MAX_NUM_APP_LAYERS) {
-        mCachedFrame.updateCounts(mCurrentFrame);
-        ALOGI("%s: Number of App layers exceeded the limit ",
-        __FUNCTION__);
-        ret = -1;
-        return ret;
-    }
-
     // Detect the start of animation and fall back to GPU only once to cache
     // all the layers in FB and display FB content untill animation completes.
     if(ctx->listStats[mDpy].isDisplayAnimating) {
@@ -1308,86 +1355,40 @@
     }
 
     //Hard conditions, if not met, cannot do MDP comp
-    if(!isFrameDoable(ctx)) {
-        ALOGD_IF( isDebug(),"%s: MDP Comp not possible for this frame",
-                __FUNCTION__);
-        reset(numLayers, list);
-        ret = -1;
-        goto exit;
-    }
+    if(isFrameDoable(ctx)) {
+        generateROI(ctx, list);
 
-    generateROI(ctx, list);
-
-    //Convert from kbps to gbps
-    sMaxBw = mdpVersion.getHighBw() / 1000000.0;
-    if (ctx->mExtDisplay->isConnected() || ctx->mMDP.panel != MIPI_CMD_PANEL) {
-        sMaxBw = mdpVersion.getLowBw() / 1000000.0;
-    }
-
-    //Check whether layers marked for MDP Composition is actually doable.
-    if(isFullFrameDoable(ctx, list)) {
-        mCurrentFrame.map();
-        //Acquire and Program MDP pipes
-        if(!programMDP(ctx, list)) {
-            reset(numLayers, list);
-            ctx->mOverlay->clear(mDpy);
-            ctx->mLayerRotMap[mDpy]->clear();
-            ret = -1;
-            goto exit;
-        } else { //Success
-            //Any change in composition types needs an FB refresh
-            mCurrentFrame.needsRedraw = false;
-            if(!mCachedFrame.isSameFrame(mCurrentFrame, list) ||
-                     (list->flags & HWC_GEOMETRY_CHANGED) ||
-                     isSkipPresent(ctx, mDpy)) {
-                mCurrentFrame.needsRedraw = true;
-            }
-        }
-    } else if(isOnlyVideoDoable(ctx, list, false /*secure only*/) ||
-            isOnlyVideoDoable(ctx, list, true /*secure only*/)) {
-        //All layers marked for MDP comp cannot be bypassed.
-        //Try to compose atleast YUV layers through MDP comp and let
-        //all the RGB layers compose in FB
-        //Destination over
-
-        mCurrentFrame.fbZ = -1;
-        if(mCurrentFrame.fbCount)
-            mCurrentFrame.fbZ = mCurrentFrame.mdpCount;
-
-        if(sEnable4k2kYUVSplit){
-            adjustForSourceSplit(ctx, list);
+        //Convert from kbps to gbps
+        sMaxBw = mdpVersion.getHighBw() / 1000000.0;
+        if (ctx->mExtDisplay->isConnected() ||
+                    ctx->mMDP.panel != MIPI_CMD_PANEL) {
+            sMaxBw = mdpVersion.getLowBw() / 1000000.0;
         }
 
-        mCurrentFrame.map();
-
-        if(!programMDP(ctx, list)) {
-            reset(numLayers, list);
-            ctx->mOverlay->clear(mDpy);
-            ctx->mLayerRotMap[mDpy]->clear();
+        if(tryFullFrame(ctx, list) || tryVideoOnly(ctx, list)) {
+            setMDPCompLayerFlags(ctx, list);
+        } else {
+            reset(ctx);
+            memset(&mCurrentFrame.drop, 0, sizeof(mCurrentFrame.drop));
+            mCurrentFrame.dropCount = 0;
             ret = -1;
-            goto exit;
         }
     } else {
-        reset(numLayers, list);
-        memset(&mCurrentFrame.drop, 0, sizeof(mCurrentFrame.drop));
-        mCurrentFrame.dropCount = 0;
+        ALOGD_IF( isDebug(),"%s: MDP Comp not possible for this frame",
+                __FUNCTION__);
         ret = -1;
-        goto exit;
     }
-    //UpdateLayerFlags
-    setMDPCompLayerFlags(ctx, list);
-    mCachedFrame.cacheAll(list);
-    mCachedFrame.updateCounts(mCurrentFrame);
 
-    // unlock it before calling dump function to avoid deadlock
     if(isDebug()) {
-        ALOGD("GEOMETRY change: %d", (list->flags & HWC_GEOMETRY_CHANGED));
+        ALOGD("GEOMETRY change: %d",
+                (list->flags & HWC_GEOMETRY_CHANGED));
         android::String8 sDump("");
         dump(sDump);
-        ALOGE("%s",sDump.string());
+        ALOGD("%s",sDump.string());
     }
 
-exit:
+    mCachedFrame.cacheAll(list);
+    mCachedFrame.updateCounts(mCurrentFrame);
     double panelRefRate =
             1000000000.0 / ctx->dpyAttr[mDpy].vsync_period;
     sBwClaimed += calcMDPBytesRead(ctx, list) * panelRefRate;