h/q/d: Optimize framebuffer layer update

While doing mixed mode composition, update only the region of the
framebuffer where layer contents are cached or updated. Avoids
MDP fetch for non-visible contents of FB.

Change-Id: I20997d79e02a6bac60d7333c28c6dde134263197
diff --git a/libhwcomposer/hwc_fbupdate.cpp b/libhwcomposer/hwc_fbupdate.cpp
index 78a05e9..cc9e3b9 100644
--- a/libhwcomposer/hwc_fbupdate.cpp
+++ b/libhwcomposer/hwc_fbupdate.cpp
@@ -62,7 +62,8 @@
 
 bool IFBUpdate::prepareAndValidate(hwc_context_t *ctx,
             hwc_display_contents_1 *list, int fbZorder) {
-    return prepare(ctx, list, fbZorder) &&
+    hwc_layer_1_t *layer = &list->hwLayers[list->numHwLayers - 1];
+    return prepare(ctx, list, layer->displayFrame, fbZorder) &&
             ctx->mOverlay->validateAndSet(mDpy, ctx->dpyAttr[mDpy].fd);
 }
 
@@ -106,19 +107,19 @@
 }
 
 bool FBUpdateNonSplit::prepare(hwc_context_t *ctx, hwc_display_contents_1 *list,
-                             int fbZorder) {
+                             hwc_rect_t fbUpdatingRect, int fbZorder) {
     if(!ctx->mMDP.hasOverlay) {
         ALOGD_IF(DEBUG_FBUPDATE, "%s, this hw doesnt support overlays",
                  __FUNCTION__);
         return false;
     }
-    mModeOn = configure(ctx, list, fbZorder);
+    mModeOn = configure(ctx, list, fbUpdatingRect, fbZorder);
     return mModeOn;
 }
 
 // Configure
 bool FBUpdateNonSplit::configure(hwc_context_t *ctx, hwc_display_contents_1 *list,
-                               int fbZorder) {
+                               hwc_rect_t fbUpdatingRect, int fbZorder) {
     bool ret = false;
     hwc_layer_1_t *layer = &list->hwLayers[list->numHwLayers - 1];
     if (LIKELY(ctx->mOverlay)) {
@@ -159,6 +160,15 @@
 
         hwc_rect_t sourceCrop = integerizeSourceCrop(layer->sourceCropf);
         hwc_rect_t displayFrame = layer->displayFrame;
+
+        // No FB update optimization on (1) Custom FB resolution,
+        // (2) External Mirror mode, (3) External orientation
+        if(!ctx->dpyAttr[mDpy].customFBSize && !ctx->mBufferMirrorMode
+           && !ctx->mExtOrientation) {
+            sourceCrop = fbUpdatingRect;
+            displayFrame = fbUpdatingRect;
+        }
+
         int transform = layer->transform;
         int rotFlags = ovutils::ROT_FLAGS_NONE;
 
@@ -251,20 +261,20 @@
 }
 
 bool FBUpdateSplit::prepare(hwc_context_t *ctx, hwc_display_contents_1 *list,
-                              int fbZorder) {
+                              hwc_rect_t fbUpdatingRect, int fbZorder) {
     if(!ctx->mMDP.hasOverlay) {
         ALOGD_IF(DEBUG_FBUPDATE, "%s, this hw doesnt support overlays",
                  __FUNCTION__);
         return false;
     }
     ALOGD_IF(DEBUG_FBUPDATE, "%s, mModeOn = %d", __FUNCTION__, mModeOn);
-    mModeOn = configure(ctx, list, fbZorder);
+    mModeOn = configure(ctx, list, fbUpdatingRect, fbZorder);
     return mModeOn;
 }
 
 // Configure
 bool FBUpdateSplit::configure(hwc_context_t *ctx,
-        hwc_display_contents_1 *list, int fbZorder) {
+        hwc_display_contents_1 *list, hwc_rect_t fbUpdatingRect, int fbZorder) {
     bool ret = false;
     hwc_layer_1_t *layer = &list->hwLayers[list->numHwLayers - 1];
     if (LIKELY(ctx->mOverlay)) {
@@ -328,8 +338,8 @@
                                 getBlending(layer->blending));
         ov.setSource(pargR, destR);
 
-        hwc_rect_t sourceCrop = integerizeSourceCrop(layer->sourceCropf);
-        hwc_rect_t displayFrame = layer->displayFrame;
+        hwc_rect_t sourceCrop = fbUpdatingRect;
+        hwc_rect_t displayFrame = fbUpdatingRect;
 
         const float xres = ctx->dpyAttr[mDpy].xres;
         const int lSplit = getLeftSplit(ctx, mDpy);
diff --git a/libhwcomposer/hwc_fbupdate.h b/libhwcomposer/hwc_fbupdate.h
index da4cdfc..c8347fa 100644
--- a/libhwcomposer/hwc_fbupdate.h
+++ b/libhwcomposer/hwc_fbupdate.h
@@ -39,7 +39,7 @@
     virtual ~IFBUpdate() {};
     // Sets up members and prepares overlay if conditions are met
     virtual bool prepare(hwc_context_t *ctx, hwc_display_contents_1 *list,
-            int fbZorder) = 0;
+            hwc_rect_t fbUpdatingRect, int fbZorder) = 0;
     virtual bool prepareAndValidate(hwc_context_t *ctx,
             hwc_display_contents_1 *list, int fbZorder);
     // Draws layer
@@ -64,12 +64,12 @@
     explicit FBUpdateNonSplit(hwc_context_t *ctx, const int& dpy);
     virtual ~FBUpdateNonSplit() {};
     bool prepare(hwc_context_t *ctx, hwc_display_contents_1 *list,
-            int fbZorder);
+            hwc_rect_t fbUpdatingRect, int fbZorder);
     bool draw(hwc_context_t *ctx, private_handle_t *hnd);
     void reset();
 private:
     bool configure(hwc_context_t *ctx, hwc_display_contents_1 *list,
-            int fbZorder);
+            hwc_rect_t fbUpdatingRect, int fbZorder);
     bool preRotateExtDisplay(hwc_context_t *ctx,
                                  hwc_layer_1_t *layer,
                                  ovutils::Whf &info,
@@ -85,12 +85,12 @@
     explicit FBUpdateSplit(hwc_context_t *ctx, const int& dpy);
     virtual ~FBUpdateSplit() {};
     bool prepare(hwc_context_t *ctx, hwc_display_contents_1 *list,
-            int fbZorder);
+            hwc_rect_t fbUpdatingRect, int fbZorder);
     bool draw(hwc_context_t *ctx, private_handle_t *hnd);
     void reset();
 private:
     bool configure(hwc_context_t *ctx, hwc_display_contents_1 *list,
-            int fbZorder);
+            hwc_rect_t fbUpdatingRect, int fbZorder);
     ovutils::eDest mDestLeft; //left pipe to draw on
     ovutils::eDest mDestRight; //right pipe to draw on
 };
diff --git a/libhwcomposer/hwc_mdpcomp.cpp b/libhwcomposer/hwc_mdpcomp.cpp
index 6ff1aa3..440cbd5 100644
--- a/libhwcomposer/hwc_mdpcomp.cpp
+++ b/libhwcomposer/hwc_mdpcomp.cpp
@@ -1212,6 +1212,22 @@
              mCurrentFrame.fbCount);
 }
 
+hwc_rect_t MDPComp::getUpdatingFBRect(hwc_context_t *ctx,
+        hwc_display_contents_1_t* list){
+    hwc_rect_t fbRect = (struct hwc_rect){0, 0, 0, 0};
+    hwc_layer_1_t *fbLayer = &list->hwLayers[mCurrentFrame.layerCount];
+
+    /* Update only the region of FB needed for composition */
+    for(int i = 0; i < mCurrentFrame.layerCount; i++ ) {
+        if(mCurrentFrame.isFBComposed[i] && !mCurrentFrame.drop[i]) {
+            hwc_layer_1_t* layer = &list->hwLayers[i];
+            hwc_rect_t dst = layer->displayFrame;
+            fbRect = getUnion(fbRect, dst);
+        }
+    }
+    return fbRect;
+}
+
 bool MDPComp::postHeuristicsHandling(hwc_context_t *ctx,
         hwc_display_contents_1_t* list) {
 
@@ -1229,7 +1245,9 @@
 
     //Configure framebuffer first if applicable
     if(mCurrentFrame.fbZ >= 0) {
-        if(!ctx->mFBUpdate[mDpy]->prepare(ctx, list, mCurrentFrame.fbZ)) {
+        hwc_rect_t fbRect = getUpdatingFBRect(ctx, list);
+        if(!ctx->mFBUpdate[mDpy]->prepare(ctx, list, fbRect, mCurrentFrame.fbZ))
+        {
             ALOGD_IF(isDebug(), "%s configure framebuffer failed",
                     __FUNCTION__);
             return false;
diff --git a/libhwcomposer/hwc_mdpcomp.h b/libhwcomposer/hwc_mdpcomp.h
index f2a8eda..c5f46e3 100644
--- a/libhwcomposer/hwc_mdpcomp.h
+++ b/libhwcomposer/hwc_mdpcomp.h
@@ -223,6 +223,8 @@
     void reset(hwc_context_t *ctx);
     bool isSupportedForMDPComp(hwc_context_t *ctx, hwc_layer_1_t* layer);
     bool resourceCheck(hwc_context_t *ctx, hwc_display_contents_1_t *list);
+    hwc_rect_t getUpdatingFBRect(hwc_context_t *ctx,
+            hwc_display_contents_1_t* list);
 
     int mDpy;
     static bool sEnabled;