hwc: Use GPU to compose for smaller updates

Whether or not an update is small (conservatively set to < 5% of
screen) is checked using total dirty areas of layers and GPU is
used to compose. This is because a smaller update also means GPU
had less front end work and the MDP can avoid fetching data from
all layers until idle timeout.

Change-Id: I1ccd8913f2a1c760f570b225fdfb29f6a20b5a8d
diff --git a/libhwcomposer/hwc_mdpcomp.cpp b/libhwcomposer/hwc_mdpcomp.cpp
index 77d52dc..a81913d 100644
--- a/libhwcomposer/hwc_mdpcomp.cpp
+++ b/libhwcomposer/hwc_mdpcomp.cpp
@@ -893,6 +893,12 @@
         return false;
     }
 
+    uint32_t totalDirtyArea = 0;
+    bool computeDirtyArea = not (list->flags & HWC_GEOMETRY_CHANGED) and
+            not isYuvPresent(ctx, mDpy) and
+            not qdutils::MDPVersion::getInstance().isPartialUpdateEnabled() and
+            numAppLayers > 1;
+
     for(int i = 0; i < numAppLayers; ++i) {
         hwc_layer_1_t* layer = &list->hwLayers[i];
         private_handle_t *hnd = (private_handle_t *)layer->handle;
@@ -912,6 +918,33 @@
         if( mdpHw.is8x26() && (ctx->dpyAttr[mDpy].xres > 1024) &&
                 (transform & HWC_TRANSFORM_FLIP_H) && (!isYuvBuffer(hnd)))
             return false;
+
+#ifdef QCOM_BSP
+        if(computeDirtyArea and mCachedFrame.hnd[i] != hnd) {
+            if(needsScaling(layer)) {
+                totalDirtyArea = 0;
+                computeDirtyArea = false;
+            } else {
+                hwc_rect_t dirtyRect = layer->dirtyRect;
+                ALOGD_IF(isDebug(),
+                        "Updating layer: %d Dirty rect: %d, %d, %d, %d",
+                        i, dirtyRect.left, dirtyRect.top, dirtyRect.right,
+                        dirtyRect.bottom);
+                totalDirtyArea += (dirtyRect.right - dirtyRect.left)
+                        * (dirtyRect.bottom - dirtyRect.top);
+            }
+        }
+#endif
+    }
+
+    if(totalDirtyArea) {
+        const uint32_t fbArea = ctx->dpyAttr[mDpy].xres *
+                ctx->dpyAttr[mDpy].yres;
+        if(totalDirtyArea < (fbArea / 20)) {
+            ALOGD_IF(isDebug(), "%s: Small update, bailing out. Dirty area %u",
+                    __FUNCTION__, totalDirtyArea);
+            return false;
+        }
     }
 
     if(ctx->mAD->isDoable()) {