am a4a4524a: am 0f2848ad: (-s ours) resolved conflicts for 25016fd2 to lmp-mr1-ub-dev [DO NOT MERGE]

* commit 'a4a4524adad910a01d8af8bd1fdb2e4530e9ce7c':
  hwc: fix compilation issue on backport of Ieb91b70 [DO NOT MERGE]
diff --git a/msm8994/libgralloc/alloc_controller.cpp b/msm8994/libgralloc/alloc_controller.cpp
old mode 100644
new mode 100755
index 4cb1661..bc5e68c
--- a/msm8994/libgralloc/alloc_controller.cpp
+++ b/msm8994/libgralloc/alloc_controller.cpp
@@ -137,12 +137,37 @@
 }
 
 
+bool isUncompressedRgbFormat(int format)
+{
+    bool is_rgb_format = false;
+
+    switch (format)
+    {
+        case HAL_PIXEL_FORMAT_RGBA_8888:
+        case HAL_PIXEL_FORMAT_RGBX_8888:
+        case HAL_PIXEL_FORMAT_RGB_888:
+        case HAL_PIXEL_FORMAT_RGB_565:
+        case HAL_PIXEL_FORMAT_BGRA_8888:
+        case HAL_PIXEL_FORMAT_RGBA_5551:
+        case HAL_PIXEL_FORMAT_RGBA_4444:
+        case HAL_PIXEL_FORMAT_R_8:
+        case HAL_PIXEL_FORMAT_RG_88:
+        case HAL_PIXEL_FORMAT_BGRX_8888:    // Intentional fallthrough
+            is_rgb_format = true;
+            break;
+        default:
+            break;
+    }
+
+    return is_rgb_format;
+}
+
 void AdrenoMemInfo::getAlignedWidthAndHeight(int width, int height, int format,
                             int usage, int& aligned_w, int& aligned_h)
 {
 
     // Currently surface padding is only computed for RGB* surfaces.
-    if (format <= HAL_PIXEL_FORMAT_BGRA_8888) {
+    if (isUncompressedRgbFormat(format) == true) {
         int tileEnabled = isMacroTileEnabled(format, usage);
         AdrenoMemInfo::getInstance().getGpuAlignedWidthHeight(width,
             height, format, tileEnabled, aligned_w, aligned_h);
diff --git a/msm8994/libgralloc/gpu.cpp b/msm8994/libgralloc/gpu.cpp
index 6789133..447dde4 100644
--- a/msm8994/libgralloc/gpu.cpp
+++ b/msm8994/libgralloc/gpu.cpp
@@ -192,12 +192,9 @@
 {
     *bufferType = BUFFER_TYPE_VIDEO;
 
-    if (inputFormat <= HAL_PIXEL_FORMAT_BGRA_8888) {
+    if (isUncompressedRgbFormat(inputFormat) == TRUE) {
         // RGB formats
         *bufferType = BUFFER_TYPE_UI;
-    } else if ((inputFormat == HAL_PIXEL_FORMAT_R_8) ||
-               (inputFormat == HAL_PIXEL_FORMAT_RG_88)) {
-        *bufferType = BUFFER_TYPE_UI;
     }
 }
 
@@ -295,11 +292,19 @@
             grallocFormat = HAL_PIXEL_FORMAT_NV21_ZSL; //NV21 ZSL
         else if(usage & GRALLOC_USAGE_HW_CAMERA_READ)
             grallocFormat = HAL_PIXEL_FORMAT_YCrCb_420_SP; //NV21
-        else if(usage & GRALLOC_USAGE_HW_CAMERA_WRITE)
-            grallocFormat = HAL_PIXEL_FORMAT_YCrCb_420_SP; //NV21
-        else if(usage & GRALLOC_USAGE_HW_COMPOSER)
+        else if(usage & GRALLOC_USAGE_HW_CAMERA_WRITE) {
+           if (format == HAL_PIXEL_FORMAT_YCbCr_420_888) {
+               grallocFormat = HAL_PIXEL_FORMAT_NV21_ZSL; //NV21
+           } else {
+               grallocFormat = HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS; //NV12 preview
+           }
+        } else if(usage & GRALLOC_USAGE_HW_COMPOSER)
             //XXX: If we still haven't set a format, default to RGBA8888
             grallocFormat = HAL_PIXEL_FORMAT_RGBA_8888;
+        else if(format == HAL_PIXEL_FORMAT_YCbCr_420_888)
+            //If no other usage flags are detected, default the
+            //flexible YUV format to NV21_ZSL
+            grallocFormat = HAL_PIXEL_FORMAT_NV21_ZSL;
     }
 
     getGrallocInformationFromFormat(grallocFormat, &bufferType);
diff --git a/msm8994/libgralloc/gr.h b/msm8994/libgralloc/gr.h
index 5ee0cf8..54202c5 100644
--- a/msm8994/libgralloc/gr.h
+++ b/msm8994/libgralloc/gr.h
@@ -75,6 +75,9 @@
 // To query if UBWC is enabled, based on format and usage flags
 bool isUBwcEnabled(int format, int usage);
 
+// Function to check if the format is an uncompressed RGB format
+bool isUncompressedRgbFormat(int format);
+
 /*****************************************************************************/
 
 class Locker {
diff --git a/msm8994/libhdmi/hdmi.cpp b/msm8994/libhdmi/hdmi.cpp
index 7d709cb..c8d36ef 100644
--- a/msm8994/libhdmi/hdmi.cpp
+++ b/msm8994/libhdmi/hdmi.cpp
@@ -152,6 +152,7 @@
     mUnderscanSupported(false), mMDPDownscaleEnabled(false)
 {
     memset(&mVInfo, 0, sizeof(mVInfo));
+    mFbNum = qdutils::getHDMINode();
 
     mDisplayId = HWC_DISPLAY_EXTERNAL;
     // Update the display if HDMI is connected as primary
@@ -159,7 +160,6 @@
         mDisplayId = HWC_DISPLAY_PRIMARY;
     }
 
-    mFbNum = overlay::Overlay::getInstance()->getFbForDpy(mDisplayId);
     // Disable HPD at start if HDMI is external, it will be enabled later
     // when the display powers on
     // This helps for framework reboot or adb shell stop/start
@@ -684,8 +684,7 @@
 }
 
 bool HDMIDisplay::isHDMIPrimaryDisplay() {
-    int hdmiNode = qdutils::getHDMINode();
-    return (hdmiNode == HWC_DISPLAY_PRIMARY);
+    return (mFbNum == HWC_DISPLAY_PRIMARY);
 }
 
 int HDMIDisplay::getConnectedState() {
diff --git a/msm8994/libhwcomposer/Android.mk b/msm8994/libhwcomposer/Android.mk
index df3e464..293eb49 100644
--- a/msm8994/libhwcomposer/Android.mk
+++ b/msm8994/libhwcomposer/Android.mk
@@ -17,7 +17,8 @@
 LOCAL_SHARED_LIBRARIES += libskia
 endif #TARGET_USES_QCOM_BSP
 
-LOCAL_CFLAGS                  := $(common_flags) -DLOG_TAG=\"qdhwcomposer\"
+LOCAL_CFLAGS                  := $(common_flags) -DLOG_TAG=\"qdhwcomposer\" \
+                                 -std=c++11
 #Enable Dynamic FPS if PHASE_OFFSET is not set
 ifeq ($(VSYNC_EVENT_PHASE_OFFSET_NS),)
     LOCAL_CFLAGS += -DDYNAMIC_FPS
diff --git a/msm8994/libhwcomposer/hwc.cpp b/msm8994/libhwcomposer/hwc.cpp
index beade83..fc0842b 100644
--- a/msm8994/libhwcomposer/hwc.cpp
+++ b/msm8994/libhwcomposer/hwc.cpp
@@ -255,6 +255,8 @@
     hwc_context_t* ctx = (hwc_context_t*)(dev);
     const int dpy = HWC_DISPLAY_PRIMARY;
     bool fbComp = false;
+    if (!ctx->mDefaultModeApplied)
+        applyDefaultMode(ctx);
     if (LIKELY(list && list->numHwLayers > 1) && ctx->dpyAttr[dpy].connected &&
             (ctx->dpyAttr[dpy].isActive ||
              ctx->mHDMIDisplay->isHDMIPrimaryDisplay())
@@ -633,7 +635,11 @@
             }
         }
 
-        int lSplit = getLeftSplit(ctx, dpy);
+        /* When source split is enabled, right ROI will always be NULL since the
+         * ROI for the whole panel generated in a single coordinate system will
+         * be populuated in left ROI. So leave the right ROI untouched */
+        int lSplit = qdutils::MDPVersion::getInstance().isSrcSplit() ? 0 :
+                    (isDisplaySplit(ctx, dpy) ? getLeftSplit(ctx, dpy) : 0);
         qhwc::ovutils::Dim lRoi = qhwc::ovutils::Dim(
             ctx->listStats[dpy].lRoi.left,
             ctx->listStats[dpy].lRoi.top,
@@ -766,8 +772,15 @@
             if (hotPluggable) {
                 ctx->mHDMIDisplay->getDisplayConfigs(configs, numConfigs);
             } else {
-                configs[0] = 0;
-                *numConfigs = 1;
+                if(ctx->mColorMode->getNumModes() > 0) {
+                    *numConfigs = ctx->mColorMode->getNumModes();
+                    for (size_t i = 0; i < *numConfigs; i++)
+                        configs[i] = (uint32_t) i;
+
+                } else {
+                    configs[0] = 0;
+                    *numConfigs = 1;
+                }
             }
             break;
         case HWC_DISPLAY_EXTERNAL:
@@ -795,22 +808,6 @@
         return -EINVAL;
     }
 
-    //From HWComposer
-    static const uint32_t DISPLAY_ATTRIBUTES[] = {
-        HWC_DISPLAY_VSYNC_PERIOD,
-        HWC_DISPLAY_WIDTH,
-        HWC_DISPLAY_HEIGHT,
-        HWC_DISPLAY_DPI_X,
-        HWC_DISPLAY_DPI_Y,
-#ifdef QCOM_BSP
-        HWC_DISPLAY_SECURE,
-#endif
-        HWC_DISPLAY_NO_ATTRIBUTE,
-    };
-
-    const size_t NUM_DISPLAY_ATTRIBUTES = (sizeof(DISPLAY_ATTRIBUTES) /
-            sizeof(DISPLAY_ATTRIBUTES)[0]);
-
     uint32_t xres = 0, yres = 0, refresh = 0;
     int ret = 0;
     if (hotPluggable) {
@@ -822,7 +819,7 @@
         }
     }
 
-    for (size_t i = 0; i < NUM_DISPLAY_ATTRIBUTES - 1; i++) {
+    for (size_t i = 0; attributes[i] != HWC_DISPLAY_NO_ATTRIBUTE; i++) {
         switch (attributes[i]) {
         case HWC_DISPLAY_VSYNC_PERIOD:
             values[i] =
@@ -851,11 +848,9 @@
         case HWC_DISPLAY_DPI_Y:
             values[i] = (int32_t) (ctx->dpyAttr[disp].ydpi*1000.0);
             break;
-#ifdef QCOM_BSP
-        case HWC_DISPLAY_SECURE:
-            values[i] = (int32_t) (ctx->dpyAttr[disp].secure);
+        case HWC_DISPLAY_COLOR_TRANSFORM:
+            values[i] = ctx->mColorMode->getModeForIndex(config);
             break;
-#endif
         default:
             ALOGE("Unknown display attribute %d",
                     attributes[i]);
@@ -908,7 +903,9 @@
 
     // For use cases when primary panel is the default interface we only have
     // the default config (0th index)
-    if (!hotPluggable) {
+    if (!hotPluggable && HWC_DISPLAY_PRIMARY) {
+        return ctx->mColorMode->getActiveModeIndex();
+    } else if (isVirtualDisplay) {
         return 0;
     }
 
@@ -928,10 +925,12 @@
         return -EINVAL;
     }
 
-    // For use cases when primary panel is the default interface we only have
-    // the default config (0th index)
-    if (!hotPluggable) {
-        // Primary and virtual supports only the default config (0th index)
+    // For use cases when primary panel is the default interface we only switch
+    // color modes
+    if(!hotPluggable && disp == HWC_DISPLAY_PRIMARY) {
+        return ctx->mColorMode->applyModeByIndex(index);
+    } else if (isVirtualDisplay) {
+        // virtual supports only the default config (0th index)
         return (index == 0) ? index : -EINVAL;
     }
 
@@ -967,7 +966,7 @@
 
         //Setup HWC methods
         dev->device.common.tag          = HARDWARE_DEVICE_TAG;
-        dev->device.common.version      = HWC_DEVICE_API_VERSION_1_4;
+        dev->device.common.version      = HWC_DEVICE_API_VERSION_1_5;
         dev->device.common.module       = const_cast<hw_module_t*>(module);
         dev->device.common.close        = hwc_device_close;
         dev->device.prepare             = hwc_prepare;
diff --git a/msm8994/libhwcomposer/hwc_fbupdate.cpp b/msm8994/libhwcomposer/hwc_fbupdate.cpp
index b63fb3a..8660740 100644
--- a/msm8994/libhwcomposer/hwc_fbupdate.cpp
+++ b/msm8994/libhwcomposer/hwc_fbupdate.cpp
@@ -541,7 +541,7 @@
             return false;
         }
 
-        if(ctx->mOverlay->comparePipePriority(destL, destR) == -1) {
+        if(ctx->mOverlay->needsPrioritySwap(destL, destR)) {
             qhwc::swap(destL, destR);
         }
 
diff --git a/msm8994/libhwcomposer/hwc_mdpcomp.cpp b/msm8994/libhwcomposer/hwc_mdpcomp.cpp
index d2962a3..4c7c7ad 100644
--- a/msm8994/libhwcomposer/hwc_mdpcomp.cpp
+++ b/msm8994/libhwcomposer/hwc_mdpcomp.cpp
@@ -51,6 +51,7 @@
 int MDPComp::sMaxSecLayers = 1;
 bool MDPComp::enablePartialUpdateForMDP3 = false;
 bool MDPComp::sIsPartialUpdateActive = true;
+bool MDPComp::sIsSingleFullScreenUpdate = false;
 void *MDPComp::sLibPerfHint = NULL;
 int MDPComp::sPerfLockHandle = 0;
 int (*MDPComp::sPerfLockAcquire)(int, int, int*, int) = NULL;
@@ -351,19 +352,11 @@
 }
 
 void MDPComp::LayerCache::reset() {
-    memset(&hnd, 0, sizeof(hnd));
     memset(&isFBComposed, true, sizeof(isFBComposed));
     memset(&drop, false, sizeof(drop));
     layerCount = 0;
 }
 
-void MDPComp::LayerCache::cacheAll(hwc_display_contents_1_t* list) {
-    const int numAppLayers = (int)list->numHwLayers - 1;
-    for(int i = 0; i < numAppLayers; i++) {
-        hnd[i] = list->hwLayers[i].handle;
-    }
-}
-
 void MDPComp::LayerCache::updateCounts(const FrameInfo& curFrame) {
     layerCount = curFrame.layerCount;
     memcpy(&isFBComposed, &curFrame.isFBComposed, sizeof(isFBComposed));
@@ -379,8 +372,8 @@
                 (curFrame.drop[i] != drop[i])) {
             return false;
         }
-        if(curFrame.isFBComposed[i] &&
-           (hnd[i] != list->hwLayers[i].handle)){
+        hwc_layer_1_t const* layer = &list->hwLayers[i];
+        if(curFrame.isFBComposed[i] && layerUpdating(layer)){
             return false;
         }
     }
@@ -525,9 +518,37 @@
     return ret;
 }
 
-void MDPCompNonSplit::trimAgainstROI(hwc_context_t *ctx, hwc_rect_t& fbRect) {
+hwc_rect_t MDPComp::calculateDirtyRect(const hwc_layer_1_t* layer,
+                    hwc_rect_t& scissor) {
+  hwc_region_t surfDamage = layer->surfaceDamage;
+  hwc_rect_t src = integerizeSourceCrop(layer->sourceCropf);
+  hwc_rect_t dst = layer->displayFrame;
+  int x_off = dst.left - src.left;
+  int y_off = dst.top - src.top;
+  hwc_rect dirtyRect = (hwc_rect){0, 0, 0, 0};
+  hwc_rect_t updatingRect = dst;
+
+  if (surfDamage.numRects == 0) {
+      // full layer updating, dirty rect is full frame
+      dirtyRect = getIntersection(layer->displayFrame, scissor);
+  } else {
+      for(uint32_t i = 0; i < surfDamage.numRects; i++) {
+          updatingRect = moveRect(surfDamage.rects[i], x_off, y_off);
+          hwc_rect_t intersect = getIntersection(updatingRect, scissor);
+          if(isValidRect(intersect)) {
+              dirtyRect = getUnion(intersect, dirtyRect);
+          }
+      }
+  }
+
+  return dirtyRect;
+}
+
+void MDPCompNonSplit::trimAgainstROI(hwc_context_t *ctx, hwc_rect &crop,
+        hwc_rect &dst) {
     hwc_rect_t roi = ctx->listStats[mDpy].lRoi;
-    fbRect = getIntersection(fbRect, roi);
+    dst = getIntersection(dst, roi);
+    crop = dst;
 }
 
 /* 1) Identify layers that are not visible or lying outside the updating ROI and
@@ -587,22 +608,15 @@
 
     for(int index = 0; index < numAppLayers; index++ ) {
         hwc_layer_1_t* layer = &list->hwLayers[index];
-        if ((mCachedFrame.hnd[index] != layer->handle) ||
+        if (layerUpdating(layer) ||
                 isYuvBuffer((private_handle_t *)layer->handle)) {
-            hwc_rect_t dst = layer->displayFrame;
-            hwc_rect_t updatingRect = dst;
-
-#ifdef QCOM_BSP
-            if(!needsScaling(layer) && !layer->transform)
-            {
-                hwc_rect_t src = integerizeSourceCrop(layer->sourceCropf);
-                int x_off = dst.left - src.left;
-                int y_off = dst.top - src.top;
-                updatingRect = moveRect(layer->dirtyRect, x_off, y_off);
+            hwc_rect_t dirtyRect = getIntersection(layer->displayFrame,
+                                                    fullFrame);
+            if(!needsScaling(layer) && !layer->transform) {
+                dirtyRect = calculateDirtyRect(layer, fullFrame);
             }
-#endif
 
-            roi = getUnion(roi, updatingRect);
+            roi = getUnion(roi, dirtyRect);
         }
     }
 
@@ -622,14 +636,20 @@
             ctx->listStats[mDpy].lRoi.right, ctx->listStats[mDpy].lRoi.bottom);
 }
 
-void MDPCompSplit::trimAgainstROI(hwc_context_t *ctx, hwc_rect_t& fbRect) {
-    hwc_rect l_roi = ctx->listStats[mDpy].lRoi;
-    hwc_rect r_roi = ctx->listStats[mDpy].rRoi;
-
-    hwc_rect_t l_fbRect = getIntersection(fbRect, l_roi);
-    hwc_rect_t r_fbRect = getIntersection(fbRect, r_roi);
-    fbRect = getUnion(l_fbRect, r_fbRect);
+void MDPCompSplit::trimAgainstROI(hwc_context_t *ctx, hwc_rect &crop,
+        hwc_rect &dst) {
+    hwc_rect roi = getUnion(ctx->listStats[mDpy].lRoi,
+            ctx->listStats[mDpy].rRoi);
+    hwc_rect tmpDst = getIntersection(dst, roi);
+    if(!isSameRect(dst, tmpDst)) {
+        crop.left = crop.left + (tmpDst.left - dst.left);
+        crop.top = crop.top + (tmpDst.top - dst.top);
+        crop.right = crop.left + (tmpDst.right - tmpDst.left);
+        crop.bottom = crop.top + (tmpDst.bottom - tmpDst.top);
+        dst = tmpDst;
+    }
 }
+
 /* 1) Identify layers that are not visible or lying outside BOTH the updating
  *    ROI's and drop them from composition. If a layer is spanning across both
  *    the halves of the screen but needed by only ROI, the non-contributing
@@ -703,28 +723,23 @@
     for(int index = 0; index < numAppLayers; index++ ) {
         hwc_layer_1_t* layer = &list->hwLayers[index];
         private_handle_t *hnd = (private_handle_t *)layer->handle;
-        if ((mCachedFrame.hnd[index] != layer->handle) ||
-                isYuvBuffer(hnd)) {
-            hwc_rect_t dst = layer->displayFrame;
-            hwc_rect_t updatingRect = dst;
 
-#ifdef QCOM_BSP
-            if(!needsScaling(layer) && !layer->transform)
-            {
-                hwc_rect_t src = integerizeSourceCrop(layer->sourceCropf);
-                int x_off = dst.left - src.left;
-                int y_off = dst.top - src.top;
-                updatingRect = moveRect(layer->dirtyRect, x_off, y_off);
+        if (layerUpdating(layer) || isYuvBuffer(hnd)) {
+            hwc_rect_t l_dirtyRect = getIntersection(layer->displayFrame,
+                                        l_frame);
+            hwc_rect_t r_dirtyRect = getIntersection(layer->displayFrame,
+                                        r_frame);
+
+            if(!needsScaling(layer) && !layer->transform) {
+                l_dirtyRect = calculateDirtyRect(layer, l_frame);
+                r_dirtyRect = calculateDirtyRect(layer, r_frame);
             }
-#endif
+            if(isValidRect(l_dirtyRect))
+                l_roi = getUnion(l_roi, l_dirtyRect);
 
-            hwc_rect_t l_dst  = getIntersection(l_frame, updatingRect);
-            if(isValidRect(l_dst))
-                l_roi = getUnion(l_roi, l_dst);
+            if(isValidRect(r_dirtyRect))
+                r_roi = getUnion(r_roi, r_dirtyRect);
 
-            hwc_rect_t r_dst  = getIntersection(r_frame, updatingRect);
-            if(isValidRect(r_dst))
-                r_roi = getUnion(r_roi, r_dst);
         }
     }
 
@@ -1290,6 +1305,11 @@
     }
     if(ctx->listStats[mDpy].secureUI)
         return false;
+    if (sIsSingleFullScreenUpdate) {
+        // make sure one full screen update
+        sIsSingleFullScreenUpdate = false;
+        return false;
+    }
     return true;
 }
 
@@ -1657,7 +1677,8 @@
     int fbCount = 0;
 
     for(int i = 0; i < numAppLayers; i++) {
-        if (mCachedFrame.hnd[i] == list->hwLayers[i].handle) {
+        hwc_layer_1_t * layer = &list->hwLayers[i];
+        if (!layerUpdating(layer)) {
             if(!frame.drop[i])
                 fbCount++;
             frame.isFBComposed[i] = true;
@@ -1761,7 +1782,7 @@
             fbRect = getUnion(fbRect, dst);
         }
     }
-    trimAgainstROI(ctx, fbRect);
+    trimAgainstROI(ctx, fbRect, fbRect);
     return fbRect;
 }
 
@@ -1994,11 +2015,12 @@
 
     //Do not cache the information for next draw cycle.
     if(numLayers > MAX_NUM_APP_LAYERS or (!numLayers)) {
-        ALOGI("%s: Unsupported layer count for mdp composition",
-                __FUNCTION__);
+        ALOGI_IF(numLayers, "%s: Unsupported layer count for mdp composition: %d",
+                __FUNCTION__, numLayers);
         mCachedFrame.reset();
 #ifdef DYNAMIC_FPS
-        setDynRefreshRate(ctx, list);
+        // Reset refresh rate
+        setRefreshRate(ctx, mDpy, ctx->dpyAttr[mDpy].refreshRate);
 #endif
         return -1;
     }
@@ -2014,7 +2036,8 @@
         setMDPCompLayerFlags(ctx, list);
         mCachedFrame.updateCounts(mCurrentFrame);
 #ifdef DYNAMIC_FPS
-        setDynRefreshRate(ctx, list);
+        // Reset refresh rate
+        setRefreshRate(ctx, mDpy, ctx->dpyAttr[mDpy].refreshRate);
 #endif
         ret = -1;
         return ret;
@@ -2072,7 +2095,6 @@
 #endif
     setPerfHint(ctx, list);
 
-    mCachedFrame.cacheAll(list);
     mCachedFrame.updateCounts(mCurrentFrame);
     return ret;
 }
@@ -2608,6 +2630,120 @@
 }
 
 //================MDPCompSrcSplit==============================================
+
+bool MDPCompSrcSplit::validateAndApplyROI(hwc_context_t *ctx,
+        hwc_display_contents_1_t* list) {
+    int numAppLayers = ctx->listStats[mDpy].numAppLayers;
+    hwc_rect_t visibleRect = ctx->listStats[mDpy].lRoi;
+
+    for(int i = numAppLayers - 1; i >= 0; i--) {
+        if(!isValidRect(visibleRect)) {
+            mCurrentFrame.drop[i] = true;
+            mCurrentFrame.dropCount++;
+            continue;
+        }
+
+        const hwc_layer_1_t* layer =  &list->hwLayers[i];
+        hwc_rect_t dstRect = layer->displayFrame;
+        hwc_rect_t res  = getIntersection(visibleRect, dstRect);
+
+        if(!isValidRect(res)) {
+            mCurrentFrame.drop[i] = true;
+            mCurrentFrame.dropCount++;
+        } else {
+            /* Reset frame ROI when any layer which needs scaling also needs ROI
+             * cropping */
+            if(!isSameRect(res, dstRect) && needsScaling (layer)) {
+                ALOGI("%s: Resetting ROI due to scaling", __FUNCTION__);
+                memset(&mCurrentFrame.drop, 0, sizeof(mCurrentFrame.drop));
+                mCurrentFrame.dropCount = 0;
+                return false;
+            }
+
+            /* deduct any opaque region from visibleRect */
+            if (layer->blending == HWC_BLENDING_NONE &&
+                    layer->planeAlpha == 0xFF)
+                visibleRect = deductRect(visibleRect, res);
+        }
+    }
+    return true;
+}
+
+/*
+ * HW Limitation: ping pong split can always split the ping pong output
+ * equally across two DSI's. So the ROI programmed should be of equal width
+ * for both the halves
+ */
+void MDPCompSrcSplit::generateROI(hwc_context_t *ctx,
+        hwc_display_contents_1_t* list) {
+    int numAppLayers = ctx->listStats[mDpy].numAppLayers;
+
+    if(!canPartialUpdate(ctx, list))
+        return;
+
+    struct hwc_rect roi = (struct hwc_rect){0, 0, 0, 0};
+    hwc_rect fullFrame = (struct hwc_rect) {0, 0,(int)ctx->dpyAttr[mDpy].xres,
+        (int)ctx->dpyAttr[mDpy].yres};
+
+    for(int index = 0; index < numAppLayers; index++ ) {
+        hwc_layer_1_t* layer = &list->hwLayers[index];
+
+        // If we have a RGB layer which needs rotation, no partial update
+        if(!isYuvBuffer((private_handle_t *)layer->handle) && layer->transform)
+            return;
+
+        if (layerUpdating(layer) ||
+                isYuvBuffer((private_handle_t *)layer->handle)) {
+            hwc_rect_t dirtyRect = getIntersection(layer->displayFrame,
+                                                    fullFrame);
+            if (!needsScaling(layer) && !layer->transform) {
+                dirtyRect = calculateDirtyRect(layer, fullFrame);
+            }
+            roi = getUnion(roi, dirtyRect);
+        }
+    }
+
+    /* No layer is updating. Still SF wants a refresh.*/
+    if(!isValidRect(roi))
+        return;
+
+    if (isDisplaySplit(ctx, mDpy)) {
+        hwc_rect lFrame = fullFrame;
+        roi = expandROIFromMidPoint(roi, fullFrame);
+
+        lFrame.right = fullFrame.right / 2;
+        hwc_rect lRoi = getIntersection(roi, lFrame);
+        // Align ROI coordinates to panel restrictions
+        lRoi = getSanitizeROI(lRoi, lFrame);
+
+        hwc_rect rFrame = fullFrame;
+        rFrame.left = fullFrame.right/2;
+        hwc_rect rRoi = getIntersection(roi, rFrame);
+        // Align ROI coordinates to panel restrictions
+        rRoi = getSanitizeROI(rRoi, rFrame);
+
+        roi = getUnion(lRoi, rRoi);
+
+        ctx->listStats[mDpy].lRoi = roi;
+    } else {
+      hwc_rect lRoi = getIntersection(roi, fullFrame);
+      // Align ROI coordinates to panel restrictions
+      lRoi = getSanitizeROI(lRoi, fullFrame);
+
+      ctx->listStats[mDpy].lRoi = lRoi;
+    }
+
+    if(!validateAndApplyROI(ctx, list))
+        resetROI(ctx, mDpy);
+
+    ALOGD_IF(isDebug(),"%s: generated ROI: [%d, %d, %d, %d] [%d, %d, %d, %d]",
+            __FUNCTION__,
+            ctx->listStats[mDpy].lRoi.left, ctx->listStats[mDpy].lRoi.top,
+            ctx->listStats[mDpy].lRoi.right, ctx->listStats[mDpy].lRoi.bottom,
+            ctx->listStats[mDpy].rRoi.left, ctx->listStats[mDpy].rRoi.top,
+            ctx->listStats[mDpy].rRoi.right, ctx->listStats[mDpy].rRoi.bottom);
+}
+
 bool MDPCompSrcSplit::acquireMDPPipes(hwc_context_t *ctx, hwc_layer_1_t* layer,
         MdpPipeInfoSplit& pipe_info) {
     private_handle_t *hnd = (private_handle_t *)layer->handle;
@@ -2616,6 +2752,9 @@
     pipe_info.lIndex = ovutils::OV_INVALID;
     pipe_info.rIndex = ovutils::OV_INVALID;
 
+    if(qdutils::MDPVersion::getInstance().isPartialUpdateEnabled() && !mDpy)
+        trimAgainstROI(ctx,crop, dst);
+
     //If 2 pipes are staged on a single stage of a mixer, then the left pipe
     //should have a higher priority than the right one. Pipe priorities are
     //starting with VG0, VG1 ... , RGB0 ..., DMA1
@@ -2647,19 +2786,21 @@
     const uint32_t lSplit = getLeftSplit(ctx, mDpy);
     const uint32_t dstWidth = dst.right - dst.left;
     const uint32_t dstHeight = dst.bottom - dst.top;
-    const uint32_t cropWidth = has90Transform(layer) ? crop.bottom - crop.top :
+    uint32_t cropWidth = has90Transform(layer) ? crop.bottom - crop.top :
             crop.right - crop.left;
-    const uint32_t cropHeight = has90Transform(layer) ? crop.right - crop.left :
+    uint32_t cropHeight = has90Transform(layer) ? crop.right - crop.left :
             crop.bottom - crop.top;
     //Approximation to actual clock, ignoring the common factors in pipe and
     //mixer cases like line_time
     const uint32_t layerClock = getLayerClock(dstWidth, dstHeight, cropHeight);
     const uint32_t mixerClock = lSplit;
 
-    //TODO Even if a 4k video is going to be rot-downscaled to dimensions under
-    //pipe line length, we are still using 2 pipes. This is fine just because
-    //this is source split where destination doesn't matter. Evaluate later to
-    //see if going through all the calcs to save a pipe is worth it
+    const uint32_t downscale = getRotDownscale(ctx, layer);
+    if(downscale) {
+        cropWidth /= downscale;
+        cropHeight /= downscale;
+    }
+
     if(dstWidth > mdpHw.getMaxPipeWidth() or
             cropWidth > mdpHw.getMaxPipeWidth() or
             (primarySplitAlways and
@@ -2669,12 +2810,8 @@
             return false;
         }
 
-        // Return values
-        // 1  Left pipe is higher priority, do nothing.
-        // 0  Pipes of same priority.
-        //-1  Right pipe is of higher priority, needs swap.
-        if(ctx->mOverlay->comparePipePriority(pipe_info.lIndex,
-                pipe_info.rIndex) == -1) {
+        if(ctx->mOverlay->needsPrioritySwap(pipe_info.lIndex,
+                    pipe_info.rIndex)) {
             qhwc::swap(pipe_info.lIndex, pipe_info.rIndex);
         }
     }
@@ -2707,6 +2844,17 @@
     ALOGD_IF(isDebug(),"%s: configuring: layer: %p z_order: %d dest_pipeL: %d"
              "dest_pipeR: %d",__FUNCTION__, layer, z, lDest, rDest);
 
+    if(qdutils::MDPVersion::getInstance().isPartialUpdateEnabled() && !mDpy) {
+        /* MDP driver crops layer coordinates against ROI in Non-Split
+         * and Split MDP comp. But HWC needs to crop them for source split.
+         * Reason: 1) Source split is efficient only when the final effective
+         *            load is distributed evenly across mixers.
+         *         2) We have to know the effective width of the layer that
+         *            the ROI needs to find the no. of pipes the layer needs.
+         */
+        trimAgainstROI(ctx, crop, dst);
+    }
+
     // Handle R/B swap
     if (layer->flags & HWC_FORMAT_RB_SWAP) {
         if (hnd->format == HAL_PIXEL_FORMAT_RGBA_8888)
@@ -2910,9 +3058,7 @@
         int perfHint = 0x4501; // 45-display layer hint, 01-Enable
         sPerfLockHandle = sPerfLockAcquire(0 /*handle*/, 0/*duration*/,
                                     &perfHint, sizeof(perfHint)/sizeof(int));
-        if(sPerfLockHandle < 0) {
-            ALOGE("Perf Lock Acquire Failed");
-        } else {
+        if(sPerfLockHandle > 0) {
             perflockFlag = 1;
         }
     }
diff --git a/msm8994/libhwcomposer/hwc_mdpcomp.h b/msm8994/libhwcomposer/hwc_mdpcomp.h
index 302b047..ca03392 100644
--- a/msm8994/libhwcomposer/hwc_mdpcomp.h
+++ b/msm8994/libhwcomposer/hwc_mdpcomp.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012-2013, The Linux Foundation. All rights reserved.
+ * Copyright (C) 2012-2015, The Linux Foundation. All rights reserved.
  *
  * Not a Contribution, Apache license notifications and license are retained
  * for attribution purposes only.
@@ -59,6 +59,7 @@
     static int setPartialUpdatePref(hwc_context_t *ctx, bool enable);
     static bool getPartialUpdatePref(hwc_context_t *ctx);
     void setDynRefreshRate(hwc_context_t *ctx, hwc_display_contents_1_t* list);
+    static void setSingleFullScreenUpdate() { sIsSingleFullScreenUpdate = true; }
 
 protected:
     enum ePipeType {
@@ -127,7 +128,6 @@
     /* cached data */
     struct LayerCache {
         int layerCount;
-        buffer_handle_t hnd[MAX_NUM_APP_LAYERS];
         bool isFBComposed[MAX_NUM_APP_LAYERS];
         bool drop[MAX_NUM_APP_LAYERS];
 
@@ -135,7 +135,6 @@
         LayerCache();
         /* clear caching info*/
         void reset();
-        void cacheAll(hwc_display_contents_1_t* list);
         void updateCounts(const FrameInfo&);
         bool isSameFrame(const FrameInfo& curFrame,
                          hwc_display_contents_1_t* list);
@@ -157,12 +156,15 @@
     /* generates ROI based on the modified area of the frame */
     virtual void generateROI(hwc_context_t *ctx,
             hwc_display_contents_1_t* list) = 0;
+    /* Calculates the dirtyRegion for the given layer */
+    hwc_rect_t calculateDirtyRect(const hwc_layer_1_t* layer,
+                                hwc_rect_t& scissor);
     /* validates the ROI generated for fallback conditions */
     virtual bool validateAndApplyROI(hwc_context_t *ctx,
             hwc_display_contents_1_t* list) = 0;
-    /* Trims fbRect calculated against ROI generated */
-    virtual void trimAgainstROI(hwc_context_t *ctx, hwc_rect_t& fbRect) = 0;
-
+    /* Trims layer coordinates against ROI generated */
+    virtual void trimAgainstROI(hwc_context_t *ctx, hwc_rect_t& crop,
+            hwc_rect& dst) = 0;
     /* set/reset flags for MDPComp */
     void setMDPCompLayerFlags(hwc_context_t *ctx,
                               hwc_display_contents_1_t* list);
@@ -263,6 +265,7 @@
     static int sMaxPipesPerMixer;
     static bool sSrcSplitEnabled;
     static IdleInvalidator *sIdleInvalidator;
+    static bool sIsSingleFullScreenUpdate;
     static int sMaxSecLayers;
     static bool sIsPartialUpdateActive;
     struct FrameInfo mCurrentFrame;
@@ -315,8 +318,9 @@
     /* validates the ROI generated for fallback conditions */
     virtual bool validateAndApplyROI(hwc_context_t *ctx,
             hwc_display_contents_1_t* list);
-    /* Trims fbRect calculated against ROI generated */
-    virtual void trimAgainstROI(hwc_context_t *ctx, hwc_rect_t& fbRect);
+    /* Trims layer coordinates against ROI generated */
+    virtual void trimAgainstROI(hwc_context_t *ctx, hwc_rect_t& crop,
+            hwc_rect& dst);
 };
 
 class MDPCompSplit : public MDPComp {
@@ -342,6 +346,9 @@
     /* allocates pipes to selected candidates */
     virtual bool allocLayerPipes(hwc_context_t *ctx,
                                  hwc_display_contents_1_t* list);
+    /* Trims layer coordinates against ROI generated */
+    virtual void trimAgainstROI(hwc_context_t *ctx, hwc_rect_t& crop,
+            hwc_rect& dst);
 private:
     /* Increments mdpCount if 4k2k yuv layer split is enabled.
      * updates framebuffer z order if fb lies above source-split layer */
@@ -357,8 +364,6 @@
     /* validates the ROI generated for fallback conditions */
     virtual bool validateAndApplyROI(hwc_context_t *ctx,
             hwc_display_contents_1_t* list);
-    /* Trims fbRect calculated against ROI generated */
-    virtual void trimAgainstROI(hwc_context_t *ctx, hwc_rect_t& fbRect);
 };
 
 class MDPCompSrcSplit : public MDPCompSplit {
@@ -371,6 +376,12 @@
 
     virtual int configure(hwc_context_t *ctx, hwc_layer_1_t *layer,
             PipeLayerPair& pipeLayerPair);
+    /* generates ROI based on the modified area of the frame */
+    virtual void generateROI(hwc_context_t *ctx,
+            hwc_display_contents_1_t* list);
+    /* validates the ROI generated for fallback conditions */
+    virtual bool validateAndApplyROI(hwc_context_t *ctx,
+            hwc_display_contents_1_t* list);
 };
 
 }; //namespace
diff --git a/msm8994/libhwcomposer/hwc_qclient.cpp b/msm8994/libhwcomposer/hwc_qclient.cpp
index 09013c6..6d05d38 100644
--- a/msm8994/libhwcomposer/hwc_qclient.cpp
+++ b/msm8994/libhwcomposer/hwc_qclient.cpp
@@ -1,5 +1,5 @@
 /*
- *  Copyright (c) 2013-14, The Linux Foundation. All rights reserved.
+ *  Copyright (c) 2013-15, The Linux Foundation. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are
@@ -35,6 +35,7 @@
 #include <hwc_virtual.h>
 #include <overlay.h>
 #include <display_config.h>
+#include <dlfcn.h>
 
 #define QCLIENT_DEBUG 0
 
@@ -338,6 +339,14 @@
     }
 }
 
+static void applyModeById(hwc_context_t* ctx, int32_t modeId) {
+    int err = ctx->mColorMode->applyModeByID(modeId);
+    if (err)
+        ALOGD("%s: Not able to apply mode: %d", __FUNCTION__, modeId);
+    else
+        ctx->proc->invalidate(ctx->proc);
+}
+
 status_t QClient::notifyCallback(uint32_t command, const Parcel* inParcel,
         Parcel* outParcel) {
     status_t ret = NO_ERROR;
@@ -350,6 +359,7 @@
             unsecuring(mHwcContext, inParcel->readInt32());
             break;
         case IQService::SCREEN_REFRESH:
+            qhwc::MDPComp::setSingleFullScreenUpdate();
             return screenRefresh(mHwcContext);
             break;
         case IQService::EXTERNAL_ORIENTATION:
@@ -398,6 +408,9 @@
         case IQService::TOGGLE_SCREEN_UPDATE:
             toggleScreenUpdate(mHwcContext, inParcel->readInt32());
             break;
+        case IQService::APPLY_MODE_BY_ID:
+            applyModeById(mHwcContext, inParcel->readInt32());
+            break;
         default:
             ret = NO_ERROR;
     }
diff --git a/msm8994/libhwcomposer/hwc_utils.cpp b/msm8994/libhwcomposer/hwc_utils.cpp
index 8139013..98c4166 100644
--- a/msm8994/libhwcomposer/hwc_utils.cpp
+++ b/msm8994/libhwcomposer/hwc_utils.cpp
@@ -44,6 +44,7 @@
 #include "hwc_virtual.h"
 #include "qd_utils.h"
 #include <sys/sysinfo.h>
+#include <dlfcn.h>
 
 using namespace qClient;
 using namespace qService;
@@ -389,6 +390,9 @@
     property_get("debug.sf.hwc.canUseABC", value, "0");
     ctx->enableABC  = atoi(value) ? true : false;
 
+    // Initializing boot anim completed check to false
+    ctx->mDefaultModeApplied = false;
+
     // Initialize gpu perfomance hint related parameters
     property_get("sys.hwc.gpu_perf_mode", value, "0");
 #ifdef QCOM_BSP
@@ -414,6 +418,8 @@
 
     memset(&(ctx->mPtorInfo), 0, sizeof(ctx->mPtorInfo));
     ctx->mHPDEnabled = false;
+    ctx->mColorMode = new ColorMode();
+    ctx->mColorMode->init();
     ALOGI("Initializing Qualcomm Hardware Composer");
     ALOGI("MDP version: %d", ctx->mMDP.version);
 }
@@ -468,7 +474,11 @@
         ctx->mAD = NULL;
     }
 
-
+    if(ctx->mColorMode) {
+        ctx->mColorMode->destroy();
+        delete ctx->mColorMode;
+        ctx->mColorMode = NULL;
+    }
 }
 
 //Helper to roundoff the refreshrates
@@ -1311,6 +1321,12 @@
     return false;
 }
 
+bool layerUpdating(const hwc_layer_1_t* layer) {
+    hwc_region_t surfDamage = layer->surfaceDamage;
+    return ((surfDamage.numRects == 0) ||
+            isValidRect(layer->surfaceDamage.rects[0]));
+}
+
 hwc_rect_t moveRect(const hwc_rect_t& rect, const int& x_off, const int& y_off)
 {
     hwc_rect_t res;
@@ -2492,6 +2508,27 @@
     return (eqBounds == 3);
 }
 
+void applyDefaultMode(hwc_context_t *ctx) {
+    char value[PROPERTY_VALUE_MAX];
+    int boot_finished = 0;
+    static int ret = ctx->mColorMode->applyDefaultMode();
+    if(!ret) {
+        ctx->mDefaultModeApplied = true;
+        return;
+    }
+
+    // Reading property set on boot finish in SF
+    property_get("service.bootanim.exit", value, "0");
+    boot_finished = atoi(value);
+    if (!boot_finished)
+        return;
+
+    ret = ctx->mColorMode->applyDefaultMode();
+    if (ret)
+        ALOGD("%s: Not able to apply default mode", __FUNCTION__);
+    ctx->mDefaultModeApplied = true;
+}
+
 void BwcPM::setBwc(const hwc_context_t *ctx, const int& dpy,
         const private_handle_t *hnd,
         const hwc_rect_t& crop, const hwc_rect_t& dst,
@@ -2522,6 +2559,10 @@
     if(src_w > (int) qdutils::MDPVersion::getInstance().getMaxPipeWidth()) {
         return;
     }
+    //H/w requirement for BWC only. Pipe can still support 4096
+    if(src_h > 4092) {
+        return;
+    }
     //Decimation necessary, cannot use BWC. H/W requirement.
     if(qdutils::MDPVersion::getInstance().supportsDecimation()) {
         uint8_t horzDeci = 0;
@@ -2578,10 +2619,40 @@
     }
 }
 
+hwc_rect expandROIFromMidPoint(hwc_rect roi, hwc_rect fullFrame) {
+    int lRoiWidth = 0, rRoiWidth = 0;
+    int half_frame_width = fullFrame.right/2;
+
+    hwc_rect lFrame = fullFrame;
+    hwc_rect rFrame = fullFrame;
+    lFrame.right = (lFrame.right - lFrame.left)/2;
+    rFrame.left = lFrame.right;
+
+    hwc_rect lRoi = getIntersection(roi, lFrame);
+    hwc_rect rRoi = getIntersection(roi, rFrame);
+
+    lRoiWidth = lRoi.right - lRoi.left;
+    rRoiWidth = rRoi.right - rRoi.left;
+
+    if(lRoiWidth && rRoiWidth) {
+        if(lRoiWidth < rRoiWidth)
+            roi.left = half_frame_width - rRoiWidth;
+        else
+            roi.right = half_frame_width + lRoiWidth;
+    }
+    return roi;
+}
+
 void resetROI(hwc_context_t *ctx, const int dpy) {
     const int fbXRes = (int)ctx->dpyAttr[dpy].xres;
     const int fbYRes = (int)ctx->dpyAttr[dpy].yres;
-    if(isDisplaySplit(ctx, dpy)) {
+
+    /* When source split is enabled, both the panels are calibrated
+     * in a single coordinate system. So only one ROI is generated
+     * for the whole panel extending equally from the midpoint and
+     * populated for the left side. */
+    if(!qdutils::MDPVersion::getInstance().isSrcSplit() &&
+            isDisplaySplit(ctx, dpy)) {
         const int lSplit = getLeftSplit(ctx, dpy);
         ctx->listStats[dpy].lRoi = (struct hwc_rect){0, 0, lSplit, fbYRes};
         ctx->listStats[dpy].rRoi = (struct hwc_rect){lSplit, 0, fbXRes, fbYRes};
@@ -2607,18 +2678,28 @@
 
    /* Align to minimum width recommended by the panel */
    if((t_roi.right - t_roi.left) < MIN_WIDTH) {
-       if((t_roi.left + MIN_WIDTH) > boundary.right)
-           t_roi.left = t_roi.right - MIN_WIDTH;
-       else
-           t_roi.right = t_roi.left + MIN_WIDTH;
+       if(MIN_WIDTH == boundary.right - boundary.left) {
+           t_roi.left = 0;
+           t_roi.right = MIN_WIDTH;
+       } else {
+           if((t_roi.left + MIN_WIDTH) > boundary.right)
+               t_roi.left = t_roi.right - MIN_WIDTH;
+           else
+               t_roi.right = t_roi.left + MIN_WIDTH;
+       }
    }
 
   /* Align to minimum height recommended by the panel */
    if((t_roi.bottom - t_roi.top) < MIN_HEIGHT) {
-       if((t_roi.top + MIN_HEIGHT) > boundary.bottom)
-           t_roi.top = t_roi.bottom - MIN_HEIGHT;
-       else
-           t_roi.bottom = t_roi.top + MIN_HEIGHT;
+       if(MIN_HEIGHT == boundary.bottom - boundary.top) {
+           t_roi.top = 0;
+           t_roi.bottom = MIN_HEIGHT;
+       } else {
+           if((t_roi.top + MIN_HEIGHT) > boundary.bottom)
+               t_roi.top = t_roi.bottom - MIN_HEIGHT;
+           else
+               t_roi.bottom = t_roi.top + MIN_HEIGHT;
+       }
    }
 
    /* Align left and width to meet panel restrictions */
@@ -2639,7 +2720,6 @@
        }
    }
 
-
    /* Align top and height to meet panel restrictions */
    if(TOP_ALIGN)
        t_roi.top = t_roi.top - (t_roi.top % TOP_ALIGN);
@@ -2658,7 +2738,6 @@
        }
    }
 
-
    return t_roi;
 }
 
@@ -2769,4 +2848,104 @@
     }
 }
 
+void ColorMode::init() {
+    //Map symbols from libmm-qdcm and get list of modes
+    mModeHandle = dlopen("libmm-qdcm.so", RTLD_NOW);
+    if (mModeHandle) {
+        *(void **)& fnApplyDefaultMode = dlsym(mModeHandle, "applyDefaults");
+        *(void **)& fnApplyModeById = dlsym(mModeHandle, "applyModeById");
+        *(void **)& fnGetNumModes = dlsym(mModeHandle, "getNumDisplayModes");
+        *(void **)& fnGetModeList = dlsym(mModeHandle, "getDisplayModeIdList");
+        *(void **)& fnSetDefaultMode = dlsym(mModeHandle, "setDefaultMode");
+    } else {
+        ALOGW("Unable to load libmm-qdcm");
+    }
+
+    if(fnGetNumModes) {
+        mNumModes = fnGetNumModes(HWC_DISPLAY_PRIMARY);
+        if(mNumModes > MAX_NUM_COLOR_MODES) {
+            ALOGE("Number of modes is above the limit: %d", mNumModes);
+            mNumModes = 0;
+            return;
+        }
+        if(fnGetModeList) {
+            fnGetModeList(mModeList, &mCurMode, HWC_DISPLAY_PRIMARY);
+            mCurModeIndex = getIndexForMode(mCurMode);
+            ALOGI("ColorMode: current mode: %d current mode index: %d number of modes: %d",
+                    mCurMode, mCurModeIndex, mNumModes);
+        }
+    }
+}
+
+//Legacy API
+int ColorMode::applyDefaultMode() {
+    if(fnApplyDefaultMode) {
+        return fnApplyDefaultMode(HWC_DISPLAY_PRIMARY);
+    } else {
+        return -EINVAL;
+    }
+}
+
+int ColorMode::applyModeByID(int modeID) {
+    if(fnApplyModeById) {
+        int ret = fnApplyModeById(modeID, HWC_DISPLAY_PRIMARY);
+        if (!ret)
+            ret = setDefaultMode(modeID);
+        return ret;
+    } else {
+        return -EINVAL;
+    }
+}
+
+//This API is called from setActiveConfig
+//The value here must be set as default
+int ColorMode::applyModeByIndex(int index) {
+    int ret = 0;
+    int mode  = getModeForIndex(index);
+    if(mode < 0) {
+        ALOGE("Invalid mode for index: %d", index);
+        return -EINVAL;
+    }
+    ALOGD("%s: Applying mode index: %d modeID: %d", __FUNCTION__, index, mode);
+    ret = applyModeByID(mode);
+    if(!ret) {
+        mCurModeIndex = index;
+        setDefaultMode(mode);
+    }
+    return ret;
+}
+
+int ColorMode::setDefaultMode(int modeID) {
+    if(fnSetDefaultMode) {
+        ALOGD("Setting default color mode to %d", modeID);
+        return fnSetDefaultMode(modeID, HWC_DISPLAY_PRIMARY);
+    } else {
+        return -EINVAL;
+    }
+}
+
+int ColorMode::getModeForIndex(int index) {
+    if(index < mNumModes) {
+        return mModeList[index];
+    } else {
+        return -EINVAL;
+    }
+}
+
+int ColorMode::getIndexForMode(int mode) {
+    if(mModeList) {
+        for(int32_t i = 0; i < mNumModes; i++)
+            if(mModeList[i] == mode)
+                return i;
+    }
+    return -EINVAL;
+}
+
+void ColorMode::destroy() {
+    if(mModeHandle) {
+        dlclose(mModeHandle);
+        mModeHandle = NULL;
+    }
+}
+
 };//namespace qhwc
diff --git a/msm8994/libhwcomposer/hwc_utils.h b/msm8994/libhwcomposer/hwc_utils.h
index 797f9b0..c9f35e5 100644
--- a/msm8994/libhwcomposer/hwc_utils.h
+++ b/msm8994/libhwcomposer/hwc_utils.h
@@ -48,6 +48,7 @@
 #define STR(f) #f;
 // Max number of PTOR layers handled
 #define MAX_PTOR_LAYERS 2
+#define MAX_NUM_COLOR_MODES 32
 
 //Fwrd decls
 struct hwc_context_t;
@@ -229,6 +230,36 @@
     uint32_t mCount;
 };
 
+//ColorModes for primary displays
+class ColorMode {
+public:
+    void init();
+    void destroy();
+    int32_t getNumModes() { return mNumModes; }
+    const int32_t* getModeList() { return mModeList; }
+    int32_t getModeForIndex(int32_t index);
+    int32_t getIndexForMode(int32_t mode);
+    int applyDefaultMode();
+    int applyModeByID(int modeID);
+    int applyModeByIndex(int index);
+    int setDefaultMode(int modeID);
+    int getActiveModeIndex() { return mCurModeIndex; }
+private:
+    int32_t (*fnGetNumModes)(int /*dispID*/);
+    int32_t (*fnGetModeList)(int32_t* /*mModeList*/, int32_t* /*current default*/,
+            int32_t /*dispID*/);
+    int (*fnApplyDefaultMode)(int /*dispID*/);
+    int (*fnApplyModeById)(int /*modeID*/, int /*dispID*/);
+    int (*fnSetDefaultMode)(int /*modeID*/, int /*dispID*/);
+
+    void*     mModeHandle = NULL;
+    int32_t   mModeList[MAX_NUM_COLOR_MODES];
+    int32_t   mNumModes = 0;
+    int32_t   mCurModeIndex = 0;
+    int32_t   mCurMode = 0;
+
+};
+
 inline uint32_t LayerRotMap::getCount() const {
     return mCount;
 }
@@ -316,6 +347,7 @@
 bool areLayersIntersecting(const hwc_layer_1_t* layer1,
         const hwc_layer_1_t* layer2);
 bool operator ==(const hwc_rect_t& lhs, const hwc_rect_t& rhs);
+bool layerUpdating(const hwc_layer_1_t* layer);
 
 // returns true if Action safe dimensions are set and target supports Actionsafe
 bool isActionSafePresent(hwc_context_t *ctx, int dpy);
@@ -352,6 +384,9 @@
 // Resets display ROI to full panel resoluion
 void resetROI(hwc_context_t *ctx, const int dpy);
 
+// Modifies ROI even from middle of the screen
+hwc_rect expandROIFromMidPoint(hwc_rect roi, hwc_rect fullFrame);
+
 // Aligns updating ROI to panel restrictions
 hwc_rect_t getSanitizeROI(struct hwc_rect roi, hwc_rect boundary);
 
@@ -439,6 +474,9 @@
 // Returns true if rect1 is peripheral to rect2, false otherwise.
 bool isPeripheral(const hwc_rect_t& rect1, const hwc_rect_t& rect2);
 
+// Applies default mode at boot
+void applyDefaultMode(hwc_context_t *ctx);
+
 // Inline utility functions
 static inline bool isSkipLayer(const hwc_layer_1_t* l) {
     return (UNLIKELY(l && (l->flags & HWC_SKIP_LAYER)));
@@ -641,6 +679,10 @@
     bool mUseMetaDataRefreshRate;
    // Stores the hpd enabled status- avoids re-enabling HDP on suspend resume.
     bool mHPDEnabled;
+    //Used to notify that default mode has been applied
+    bool mDefaultModeApplied;
+    //Manages color modes
+    qhwc::ColorMode *mColorMode;
 };
 
 namespace qhwc {
diff --git a/msm8994/libhwcomposer/hwc_virtual.cpp b/msm8994/libhwcomposer/hwc_virtual.cpp
index 06418bf..a294a75 100644
--- a/msm8994/libhwcomposer/hwc_virtual.cpp
+++ b/msm8994/libhwcomposer/hwc_virtual.cpp
@@ -223,13 +223,15 @@
         private_handle_t* ohnd, int dpy) {
     bool scalingMode = false;
     int fbWidth = ctx->dpyAttr[dpy].xres;
-    int fbHeight =  ctx->dpyAttr[dpy].yres;
-    if((getWidth(ohnd) != fbWidth) || (getHeight(ohnd) != fbHeight)) {
+    int fbHeight = ctx->dpyAttr[dpy].yres;
+    int alW = 0, alH = 0;
+    getBufferSizeAndDimensions(fbWidth, fbHeight, ohnd->format, alW, alH);
+    if((getWidth(ohnd) != alW) || (getHeight(ohnd) != alH)) {
         scalingMode = true;
     }
     ctx->dpyAttr[dpy].mMDPScalingMode = scalingMode;
 
     ALOGD_IF(HWCVIRTUAL_LOG, "%s fb(%dx%d) outputBuffer(%dx%d) scalingMode=%d",
-            __FUNCTION__, fbWidth, fbHeight,
+            __FUNCTION__, alW, alH,
             getWidth(ohnd), getHeight(ohnd), scalingMode);
 }
diff --git a/msm8994/libmemtrack/kgsl.c b/msm8994/libmemtrack/kgsl.c
index 6dc9774..3a63d09 100644
--- a/msm8994/libmemtrack/kgsl.c
+++ b/msm8994/libmemtrack/kgsl.c
@@ -99,7 +99,7 @@
          *  gpuaddr useraddr     size    id flags       type            usage sglen
          * 545ba000 545ba000     4096     1 ----pY     gpumem      arraybuffer     1
          */
-        ret = sscanf(line, "%*x %*x %lu %*d %6s %6s %18s %*d\n",
+        ret = sscanf(line, "%*x %*lx %lu %*d %6s %6s %18s %*d\n",
                      &size, flags, line_type, line_usage);
         if (ret != 4) {
             continue;
@@ -113,7 +113,7 @@
                 unaccounted_size += size;
 
         } else if (type == MEMTRACK_TYPE_GRAPHICS && strcmp(line_type, "ion") == 0) {
-            if ( !(is_surfaceflinger == false && strcmp(line_usage, "egl_surface") == 0)) {
+            if (!is_surfaceflinger || strcmp(line_usage, "egl_image") != 0) {
                 unaccounted_size += size;
             }
         }
diff --git a/msm8994/liboverlay/overlay.cpp b/msm8994/liboverlay/overlay.cpp
index c250919..a34e599 100644
--- a/msm8994/liboverlay/overlay.cpp
+++ b/msm8994/liboverlay/overlay.cpp
@@ -282,38 +282,62 @@
     return false;
 }
 
-int Overlay::comparePipePriority(utils::eDest pipe1Index,
+bool Overlay::needsPrioritySwap(utils::eDest pipe1Index,
         utils::eDest pipe2Index) {
     validate((int)pipe1Index);
     validate((int)pipe2Index);
+
     uint8_t pipe1Prio = mPipeBook[(int)pipe1Index].mPipe->getPriority();
     uint8_t pipe2Prio = mPipeBook[(int)pipe2Index].mPipe->getPriority();
-    if(pipe1Prio > pipe2Prio)
-        return -1;
-    else if(pipe1Prio < pipe2Prio)
-        return 1;
-    else {
+
+    int pipe1Id = mPipeBook[(int)pipe1Index].mPipe->getPipeId();
+    int pipe2Id = mPipeBook[(int)pipe2Index].mPipe->getPipeId();
+
+    utils::eMdpPipeType leftType = PipeBook::getPipeType(pipe1Index);
+    utils::eMdpPipeType rightType = PipeBook::getPipeType(pipe2Index);
+
+    if(pipe1Id >=0 && pipe2Id >=0) {
+        // LEFT priority should be higher then RIGHT
+        return (pipe1Prio > pipe2Prio);
+    } else if(pipe1Id < 0 && pipe2Id < 0) {
         // If we are here, Source Split is enabled and both pipes are
         // new requests. In this case left type should be of higher prio
         // than right type
-        utils::eMdpPipeType leftType = PipeBook::getPipeType(pipe1Index);
-        utils::eMdpPipeType rightType = PipeBook::getPipeType(pipe2Index);
-
         if(leftType == rightType) {
             //Safe. Onus on driver to assign correct pipes within same type
-            return 1;
-        } else if(leftType == OV_MDP_PIPE_DMA or rightType == OV_MDP_PIPE_VG) {
-            //If we are here, right is definitely a higher prio type.
+            return false;
+        } else {
             //This check takes advantage of having only 3 types and avoids 3
             //different failure combination checks.
-            return -1;
+            // Swap IF:
+            // ----------------
+            // | Left | Right |
+            // ================
+            // | DMA  | ViG   |
+            // ----------------
+            // | DMA  | RGB   |
+            // ----------------
+            // | RGB  | ViG   |
+            // ----------------
+            return (leftType == OV_MDP_PIPE_DMA or rightType == OV_MDP_PIPE_VG);
+        }
+    } else if(pipe1Id < 0) {
+        //LEFT needs new allocation.
+        if(leftType == rightType) {
+            // If RIGHT has highest priority(lowest id), swap it.
+            return (pipe2Id == PipeBook::pipeMinID[leftType]);
         } else {
-            //Types are correct priority-wise
-            return 1;
+            return (leftType == OV_MDP_PIPE_DMA or rightType == OV_MDP_PIPE_VG);
+        }
+    } else { /* if (pipe2Id < 0) */
+        // RIGHT needs new allocation.
+        if(leftType == rightType) {
+            // If LEFT has lowest priority(highest id), swap it.
+            return (pipe1Id == PipeBook::pipeMaxID[leftType]);
+        } else {
+            return (leftType == OV_MDP_PIPE_DMA or rightType == OV_MDP_PIPE_VG);
         }
     }
-
-    return 0;
 }
 
 bool Overlay::commit(utils::eDest dest) {
@@ -413,6 +437,13 @@
         }
     }
 
+    PipeBook::pipeMinID[OV_MDP_PIPE_RGB] = 8;
+    PipeBook::pipeMaxID[OV_MDP_PIPE_RGB] = (numPipesXType[OV_MDP_PIPE_RGB] == 3)? 32 : 512;
+    PipeBook::pipeMinID[OV_MDP_PIPE_VG] = 1;
+    PipeBook::pipeMaxID[OV_MDP_PIPE_VG] = (numPipesXType[OV_MDP_PIPE_VG] == 3)? 4 : 256;
+    PipeBook::pipeMinID[OV_MDP_PIPE_DMA] = 64;
+    PipeBook::pipeMaxID[OV_MDP_PIPE_DMA] = 128;
+
     FILE *displayDeviceFP = NULL;
     char fbType[MAX_FRAME_BUFFER_NAME_SIZE];
     char msmFbTypePath[MAX_FRAME_BUFFER_NAME_SIZE];
@@ -578,6 +609,8 @@
 int Overlay::PipeBook::sAllocatedBitmap = 0;
 utils::eMdpPipeType Overlay::PipeBook::pipeTypeLUT[utils::OV_MAX] =
     {utils::OV_MDP_PIPE_ANY};
+int Overlay::PipeBook::pipeMinID[utils::OV_MDP_PIPE_ANY] = {0};
+int Overlay::PipeBook::pipeMaxID[utils::OV_MDP_PIPE_ANY] = {0};
 void *Overlay::sLibScaleHandle = NULL;
 int (*Overlay::sFnProgramScale)(struct mdp_overlay_list *) = NULL;
 /* Dynamically link ABL library */
diff --git a/msm8994/liboverlay/overlay.h b/msm8994/liboverlay/overlay.h
index 984b439..45b5e57 100644
--- a/msm8994/liboverlay/overlay.h
+++ b/msm8994/liboverlay/overlay.h
@@ -123,11 +123,10 @@
      */
     bool isPipeTypeAttached(utils::eMdpPipeType type);
     /* Compare pipe priorities and return
-     * 1 if 1st pipe has a higher priority
-     * 0 if both have the same priority
-     *-1 if 2nd pipe has a higher priority
+     * true - A swap is needed to fix the priority.
+     * false - Good, priority wise.
      */
-    int comparePipePriority(utils::eDest pipe1Index, utils::eDest pipe2Index);
+    bool needsPrioritySwap(utils::eDest pipe1Index, utils::eDest pipe2Index);
     /* Returns pipe dump. Expects a NULL terminated buffer of big enough size
      * to populate.
      */
@@ -229,6 +228,9 @@
 
         static int NUM_PIPES;
         static utils::eMdpPipeType pipeTypeLUT[utils::OV_MAX];
+        static int pipeMinID[utils::OV_MDP_PIPE_ANY];
+        static int pipeMaxID[utils::OV_MDP_PIPE_ANY];
+
         /* Session for reserved pipes */
         enum Session {
             NONE,
diff --git a/msm8994/liboverlay/overlayMdp.cpp b/msm8994/liboverlay/overlayMdp.cpp
index 3932c4c..04e6672 100644
--- a/msm8994/liboverlay/overlayMdp.cpp
+++ b/msm8994/liboverlay/overlayMdp.cpp
@@ -353,8 +353,31 @@
     mdp_overlay* ovArray[count];
     memset(&ovArray, 0, sizeof(ovArray));
 
+    uint8_t max_horz_deci = 0, max_vert_deci = 0;
+
+    // Decimation factor for the left and right pipe differs, when there is a
+    // one pixel difference in the dst width of right pipe and the left pipe.
+    // libscalar returns a failure as it expects decimation on both the pipe
+    // to be same. So compare the decimation factor on both the pipes and assign
+    // the maximum of it.
     for(int i = 0; i < count; i++) {
-        ovArray[i] = &mdpCtrlArray[i]->mOVInfo;
+        mdp_overlay *ov_current = &mdpCtrlArray[i]->mOVInfo;
+        for(int j = i + 1; j < count; j++) {
+            mdp_overlay *ov_next = &mdpCtrlArray[j]->mOVInfo;
+            if(ov_current->z_order == ov_next->z_order) {
+                max_horz_deci = utils::max(ov_current->horz_deci,
+                                           ov_next->horz_deci);
+                max_vert_deci = utils::max(ov_current->vert_deci,
+                                           ov_next->vert_deci);
+
+                ov_current->horz_deci = max_horz_deci;
+                ov_next->horz_deci = max_horz_deci;
+                ov_current->vert_deci = max_vert_deci;
+                ov_next->vert_deci = max_vert_deci;
+                break;
+            }
+        }
+        ovArray[i] = ov_current;
     }
 
     struct mdp_overlay_list list;
diff --git a/msm8994/libqdutils/mdp_version.cpp b/msm8994/libqdutils/mdp_version.cpp
index 402e129..5949dc9 100644
--- a/msm8994/libqdutils/mdp_version.cpp
+++ b/msm8994/libqdutils/mdp_version.cpp
@@ -256,6 +256,7 @@
                 ALOGI("PartialUpdate disabled by property");
         }
         fclose(panelInfoNodeFP);
+        free(readLine);
     } else {
         ALOGE("Failed to open msm_fb_panel_info node");
     }
diff --git a/msm8994/libqdutils/qd_utils.cpp b/msm8994/libqdutils/qd_utils.cpp
index 5726202..d841712 100644
--- a/msm8994/libqdutils/qd_utils.cpp
+++ b/msm8994/libqdutils/qd_utils.cpp
@@ -53,14 +53,14 @@
             }
             fclose(displayDeviceFP);
         } else {
-            ALOGE("%s: Failed to open fb node %d", __func__, j);
+            ALOGD("%s: fb node %d not present", __func__, j);
         }
     }
 
     if (j < HWC_NUM_DISPLAY_TYPES)
         return j;
     else
-        ALOGE("%s: Failed to find HDMI node", __func__);
+        ALOGI("%s: No HDMI node on this device", __func__);
 
     return -1;
 }
diff --git a/msm8994/libqservice/IQService.h b/msm8994/libqservice/IQService.h
index ef47475..8ece946 100644
--- a/msm8994/libqservice/IQService.h
+++ b/msm8994/libqservice/IQService.h
@@ -59,6 +59,7 @@
         CONFIGURE_DYN_REFRESH_RATE = 18,
         SET_PARTIAL_UPDATE = 19,   // Preference on partial update feature
         TOGGLE_SCREEN_UPDATE = 20, // Provides ability to disable screen updates
+        APPLY_MODE_BY_ID = 40, //Apply display mode by ID
         COMMAND_LIST_END = 400,
     };