hwc: Do not re-program H/W, if the frame geometry has not changed

There is no need to re-program the H/W, if the frame geometry of all
active displays, has not changed. It will help to improve performance
by avoiding re-configuration of HAL and driver, if it is not needed.

Change-Id: Ie01dce33be89afc7308a8103128d27b4b9fb5c4b
diff --git a/libhwcomposer/hwc.cpp b/libhwcomposer/hwc.cpp
index cbc42b2..b0d7be7 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();
@@ -338,6 +380,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_mdpcomp.h b/libhwcomposer/hwc_mdpcomp.h
index beb858b..ff73524 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/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