Merge "libgralloc: correct assigment of HAL_PIXEL_FORMAT_RGBA_8888"
diff --git a/common.mk b/common.mk
index cfe84be..47c455f 100644
--- a/common.mk
+++ b/common.mk
@@ -31,12 +31,12 @@
 endif
 
 ifeq ($(call is-board-platform-in-list, msm8974 msm8226 msm8610 apq8084 \
-        mpq8092 msm_bronze), true)
+        mpq8092 msm_bronze msm8916), true)
     common_flags += -DVENUS_COLOR_FORMAT
     common_flags += -DMDSS_TARGET
 endif
 
-ifeq ($(call is-board-platform-in-list, mpq8092 msm_bronze), true)
+ifeq ($(call is-board-platform-in-list, mpq8092 msm_bronze msm8916), true)
     #XXX: Replace with check from MDP when available
     common_flags += -DVPU_TARGET
 endif
diff --git a/libgralloc/gralloc_priv.h b/libgralloc/gralloc_priv.h
index 29c5aa5..f6d244a 100644
--- a/libgralloc/gralloc_priv.h
+++ b/libgralloc/gralloc_priv.h
@@ -108,7 +108,8 @@
     HAL_PIXEL_FORMAT_BGRX_8888              = 0x112,
     HAL_PIXEL_FORMAT_NV21_ZSL               = 0x113,
     HAL_PIXEL_FORMAT_INTERLACE              = 0x180,
-
+    //v4l2_fourcc('Y', 'U', 'Y', 'L'). 24 bpp YUYV 4:2:2 10 bit per component
+    HAL_PIXEL_FORMAT_YCbCr_422_I_10BIT      = 0x4C595559,
 };
 
 /* possible formats for 3D content*/
diff --git a/libgralloc/ionalloc.cpp b/libgralloc/ionalloc.cpp
index fd3abbc..311fd8f 100644
--- a/libgralloc/ionalloc.cpp
+++ b/libgralloc/ionalloc.cpp
@@ -177,7 +177,7 @@
     struct ion_flush_data flush_data;
     struct ion_fd_data fd_data;
     struct ion_handle_data handle_data;
-    struct ion_handle* handle;
+    ion_user_handle_t handle;
     int err = 0;
 
     err = open_device();
diff --git a/libhwcomposer/Android.mk b/libhwcomposer/Android.mk
index 4ef4286..7b2092d 100644
--- a/libhwcomposer/Android.mk
+++ b/libhwcomposer/Android.mk
@@ -25,7 +25,7 @@
                                  hwc_dump_layers.cpp \
                                  hwc_ad.cpp
 
-ifeq ($(call is-board-platform-in-list, mpq8092 msm_bronze), true)
+ifeq ($(call is-board-platform-in-list, mpq8092 msm_bronze msm8916), true)
     LOCAL_SRC_FILES += hwc_vpuclient.cpp
 endif
 
diff --git a/libhwcomposer/hwc.cpp b/libhwcomposer/hwc.cpp
index a805486..eb999f7 100644
--- a/libhwcomposer/hwc.cpp
+++ b/libhwcomposer/hwc.cpp
@@ -179,21 +179,15 @@
                 const int fbZ = 0;
                 ctx->mFBUpdate[dpy]->prepare(ctx, list, fbZ);
             }
-
-            if(ctx->listStats[dpy].isDisplayAnimating) {
-                // Mark all app layers as HWC_OVERLAY for external during
-                // animation, so that SF doesnt draw it on FB
-                for(int i = 0 ;i < ctx->listStats[dpy].numAppLayers; i++) {
-                    hwc_layer_1_t *layer = &list->hwLayers[i];
-                    layer->compositionType = HWC_OVERLAY;
-                }
-            }
         } else {
-            // External Display is in Pause state.
-            // ToDo:
-            // Mark all application layers as OVERLAY so that
-            // GPU will not compose. This is done for power
-            // optimization
+            /* External Display is in Pause state.
+             * Mark all application layers as OVERLAY so that
+             * GPU will not compose.
+             */
+            for(size_t i = 0 ;i < (size_t)(list->numHwLayers - 1); i++) {
+                hwc_layer_1_t *layer = &list->hwLayers[i];
+                layer->compositionType = HWC_OVERLAY;
+            }
         }
     }
     return 0;
@@ -217,21 +211,15 @@
                 const int fbZ = 0;
                 ctx->mFBUpdate[dpy]->prepare(ctx, list, fbZ);
             }
-
-            if(ctx->listStats[dpy].isDisplayAnimating) {
-                // Mark all app layers as HWC_OVERLAY for virtual during
-                // animation, so that SF doesnt draw it on FB
-                for(int i = 0 ;i < ctx->listStats[dpy].numAppLayers; i++) {
-                    hwc_layer_1_t *layer = &list->hwLayers[i];
-                    layer->compositionType = HWC_OVERLAY;
-                }
-            }
         } else {
-            // Virtual Display is in Pause state.
-            // ToDo:
-            // Mark all application layers as OVERLAY so that
-            // GPU will not compose. This is done for power
-            // optimization
+            /* Virtual Display is in Pause state.
+             * Mark all application layers as OVERLAY so that
+             * GPU will not compose.
+             */
+            for(size_t i = 0 ;i < (size_t)(list->numHwLayers - 1); i++) {
+                hwc_layer_1_t *layer = &list->hwLayers[i];
+                layer->compositionType = HWC_OVERLAY;
+            }
         }
     }
     return 0;
@@ -303,8 +291,6 @@
             if(dpy == HWC_DISPLAY_PRIMARY) {
                 Locker::Autolock _l(ctx->mDrawLock);
                 // store the primary display orientation
-                // will be used in hwc_video::configure to disable
-                // rotation animation on external display
                 ctx->deviceOrientation = enable;
             }
             break;
@@ -500,7 +486,7 @@
         //TODO We dont check for SKIP flag on this layer because we need PAN
         //always. Last layer is always FB
         private_handle_t *hnd = (private_handle_t *)fbLayer->handle;
-        if(copybitDone) {
+        if(copybitDone && ctx->mMDP.version >= qdutils::MDP_V4_0) {
             hnd = ctx->mCopyBit[dpy]->getCurrentRenderBuffer();
         }
 
diff --git a/libhwcomposer/hwc_copybit.cpp b/libhwcomposer/hwc_copybit.cpp
index 4695a4f..47b9225 100644
--- a/libhwcomposer/hwc_copybit.cpp
+++ b/libhwcomposer/hwc_copybit.cpp
@@ -199,7 +199,8 @@
     }
 
     //Allocate render buffers if they're not allocated
-    if (useCopybitForYUV || useCopybitForRGB) {
+    if (ctx->mMDP.version != qdutils::MDP_V3_0_4 &&
+            (useCopybitForYUV || useCopybitForRGB)) {
         int ret = allocRenderBuffers(mAlignedFBWidth,
                                      mAlignedFBHeight,
                                      HAL_PIXEL_FORMAT_RGBA_8888);
@@ -223,7 +224,10 @@
         // Mark all layers to be drawn by copybit
         for (int i = ctx->listStats[dpy].numAppLayers-1; i >= 0 ; i--) {
             layerProp[i].mFlags |= HWC_COPYBIT;
-            list->hwLayers[i].compositionType = HWC_OVERLAY;
+            if (ctx->mMDP.version == qdutils::MDP_V3_0_4)
+                list->hwLayers[i].compositionType = HWC_BLIT;
+            else
+                list->hwLayers[i].compositionType = HWC_OVERLAY;
         }
     }
 
@@ -254,13 +258,20 @@
     // draw layers marked for COPYBIT
     int retVal = true;
     int copybitLayerCount = 0;
+    uint32_t last = 0;
     LayerProp *layerProp = ctx->layerProp[dpy];
+    private_handle_t *renderBuffer;
 
     if(mCopyBitDraw == false) // there is no layer marked for copybit
         return false ;
 
     //render buffer
-    private_handle_t *renderBuffer = getCurrentRenderBuffer();
+    if (ctx->mMDP.version == qdutils::MDP_V3_0_4) {
+        last = list->numHwLayers - 1;
+        renderBuffer = (private_handle_t *)list->hwLayers[last].handle;
+    } else {
+        renderBuffer = getCurrentRenderBuffer();
+    }
     if (!renderBuffer) {
         ALOGE("%s: Render buffer layer handle is NULL", __FUNCTION__);
         return false;
@@ -274,9 +285,9 @@
             mRelFd[mCurRenderBufferIndex] = -1;
         }
     } else {
-        if(mRelFd[mCurRenderBufferIndex] >=0) {
+        if(list->hwLayers[last].acquireFenceFd >=0) {
             copybit_device_t *copybit = getCopyBitDevice();
-            copybit->set_sync(copybit, mRelFd[mCurRenderBufferIndex]);
+            copybit->set_sync(copybit, list->hwLayers[last].acquireFenceFd);
         }
     }
 
@@ -316,10 +327,10 @@
         copybit_device_t *copybit = getCopyBitDevice();
         // Async mode
         copybit->flush_get_fence(copybit, fd);
-        if(mRelFd[mCurRenderBufferIndex] >=0 &&
-           ctx->mMDP.version == qdutils::MDP_V3_0_4) {
-            close(mRelFd[mCurRenderBufferIndex]);
-            mRelFd[mCurRenderBufferIndex] = -1;
+        if(ctx->mMDP.version == qdutils::MDP_V3_0_4 &&
+                list->hwLayers[last].acquireFenceFd >= 0) {
+            close(list->hwLayers[last].acquireFenceFd);
+            list->hwLayers[last].acquireFenceFd = -1;
         }
     }
     return true;
diff --git a/libhwcomposer/hwc_fbupdate.cpp b/libhwcomposer/hwc_fbupdate.cpp
index bb9adbf..d601f8f 100644
--- a/libhwcomposer/hwc_fbupdate.cpp
+++ b/libhwcomposer/hwc_fbupdate.cpp
@@ -78,13 +78,17 @@
     if(mDpy && (extOrient & HWC_TRANSFORM_ROT_90)) {
         mRot = ctx->mRotMgr->getNext();
         if(mRot == NULL) return false;
+        // Composed FB content will have black bars, if the viewFrame of the
+        // external is different from {0, 0, fbWidth, fbHeight}, so intersect
+        // viewFrame with sourceCrop to avoid those black bars
+        sourceCrop = getIntersection(sourceCrop, ctx->mViewFrame[mDpy]);
         //Configure rotator for pre-rotation
         if(configRotator(mRot, info, sourceCrop, mdpFlags, orient, 0) < 0) {
             ALOGE("%s: configRotator Failed!", __FUNCTION__);
             mRot = NULL;
             return false;
         }
-       ctx->mLayerRotMap[mDpy]->add(layer, mRot);
+        ctx->mLayerRotMap[mDpy]->add(layer, mRot);
         info.format = (mRot)->getDstFormat();
         updateSource(orient, info, sourceCrop);
         rotFlags |= ovutils::ROT_PREROTATED;
@@ -172,6 +176,8 @@
         }
         calcExtDisplayPosition(ctx, NULL, mDpy, sourceCrop, displayFrame,
                                    transform, orient);
+        //Store the displayFrame, will be used in getDisplayViewFrame
+        ctx->dpyAttr[mDpy].mDstRect = displayFrame;
         setMdpFlags(layer, mdpFlags, 0, transform);
         // For External use rotator if there is a rotation value set
         ret = preRotateExtDisplay(ctx, layer, info,
diff --git a/libhwcomposer/hwc_mdpcomp.cpp b/libhwcomposer/hwc_mdpcomp.cpp
index baef9d2..8048d71 100644
--- a/libhwcomposer/hwc_mdpcomp.cpp
+++ b/libhwcomposer/hwc_mdpcomp.cpp
@@ -157,10 +157,11 @@
     return true;
 }
 
-void MDPComp::reset(const int& numLayers, hwc_display_contents_1_t* list) {
+void MDPComp::reset(hwc_context_t *ctx) {
+    const int numLayers = ctx->listStats[mDpy].numAppLayers;
     mCurrentFrame.reset(numLayers);
-    mCachedFrame.cacheAll(list);
-    mCachedFrame.updateCounts(mCurrentFrame);
+    ctx->mOverlay->clear(mDpy);
+    ctx->mLayerRotMap[mDpy]->clear();
 }
 
 void MDPComp::timeout_handler(void *udata) {
@@ -200,6 +201,16 @@
     }
 }
 
+void MDPComp::setRedraw(hwc_context_t *ctx,
+        hwc_display_contents_1_t* list) {
+    mCurrentFrame.needsRedraw = false;
+    if(!mCachedFrame.isSameFrame(mCurrentFrame, list) ||
+            (list->flags & HWC_GEOMETRY_CHANGED) ||
+            isSkipPresent(ctx, mDpy)) {
+        mCurrentFrame.needsRedraw = true;
+    }
+}
+
 MDPComp::FrameInfo::FrameInfo() {
     reset(0);
 }
@@ -513,7 +524,7 @@
 
 /* Checks for conditions where all the layers marked for MDP comp cannot be
  * bypassed. On such conditions we try to bypass atleast YUV layers */
-bool MDPComp::isFullFrameDoable(hwc_context_t *ctx,
+bool MDPComp::tryFullFrame(hwc_context_t *ctx,
                                 hwc_display_contents_1_t* list){
 
     const int numAppLayers = ctx->listStats[mDpy].numAppLayers;
@@ -563,11 +574,6 @@
         ret = true;
     }
 
-    if(!hwLimitationsCheck(ctx, list)) {
-        ALOGD_IF(isDebug(), "%s: HW limitations",__FUNCTION__);
-        return false;
-    }
-
     return ret;
 }
 
@@ -596,6 +602,7 @@
                                 qhwc::needsScaling(layer))
             return false;
     }
+
     mCurrentFrame.fbCount = 0;
     mCurrentFrame.fbZ = -1;
     memcpy(&mCurrentFrame.isFBComposed, &mCurrentFrame.drop,
@@ -607,8 +614,9 @@
         adjustForSourceSplit(ctx, list);
     }
 
-    if(!resourceCheck(ctx, list)) {
-        ALOGD_IF(isDebug(), "%s: resource check failed", __FUNCTION__);
+    if(!postHeuristicsHandling(ctx, list)) {
+        ALOGD_IF(isDebug(), "post heuristic handling failed");
+        reset(ctx);
         return false;
     }
 
@@ -623,15 +631,16 @@
     }
 
     bool ret = false;
-    if(isLoadBasedCompDoable(ctx, list)) {
-        ret = loadBasedCompPreferGPU(ctx, list) ||
+    if(list->flags & HWC_GEOMETRY_CHANGED) { //Try load based first
+        ret =   loadBasedCompPreferGPU(ctx, list) or
+                loadBasedCompPreferMDP(ctx, list) or
+                cacheBasedComp(ctx, list);
+    } else {
+        ret =   cacheBasedComp(ctx, list) or
+                loadBasedCompPreferGPU(ctx, list) or
                 loadBasedCompPreferMDP(ctx, list);
     }
 
-    if(!ret) {
-        ret = cacheBasedComp(ctx, list);
-    }
-
     return ret;
 }
 
@@ -648,6 +657,7 @@
             if(not isSupportedForMDPComp(ctx, layer)) {
                 ALOGD_IF(isDebug(), "%s: Unsupported layer in list",
                         __FUNCTION__);
+                reset(ctx);
                 return false;
             }
         }
@@ -657,6 +667,7 @@
     bool ret = markLayersForCaching(ctx, list); //sets up fbZ also
     if(!ret) {
         ALOGD_IF(isDebug(),"%s: batching failed, dpy %d",__FUNCTION__, mDpy);
+        reset(ctx);
         return false;
     }
 
@@ -670,11 +681,13 @@
     if((mDpy > HWC_DISPLAY_PRIMARY) and
             (mdpCount > MAX_SEC_LAYERS)) {
         ALOGD_IF(isDebug(), "%s: Exceeds max secondary pipes",__FUNCTION__);
+        reset(ctx);
         return false;
     }
 
-    if(!resourceCheck(ctx, list)) {
-        ALOGD_IF(isDebug(), "%s: resource check failed", __FUNCTION__);
+    if(!postHeuristicsHandling(ctx, list)) {
+        ALOGD_IF(isDebug(), "post heuristic handling failed");
+        reset(ctx);
         return false;
     }
 
@@ -683,6 +696,10 @@
 
 bool MDPComp::loadBasedCompPreferGPU(hwc_context_t *ctx,
         hwc_display_contents_1_t* list) {
+    if(not isLoadBasedCompDoable(ctx, list)) {
+        return false;
+    }
+
     int numAppLayers = ctx->listStats[mDpy].numAppLayers;
     mCurrentFrame.reset(numAppLayers);
 
@@ -726,6 +743,7 @@
             if(not isSupportedForMDPComp(ctx, layer)) {
                 ALOGD_IF(isDebug(), "%s: MDP unsupported layer found at %d",
                         __FUNCTION__, i);
+                reset(ctx);
                 return false;
             }
             mCurrentFrame.isFBComposed[i] = false;
@@ -736,24 +754,31 @@
     mCurrentFrame.fbCount = batchSize;
     mCurrentFrame.mdpCount = mCurrentFrame.layerCount - batchSize;
 
+    ALOGD_IF(isDebug(), "%s: fbZ %d batchSize %d",
+                __FUNCTION__, mCurrentFrame.fbZ, batchSize);
+
     if(sEnable4k2kYUVSplit){
         adjustForSourceSplit(ctx, list);
     }
 
-    if(!resourceCheck(ctx, list)) {
-        ALOGD_IF(isDebug(), "%s: resource check failed", __FUNCTION__);
+    if(!postHeuristicsHandling(ctx, list)) {
+        ALOGD_IF(isDebug(), "post heuristic handling failed");
+        reset(ctx);
         return false;
     }
 
-    ALOGD_IF(isDebug(), "%s: fbZ %d batchSize %d",
-                __FUNCTION__, mCurrentFrame.fbZ, batchSize);
     return true;
 }
 
 bool MDPComp::loadBasedCompPreferMDP(hwc_context_t *ctx,
         hwc_display_contents_1_t* list) {
+    if(not isLoadBasedCompDoable(ctx, list)) {
+        return false;
+    }
+
     const int numAppLayers = ctx->listStats[mDpy].numAppLayers;
-    //TODO get the ib from sysfs node.
+    mCurrentFrame.reset(numAppLayers);
+
     //Full screen is from ib perspective, not actual full screen
     const int bpp = 4;
     double panelRefRate =
@@ -782,6 +807,7 @@
         if(not isSupportedForMDPComp(ctx, layer)) {
             ALOGD_IF(isDebug(), "%s: MDP unsupported layer found at %d",
                     __FUNCTION__, i);
+            reset(ctx);
             return false;
         }
         mCurrentFrame.isFBComposed[i] = false;
@@ -791,32 +817,39 @@
     mCurrentFrame.fbCount = fbBatchSize;
     mCurrentFrame.mdpCount = mCurrentFrame.layerCount - fbBatchSize;
 
+    ALOGD_IF(isDebug(), "%s: FB Z %d, num app layers %d, MDP Batch Size %d",
+                __FUNCTION__, mCurrentFrame.fbZ, numAppLayers,
+                numAppLayers - fbBatchSize);
+
     if(sEnable4k2kYUVSplit){
         adjustForSourceSplit(ctx, list);
     }
 
-    if(!resourceCheck(ctx, list)) {
-        ALOGD_IF(isDebug(), "%s: resource check failed", __FUNCTION__);
+    if(!postHeuristicsHandling(ctx, list)) {
+        ALOGD_IF(isDebug(), "post heuristic handling failed");
+        reset(ctx);
         return false;
     }
 
-    ALOGD_IF(isDebug(), "%s: FB Z %d, num app layers %d, MDP Batch Size %d",
-                __FUNCTION__, mCurrentFrame.fbZ, numAppLayers,
-                numAppLayers - fbBatchSize);
-
     return true;
 }
 
 bool MDPComp::isLoadBasedCompDoable(hwc_context_t *ctx,
         hwc_display_contents_1_t* list) {
-    if(mDpy or isSecurePresent(ctx, mDpy) or
-            not (list->flags & HWC_GEOMETRY_CHANGED)) {
+    if(mDpy or isSecurePresent(ctx, mDpy)) {
         return false;
     }
     return true;
 }
 
-bool MDPComp::isOnlyVideoDoable(hwc_context_t *ctx,
+bool MDPComp::tryVideoOnly(hwc_context_t *ctx,
+        hwc_display_contents_1_t* list) {
+    const bool secureOnly = true;
+    return videoOnlyComp(ctx, list, not secureOnly) or
+            videoOnlyComp(ctx, list, secureOnly);
+}
+
+bool MDPComp::videoOnlyComp(hwc_context_t *ctx,
         hwc_display_contents_1_t* list, bool secureOnly) {
     int numAppLayers = ctx->listStats[mDpy].numAppLayers;
 
@@ -824,21 +857,28 @@
     updateYUV(ctx, list, secureOnly);
     int mdpCount = mCurrentFrame.mdpCount;
 
-    if(!isYuvPresent(ctx, mDpy)) {
+    if(!isYuvPresent(ctx, mDpy) or (mdpCount == 0)) {
+        reset(ctx);
         return false;
     }
 
     /* Bail out if we are processing only secured video layers
      * and we dont have any */
     if(!isSecurePresent(ctx, mDpy) && secureOnly){
+        reset(ctx);
         return false;
     }
 
-    if(!mdpCount)
-        return false;
+    if(mCurrentFrame.fbCount)
+        mCurrentFrame.fbZ = mCurrentFrame.mdpCount;
 
-    if(!resourceCheck(ctx, list)) {
-        ALOGD_IF(isDebug(), "%s: resource check failed", __FUNCTION__);
+    if(sEnable4k2kYUVSplit){
+        adjustForSourceSplit(ctx, list);
+    }
+
+    if(!postHeuristicsHandling(ctx, list)) {
+        ALOGD_IF(isDebug(), "post heuristic handling failed");
+        reset(ctx);
         return false;
     }
 
@@ -847,9 +887,7 @@
 
 /* Checks for conditions where YUV layers cannot be bypassed */
 bool MDPComp::isYUVDoable(hwc_context_t* ctx, hwc_layer_1_t* layer) {
-    bool extAnimBlockFeature = mDpy && ctx->listStats[mDpy].isDisplayAnimating;
-
-    if(isSkipLayer(layer) && !extAnimBlockFeature) {
+    if(isSkipLayer(layer)) {
         ALOGD_IF(isDebug(), "%s: Video marked SKIP dpy %d", __FUNCTION__, mDpy);
         return false;
     }
@@ -1069,15 +1107,6 @@
 void MDPComp::updateYUV(hwc_context_t* ctx, hwc_display_contents_1_t* list,
         bool secureOnly) {
     int nYuvCount = ctx->listStats[mDpy].yuvCount;
-    if(!nYuvCount && mDpy) {
-        //Reset "No animation on external display" related  parameters.
-        ctx->mPrevCropVideo.left = ctx->mPrevCropVideo.top =
-            ctx->mPrevCropVideo.right = ctx->mPrevCropVideo.bottom = 0;
-        ctx->mPrevDestVideo.left = ctx->mPrevDestVideo.top =
-            ctx->mPrevDestVideo.right = ctx->mPrevDestVideo.bottom = 0;
-        ctx->mPrevTransformVideo = 0;
-        return;
-     }
     for(int index = 0;index < nYuvCount; index++){
         int nYuvIndex = ctx->listStats[mDpy].yuvIndices[index];
         hwc_layer_1_t* layer = &list->hwLayers[nYuvIndex];
@@ -1104,7 +1133,21 @@
              mCurrentFrame.fbCount);
 }
 
-bool MDPComp::programMDP(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
+bool MDPComp::postHeuristicsHandling(hwc_context_t *ctx,
+        hwc_display_contents_1_t* list) {
+
+    //Capability checks
+    if(!resourceCheck(ctx, list)) {
+        ALOGD_IF(isDebug(), "%s: resource check failed", __FUNCTION__);
+        return false;
+    }
+
+    //Limitations checks
+    if(!hwLimitationsCheck(ctx, list)) {
+        ALOGD_IF(isDebug(), "%s: HW limitations",__FUNCTION__);
+        return false;
+    }
+
     //Configure framebuffer first if applicable
     if(mCurrentFrame.fbZ >= 0) {
         if(!ctx->mFBUpdate[mDpy]->prepare(ctx, list, mCurrentFrame.fbZ)) {
@@ -1114,6 +1157,8 @@
         }
     }
 
+    mCurrentFrame.map();
+
     if(!allocLayerPipes(ctx, list)) {
         ALOGD_IF(isDebug(), "%s: Unable to allocate MDP pipes", __FUNCTION__);
         return false;
@@ -1154,6 +1199,7 @@
         }
     }
 
+    setRedraw(ctx, list);
     return true;
 }
 
@@ -1278,100 +1324,71 @@
     const int numLayers = ctx->listStats[mDpy].numAppLayers;
     MDPVersion& mdpVersion = qdutils::MDPVersion::getInstance();
 
+    //number of app layers exceeds MAX_NUM_APP_LAYERS fall back to GPU
+    //do not cache the information for next draw cycle.
+    if(numLayers > MAX_NUM_APP_LAYERS) {
+        ALOGI("%s: Number of App layers exceeded the limit ",
+        __FUNCTION__);
+        mCachedFrame.reset();
+        return -1;
+    }
+
     //reset old data
     mCurrentFrame.reset(numLayers);
     memset(&mCurrentFrame.drop, 0, sizeof(mCurrentFrame.drop));
     mCurrentFrame.dropCount = 0;
 
-    //number of app layers exceeds MAX_NUM_APP_LAYERS fall back to GPU
-    //do not cache the information for next draw cycle.
-    if(numLayers > MAX_NUM_APP_LAYERS) {
+    // Detect the start of animation and fall back to GPU only once to cache
+    // all the layers in FB and display FB content untill animation completes.
+    if(ctx->listStats[mDpy].isDisplayAnimating) {
+        mCurrentFrame.needsRedraw = false;
+        if(ctx->mAnimationState[mDpy] == ANIMATION_STOPPED) {
+            mCurrentFrame.needsRedraw = true;
+            ctx->mAnimationState[mDpy] = ANIMATION_STARTED;
+        }
+        setMDPCompLayerFlags(ctx, list);
         mCachedFrame.updateCounts(mCurrentFrame);
-        ALOGI("%s: Number of App layers exceeded the limit ",
-        __FUNCTION__);
         ret = -1;
         return ret;
+    } else {
+        ctx->mAnimationState[mDpy] = ANIMATION_STOPPED;
     }
 
     //Hard conditions, if not met, cannot do MDP comp
-    if(!isFrameDoable(ctx)) {
-        ALOGD_IF( isDebug(),"%s: MDP Comp not possible for this frame",
-                __FUNCTION__);
-        reset(numLayers, list);
-        ret = -1;
-        goto exit;
-    }
+    if(isFrameDoable(ctx)) {
+        generateROI(ctx, list);
 
-    generateROI(ctx, list);
-
-    //Convert from kbps to gbps
-    sMaxBw = mdpVersion.getHighBw() / 1000000.0;
-    if (ctx->mExtDisplay->isConnected() || ctx->mMDP.panel != MIPI_CMD_PANEL) {
-        sMaxBw = mdpVersion.getLowBw() / 1000000.0;
-    }
-
-    //Check whether layers marked for MDP Composition is actually doable.
-    if(isFullFrameDoable(ctx, list)) {
-        mCurrentFrame.map();
-        //Acquire and Program MDP pipes
-        if(!programMDP(ctx, list)) {
-            reset(numLayers, list);
-            ctx->mOverlay->clear(mDpy);
-            ret = -1;
-            goto exit;
-        } else { //Success
-            //Any change in composition types needs an FB refresh
-            mCurrentFrame.needsRedraw = false;
-            if(!mCachedFrame.isSameFrame(mCurrentFrame, list) ||
-                     (list->flags & HWC_GEOMETRY_CHANGED) ||
-                     isSkipPresent(ctx, mDpy)) {
-                mCurrentFrame.needsRedraw = true;
-            }
-        }
-    } else if(isOnlyVideoDoable(ctx, list, false /*secure only*/) ||
-            isOnlyVideoDoable(ctx, list, true /*secure only*/)) {
-        //All layers marked for MDP comp cannot be bypassed.
-        //Try to compose atleast YUV layers through MDP comp and let
-        //all the RGB layers compose in FB
-        //Destination over
-
-        mCurrentFrame.fbZ = -1;
-        if(mCurrentFrame.fbCount)
-            mCurrentFrame.fbZ = mCurrentFrame.mdpCount;
-
-        if(sEnable4k2kYUVSplit){
-            adjustForSourceSplit(ctx, list);
+        //Convert from kbps to gbps
+        sMaxBw = mdpVersion.getHighBw() / 1000000.0;
+        if (ctx->mExtDisplay->isConnected() ||
+                    ctx->mMDP.panel != MIPI_CMD_PANEL) {
+            sMaxBw = mdpVersion.getLowBw() / 1000000.0;
         }
 
-        mCurrentFrame.map();
-
-        if(!programMDP(ctx, list)) {
-            reset(numLayers, list);
-            ctx->mOverlay->clear(mDpy);
+        if(tryFullFrame(ctx, list) || tryVideoOnly(ctx, list)) {
+            setMDPCompLayerFlags(ctx, list);
+        } else {
+            reset(ctx);
+            memset(&mCurrentFrame.drop, 0, sizeof(mCurrentFrame.drop));
+            mCurrentFrame.dropCount = 0;
             ret = -1;
-            goto exit;
         }
     } else {
-        reset(numLayers, list);
-        memset(&mCurrentFrame.drop, 0, sizeof(mCurrentFrame.drop));
-        mCurrentFrame.dropCount = 0;
+        ALOGD_IF( isDebug(),"%s: MDP Comp not possible for this frame",
+                __FUNCTION__);
         ret = -1;
-        goto exit;
     }
-    //UpdateLayerFlags
-    setMDPCompLayerFlags(ctx, list);
-    mCachedFrame.cacheAll(list);
-    mCachedFrame.updateCounts(mCurrentFrame);
 
-    // unlock it before calling dump function to avoid deadlock
     if(isDebug()) {
-        ALOGD("GEOMETRY change: %d", (list->flags & HWC_GEOMETRY_CHANGED));
+        ALOGD("GEOMETRY change: %d",
+                (list->flags & HWC_GEOMETRY_CHANGED));
         android::String8 sDump("");
         dump(sDump);
-        ALOGE("%s",sDump.string());
+        ALOGD("%s",sDump.string());
     }
 
-exit:
+    mCachedFrame.cacheAll(list);
+    mCachedFrame.updateCounts(mCurrentFrame);
     double panelRefRate =
             1000000000.0 / ctx->dpyAttr[mDpy].vsync_period;
     sBwClaimed += calcMDPBytesRead(ctx, list) * panelRefRate;
diff --git a/libhwcomposer/hwc_mdpcomp.h b/libhwcomposer/hwc_mdpcomp.h
index 7e52679..05a560b 100644
--- a/libhwcomposer/hwc_mdpcomp.h
+++ b/libhwcomposer/hwc_mdpcomp.h
@@ -149,10 +149,12 @@
     /* 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 */
     bool isFrameDoable(hwc_context_t *ctx);
     /* checks for conditions where RGB layers cannot be bypassed */
-    bool isFullFrameDoable(hwc_context_t *ctx, hwc_display_contents_1_t* list);
+    bool tryFullFrame(hwc_context_t *ctx, hwc_display_contents_1_t* list);
     /* checks if full MDP comp can be done */
     bool fullMDPComp(hwc_context_t *ctx, hwc_display_contents_1_t* list);
     /* check if we can use layer cache to do at least partial MDP comp */
@@ -173,7 +175,8 @@
     bool isLoadBasedCompDoable(hwc_context_t *ctx,
             hwc_display_contents_1_t* list);
     /* checks for conditions where only video can be bypassed */
-    bool isOnlyVideoDoable(hwc_context_t *ctx, hwc_display_contents_1_t* list,
+    bool tryVideoOnly(hwc_context_t *ctx, hwc_display_contents_1_t* list);
+    bool videoOnlyComp(hwc_context_t *ctx, hwc_display_contents_1_t* list,
             bool secureOnly);
     /* checks for conditions where YUV layers cannot be bypassed */
     bool isYUVDoable(hwc_context_t* ctx, hwc_layer_1_t* layer);
@@ -212,8 +215,16 @@
         /* updates cache map with YUV info */
     void updateYUV(hwc_context_t* ctx, hwc_display_contents_1_t* list,
             bool secureOnly);
-    bool programMDP(hwc_context_t *ctx, hwc_display_contents_1_t* list);
-    void reset(const int& numAppLayers, hwc_display_contents_1_t* list);
+    /* Validates if the GPU/MDP layer split chosen by a strategy is supported
+     * by MDP.
+     * Sets up MDP comp data structures to reflect covnversion from layers to
+     * overlay pipes.
+     * Configures overlay.
+     * Configures if GPU should redraw.
+     */
+    bool postHeuristicsHandling(hwc_context_t *ctx,
+            hwc_display_contents_1_t* list);
+    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);
 
diff --git a/libhwcomposer/hwc_qclient.cpp b/libhwcomposer/hwc_qclient.cpp
index a3f6b5b..50e94c9 100644
--- a/libhwcomposer/hwc_qclient.cpp
+++ b/libhwcomposer/hwc_qclient.cpp
@@ -140,8 +140,34 @@
     ctx->mBufferMirrorMode = enable;
 }
 
+static status_t getDisplayVisibleRegion(hwc_context_t* ctx, int dpy,
+                                Parcel* outParcel) {
+    // Get the info only if the dpy is valid
+    if(dpy >= HWC_DISPLAY_PRIMARY && dpy <= HWC_DISPLAY_VIRTUAL) {
+        Locker::Autolock _sl(ctx->mDrawLock);
+        if(dpy && (ctx->mExtOrientation || ctx->mBufferMirrorMode)) {
+            // Return the destRect on external, if external orienation
+            // is enabled
+            outParcel->writeInt32(ctx->dpyAttr[dpy].mDstRect.left);
+            outParcel->writeInt32(ctx->dpyAttr[dpy].mDstRect.top);
+            outParcel->writeInt32(ctx->dpyAttr[dpy].mDstRect.right);
+            outParcel->writeInt32(ctx->dpyAttr[dpy].mDstRect.bottom);
+        } else {
+            outParcel->writeInt32(ctx->mViewFrame[dpy].left);
+            outParcel->writeInt32(ctx->mViewFrame[dpy].top);
+            outParcel->writeInt32(ctx->mViewFrame[dpy].right);
+            outParcel->writeInt32(ctx->mViewFrame[dpy].bottom);
+        }
+        return NO_ERROR;
+    } else {
+        ALOGE("In %s: invalid dpy index %d", __FUNCTION__, dpy);
+        return BAD_VALUE;
+    }
+}
+
 status_t QClient::notifyCallback(uint32_t command, const Parcel* inParcel,
         Parcel* outParcel) {
+    status_t ret = NO_ERROR;
 
     if (command > IQService::VPU_COMMAND_LIST_START &&
         command < IQService::VPU_COMMAND_LIST_END) {
@@ -164,6 +190,10 @@
         case IQService::BUFFER_MIRRORMODE:
             setBufferMirrorMode(mHwcContext, inParcel->readInt32());
             break;
+        case IQService::GET_DISPLAY_VISIBLE_REGION:
+            ret = getDisplayVisibleRegion(mHwcContext, inParcel->readInt32(),
+                                    outParcel);
+            break;
         case IQService::CHECK_EXTERNAL_STATUS:
             isExternalConnected(mHwcContext, outParcel);
             break;
@@ -174,9 +204,9 @@
             setHSIC(mHwcContext, inParcel);
             break;
         default:
-            return NO_ERROR;
+            ret = NO_ERROR;
     }
-    return NO_ERROR;
+    return ret;
 }
 
 
diff --git a/libhwcomposer/hwc_utils.cpp b/libhwcomposer/hwc_utils.cpp
index e632843..57a7554 100644
--- a/libhwcomposer/hwc_utils.cpp
+++ b/libhwcomposer/hwc_utils.cpp
@@ -134,7 +134,7 @@
     ctx->mMDP.panel = qdutils::MDPVersion::getInstance().getPanelType();
     overlay::Overlay::initOverlay();
     ctx->mOverlay = overlay::Overlay::getInstance();
-    ctx->mRotMgr = new RotMgr();
+    ctx->mRotMgr = RotMgr::getInstance();
 
     //Is created and destroyed only once for primary
     //For external it could get created and destroyed multiple times depending
@@ -172,6 +172,7 @@
     for (uint32_t i = 0; i < HWC_NUM_DISPLAY_TYPES; i++) {
         ctx->mHwcDebug[i] = new HwcDebug(i);
         ctx->mLayerRotMap[i] = new LayerRotMap();
+        ctx->mAnimationState[i] = ANIMATION_STOPPED;
     }
 
     MDPComp::init(ctx);
@@ -189,13 +190,8 @@
             defaultServiceManager()->getService(
             String16("display.qservice")))->connect(client);
 
-    // Initialize "No animation on external display" related  parameters.
+    // Initialize device orientation to its default orientation
     ctx->deviceOrientation = 0;
-    ctx->mPrevCropVideo.left = ctx->mPrevCropVideo.top =
-        ctx->mPrevCropVideo.right = ctx->mPrevCropVideo.bottom = 0;
-    ctx->mPrevDestVideo.left = ctx->mPrevDestVideo.top =
-        ctx->mPrevDestVideo.right = ctx->mPrevDestVideo.bottom = 0;
-    ctx->mPrevTransformVideo = 0;
     ctx->mBufferMirrorMode = false;
 #ifdef VPU_TARGET
     ctx->mVPUClient = new VPUClient();
@@ -390,6 +386,7 @@
 // based on the position and aspect ratio with orientation
 void getAspectRatioPosition(hwc_context_t* ctx, int dpy, int extOrientation,
                             hwc_rect_t& inRect, hwc_rect_t& outRect) {
+    hwc_rect_t viewFrame = ctx->mViewFrame[dpy];
     // Physical display resolution
     float fbWidth  = ctx->dpyAttr[dpy].xres;
     float fbHeight = ctx->dpyAttr[dpy].yres;
@@ -427,14 +424,20 @@
         yPos = rect.top;
         width = rect.right - rect.left;
         height = rect.bottom - rect.top;
+        // swap viewframe coordinates for 90 degree rotation.
+        swap(viewFrame.left, viewFrame.top);
+        swap(viewFrame.right, viewFrame.bottom);
     }
+    // if viewframe left and top coordinates are non zero value then exclude it
+    // during the computation of xRatio and yRatio
+    xRatio = (inPos.x - viewFrame.left)/actualWidth;
+    yRatio = (inPos.y - viewFrame.top)/actualHeight;
+    // Use viewframe width and height to compute wRatio and hRatio.
+    wRatio = inPos.w/(viewFrame.right - viewFrame.left);
+    hRatio = inPos.h/(viewFrame.bottom - viewFrame.top);
+
 
     //Calculate the position...
-    xRatio = inPos.x/actualWidth;
-    yRatio = inPos.y/actualHeight;
-    wRatio = inPos.w/actualWidth;
-    hRatio = inPos.h/actualHeight;
-
     outPos.x = (xRatio * width) + xPos;
     outPos.y = (yRatio * height) + yPos;
     outPos.w = wRatio * width;
@@ -657,11 +660,13 @@
     cropL = sourceCrop;
     dstL = displayFrame;
     hwc_rect_t scissorL = { 0, 0, lSplit, hw_h };
+    scissorL = getIntersection(ctx->mViewFrame[dpy], scissorL);
     qhwc::calculate_crop_rects(cropL, dstL, scissorL, 0);
 
     cropR = sourceCrop;
     dstR = displayFrame;
     hwc_rect_t scissorR = { lSplit, 0, hw_w, hw_h };
+    scissorR = getIntersection(ctx->mViewFrame[dpy], scissorR);
     qhwc::calculate_crop_rects(cropR, dstR, scissorR, 0);
 
     // Sanitize Crop to stitch
@@ -719,6 +724,7 @@
     if(dst.left < 0 || dst.top < 0 ||
             dst.right > hw_w || dst.bottom > hw_h) {
         hwc_rect_t scissor = {0, 0, hw_w, hw_h };
+        scissor = getIntersection(ctx->mViewFrame[dpy], scissor);
         qhwc::calculate_crop_rects(crop, dst, scissor, transform);
     }
 }
@@ -1182,7 +1188,8 @@
 
     //Accumulate acquireFenceFds for MDP
     for(uint32_t i = 0; i < list->numHwLayers; i++) {
-        if(list->hwLayers[i].compositionType == HWC_OVERLAY &&
+        if((list->hwLayers[i].compositionType == HWC_OVERLAY  ||
+                        list->hwLayers[i].compositionType == HWC_BLIT) &&
                         list->hwLayers[i].acquireFenceFd >= 0) {
             if(UNLIKELY(swapzero))
                 acquireFd[count++] = -1;
@@ -1224,6 +1231,7 @@
 
     for(uint32_t i = 0; i < list->numHwLayers; i++) {
         if(list->hwLayers[i].compositionType == HWC_OVERLAY ||
+           list->hwLayers[i].compositionType == HWC_BLIT ||
            list->hwLayers[i].compositionType == HWC_FRAMEBUFFER_TARGET) {
             //Populate releaseFenceFds.
             if(UNLIKELY(swapzero)) {
@@ -1231,12 +1239,7 @@
             } else if(isExtAnimating) {
                 // Release all the app layer fds immediately,
                 // if animation is in progress.
-                hwc_layer_1_t const* layer = &list->hwLayers[i];
-                private_handle_t *hnd = (private_handle_t *)layer->handle;
-                if(isYuvBuffer(hnd)) {
-                    list->hwLayers[i].releaseFenceFd = dup(releaseFd);
-                } else
-                    list->hwLayers[i].releaseFenceFd = -1;
+                list->hwLayers[i].releaseFenceFd = -1;
             } else if(list->hwLayers[i].releaseFenceFd < 0) {
                 //If rotator has not already populated this field.
                 list->hwLayers[i].releaseFenceFd = dup(releaseFd);
@@ -1483,29 +1486,7 @@
             whf.format = getMdpFormat(HAL_PIXEL_FORMAT_BGRX_8888);
     }
 
-    if(dpy && isYuvBuffer(hnd)) {
-        if(!ctx->listStats[dpy].isDisplayAnimating) {
-            ctx->mPrevCropVideo = crop;
-            ctx->mPrevDestVideo = dst;
-            ctx->mPrevTransformVideo = transform;
-        } else {
-            // Restore the previous crop, dest rect and transform values, during
-            // animation to avoid displaying videos at random coordinates.
-            crop = ctx->mPrevCropVideo;
-            dst = ctx->mPrevDestVideo;
-            transform = ctx->mPrevTransformVideo;
-            orient = static_cast<eTransform>(transform);
-            //In you tube use case when a device rotated from landscape to
-            // portrait, set the isFg flag and zOrder to avoid displaying UI on
-            // hdmi during animation
-            if(ctx->deviceOrientation) {
-                isFg = ovutils::IS_FG_SET;
-                z = ZORDER_1;
-            }
-        }
-        calcExtDisplayPosition(ctx, hnd, dpy, crop, dst,
-                                           transform, orient);
-    }
+    calcExtDisplayPosition(ctx, hnd, dpy, crop, dst, transform, orient);
 
     if(isYuvBuffer(hnd) && ctx->mMDP.version >= qdutils::MDP_V4_2 &&
        ctx->mMDP.version < qdutils::MDSS_V5) {
@@ -1530,8 +1511,6 @@
         //Configure rotator for pre-rotation
         if(configRotator(*rot, whf, crop, mdpFlags, orient, downscale) < 0) {
             ALOGE("%s: configRotator failed!", __FUNCTION__);
-            ctx->mOverlay->clear(dpy);
-            ctx->mLayerRotMap[dpy]->clear();
             return -1;
         }
         ctx->mLayerRotMap[dpy]->add(layer, *rot);
@@ -1549,7 +1528,6 @@
 
     if(configMdp(ctx->mOverlay, parg, orient, crop, dst, metadata, dest) < 0) {
         ALOGE("%s: commit failed for low res panel", __FUNCTION__);
-        ctx->mLayerRotMap[dpy]->clear();
         return -1;
     }
     return 0;
@@ -1616,28 +1594,6 @@
             whf.format = getMdpFormat(HAL_PIXEL_FORMAT_BGRX_8888);
     }
 
-    if(dpy && isYuvBuffer(hnd)) {
-        if(!ctx->listStats[dpy].isDisplayAnimating) {
-            ctx->mPrevCropVideo = crop;
-            ctx->mPrevDestVideo = dst;
-            ctx->mPrevTransformVideo = transform;
-        } else {
-            // Restore the previous crop, dest rect and transform values, during
-            // animation to avoid displaying videos at random coordinates.
-            crop = ctx->mPrevCropVideo;
-            dst = ctx->mPrevDestVideo;
-            transform = ctx->mPrevTransformVideo;
-            orient = static_cast<eTransform>(transform);
-            //In you tube use case when a device rotated from landscape to
-            // portrait, set the isFg flag and zOrder to avoid displaying UI on
-            // hdmi during animation
-            if(ctx->deviceOrientation) {
-                isFg = ovutils::IS_FG_SET;
-                z = ZORDER_1;
-            }
-        }
-    }
-
     setMdpFlags(layer, mdpFlagsL, 0, transform);
 
     if(lDest != OV_INVALID && rDest != OV_INVALID) {
@@ -1658,8 +1614,6 @@
         //Configure rotator for pre-rotation
         if(configRotator(*rot, whf, crop, mdpFlagsL, orient, downscale) < 0) {
             ALOGE("%s: configRotator failed!", __FUNCTION__);
-            ctx->mOverlay->clear(dpy);
-            ctx->mLayerRotMap[dpy]->clear();
             return -1;
         }
         ctx->mLayerRotMap[dpy]->add(layer, *rot);
@@ -1680,12 +1634,14 @@
         tmp_cropL = crop;
         tmp_dstL = dst;
         hwc_rect_t scissor = {0, 0, lSplit, hw_h };
+        scissor = getIntersection(ctx->mViewFrame[dpy], scissor);
         qhwc::calculate_crop_rects(tmp_cropL, tmp_dstL, scissor, 0);
     }
     if(rDest != OV_INVALID) {
         tmp_cropR = crop;
         tmp_dstR = dst;
         hwc_rect_t scissor = {lSplit, 0, hw_w, hw_h };
+        scissor = getIntersection(ctx->mViewFrame[dpy], scissor);
         qhwc::calculate_crop_rects(tmp_cropR, tmp_dstR, scissor, 0);
     }
 
@@ -1725,7 +1681,6 @@
         if(configMdp(ctx->mOverlay, pargL, orient,
                 tmp_cropL, tmp_dstL, metadata, lDest) < 0) {
             ALOGE("%s: commit failed for left mixer config", __FUNCTION__);
-            ctx->mLayerRotMap[dpy]->clear();
             return -1;
         }
     }
@@ -1741,7 +1696,6 @@
         if(configMdp(ctx->mOverlay, pargR, orient,
                 tmp_cropR, tmp_dstR, metadata, rDest) < 0) {
             ALOGE("%s: commit failed for right mixer config", __FUNCTION__);
-            ctx->mLayerRotMap[dpy]->clear();
             return -1;
         }
     }
@@ -1788,7 +1742,6 @@
         //Configure rotator for pre-rotation
         if(configRotator(*rot, whf, crop, mdpFlagsL, orient, downscale) < 0) {
             ALOGE("%s: configRotator failed!", __FUNCTION__);
-            ctx->mOverlay->clear(dpy);
             return -1;
         }
         ctx->mLayerRotMap[dpy]->add(layer, *rot);
@@ -1967,17 +1920,7 @@
 }
 
 void LayerRotMap::clear() {
-    for (uint32_t i = 0; i < mCount; i++) {
-        //mCount represents rotator objects for just this display.
-        //We could have popped mCount topmost objects from mRotMgr, but if each
-        //round has the same failure, typical of stability runs, it would lead
-        //to unnecessary memory allocation, deallocation each time. So we let
-        //the rotator objects be around, but just knock off the fences they
-        //hold. Ultimately the rotator objects will be GCed when not required.
-        //Also resetting fences is required if at least one rotation round has
-        //succeeded before. It'll be a NOP otherwise.
-        mRot[i]->resetReleaseFd();
-    }
+    RotMgr::getInstance()->markUnusedTop(mCount);
     reset();
 }
 
diff --git a/libhwcomposer/hwc_utils.h b/libhwcomposer/hwc_utils.h
index 7db0f36..cd84f73 100644
--- a/libhwcomposer/hwc_utils.h
+++ b/libhwcomposer/hwc_utils.h
@@ -87,6 +87,8 @@
     bool isConfiguring;
     // External Display is in MDP Downscale mode indicator
     bool mDownScaleMode;
+    // Ext dst Rect
+    hwc_rect_t mDstRect;
 };
 
 struct ListStats {
@@ -410,6 +412,11 @@
 
 }; //qhwc namespace
 
+enum eAnimationState{
+    ANIMATION_STOPPED,
+    ANIMATION_STARTED,
+};
+
 // -----------------------------------------------------------------------------
 // HWC context
 // This structure contains overall state
@@ -440,14 +447,10 @@
     hwc_rect_t mViewFrame[HWC_NUM_DISPLAY_TYPES];
     qhwc::AssertiveDisplay *mAD;
     qhwc::VPUClient *mVPUClient;
+    eAnimationState mAnimationState[HWC_NUM_DISPLAY_TYPES];
 
-    // No animation on External display feature
-    // Notifies hwcomposer about the device orientation before animation.
+    // stores the primary device orientation
     int deviceOrientation;
-    // Stores the crop, dest rect and transform value of video before animation.
-    hwc_rect_t mPrevCropVideo;
-    hwc_rect_t mPrevDestVideo;
-    int mPrevTransformVideo;
     //Securing in progress indicator
     bool mSecuring;
     //WFD on proprietary stack
diff --git a/libmemtrack/kgsl.c b/libmemtrack/kgsl.c
index 4843742..6dd4e27 100644
--- a/libmemtrack/kgsl.c
+++ b/libmemtrack/kgsl.c
@@ -47,7 +47,7 @@
     size_t allocated_records = min(*num_records, ARRAY_SIZE(record_templates));
     int i;
     FILE *fp;
-    FILE *smaps_fp;
+    FILE *smaps_fp = NULL;
     char line[1024];
     char tmp[128];
     size_t accounted_size = 0;
@@ -74,6 +74,7 @@
         snprintf(tmp, sizeof(tmp), "/proc/%d/smaps", pid);
         smaps_fp = fopen(tmp, "r");
         if (smaps_fp == NULL) {
+            fclose(fp);
             return -errno;
         }
     }
@@ -145,6 +146,8 @@
         records[1].size_in_bytes = unaccounted_size;
     }
 
+    if (smaps_fp)
+        fclose(smaps_fp);
     fclose(fp);
 
     return 0;
diff --git a/liboverlay/overlayRotator.cpp b/liboverlay/overlayRotator.cpp
index 4b6a8bc..d912dc7 100644
--- a/liboverlay/overlayRotator.cpp
+++ b/liboverlay/overlayRotator.cpp
@@ -107,13 +107,15 @@
     mRelFence[mCurrOffset] = fence;
 }
 
-void RotMem::Mem::resetReleaseFd() {
-    //Will wait for previous offline rotation to finish, close fence fd
-    //and reset
-    setReleaseFd(-1);
-}
-
 //============RotMgr=========================
+RotMgr * RotMgr::sRotMgr = NULL;
+
+RotMgr* RotMgr::getInstance() {
+    if(sRotMgr == NULL) {
+        sRotMgr = new RotMgr();
+    }
+    return sRotMgr;
+}
 
 RotMgr::RotMgr() {
     for(int i = 0; i < MAX_ROT_SESS; i++) {
diff --git a/liboverlay/overlayRotator.h b/liboverlay/overlayRotator.h
index 6bb94a6..2bbfb91 100644
--- a/liboverlay/overlayRotator.h
+++ b/liboverlay/overlayRotator.h
@@ -56,7 +56,6 @@
         bool close() { return m.close(); }
         uint32_t size() const { return m.bufSz(); }
         void setReleaseFd(const int& fence);
-        void resetReleaseFd();
         // Max rotator buffers
         enum { ROT_NUM_BUFS = 2 };
         // rotator data info dst offset
@@ -73,7 +72,6 @@
     Mem& prev() { return m[(_curr+1) % MAX_ROT_MEM]; }
     RotMem& operator++() { ++_curr; return *this; }
     void setReleaseFd(const int& fence) { curr().setReleaseFd(fence); }
-    void resetReleaseFd() { curr().resetReleaseFd(); }
     bool close();
     uint32_t _curr;
     Mem m[MAX_ROT_MEM];
@@ -98,7 +96,6 @@
     virtual void dump() const = 0;
     virtual void getDump(char *buf, size_t len) const = 0;
     void setReleaseFd(const int& fence) { mMem.setReleaseFd(fence); }
-    void resetReleaseFd() { mMem.resetReleaseFd(); }
     static Rotator *getRotator();
 
 protected:
@@ -230,21 +227,29 @@
     //Maximum sessions based on VG pipes, since rotator is used only for videos.
     //Even though we can have 4 mixer stages, that much may be unnecessary.
     enum { MAX_ROT_SESS = 3 };
-    RotMgr();
+
     ~RotMgr();
     void configBegin();
     void configDone();
     overlay::Rotator *getNext();
     void clear(); //Removes all instances
+    //Resets the usage of top count objects, making them available for reuse
+    void markUnusedTop(const uint32_t& count) { mUseCount -= count; }
     /* Returns rot dump.
      * Expects a NULL terminated buffer of big enough size.
      */
     void getDump(char *buf, size_t len);
     int getRotDevFd();
     int getNumActiveSessions() { return mUseCount; }
+
+    static RotMgr *getInstance();
+
 private:
+    RotMgr();
+    static RotMgr *sRotMgr;
+
     overlay::Rotator *mRot[MAX_ROT_SESS];
-    int mUseCount;
+    uint32_t mUseCount;
     int mRotDevFd;
 };
 
diff --git a/libqdutils/display_config.cpp b/libqdutils/display_config.cpp
index eaf5384..45b0211 100644
--- a/libqdutils/display_config.cpp
+++ b/libqdutils/display_config.cpp
@@ -91,4 +91,26 @@
         ALOGE("%s: Failed to get external status err=%d", __FUNCTION__, err);
     return err;
 }
+
+int getDisplayVisibleRegion(int dpy, hwc_rect_t &rect) {
+    status_t err = FAILED_TRANSACTION;
+    sp<IQService> binder = getBinder();
+    Parcel inParcel, outParcel;
+    inParcel.writeInt32(dpy);
+    if(binder != NULL) {
+        err = binder->dispatch(IQService::GET_DISPLAY_VISIBLE_REGION,
+                &inParcel, &outParcel);
+    }
+    if(!err) {
+        rect.left = outParcel.readInt32();
+        rect.top = outParcel.readInt32();
+        rect.right = outParcel.readInt32();
+        rect.bottom = outParcel.readInt32();
+    } else {
+        ALOGE("%s: Failed to getVisibleRegion for dpy =%d: err = %d",
+              __FUNCTION__, dpy, err);
+    }
+    return err;
+}
+
 }; //namespace
diff --git a/libqdutils/display_config.h b/libqdutils/display_config.h
index c7d8ce9..29edbef 100644
--- a/libqdutils/display_config.h
+++ b/libqdutils/display_config.h
@@ -29,6 +29,7 @@
 #include <gralloc_priv.h>
 #include <qdMetaData.h>
 #include <mdp_version.h>
+#include <hardware/hwcomposer.h>
 
 // This header is for clients to use to set/get global display configuration
 // The functions in this header run in the client process and wherever necessary
@@ -69,4 +70,7 @@
 // Returns 0 on success, negative values on errors
 int setHSIC(int dpy, const HSICData_t& hsic_data);
 
+// get the active visible region for the display
+// Returns 0 on success, negative values on errors
+int getDisplayVisibleRegion(int dpy, hwc_rect_t &rect);
 }; //namespace
diff --git a/libqservice/IQService.h b/libqservice/IQService.h
index d6e525a..f8e58ab 100644
--- a/libqservice/IQService.h
+++ b/libqservice/IQService.h
@@ -48,6 +48,7 @@
         CHECK_EXTERNAL_STATUS,   // Check status of external display
         GET_DISPLAY_ATTRIBUTES,  // Get display attributes
         SET_HSIC_DATA,           // Set HSIC on dspp
+        GET_DISPLAY_VISIBLE_REGION,  // Get the visibleRegion for dpy
         VPU_COMMAND_LIST_START = 100, //Reserved block for VPU commands
         VPU_COMMAND_LIST_END   = 200,
         COMMAND_LIST_END = 400,