Merge "hwc: Use layer dirty rect to calculate frame's updating ROI"
diff --git a/libhwcomposer/hwc.cpp b/libhwcomposer/hwc.cpp
index cbc42b2..f4baa25 100644
--- a/libhwcomposer/hwc.cpp
+++ b/libhwcomposer/hwc.cpp
@@ -260,6 +260,48 @@
     }
 }
 
+static bool optimizePrepare(hwc_context_t *ctx, int numDisplays,
+                            hwc_display_contents_1_t** displays) {
+
+    /* Do not re-program H/W, if frame geometry has not changed.
+     * But honor these exceptions:
+     * 1. Padding round
+     * 2. Idle fallback
+     * 3. Overlay is not configured
+     * 4. External/Virtual display is in Configure state
+     * 5. External/Virtual is Paused OR not connected/active
+     * 6. Non-Overlay device
+     */
+
+    if (ctx->isPaddingRound || MDPComp::isIdleFallback() ||
+        !ctx->mOverlay->isConfigured() || isSecondaryConfiguring(ctx) ||
+        ctx->mMDP.version < qdutils::MDP_V4_0) {
+        return false;
+    }
+
+    bool isOptimized = false;
+    for (uint32_t i = 0; i < numDisplays; i++) {
+        hwc_display_contents_1_t *list = displays[i];
+
+        if (list) {
+            if (list->flags & HWC_GEOMETRY_CHANGED) {
+                return false;
+            }
+            int dpy = getDpyforExternalDisplay(ctx, i);
+            if (dpy && (ctx->dpyAttr[dpy].isPause ||
+                !ctx->dpyAttr[dpy].connected ||
+                !ctx->dpyAttr[dpy].isActive)) {
+                return false;
+            }
+            // Set layer composition type as per last frame
+            ctx->mMDPComp[dpy]->setMDPCompLayerFlags(ctx, list);
+            isOptimized = true;
+        }
+    }
+
+    return isOptimized;
+}
+
 static int hwc_prepare_primary(hwc_composer_device_1 *dev,
         hwc_display_contents_1_t *list) {
     ATRACE_CALL();
@@ -279,7 +321,10 @@
 
         if (fbComp) {
             const int fbZ = 0;
-            ctx->mFBUpdate[dpy]->prepareAndValidate(ctx, list, fbZ);
+            if(not ctx->mFBUpdate[dpy]->prepareAndValidate(ctx, list, fbZ)) {
+                ctx->mOverlay->clear(dpy);
+                ctx->mLayerRotMap[dpy]->clear();
+            }
         }
 
         if (ctx->mMDP.version < qdutils::MDP_V4_0) {
@@ -306,7 +351,11 @@
             setListStats(ctx, list, dpy);
             if(ctx->mMDPComp[dpy]->prepare(ctx, list) < 0) {
                 const int fbZ = 0;
-                ctx->mFBUpdate[dpy]->prepareAndValidate(ctx, list, fbZ);
+                if(not ctx->mFBUpdate[dpy]->prepareAndValidate(ctx, list, fbZ))
+                {
+                    ctx->mOverlay->clear(dpy);
+                    ctx->mLayerRotMap[dpy]->clear();
+                }
             }
         } else {
             /* External Display is in Pause state.
@@ -338,6 +387,12 @@
     setPaddingRound(ctx,numDisplays,displays);
     setDMAState(ctx,numDisplays,displays);
     setNumActiveDisplays(ctx,numDisplays,displays);
+
+    if (optimizePrepare(ctx, numDisplays, displays)) {
+        // Do not re-program H/W, if it is not needed
+        return ret;
+    }
+
     reset(ctx, (int)numDisplays, displays);
 
     ctx->mOverlay->configBegin();
diff --git a/libhwcomposer/hwc_fbupdate.cpp b/libhwcomposer/hwc_fbupdate.cpp
index 74e6da4..c733523 100644
--- a/libhwcomposer/hwc_fbupdate.cpp
+++ b/libhwcomposer/hwc_fbupdate.cpp
@@ -208,8 +208,6 @@
                 sourceCrop, mdpFlags, rotFlags);
         if(!ret) {
             ALOGE("%s: preRotate for external Failed!", __FUNCTION__);
-            ctx->mOverlay->clear(mDpy);
-            ctx->mLayerRotMap[mDpy]->clear();
             return false;
         }
         //For the mdp, since either we are pre-rotating or MDP does flips
@@ -224,7 +222,6 @@
         if(configMdp(ctx->mOverlay, parg, orient, sourceCrop, displayFrame,
                     NULL, mDest) < 0) {
             ALOGE("%s: configMdp failed for dpy %d", __FUNCTION__, mDpy);
-            ctx->mLayerRotMap[mDpy]->clear();
             ret = false;
         }
     }
@@ -387,10 +384,6 @@
                 ret = false;
             }
         }
-
-        if(ret == false) {
-            ctx->mLayerRotMap[mDpy]->clear();
-        }
     }
     return ret;
 }
@@ -425,7 +418,6 @@
 
 bool FBSrcSplit::configure(hwc_context_t *ctx, hwc_display_contents_1 *list,
         hwc_rect_t fbUpdatingRect, int fbZorder) {
-    bool ret = false;
     hwc_layer_1_t *layer = &list->hwLayers[list->numHwLayers - 1];
     int extOnlyLayerIndex = ctx->listStats[mDpy].extOnlyLayerIndex;
     // ext only layer present..
@@ -502,7 +494,6 @@
         if(configMdp(ctx->mOverlay, parg, orient,
                     cropL, cropL, NULL /*metadata*/, destL) < 0) {
             ALOGE("%s: commit failed for left mixer config", __FUNCTION__);
-            ctx->mLayerRotMap[mDpy]->clear();
             return false;
         }
     }
@@ -512,7 +503,6 @@
         if(configMdp(ctx->mOverlay, parg, orient,
                     cropR, cropR, NULL /*metadata*/, destR) < 0) {
             ALOGE("%s: commit failed for right mixer config", __FUNCTION__);
-            ctx->mLayerRotMap[mDpy]->clear();
             return false;
         }
     }
diff --git a/libhwcomposer/hwc_mdpcomp.h b/libhwcomposer/hwc_mdpcomp.h
index 8186fff..7d4214a 100644
--- a/libhwcomposer/hwc_mdpcomp.h
+++ b/libhwcomposer/hwc_mdpcomp.h
@@ -54,6 +54,9 @@
     static void resetIdleFallBack() { sIdleFallBack = false; }
     static void reset() { sHandleTimeout = false; };
     static bool isIdleFallback() { return sIdleFallBack; }
+    /* set/reset flags for MDPComp */
+    void setMDPCompLayerFlags(hwc_context_t *ctx,
+                              hwc_display_contents_1_t* list);
 
 protected:
     enum { MAX_SEC_LAYERS = 1 }; //TODO add property support
@@ -142,9 +145,6 @@
     /* configures 4kx2k yuv layer*/
     virtual int configure4k2kYuv(hwc_context_t *ctx, hwc_layer_1_t *layer,
             PipeLayerPair& PipeLayerPair) = 0;
-    /* set/reset flags for MDPComp */
-    void setMDPCompLayerFlags(hwc_context_t *ctx,
-                              hwc_display_contents_1_t* list);
     void setRedraw(hwc_context_t *ctx,
             hwc_display_contents_1_t* list);
     /* checks for conditions where mdpcomp is not possible */
diff --git a/libhwcomposer/hwc_virtual.cpp b/libhwcomposer/hwc_virtual.cpp
index 10ed9d1..97b19ea 100644
--- a/libhwcomposer/hwc_virtual.cpp
+++ b/libhwcomposer/hwc_virtual.cpp
@@ -126,7 +126,11 @@
 
             if(ctx->mMDPComp[dpy]->prepare(ctx, list) < 0) {
                 const int fbZ = 0;
-                ctx->mFBUpdate[dpy]->prepareAndValidate(ctx, list, fbZ);
+                if(not ctx->mFBUpdate[dpy]->prepareAndValidate(ctx, list, fbZ))
+                {
+                    ctx->mOverlay->clear(dpy);
+                    ctx->mLayerRotMap[dpy]->clear();
+                }
             }
         } else {
             /* Virtual Display is in Pause state.
@@ -260,7 +264,11 @@
             setListStats(ctx, list, dpy);
             if(ctx->mMDPComp[dpy]->prepare(ctx, list) < 0) {
                 const int fbZ = 0;
-                ctx->mFBUpdate[dpy]->prepareAndValidate(ctx, list, fbZ);
+                if(not ctx->mFBUpdate[dpy]->prepareAndValidate(ctx, list, fbZ))
+                {
+                    ctx->mOverlay->clear(dpy);
+                    ctx->mLayerRotMap[dpy]->clear();
+                }
             }
         } else {
             /* Virtual Display is in Pause state.
diff --git a/liboverlay/overlay.h b/liboverlay/overlay.h
index fa19dc3..3e6af22 100644
--- a/liboverlay/overlay.h
+++ b/liboverlay/overlay.h
@@ -135,6 +135,8 @@
     void clear(int dpy);
     /* Validate the set of pipes for a display and set them in driver */
     bool validateAndSet(const int& dpy, const int& fbFd);
+    /* Returns true if PipeBook has been configured, false otherwise */
+    bool isConfigured();
 
     /* Closes open pipes, called during startup */
     static int initOverlay();
@@ -199,6 +201,7 @@
         static void resetAllocation(int index);
         static bool isAllocated(int index);
         static bool isNotAllocated(int index);
+        static bool isConfigured();
 
         static utils::eMdpPipeType getPipeType(utils::eDest dest);
         static const char* getDestStr(utils::eDest dest);
@@ -389,6 +392,14 @@
     return "Invalid";
 }
 
+inline bool Overlay::PipeBook::isConfigured() {
+    return (sAllocatedBitmap != 0);
+}
+
+inline bool Overlay::isConfigured() {
+    return PipeBook::isConfigured();
+}
+
 }; // overlay
 
 #endif // OVERLAY_H