Merge "display: Add display HAL support for msm_bronze"
diff --git a/libcopybit/copybit.cpp b/libcopybit/copybit.cpp
index ec12b83..3b7039c 100644
--- a/libcopybit/copybit.cpp
+++ b/libcopybit/copybit.cpp
@@ -126,6 +126,7 @@
     switch (format) {
         case HAL_PIXEL_FORMAT_RGB_565:       return MDP_RGB_565;
         case HAL_PIXEL_FORMAT_RGBX_8888:     return MDP_RGBX_8888;
+        case HAL_PIXEL_FORMAT_BGRX_8888:     return MDP_BGRX_8888;
         case HAL_PIXEL_FORMAT_RGB_888:       return MDP_RGB_888;
         case HAL_PIXEL_FORMAT_RGBA_8888:     return MDP_RGBA_8888;
         case HAL_PIXEL_FORMAT_BGRA_8888:     return MDP_BGRA_8888;
diff --git a/libexternal/external.cpp b/libexternal/external.cpp
index 609f9c1..045edd8 100644
--- a/libexternal/external.cpp
+++ b/libexternal/external.cpp
@@ -588,7 +588,9 @@
             // if primary resolution is more than the hdmi resolution
             // configure dpy attr to primary resolution and set
             // downscale mode
-            if((priW * priH) > (width * height)) {
+            // Restrict this upto 1080p resolution max
+            if(((priW * priH) > (width * height)) &&
+                 (priW <= qdutils::MAX_DISPLAY_DIM )) {
                 mHwcContext->dpyAttr[HWC_DISPLAY_EXTERNAL].xres = priW;
                 mHwcContext->dpyAttr[HWC_DISPLAY_EXTERNAL].yres = priH;
                 // HDMI is always in landscape, so always assign the higher
diff --git a/libgralloc/alloc_controller.cpp b/libgralloc/alloc_controller.cpp
index 9af45e2..98047e4 100644
--- a/libgralloc/alloc_controller.cpp
+++ b/libgralloc/alloc_controller.cpp
@@ -184,12 +184,6 @@
 IonController::IonController()
 {
     mIonAlloc = new IonAlloc();
-    mUseTZProtection = false;
-    char property[PROPERTY_VALUE_MAX];
-    if ((property_get("persist.gralloc.cp.level3", property, NULL) <= 0) ||
-                            (atoi(property) != 1)) {
-        mUseTZProtection = true;
-    }
 }
 
 int IonController::allocate(alloc_data& data, int usage)
@@ -210,7 +204,7 @@
         ionFlags |= ION_HEAP(ION_IOMMU_HEAP_ID);
 
     if(usage & GRALLOC_USAGE_PROTECTED) {
-        if ((mUseTZProtection) && (usage & GRALLOC_USAGE_PRIVATE_MM_HEAP)) {
+        if (usage & GRALLOC_USAGE_PRIVATE_MM_HEAP) {
             ionFlags |= ION_HEAP(ION_CP_MM_HEAP_ID);
             ionFlags |= ION_SECURE;
         } else {
diff --git a/libgralloc/alloc_controller.h b/libgralloc/alloc_controller.h
index 8954d39..5fe81fa 100644
--- a/libgralloc/alloc_controller.h
+++ b/libgralloc/alloc_controller.h
@@ -65,7 +65,6 @@
 
     private:
     IonAlloc* mIonAlloc;
-    bool mUseTZProtection;
 
 };
 } //end namespace gralloc
diff --git a/libgralloc/gpu.cpp b/libgralloc/gpu.cpp
index ce15304..0136407 100644
--- a/libgralloc/gpu.cpp
+++ b/libgralloc/gpu.cpp
@@ -146,6 +146,10 @@
             flags |= private_handle_t::PRIV_FLAGS_HW_TEXTURE;
         }
 
+        if(usage & GRALLOC_USAGE_PRIVATE_SECURE_DISPLAY) {
+            flags |= private_handle_t::PRIV_FLAGS_SECURE_DISPLAY;
+        }
+
         flags |= data.allocType;
         int eBaseAddr = int(eData.base) + eData.offset;
         private_handle_t *hnd = new private_handle_t(data.fd, size, flags,
diff --git a/libgralloc/gralloc_priv.h b/libgralloc/gralloc_priv.h
index b3fddf1..03d15a7 100644
--- a/libgralloc/gralloc_priv.h
+++ b/libgralloc/gralloc_priv.h
@@ -70,6 +70,9 @@
 
     /* CAMERA heap is a carveout heap for camera, is not secured*/
     GRALLOC_USAGE_PRIVATE_CAMERA_HEAP     =       0x00400000,
+
+    /* This flag is used for SECURE display usecase */
+    GRALLOC_USAGE_PRIVATE_SECURE_DISPLAY  =       0x00800000,
 };
 
 enum {
@@ -101,6 +104,7 @@
     HAL_PIXEL_FORMAT_YCbCr_444_SP           = 0x10F,
     HAL_PIXEL_FORMAT_YCrCb_444_SP           = 0x110,
     HAL_PIXEL_FORMAT_YCrCb_422_I            = 0x111,
+    HAL_PIXEL_FORMAT_BGRX_8888              = 0x112,
     HAL_PIXEL_FORMAT_INTERLACE              = 0x180,
 
 };
@@ -162,6 +166,7 @@
             PRIV_FLAGS_ITU_R_601          = 0x00200000,
             PRIV_FLAGS_ITU_R_601_FR       = 0x00400000,
             PRIV_FLAGS_ITU_R_709          = 0x00800000,
+            PRIV_FLAGS_SECURE_DISPLAY     = 0x01000000,
         };
 
         // file-descriptors
diff --git a/libhwcomposer/hwc.cpp b/libhwcomposer/hwc.cpp
index ec9abfb..5038025 100644
--- a/libhwcomposer/hwc.cpp
+++ b/libhwcomposer/hwc.cpp
@@ -446,6 +446,9 @@
             supported |= HWC_DISPLAY_EXTERNAL_BIT;
         value[0] = supported;
         break;
+    case HWC_FORMAT_RB_SWAP:
+        value[0] = 1;
+        break;
     default:
         return -EINVAL;
     }
diff --git a/libhwcomposer/hwc_copybit.cpp b/libhwcomposer/hwc_copybit.cpp
index 8f2cf55..912da27 100644
--- a/libhwcomposer/hwc_copybit.cpp
+++ b/libhwcomposer/hwc_copybit.cpp
@@ -246,8 +246,8 @@
         rect.bottom};
 
     copybit_image_t buf;
-    buf.w = ALIGN(hnd->width,32);
-    buf.h = hnd->height;
+    buf.w = ALIGN(getWidth(hnd),32);
+    buf.h = getHeight(hnd);
     buf.format = hnd->format;
     buf.base = (void *)hnd->base;
     buf.handle = (native_handle_t *)hnd;
@@ -347,12 +347,22 @@
 
     // Set the copybit source:
     copybit_image_t src;
-    src.w = hnd->width;
-    src.h = hnd->height;
+    src.w = getWidth(hnd);
+    src.h = getHeight(hnd);
     src.format = hnd->format;
+
+    // Handle R/B swap
+    if ((layer->flags & HWC_FORMAT_RB_SWAP)) {
+        if (src.format == HAL_PIXEL_FORMAT_RGBA_8888) {
+            src.format = HAL_PIXEL_FORMAT_BGRA_8888;
+        } else if (src.format == HAL_PIXEL_FORMAT_RGBX_8888) {
+            src.format = HAL_PIXEL_FORMAT_BGRX_8888;
+        }
+    }
+
     src.base = (void *)hnd->base;
     src.handle = (native_handle_t *)layer->handle;
-    src.horiz_padding = src.w - hnd->width;
+    src.horiz_padding = src.w - getWidth(hnd);
     // Initialize vertical padding to zero for now,
     // this needs to change to accomodate vertical stride
     // if needed in the future
diff --git a/libhwcomposer/hwc_dump_layers.cpp b/libhwcomposer/hwc_dump_layers.cpp
index b9c09b6..1b3d097 100644
--- a/libhwcomposer/hwc_dump_layers.cpp
+++ b/libhwcomposer/hwc_dump_layers.cpp
@@ -236,7 +236,7 @@
     // Log Line 1
     ALOGI("Display[%s] Layer[%d] SrcBuff[%dx%d] SrcCrop[%dl, %dt, %dr, %db] "
         "DispFrame[%dl, %dt, %dr, %db] VisRegsScr%s", mDisplayName, layerIndex,
-        (hnd)? hnd->width : -1, (hnd)? hnd->height : -1,
+        (hnd)? getWidth(hnd) : -1, (hnd)? getHeight(hnd) : -1,
         sourceCrop.left, sourceCrop.top,
         sourceCrop.right, sourceCrop.bottom,
         displayFrame.left, displayFrame.top,
@@ -328,7 +328,7 @@
                 break;
         }
         if (SkBitmap::kNo_Config != tempSkBmpConfig) {
-            tempSkBmp->setConfig(tempSkBmpConfig, hnd->width, hnd->height);
+            tempSkBmp->setConfig(tempSkBmpConfig, getWidth(hnd), getHeight(hnd));
             tempSkBmp->setPixels((void*)hnd->base);
             bResult = SkImageEncoder::EncodeFile(dumpFilename,
                                     *tempSkBmp, SkImageEncoder::kPNG_Type, 100);
@@ -348,7 +348,7 @@
         bool bResult = false;
         sprintf(dumpFilename, "%s/sfdump%03d.layer%d.%dx%d.%s.%s.raw",
             mDumpDirRaw, mDumpCntrRaw,
-            layerIndex, hnd->width, hnd->height,
+            layerIndex, getWidth(hnd), getHeight(hnd),
             pixFormatStr, mDisplayName);
         FILE* fp = fopen(dumpFilename, "w+");
         if (NULL != fp) {
diff --git a/libhwcomposer/hwc_fbupdate.cpp b/libhwcomposer/hwc_fbupdate.cpp
index 53b3d18..12177b3 100644
--- a/libhwcomposer/hwc_fbupdate.cpp
+++ b/libhwcomposer/hwc_fbupdate.cpp
@@ -106,7 +106,7 @@
         }
         overlay::Overlay& ov = *(ctx->mOverlay);
         private_handle_t *hnd = (private_handle_t *)layer->handle;
-        ovutils::Whf info(hnd->width, hnd->height,
+        ovutils::Whf info(getWidth(hnd), getHeight(hnd),
                           ovutils::getMdpFormat(hnd->format), hnd->size);
 
         //Request a pipe
@@ -244,7 +244,7 @@
         }
         overlay::Overlay& ov = *(ctx->mOverlay);
         private_handle_t *hnd = (private_handle_t *)layer->handle;
-        ovutils::Whf info(hnd->width, hnd->height,
+        ovutils::Whf info(getWidth(hnd), getHeight(hnd),
                           ovutils::getMdpFormat(hnd->format), hnd->size);
 
         //Request left pipe
diff --git a/libhwcomposer/hwc_mdpcomp.cpp b/libhwcomposer/hwc_mdpcomp.cpp
index 4bbad8b..e65d5e7 100644
--- a/libhwcomposer/hwc_mdpcomp.cpp
+++ b/libhwcomposer/hwc_mdpcomp.cpp
@@ -480,7 +480,7 @@
 
     const int numAppLayers = ctx->listStats[mDpy].numAppLayers;
 
-    if(sIdleFallBack) {
+    if(sIdleFallBack && !ctx->listStats[mDpy].secureUI) {
         ALOGD_IF(isDebug(), "%s: Idle fallback dpy %d",__FUNCTION__, mDpy);
         return false;
     }
@@ -576,14 +576,26 @@
 
 bool MDPComp::partialMDPComp(hwc_context_t *ctx, hwc_display_contents_1_t* list)
 {
-    int numAppLayers = ctx->listStats[mDpy].numAppLayers;
-
     if(!sEnableMixedMode) {
         //Mixed mode is disabled. No need to even try caching.
         return false;
     }
 
-    //Setup mCurrentFrame
+    bool ret = false;
+    if(isLoadBasedCompDoable(ctx, list)) {
+        ret = loadBasedComp(ctx, list);
+    }
+
+    if(!ret) {
+        ret = cacheBasedComp(ctx, list);
+    }
+
+    return ret;
+}
+
+bool MDPComp::cacheBasedComp(hwc_context_t *ctx,
+        hwc_display_contents_1_t* list) {
+    int numAppLayers = ctx->listStats[mDpy].numAppLayers;
     mCurrentFrame.reset(numAppLayers);
     updateLayerCache(ctx, list);
 
@@ -600,7 +612,7 @@
     }
 
     updateYUV(ctx, list, false /*secure only*/);
-    bool ret = batchLayers(ctx, list); //sets up fbZ also
+    bool ret = markLayersForCaching(ctx, list); //sets up fbZ also
     if(!ret) {
         ALOGD_IF(isDebug(),"%s: batching failed, dpy %d",__FUNCTION__, mDpy);
         return false;
@@ -633,6 +645,77 @@
     return true;
 }
 
+bool MDPComp::loadBasedComp(hwc_context_t *ctx,
+        hwc_display_contents_1_t* list) {
+    int numAppLayers = ctx->listStats[mDpy].numAppLayers;
+    mCurrentFrame.reset(numAppLayers);
+
+    //TODO BatchSize could be optimized further based on available pipes, split
+    //displays etc.
+    const int batchSize = numAppLayers - (sMaxPipesPerMixer - 1);
+    if(batchSize <= 0) {
+        ALOGD_IF(isDebug(), "%s: Not attempting", __FUNCTION__);
+        return false;
+    }
+
+    int minBatchStart = -1;
+    size_t minBatchPixelCount = SIZE_MAX;
+
+    for(int i = 0; i <= numAppLayers - batchSize; i++) {
+        uint32_t batchPixelCount = 0;
+        for(int j = i; j < i + batchSize; j++) {
+            hwc_layer_1_t* layer = &list->hwLayers[j];
+            hwc_rect_t crop = layer->sourceCrop;
+            batchPixelCount += (crop.right - crop.left) *
+                    (crop.bottom - crop.top);
+        }
+
+        if(batchPixelCount < minBatchPixelCount) {
+            minBatchPixelCount = batchPixelCount;
+            minBatchStart = i;
+        }
+    }
+
+    if(minBatchStart < 0) {
+        ALOGD_IF(isDebug(), "%s: No batch found batchSize %d numAppLayers %d",
+                __FUNCTION__, batchSize, numAppLayers);
+        return false;
+    }
+
+    for(int i = 0; i < numAppLayers; i++) {
+        if(i < minBatchStart || i >= minBatchStart + batchSize) {
+            hwc_layer_1_t* layer = &list->hwLayers[i];
+            if(not isSupportedForMDPComp(ctx, layer)) {
+                ALOGD_IF(isDebug(), "%s: MDP unsupported layer found at %d",
+                        __FUNCTION__, i);
+                return false;
+            }
+            mCurrentFrame.isFBComposed[i] = false;
+        }
+    }
+
+    mCurrentFrame.fbZ = minBatchStart;
+    mCurrentFrame.fbCount = batchSize;
+    mCurrentFrame.mdpCount = mCurrentFrame.layerCount - batchSize;
+
+    if(!arePipesAvailable(ctx, list)) {
+        return false;
+    }
+
+    ALOGD_IF(isDebug(), "%s: fbZ %d batchSize %d",
+                __FUNCTION__, mCurrentFrame.fbZ, batchSize);
+    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)) {
+        return false;
+    }
+    return true;
+}
+
 bool MDPComp::isOnlyVideoDoable(hwc_context_t *ctx,
         hwc_display_contents_1_t* list, bool secureOnly) {
     int numAppLayers = ctx->listStats[mDpy].numAppLayers;
@@ -702,14 +785,126 @@
     return true;
 }
 
-bool MDPComp::batchLayers(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
-    /* Idea is to keep as many contiguous non-updating(cached) layers in FB and
-     * send rest of them through MDP. NEVER mark an updating layer for caching.
-     * But cached ones can be marked for MDP*/
+/* starts at fromIndex and check for each layer to find
+ * if it it has overlapping with any Updating layer above it in zorder
+ * till the end of the batch. returns true if it finds any intersection */
+bool MDPComp::canPushBatchToTop(const hwc_display_contents_1_t* list,
+        int fromIndex, int toIndex) {
+    for(int i = fromIndex; i < toIndex; i++) {
+        if(mCurrentFrame.isFBComposed[i] && !mCurrentFrame.drop[i]) {
+            if(intersectingUpdatingLayers(list, i+1, toIndex, i)) {
+                return false;
+            }
+        }
+    }
+    return true;
+}
+
+/* Checks if given layer at targetLayerIndex has any
+ * intersection with all the updating layers in beween
+ * fromIndex and toIndex. Returns true if it finds intersectiion */
+bool MDPComp::intersectingUpdatingLayers(const hwc_display_contents_1_t* list,
+        int fromIndex, int toIndex, int targetLayerIndex) {
+    for(int i = fromIndex; i <= toIndex; i++) {
+        if(!mCurrentFrame.isFBComposed[i]) {
+            if(areLayersIntersecting(&list->hwLayers[i],
+                        &list->hwLayers[targetLayerIndex]))  {
+                return true;
+            }
+        }
+    }
+    return false;
+}
+
+int MDPComp::getBatch(hwc_display_contents_1_t* list,
+        int& maxBatchStart, int& maxBatchEnd,
+        int& maxBatchCount) {
+    int i = 0;
+    int updatingLayersAbove = 0;//Updating layer count in middle of batch
+    int fbZOrder =-1;
+    while (i < mCurrentFrame.layerCount) {
+        int batchCount = 0;
+        int batchStart = i;
+        int batchEnd = i;
+        int fbZ = batchStart;
+        int firstZReverseIndex = -1;
+        while(i < mCurrentFrame.layerCount) {
+            if(!mCurrentFrame.isFBComposed[i]) {
+                if(!batchCount) {
+                    i++;
+                    break;
+                }
+                updatingLayersAbove++;
+                i++;
+                continue;
+            } else {
+                if(mCurrentFrame.drop[i]) {
+                    i++;
+                    continue;
+                } else if(updatingLayersAbove <= 0) {
+                    batchCount++;
+                    batchEnd = i;
+                    i++;
+                    continue;
+                } else { //Layer is FBComposed, not a drop & updatingLayer > 0
+
+                    // We have a valid updating layer already. If layer-i not
+                    // have overlapping with all updating layers in between
+                    // batch-start and i, then we can add layer i to batch.
+                    if(!intersectingUpdatingLayers(list, batchStart, i-1, i)) {
+                        batchCount++;
+                        batchEnd = i;
+                        i++;
+                        continue;
+                    } else if(canPushBatchToTop(list, batchStart, i)) {
+                        //If All the non-updating layers with in this batch
+                        //does not have intersection with the updating layers
+                        //above in z-order, then we can safely move the batch to
+                        //higher z-order. Increment fbZ as it is moving up.
+                        if( firstZReverseIndex < 0) {
+                            firstZReverseIndex = i;
+                        }
+                        batchCount++;
+                        batchEnd = i;
+                        fbZ += updatingLayersAbove;
+                        i++;
+                        updatingLayersAbove = 0;
+                        continue;
+                    } else {
+                        //both failed.start the loop again from here.
+                        if(firstZReverseIndex >= 0) {
+                            i = firstZReverseIndex;
+                        }
+                        break;
+                    }
+                }
+            }
+        }
+        if(batchCount > maxBatchCount) {
+            maxBatchCount = batchCount;
+            maxBatchStart = batchStart;
+            maxBatchEnd = batchEnd;
+            fbZOrder = fbZ;
+        }
+    }
+    return fbZOrder;
+}
+
+bool  MDPComp::markLayersForCaching(hwc_context_t* ctx,
+        hwc_display_contents_1_t* list) {
+    /* Idea is to keep as many non-updating(cached) layers in FB and
+     * send rest of them through MDP. This is done in 2 steps.
+     *   1. Find the maximum contiguous batch of non-updating layers.
+     *   2. See if we can improve this batch size for caching by adding
+     *      opaque layers around the batch, if they don't have
+     *      any overlapping with the updating layers in between.
+     * NEVER mark an updating layer for caching.
+     * But cached ones can be marked for MDP */
 
     int maxBatchStart = -1;
     int maxBatchEnd = -1;
     int maxBatchCount = 0;
+    int fbZ = -1;
 
     /* All or Nothing is cached. No batching needed */
     if(!mCurrentFrame.fbCount) {
@@ -721,33 +916,13 @@
         return true;
     }
 
-    /* Search for max number of contiguous (cached) layers excluding dropped
-     * layers */
-    int i = 0;
-    while (i < mCurrentFrame.layerCount) {
-        int count = 0;
-        int start = i;
-        while(mCurrentFrame.isFBComposed[i] && i < mCurrentFrame.layerCount) {
-            if(!mCurrentFrame.drop[i])
-                count++;
-            i++;
-        }
-        if(count > maxBatchCount) {
-            maxBatchCount = count;
-            maxBatchStart = start;
-            maxBatchEnd = i - 1;
-            mCurrentFrame.fbZ = maxBatchStart;
-        }
-        if(i < mCurrentFrame.layerCount) i++;
-    }
+    fbZ = getBatch(list, maxBatchStart, maxBatchEnd, maxBatchCount);
 
-    mCurrentFrame.fbCount = maxBatchCount;
-
-    /* reset rest of the layers lying inside ROI for MDP comp  */
+    /* reset rest of the layers lying inside ROI for MDP comp */
     for(int i = 0; i < mCurrentFrame.layerCount; i++) {
         hwc_layer_1_t* layer = &list->hwLayers[i];
         if((i < maxBatchStart || i > maxBatchEnd) &&
-                                    mCurrentFrame.isFBComposed[i]){
+                mCurrentFrame.isFBComposed[i]){
             if(!mCurrentFrame.drop[i]){
                 //If an unsupported layer is being attempted to
                 //be pulled out we should fail
@@ -759,11 +934,14 @@
         }
     }
 
+    // update the frame data
+    mCurrentFrame.fbZ = fbZ;
+    mCurrentFrame.fbCount = maxBatchCount;
     mCurrentFrame.mdpCount = mCurrentFrame.layerCount -
             mCurrentFrame.fbCount - mCurrentFrame.dropCount;
 
     ALOGD_IF(isDebug(),"%s: cached count: %d",__FUNCTION__,
-             mCurrentFrame.fbCount);
+            mCurrentFrame.fbCount);
 
     return true;
 }
@@ -838,24 +1016,25 @@
         return false;
     }
 
-    bool fbBatch = false;
     for (int index = 0, mdpNextZOrder = 0; index < mCurrentFrame.layerCount;
             index++) {
         if(!mCurrentFrame.isFBComposed[index]) {
             int mdpIndex = mCurrentFrame.layerToMDP[index];
             hwc_layer_1_t* layer = &list->hwLayers[index];
 
+            //Leave fbZ for framebuffer. CACHE/GLES layers go here.
+            if(mdpNextZOrder == mCurrentFrame.fbZ) {
+                mdpNextZOrder++;
+            }
             MdpPipeInfo* cur_pipe = mCurrentFrame.mdpToLayer[mdpIndex].pipeInfo;
             cur_pipe->zOrder = mdpNextZOrder++;
 
+
             if(configure(ctx, layer, mCurrentFrame.mdpToLayer[mdpIndex]) != 0 ){
                 ALOGD_IF(isDebug(), "%s: Failed to configure overlay for \
                          layer %d",__FUNCTION__, index);
                 return false;
             }
-        } else if(fbBatch == false && !mCurrentFrame.drop[index]) {
-                mdpNextZOrder++;
-                fbBatch = true;
         }
     }
 
diff --git a/libhwcomposer/hwc_mdpcomp.h b/libhwcomposer/hwc_mdpcomp.h
index d872cdf..3882bee 100644
--- a/libhwcomposer/hwc_mdpcomp.h
+++ b/libhwcomposer/hwc_mdpcomp.h
@@ -144,6 +144,13 @@
     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 */
     bool partialMDPComp(hwc_context_t *ctx, hwc_display_contents_1_t* list);
+    /* Partial MDP comp that uses caching to save power as primary goal */
+    bool cacheBasedComp(hwc_context_t *ctx, hwc_display_contents_1_t* list);
+    /* Partial MDP comp that uses number of pixels to optimize perf goal */
+    bool loadBasedComp(hwc_context_t *ctx, hwc_display_contents_1_t* list);
+    /* Checks if its worth doing load based partial comp */
+    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 secureOnly);
@@ -168,8 +175,17 @@
     /* tracks non updating layers*/
     void updateLayerCache(hwc_context_t* ctx, hwc_display_contents_1_t* list);
     /* optimize layers for mdp comp*/
-    bool batchLayers(hwc_context_t *ctx, hwc_display_contents_1_t* list);
-    /* updates cache map with YUV info */
+    bool markLayersForCaching(hwc_context_t* ctx,
+            hwc_display_contents_1_t* list);
+    int getBatch(hwc_display_contents_1_t* list,
+            int& maxBatchStart, int& maxBatchEnd,
+            int& maxBatchCount);
+    bool canPushBatchToTop(const hwc_display_contents_1_t* list,
+            int fromIndex, int toIndex);
+    bool intersectingUpdatingLayers(const hwc_display_contents_1_t* list,
+            int fromIndex, int toIndex, int targetLayerIndex);
+
+        /* 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);
diff --git a/libhwcomposer/hwc_uevents.cpp b/libhwcomposer/hwc_uevents.cpp
index 8c3d00d..8906216 100644
--- a/libhwcomposer/hwc_uevents.cpp
+++ b/libhwcomposer/hwc_uevents.cpp
@@ -141,6 +141,7 @@
                          "event", __FUNCTION__);
                 ctx->proc->hotplug(ctx->proc, HWC_DISPLAY_EXTERNAL,
                                    EXTERNAL_OFFLINE);
+                ctx->mVirtualonExtActive = false;
             }
             break;
         }
@@ -309,7 +310,10 @@
     char thread_name[64] = HWC_UEVENT_THREAD_NAME;
     prctl(PR_SET_NAME, (unsigned long) &thread_name, 0, 0, 0);
     setpriority(PRIO_PROCESS, 0, HAL_PRIORITY_URGENT_DISPLAY);
-    uevent_init();
+    if(!uevent_init()) {
+        ALOGE("%s: failed to init uevent ",__FUNCTION__);
+        return NULL;
+    }
 
     while(1) {
         len = uevent_next_event(udata, sizeof(udata) - 2);
diff --git a/libhwcomposer/hwc_utils.cpp b/libhwcomposer/hwc_utils.cpp
index aa18abf..06d387d 100644
--- a/libhwcomposer/hwc_utils.cpp
+++ b/libhwcomposer/hwc_utils.cpp
@@ -704,12 +704,14 @@
     ctx->listStats[dpy].skipCount = 0;
     ctx->listStats[dpy].needsAlphaScale = false;
     ctx->listStats[dpy].preMultipliedAlpha = false;
+    ctx->listStats[dpy].isSecurePresent = false;
     ctx->listStats[dpy].yuvCount = 0;
     char property[PROPERTY_VALUE_MAX];
     ctx->listStats[dpy].extOnlyLayerIndex = -1;
     ctx->listStats[dpy].isDisplayAnimating = false;
     ctx->listStats[dpy].roi = ovutils::Dim(0, 0,
                       (int)ctx->dpyAttr[dpy].xres, (int)ctx->dpyAttr[dpy].yres);
+    ctx->listStats[dpy].secureUI = false;
 
     optimizeLayerRects(ctx, list, dpy);
 
@@ -721,6 +723,9 @@
         if (layer->flags & HWC_SCREENSHOT_ANIMATOR_LAYER) {
             ctx->listStats[dpy].isDisplayAnimating = true;
         }
+        if(isSecureDisplayBuffer(hnd)) {
+            ctx->listStats[dpy].secureUI = true;
+        }
 #endif
         // continue if number of app layers exceeds MAX_NUM_APP_LAYERS
         if(ctx->listStats[dpy].numAppLayers > MAX_NUM_APP_LAYERS)
@@ -729,6 +734,10 @@
         //reset yuv indices
         ctx->listStats[dpy].yuvIndices[i] = -1;
 
+        if (isSecureBuffer(hnd)) {
+            ctx->listStats[dpy].isSecurePresent = true;
+        }
+
         if (isSkipLayer(&list->hwLayers[i])) {
             ctx->listStats[dpy].skipCount++;
         }
@@ -919,6 +928,13 @@
     crop_b -= crop_h * bottomCutRatio;
 }
 
+bool areLayersIntersecting(const hwc_layer_1_t* layer1,
+        const hwc_layer_1_t* layer2) {
+    hwc_rect_t irect = getIntersection(layer1->displayFrame,
+            layer2->displayFrame);
+    return isValidRect(irect);
+}
+
 bool isValidRect(const hwc_rect& rect)
 {
    return ((rect.bottom > rect.top) && (rect.right > rect.left)) ;
@@ -1246,6 +1262,13 @@
         }
     }
 
+    if(isSecureDisplayBuffer(hnd)) {
+        // Secure display needs both SECURE_OVERLAY and SECURE_DISPLAY_OV
+        ovutils::setMdpFlags(mdpFlags,
+                             ovutils::OV_MDP_SECURE_OVERLAY_SESSION);
+        ovutils::setMdpFlags(mdpFlags,
+                             ovutils::OV_MDP_SECURE_DISPLAY_OVERLAY_SESSION);
+    }
     //No 90 component and no rot-downscale then flips done by MDP
     //If we use rot then it might as well do flips
     if(!(transform & HWC_TRANSFORM_ROT_90) && !rotDownscale) {
@@ -1371,9 +1394,17 @@
     eTransform orient = static_cast<eTransform>(transform);
     int downscale = 0;
     int rotFlags = ovutils::ROT_FLAGS_NONE;
-    Whf whf(hnd->width, hnd->height,
+    Whf whf(getWidth(hnd), getHeight(hnd),
             getMdpFormat(hnd->format), hnd->size);
 
+    // Handle R/B swap
+    if (layer->flags & HWC_FORMAT_RB_SWAP) {
+        if (hnd->format == HAL_PIXEL_FORMAT_RGBA_8888)
+            whf.format = getMdpFormat(HAL_PIXEL_FORMAT_BGRA_8888);
+        else if (hnd->format == HAL_PIXEL_FORMAT_RGBX_8888)
+            whf.format = getMdpFormat(HAL_PIXEL_FORMAT_BGRX_8888);
+    }
+
     if(dpy && isYuvBuffer(hnd)) {
         if(!ctx->listStats[dpy].isDisplayAnimating) {
             ctx->mPrevCropVideo = crop;
@@ -1494,9 +1525,17 @@
     const int downscale = 0;
     int rotFlags = ROT_FLAGS_NONE;
 
-    Whf whf(hnd->width, hnd->height,
+    Whf whf(getWidth(hnd), getHeight(hnd),
             getMdpFormat(hnd->format), hnd->size);
 
+    // Handle R/B swap
+    if (layer->flags & HWC_FORMAT_RB_SWAP) {
+        if (hnd->format == HAL_PIXEL_FORMAT_RGBA_8888)
+            whf.format = getMdpFormat(HAL_PIXEL_FORMAT_BGRA_8888);
+        else if (hnd->format == HAL_PIXEL_FORMAT_RGBX_8888)
+            whf.format = getMdpFormat(HAL_PIXEL_FORMAT_BGRX_8888);
+    }
+
     if(dpy && isYuvBuffer(hnd)) {
         if(!ctx->listStats[dpy].isDisplayAnimating) {
             ctx->mPrevCropVideo = crop;
diff --git a/libhwcomposer/hwc_utils.h b/libhwcomposer/hwc_utils.h
index 8822af0..d281fb0 100644
--- a/libhwcomposer/hwc_utils.h
+++ b/libhwcomposer/hwc_utils.h
@@ -102,6 +102,8 @@
     // This will be set to true during animation, otherwise false.
     bool isDisplayAnimating;
     ovutils::Dim roi;
+    bool secureUI; // Secure display layer
+    bool isSecurePresent;
 };
 
 struct LayerProp {
@@ -126,6 +128,11 @@
     HWC_COPYBIT = 0x00000002,
 };
 
+// HAL specific features
+enum {
+    HWC_FORMAT_RB_SWAP = 0x00000040,
+};
+
 class LayerRotMap {
 public:
     LayerRotMap() { reset(); }
@@ -185,13 +192,14 @@
 void dumpsys_log(android::String8& buf, const char* fmt, ...);
 
 int getExtOrientation(hwc_context_t* ctx);
-
 bool isValidRect(const hwc_rect_t& rect);
 void deductRect(const hwc_layer_1_t* layer, hwc_rect_t& irect);
 hwc_rect_t getIntersection(const hwc_rect_t& rect1, const hwc_rect_t& rect2);
 hwc_rect_t getUnion(const hwc_rect_t& rect1, const hwc_rect_t& rect2);
 void optimizeLayerRects(hwc_context_t *ctx,
-                        const hwc_display_contents_1_t *list, const int& dpy);
+        const hwc_display_contents_1_t *list, const int& dpy);
+bool areLayersIntersecting(const hwc_layer_1_t* layer1,
+        const hwc_layer_1_t* layer2);
 
 /* Calculates the destination position based on the action safe rectangle */
 void getActionSafePosition(hwc_context_t *ctx, int dpy, hwc_rect_t& dst);
@@ -304,6 +312,31 @@
     return (hnd && (hnd->flags & private_handle_t::PRIV_FLAGS_EXTERNAL_CC));
 }
 
+//Return true if the buffer is intended for Secure Display
+static inline bool isSecureDisplayBuffer(const private_handle_t* hnd) {
+    return (hnd && (hnd->flags & private_handle_t::PRIV_FLAGS_SECURE_DISPLAY));
+}
+
+static inline int getWidth(const private_handle_t* hnd) {
+    if(isYuvBuffer(hnd)) {
+        MetaData_t *metadata = (MetaData_t *)hnd->base_metadata;
+        if(metadata && metadata->operation & UPDATE_BUFFER_GEOMETRY) {
+            return metadata->bufferDim.sliceWidth;
+        }
+    }
+    return hnd->width;
+}
+
+static inline int getHeight(const private_handle_t* hnd) {
+    if(isYuvBuffer(hnd)) {
+        MetaData_t *metadata = (MetaData_t *)hnd->base_metadata;
+        if(metadata && metadata->operation & UPDATE_BUFFER_GEOMETRY) {
+            return metadata->bufferDim.sliceHeight;
+        }
+    }
+    return hnd->height;
+}
+
 template<typename T> inline T max(T a, T b) { return (a > b) ? a : b; }
 template<typename T> inline T min(T a, T b) { return (a < b) ? a : b; }
 
@@ -409,6 +442,10 @@
     return (layer->transform & HWC_TRANSFORM_ROT_90);
 }
 
+inline bool isSecurePresent(hwc_context_t *ctx, int dpy) {
+    return ctx->listStats[dpy].isSecurePresent;
+}
+
 };
 
 #endif //HWC_UTILS_H
diff --git a/liboverlay/overlayMdssRot.cpp b/liboverlay/overlayMdssRot.cpp
index 95f22c6..c6d5332 100644
--- a/liboverlay/overlayMdssRot.cpp
+++ b/liboverlay/overlayMdssRot.cpp
@@ -32,7 +32,6 @@
 #define MDSS_MDP_ROT_ONLY 0x80
 #endif
 
-#define SIZE_1M 0x00100000
 #define MDSS_ROT_MASK (MDP_ROT_90 | MDP_FLIP_UD | MDP_FLIP_LR)
 
 namespace ovutils = overlay::utils;
@@ -261,9 +260,6 @@
         opBufSize = Rotator::calcOutputBufSize(destWhf);
     }
 
-    if (mRotInfo.flags & utils::OV_MDP_SECURE_OVERLAY_SESSION)
-        opBufSize = utils::align(opBufSize, SIZE_1M);
-
     return opBufSize;
 }
 
diff --git a/liboverlay/overlayMem.h b/liboverlay/overlayMem.h
index 061d197..5e0db6f 100644
--- a/liboverlay/overlayMem.h
+++ b/liboverlay/overlayMem.h
@@ -38,6 +38,7 @@
 
 #include "gralloc_priv.h"
 #include "overlayUtils.h"
+#define SIZE_1M 0x00100000
 
 namespace overlay {
 
@@ -118,24 +119,28 @@
 {
     alloc_data data;
     int allocFlags = GRALLOC_USAGE_PRIVATE_IOMMU_HEAP;
-    if(isSecure) {
-        allocFlags = GRALLOC_USAGE_PRIVATE_MM_HEAP;
-        allocFlags |= GRALLOC_USAGE_PROTECTED;
-    }
-    // Allocate uncached rotator buffers
-    allocFlags |= GRALLOC_USAGE_PRIVATE_UNCACHED;
-
     int err = 0;
     OVASSERT(numbufs && bufSz, "numbufs=%d bufSz=%d", numbufs, bufSz);
 
-    mBufSz = bufSz;
+    if(isSecure) {
+        allocFlags = GRALLOC_USAGE_PRIVATE_MM_HEAP;
+        allocFlags |= GRALLOC_USAGE_PROTECTED;
+        mBufSz = utils::align(bufSz, SIZE_1M);
+        data.align = SIZE_1M;
+    } else {
+        mBufSz = bufSz;
+        data.align = getpagesize();
+    }
+
+    // Allocate uncached rotator buffers
+    allocFlags |= GRALLOC_USAGE_PRIVATE_UNCACHED;
+
     mNumBuffers = numbufs;
 
     data.base = 0;
     data.fd = -1;
     data.offset = 0;
     data.size = mBufSz * mNumBuffers;
-    data.align = getpagesize();
     data.uncached = true;
 
     err = mAlloc->allocate(data, allocFlags);
diff --git a/liboverlay/overlayUtils.cpp b/liboverlay/overlayUtils.cpp
index df2c09e..fd8bfe2 100644
--- a/liboverlay/overlayUtils.cpp
+++ b/liboverlay/overlayUtils.cpp
@@ -100,6 +100,8 @@
             return MDP_RGB_565;
         case HAL_PIXEL_FORMAT_BGRA_8888:
             return MDP_BGRA_8888;
+        case HAL_PIXEL_FORMAT_BGRX_8888:
+            return MDP_BGRX_8888;
         case HAL_PIXEL_FORMAT_YV12:
             return MDP_Y_CR_CB_GH2V2;
         case HAL_PIXEL_FORMAT_YCbCr_422_SP:
diff --git a/liboverlay/overlayUtils.h b/liboverlay/overlayUtils.h
index c854975..55f1767 100644
--- a/liboverlay/overlayUtils.h
+++ b/liboverlay/overlayUtils.h
@@ -261,6 +261,7 @@
     OV_MDP_PIPE_FORCE_DMA = MDP_OV_PIPE_FORCE_DMA,
     OV_MDP_DEINTERLACE = MDP_DEINTERLACE,
     OV_MDP_SECURE_OVERLAY_SESSION = MDP_SECURE_OVERLAY_SESSION,
+    OV_MDP_SECURE_DISPLAY_OVERLAY_SESSION = MDP_SECURE_DISPLAY_OVERLAY_SESSION,
     OV_MDP_SOURCE_ROTATED_90 = MDP_SOURCE_ROTATED_90,
     OV_MDP_BACKEND_COMPOSITION = MDP_BACKEND_COMPOSITION,
     OV_MDP_BLEND_FG_PREMULT = MDP_BLEND_FG_PREMULT,
diff --git a/liboverlay/overlayWriteback.cpp b/liboverlay/overlayWriteback.cpp
index f1f0eb5..5c6d773 100644
--- a/liboverlay/overlayWriteback.cpp
+++ b/liboverlay/overlayWriteback.cpp
@@ -37,9 +37,6 @@
 
 //=========== class WritebackMem ==============================================
 bool WritebackMem::manageMem(uint32_t size, bool isSecure) {
-    if(isSecure) {
-        size = utils::align(size, SIZE_1M);
-    }
     if(mBuf.bufSz() == size) {
         return true;
     }
diff --git a/libqdutils/mdp_version.cpp b/libqdutils/mdp_version.cpp
index 4a695d3..a444920 100644
--- a/libqdutils/mdp_version.cpp
+++ b/libqdutils/mdp_version.cpp
@@ -114,7 +114,7 @@
         //TODO get this from driver
         mMDPDownscale = 4;
 
-        char split[64];
+        char split[64] = {0};
         FILE* fp = fopen("/sys/class/graphics/fb0/msm_fb_split", "r");
         if(fp){
             //Format "left right" space as delimiter
diff --git a/libqdutils/qdMetaData.cpp b/libqdutils/qdMetaData.cpp
index 1316e59..89ca92e 100644
--- a/libqdutils/qdMetaData.cpp
+++ b/libqdutils/qdMetaData.cpp
@@ -78,6 +78,9 @@
         case PP_PARAM_TIMESTAMP:
             data->timestamp = *((int64_t *)param);
             break;
+        case UPDATE_BUFFER_GEOMETRY:
+            memcpy((void *)&data->bufferDim, param, sizeof(BufferDim_t));
+            break;
         default:
             ALOGE("Unknown paramType %d", paramType);
             break;
diff --git a/libqdutils/qdMetaData.h b/libqdutils/qdMetaData.h
index 9f10cf8..d5354a4 100644
--- a/libqdutils/qdMetaData.h
+++ b/libqdutils/qdMetaData.h
@@ -52,9 +52,15 @@
     uint16_t c2[MAX_IGC_LUT_ENTRIES];
 };
 
+struct BufferDim_t {
+    int32_t sliceWidth;
+    int32_t sliceHeight;
+};
+
 struct MetaData_t {
     int32_t operation;
     int32_t interlaced;
+    BufferDim_t bufferDim;
     HSICData_t hsicData;
     int32_t sharpness;
     int32_t video_interface;
@@ -70,7 +76,8 @@
     PP_PARAM_VID_INTFC  = 0x0008,
     PP_PARAM_IGC        = 0x0010,
     PP_PARAM_SHARP2     = 0x0020,
-    PP_PARAM_TIMESTAMP  = 0x0040
+    PP_PARAM_TIMESTAMP  = 0x0040,
+    UPDATE_BUFFER_GEOMETRY = 0x0080,
 } DispParamType;
 
 int setMetaData(private_handle_t *handle, DispParamType paramType, void *param);