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();