Merge "hwc/overlay: Add Color layer support in MDP Composition."
diff --git a/libcopybit/copybit.cpp b/libcopybit/copybit.cpp
index b37eee0..5d8da05 100644
--- a/libcopybit/copybit.cpp
+++ b/libcopybit/copybit.cpp
@@ -555,6 +555,63 @@
     // NOP for MDP copybit
     return 0;
 }
+static int clear_copybit(struct copybit_device_t *dev,
+                         struct copybit_image_t const *buf,
+                         struct copybit_rect_t *rect)
+{
+    struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
+    uint32_t color = 0; // black color
+
+    if (!ctx) {
+        ALOGE ("%s: Invalid copybit context", __FUNCTION__);
+        return -EINVAL;
+    }
+
+    struct blitReq list1;
+    memset((char *)&list1 , 0 ,sizeof (struct blitReq) );
+    list1.count = 1;
+    int rel_fen_fd = -1;
+    int my_tmp_get_fence = -1;
+
+    list1.sync.rel_fen_fd  =  &my_tmp_get_fence;
+    mdp_blit_req* req = &list1.req[0];
+
+    if(!req) {
+        ALOGE ("%s : Invalid request", __FUNCTION__);
+        return -EINVAL;
+    }
+
+    set_image(&req->dst, buf);
+    set_image(&req->src, buf);
+
+    if (rect->l < 0 || (uint32_t)(rect->r - rect->l) > req->dst.width ||
+       rect->t < 0 || (uint32_t)(rect->b - rect->t) > req->dst.height) {
+       ALOGE ("%s : Invalid rect : src_rect l %d t %d r %d b %d",\
+       __FUNCTION__, rect->l, rect->t, rect->r, rect->b);
+       return -EINVAL;
+    }
+
+    req->dst_rect.x  = rect->l;
+    req->dst_rect.y  = rect->t;
+    req->dst_rect.w  = rect->r - rect->l;
+    req->dst_rect.h  = rect->b - rect->t;
+
+    req->src_rect = req->dst_rect;
+
+    req->const_color.b = (uint32_t)((color >> 16) & 0xff);
+    req->const_color.g = (uint32_t)((color >> 8) & 0xff);
+    req->const_color.r = (uint32_t)((color >> 0) & 0xff);
+    req->const_color.alpha = MDP_ALPHA_NOP;
+
+    req->transp_mask = MDP_TRANSP_NOP;
+    req->flags = MDP_SOLID_FILL | MDP_MEMORY_ID_TYPE_FB | MDP_BLEND_FG_PREMULT;
+    int status = msm_copybit(ctx, &list1);
+
+    if (my_tmp_get_fence !=  -1)
+        close(my_tmp_get_fence);
+
+    return status;
+}
 
 /** Fill the rect on dst with RGBA color **/
 static int fill_color(struct copybit_device_t *dev,
@@ -653,6 +710,7 @@
     ctx->device.finish = finish_copybit;
     ctx->device.fill_color = fill_color;
     ctx->device.flush_get_fence = flush_get_fence;
+    ctx->device.clear = clear_copybit;
     ctx->mAlpha = MDP_ALPHA_NOP;
     ctx->mFlags = 0;
     ctx->sync.flags = 0;
diff --git a/libgralloc/alloc_controller.cpp b/libgralloc/alloc_controller.cpp
index 06ce156..33c4f32 100644
--- a/libgralloc/alloc_controller.cpp
+++ b/libgralloc/alloc_controller.cpp
@@ -86,8 +86,13 @@
 //-------------- AdrenoMemInfo-----------------------//
 AdrenoMemInfo::AdrenoMemInfo()
 {
+    LINK_adreno_compute_aligned_width_and_height = NULL;
+    LINK_adreno_compute_padding = NULL;
+
     libadreno_utils = ::dlopen("libadreno_utils.so", RTLD_NOW);
     if (libadreno_utils) {
+        *(void **)&LINK_adreno_compute_aligned_width_and_height =
+            ::dlsym(libadreno_utils, "compute_aligned_width_and_height");
         *(void **)&LINK_adreno_compute_padding = ::dlsym(libadreno_utils,
                                            "compute_surface_padding");
     }
@@ -100,9 +105,11 @@
     }
 }
 
-int AdrenoMemInfo::getStride(int width, int format)
+void AdrenoMemInfo::getAlignedWidthAndHeight(int width, int height, int format,
+                              int& aligned_w, int& aligned_h)
 {
-    int stride = ALIGN(width, 32);
+    aligned_w = ALIGN(width, 32);
+    aligned_h = ALIGN(height, 32);
     // Currently surface padding is only computed for RGB* surfaces.
     if (format <= HAL_PIXEL_FORMAT_sRGB_X_8888) {
         // Don't add any additional padding if debug.gralloc.map_fb_memory
@@ -111,7 +118,7 @@
         if((property_get("debug.gralloc.map_fb_memory", property, NULL) > 0) &&
            (!strncmp(property, "1", PROPERTY_VALUE_MAX ) ||
            (!strncasecmp(property,"true", PROPERTY_VALUE_MAX )))) {
-              return stride;
+              return;
         }
 
         int bpp = 4;
@@ -125,25 +132,39 @@
                 break;
             default: break;
         }
-        if ((libadreno_utils) && (LINK_adreno_compute_padding)) {
-            int surface_tile_height = 1;   // Linear surface
+        if (libadreno_utils) {
             int raster_mode         = 0;   // Adreno unknown raster mode.
             int padding_threshold   = 512; // Threshold for padding surfaces.
-            // the function below expects the width to be a multiple of
-            // 32 pixels, hence we pass stride instead of width.
-            stride = LINK_adreno_compute_padding(stride, bpp,
-                                      surface_tile_height, raster_mode,
-                                      padding_threshold);
+            // the function below computes aligned width and aligned height
+            // based on linear or macro tile mode selected.
+            if(LINK_adreno_compute_aligned_width_and_height) {
+               int tile_mode = 0;   // Linear surface
+               LINK_adreno_compute_aligned_width_and_height(width,
+                                     height, bpp, tile_mode,
+                                     raster_mode, padding_threshold,
+                                     &aligned_w, &aligned_h);
+
+            } else if(LINK_adreno_compute_padding) {
+                int surface_tile_height = 1;   // Linear surface
+                aligned_w = LINK_adreno_compute_padding(width, bpp,
+                                     surface_tile_height, raster_mode,
+                                     padding_threshold);
+                ALOGW("%s: Warning!! Old GFX API is used to calculate stride",
+                                                            __FUNCTION__);
+            } else {
+                ALOGW("%s: Warning!! Symbols compute_surface_padding and " \
+                    "compute_aligned_width_and_height not found", __FUNCTION__);
+            }
         }
     } else {
         switch (format)
         {
             case HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO:
             case HAL_PIXEL_FORMAT_RAW_SENSOR:
-                stride = ALIGN(width, 32);
+                aligned_w = ALIGN(width, 32);
                 break;
             case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED:
-                stride = ALIGN(width, 128);
+                aligned_w = ALIGN(width, 128);
                 break;
             case HAL_PIXEL_FORMAT_YCbCr_420_SP:
             case HAL_PIXEL_FORMAT_YCrCb_420_SP:
@@ -152,22 +173,21 @@
             case HAL_PIXEL_FORMAT_YCrCb_422_SP:
             case HAL_PIXEL_FORMAT_YCbCr_422_I:
             case HAL_PIXEL_FORMAT_YCrCb_422_I:
-                stride = ALIGN(width, 16);
+                aligned_w = ALIGN(width, 16);
                 break;
             case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
             case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
-                stride = VENUS_Y_STRIDE(COLOR_FMT_NV12, width);
+                aligned_w = VENUS_Y_STRIDE(COLOR_FMT_NV12, width);
                 break;
             case HAL_PIXEL_FORMAT_BLOB:
-                stride = width;
+                aligned_w = width;
                 break;
             case HAL_PIXEL_FORMAT_NV21_ZSL:
-                stride = ALIGN(width, 64);
+                aligned_w = ALIGN(width, 64);
                 break;
             default: break;
         }
     }
-    return stride;
 }
 
 //-------------- IAllocController-----------------------//
@@ -274,8 +294,11 @@
 {
     size_t size;
 
-    alignedw = AdrenoMemInfo::getInstance().getStride(width, format);
-    alignedh = ALIGN(height, 32);
+    AdrenoMemInfo::getInstance().getAlignedWidthAndHeight(width,
+                                                          height,
+                                                          format,
+                                                          alignedw,
+                                                          alignedh);
     switch (format) {
         case HAL_PIXEL_FORMAT_RGBA_8888:
         case HAL_PIXEL_FORMAT_RGBX_8888:
diff --git a/libgralloc/gr.h b/libgralloc/gr.h
index 5343c35..1949f45 100644
--- a/libgralloc/gr.h
+++ b/libgralloc/gr.h
@@ -89,12 +89,13 @@
     ~AdrenoMemInfo();
 
     /*
-     * Function to compute the adreno stride based on the width and format.
+     * Function to compute the adreno aligned width and aligned height
+     * based on the width and format.
      *
-     * @return stride.
+     * @return aligned width, aligned height
      */
-    int getStride(int width, int format);
-
+    void getAlignedWidthAndHeight(int width, int height, int format,
+                                  int& alignedw, int &alignedh);
     private:
         // Pointer to the padding library.
         void *libadreno_utils;
@@ -104,5 +105,15 @@
                                                 int surface_tile_height,
                                                 int screen_tile_height,
                                                 int padding_threshold);
+        // link to the surface padding library.
+        void (*LINK_adreno_compute_aligned_width_and_height) (int width,
+                                                int height,
+                                                int bpp,
+                                                int tile_mode,
+                                                int raster_mode,
+                                                int padding_threshold,
+                                                int *aligned_w,
+                                                int *aligned_h);
+
 };
 #endif /* GR_H_ */
diff --git a/libgralloc/mapper.cpp b/libgralloc/mapper.cpp
index ca0db00..a07bdc3 100644
--- a/libgralloc/mapper.cpp
+++ b/libgralloc/mapper.cpp
@@ -329,7 +329,10 @@
                 int width   = va_arg(args, int);
                 int format  = va_arg(args, int);
                 int *stride = va_arg(args, int *);
-                *stride = AdrenoMemInfo::getInstance().getStride(width, format);
+                int alignedw = 0, alignedh = 0;
+                AdrenoMemInfo::getInstance().getAlignedWidthAndHeight(width,
+                                     0, format, alignedw, alignedh);
+                *stride = alignedw;
                 res = 0;
             } break;
         case GRALLOC_MODULE_PERFORM_GET_CUSTOM_STRIDE_FROM_HANDLE:
diff --git a/libhwcomposer/hwc_copybit.cpp b/libhwcomposer/hwc_copybit.cpp
index 999fdb2..bb1b032 100644
--- a/libhwcomposer/hwc_copybit.cpp
+++ b/libhwcomposer/hwc_copybit.cpp
@@ -2,8 +2,7 @@
  * Copyright (C) 2010 The Android Open Source Project
  * Copyright (C) 2012-2013, The Linux Foundation. All rights reserved.
  *
- * Not a Contribution, Apache license notifications and license are retained
- * for attribution purposes only.
+ * Not a Contribution.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -25,7 +24,9 @@
 #include "hwc_copybit.h"
 #include "comptype.h"
 #include "gr.h"
+#include "cb_utils.h"
 
+using namespace qdutils;
 namespace qhwc {
 
 struct range {
@@ -127,20 +128,6 @@
     return renderArea;
 }
 
-bool checkNonWormholeRegion(private_handle_t* hnd, hwc_rect_t& rect)
-{
-    unsigned int height = rect.bottom - rect.top;
-    unsigned int width = rect.right - rect.left;
-    copybit_image_t buf;
-    buf.w = ALIGN(hnd->width, 32);
-    buf.h = hnd->height;
-
-    if (buf.h != height || buf.w != width)
-        return false;
-
-    return true;
-}
-
 bool CopyBit::prepare(hwc_context_t *ctx, hwc_display_contents_1_t *list,
                                                             int dpy) {
 
@@ -183,21 +170,33 @@
     // Following are MDP3 limitations for which we
     // need to fallback to GPU composition:
     // 1. Plane alpha is not supported by MDP3.
+    // 2. Scaling is within range
     if (qdutils::MDPVersion::getInstance().getMDPVersion() < 400) {
         for (int i = ctx->listStats[dpy].numAppLayers-1; i >= 0 ; i--) {
+            int dst_h, dst_w, src_h, src_w;
+            float dx, dy;
             hwc_layer_1_t *layer = (hwc_layer_1_t *) &list->hwLayers[i];
             if (layer->planeAlpha != 0xFF)
                 return true;
-        }
-        /*
-         * Fallback to GPU in MDP3 when NonWormholeRegion is not of frame buffer
-         * size as artifact is seen in WormholeRegion of previous frame.
-         */
-        hwc_rect_t nonWormHoleRegion;
-        getNonWormholeRegion(list, nonWormHoleRegion);
-        if(!checkNonWormholeRegion(fbHnd, nonWormHoleRegion))
-           return true;
 
+            if (layer->transform & HAL_TRANSFORM_ROT_90) {
+                src_h = layer->sourceCrop.right - layer->sourceCrop.left;
+                src_w = layer->sourceCrop.bottom - layer->sourceCrop.top;
+            } else {
+                src_h = layer->sourceCrop.bottom - layer->sourceCrop.top;
+                src_w = layer->sourceCrop.right - layer->sourceCrop.left;
+            }
+            dst_h = layer->displayFrame.bottom - layer->displayFrame.top;
+            dst_w = layer->displayFrame.right - layer->displayFrame.left;
+
+            dx = (float)dst_w/src_w;
+            dy = (float)dst_h/src_h;
+            if (dx > MAX_SCALE_FACTOR || dx < MIN_SCALE_FACTOR)
+                return false;
+
+            if (dy > MAX_SCALE_FACTOR || dy < MIN_SCALE_FACTOR)
+                return false;
+        }
     }
 
     //Allocate render buffers if they're not allocated
@@ -270,23 +269,23 @@
 
     if (ctx->mMDP.version >= qdutils::MDP_V4_0) {
         //Wait for the previous frame to complete before rendering onto it
-        if(mRelFd[0] >=0) {
-            sync_wait(mRelFd[0], 1000);
-            close(mRelFd[0]);
-            mRelFd[0] = -1;
+        if(mRelFd[mCurRenderBufferIndex] >=0) {
+            sync_wait(mRelFd[mCurRenderBufferIndex], 1000);
+            close(mRelFd[mCurRenderBufferIndex]);
+            mRelFd[mCurRenderBufferIndex] = -1;
         }
-
-        //Clear the visible region on the render buffer
-        //XXX: Do this only when needed.
-        hwc_rect_t clearRegion;
-        getNonWormholeRegion(list, clearRegion);
-        clear(renderBuffer, clearRegion);
     } else {
-        if(mRelFd[0] >=0) {
+        if(mRelFd[mCurRenderBufferIndex] >=0) {
             copybit_device_t *copybit = getCopyBitDevice();
-            copybit->set_sync(copybit, mRelFd[0]);
+            copybit->set_sync(copybit, mRelFd[mCurRenderBufferIndex]);
         }
     }
+
+    //Clear the transparent or left out region on the render buffer
+    hwc_rect_t clearRegion = {0,0,0,0};
+    if(CBUtils::getuiClearRegion(list, clearRegion, layerProp))
+        clear(renderBuffer, clearRegion);
+
     // numAppLayers-1, as we iterate from 0th layer index with HWC_COPYBIT flag
     for (int i = 0; i <= (ctx->listStats[dpy].numAppLayers-1); i++) {
         hwc_layer_1_t *layer = &list->hwLayers[i];
@@ -671,6 +670,11 @@
 {
     for (int i = 0; i < NUM_RENDER_BUFFERS; i++) {
         if(mRenderBuffer[i]) {
+            //Since we are freeing buffer close the fence if it has a valid one.
+            if(mRelFd[i] >= 0) {
+                close(mRelFd[i]);
+                mRelFd[i] = -1;
+            }
             free_buffer(mRenderBuffer[i]);
             mRenderBuffer[i] = NULL;
         }
@@ -682,10 +686,9 @@
 }
 
 void CopyBit::setReleaseFd(int fd) {
-    if(mRelFd[0] >=0)
-        close(mRelFd[0]);
-    mRelFd[0] = mRelFd[1];
-    mRelFd[1] = dup(fd);
+    if(mRelFd[mCurRenderBufferIndex] >=0)
+        close(mRelFd[mCurRenderBufferIndex]);
+    mRelFd[mCurRenderBufferIndex] = dup(fd);
 }
 
 struct copybit_device_t* CopyBit::getCopyBitDevice() {
@@ -695,10 +698,10 @@
 CopyBit::CopyBit():mIsModeOn(false), mCopyBitDraw(false),
     mCurRenderBufferIndex(0){
     hw_module_t const *module;
-    for (int i = 0; i < NUM_RENDER_BUFFERS; i++)
+    for (int i = 0; i < NUM_RENDER_BUFFERS; i++) {
         mRenderBuffer[i] = NULL;
-    mRelFd[0] = -1;
-    mRelFd[1] = -1;
+        mRelFd[i] = -1;
+    }
 
     char value[PROPERTY_VALUE_MAX];
     property_get("debug.hwc.dynThreshold", value, "2");
@@ -716,10 +719,6 @@
 CopyBit::~CopyBit()
 {
     freeRenderBuffers();
-    if(mRelFd[0] >=0)
-        close(mRelFd[0]);
-    if(mRelFd[1] >=0)
-        close(mRelFd[1]);
     if(mEngine)
     {
         copybit_close(mEngine);
diff --git a/libhwcomposer/hwc_copybit.h b/libhwcomposer/hwc_copybit.h
index 10863f3..fd5c939 100644
--- a/libhwcomposer/hwc_copybit.h
+++ b/libhwcomposer/hwc_copybit.h
@@ -22,6 +22,11 @@
 #include "hwc_utils.h"
 
 #define NUM_RENDER_BUFFERS 3
+//These scaling factors are specific for MDP3. Normally scaling factor
+//is only 4, but copybit will create temp buffer to let it run through
+//twice
+#define MAX_SCALE_FACTOR 16
+#define MIN_SCALE_FACTOR 0.0625
 
 namespace qhwc {
 
@@ -79,9 +84,8 @@
     // Index of the current intermediate render buffer
     int mCurRenderBufferIndex;
 
-    //These are the the release FDs of the T-2 and T-1 round
-    //We wait on the T-2 fence
-    int mRelFd[2];
+    // Release FDs of the intermediate render buffer
+    int mRelFd[NUM_RENDER_BUFFERS];
 
     //Dynamic composition threshold for deciding copybit usage.
     double mDynThreshold;
diff --git a/libhwcomposer/hwc_mdpcomp.cpp b/libhwcomposer/hwc_mdpcomp.cpp
index a524a78..01f4b99 100644
--- a/libhwcomposer/hwc_mdpcomp.cpp
+++ b/libhwcomposer/hwc_mdpcomp.cpp
@@ -44,7 +44,7 @@
 bool MDPComp::sEnablePartialFrameUpdate = false;
 int MDPComp::sMaxPipesPerMixer = MAX_PIPES_PER_MIXER;
 float MDPComp::sMaxBw = 2.3f;
-uint32_t MDPComp::sCompBytesClaimed = 0;
+double MDPComp::sBwClaimed = 0.0;
 
 MDPComp* MDPComp::getObject(hwc_context_t *ctx, const int& dpy) {
     if(isDisplaySplit(ctx, dpy)) {
@@ -260,7 +260,8 @@
     memcpy(&drop, &curFrame.drop, sizeof(drop));
 }
 
-bool MDPComp::LayerCache::isSameFrame(const FrameInfo& curFrame) {
+bool MDPComp::LayerCache::isSameFrame(const FrameInfo& curFrame,
+                                      hwc_display_contents_1_t* list) {
     if(layerCount != curFrame.layerCount)
         return false;
     for(int i = 0; i < curFrame.layerCount; i++) {
@@ -268,6 +269,10 @@
                 (curFrame.drop[i] != drop[i])) {
             return false;
         }
+        if(curFrame.isFBComposed[i] &&
+           (hnd[i] != list->hwLayers[i].handle)){
+            return false;
+        }
     }
     return true;
 }
@@ -305,12 +310,6 @@
 
     hwc_rect_t crop = integerizeSourceCrop(layer->sourceCropf);
     hwc_rect_t dst = layer->displayFrame;
-
-    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 };
-       qhwc::calculate_crop_rects(crop, dst, scissor, layer->transform);
-    }
-
     int crop_w = crop.right - crop.left;
     int crop_h = crop.bottom - crop.top;
     int dst_w = dst.right - dst.left;
@@ -406,6 +405,12 @@
     return ret;
 }
 
+/*
+ * 1) Identify layers that are not visible in the updating ROI and drop them
+ * from composition.
+ * 2) If we have a scaling layers which needs cropping against generated ROI.
+ * Reset ROI to full resolution.
+ */
 bool MDPComp::validateAndApplyROI(hwc_context_t *ctx,
                                hwc_display_contents_1_t* list, hwc_rect_t roi) {
     int numAppLayers = ctx->listStats[mDpy].numAppLayers;
@@ -413,15 +418,22 @@
     if(!isValidRect(roi))
         return false;
 
-    for(int i = 0; i < numAppLayers; i++){
+    hwc_rect_t visibleRect = roi;
+
+    for(int i = numAppLayers - 1; i >= 0; i--){
+
+        if(!isValidRect(visibleRect)) {
+            mCurrentFrame.drop[i] = true;
+            mCurrentFrame.dropCount++;
+        }
+
         const hwc_layer_1_t* layer =  &list->hwLayers[i];
 
         hwc_rect_t dstRect = layer->displayFrame;
         hwc_rect_t srcRect = integerizeSourceCrop(layer->sourceCropf);
         int transform = layer->transform;
-        trimLayer(ctx, mDpy, transform, srcRect, dstRect);
 
-        hwc_rect_t res  = getIntersection(roi, dstRect);
+        hwc_rect_t res  = getIntersection(visibleRect, dstRect);
 
         int res_w = res.right - res.left;
         int res_h = res.bottom - res.top;
@@ -436,12 +448,15 @@
              * cropping */
             if((res_w != dst_w || res_h != dst_h) &&
                needsScaling (ctx, layer, mDpy)) {
-                ALOGE("%s: Resetting ROI due to scaling", __FUNCTION__);
+                ALOGI("%s: Resetting ROI due to scaling", __FUNCTION__);
                 memset(&mCurrentFrame.drop, 0, sizeof(mCurrentFrame.drop));
                 mCurrentFrame.dropCount = 0;
                 return false;
             }
         }
+
+        if (layer->blending == HWC_BLENDING_NONE)
+            visibleRect = deductRect(visibleRect, res);
     }
     return true;
 }
@@ -460,6 +475,9 @@
         return;
     }
 
+    if(isSkipPresent(ctx, mDpy))
+        return;
+
     if(list->flags & HWC_GEOMETRY_CHANGED)
         return;
 
@@ -473,7 +491,6 @@
             int transform = list->hwLayers[index].transform;
 
             /* Intersect against display boundaries */
-            trimLayer(ctx, mDpy, transform, srcRect, dstRect);
             roi = getUnion(roi, dstRect);
         }
     }
@@ -575,18 +592,8 @@
     mCurrentFrame.mdpCount = mCurrentFrame.layerCount - mCurrentFrame.fbCount -
         mCurrentFrame.dropCount;
 
-    if(mCurrentFrame.mdpCount > sMaxPipesPerMixer) {
-        ALOGD_IF(isDebug(), "%s: Exceeds MAX_PIPES_PER_MIXER",__FUNCTION__);
-        return false;
-    }
-
-    if(!arePipesAvailable(ctx, list)) {
-        return false;
-    }
-
-    uint32_t size = calcMDPBytesRead(ctx, list);
-    if(!bandwidthCheck(ctx, size)) {
-        ALOGD_IF(isDebug(), "%s: Exceeds bandwidth",__FUNCTION__);
+    if(!resourceCheck(ctx, list)) {
+        ALOGD_IF(isDebug(), "%s: resource check failed", __FUNCTION__);
         return false;
     }
 
@@ -602,7 +609,8 @@
 
     bool ret = false;
     if(isLoadBasedCompDoable(ctx, list)) {
-        ret = loadBasedComp(ctx, list);
+        ret = loadBasedCompPreferGPU(ctx, list) ||
+                loadBasedCompPreferMDP(ctx, list);
     }
 
     if(!ret) {
@@ -646,32 +654,24 @@
         return false;
     }
 
-    if(mdpCount > (sMaxPipesPerMixer - 1)) { // -1 since FB is used
-        ALOGD_IF(isDebug(), "%s: Exceeds MAX_PIPES_PER_MIXER",__FUNCTION__);
-        return false;
-    }
-
-    if(!arePipesAvailable(ctx, list)) {
-        return false;
-    }
-
-    uint32_t size = calcMDPBytesRead(ctx, list);
-    if(!bandwidthCheck(ctx, size)) {
-        ALOGD_IF(isDebug(), "%s: Exceeds bandwidth",__FUNCTION__);
+    if(!resourceCheck(ctx, list)) {
+        ALOGD_IF(isDebug(), "%s: resource check failed", __FUNCTION__);
         return false;
     }
 
     return true;
 }
 
-bool MDPComp::loadBasedComp(hwc_context_t *ctx,
+bool MDPComp::loadBasedCompPreferGPU(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);
+    int stagesForMDP = min(sMaxPipesPerMixer, ctx->mOverlay->availablePipes(
+            mDpy, Overlay::MIXER_DEFAULT));
+    //If MDP has X possible stages, it can take X layers.
+    const int batchSize = numAppLayers - (stagesForMDP - 1); //1 for FB
+
     if(batchSize <= 0) {
         ALOGD_IF(isDebug(), "%s: Not attempting", __FUNCTION__);
         return false;
@@ -717,7 +717,8 @@
     mCurrentFrame.fbCount = batchSize;
     mCurrentFrame.mdpCount = mCurrentFrame.layerCount - batchSize;
 
-    if(!arePipesAvailable(ctx, list)) {
+    if(!resourceCheck(ctx, list)) {
+        ALOGD_IF(isDebug(), "%s: resource check failed", __FUNCTION__);
         return false;
     }
 
@@ -726,6 +727,59 @@
     return true;
 }
 
+bool MDPComp::loadBasedCompPreferMDP(hwc_context_t *ctx,
+        hwc_display_contents_1_t* list) {
+    const int numAppLayers = ctx->listStats[mDpy].numAppLayers;
+    //TODO get the ib from sysfs node.
+    //Full screen is from ib perspective, not actual full screen
+    const int bpp = 4;
+    double panelRefRate =
+                1000000000.0 / ctx->dpyAttr[mDpy].vsync_period;
+
+    double bwLeft = sMaxBw - sBwClaimed;
+
+    const int fullScreenLayers = bwLeft * 1000000000 / (ctx->dpyAttr[mDpy].xres
+            * ctx->dpyAttr[mDpy].yres * bpp * panelRefRate);
+
+    const int fbBatchSize = numAppLayers - (fullScreenLayers - 1);
+    //If batch size is not at least 2, we aren't really preferring MDP, since
+    //only 1 layer going to GPU could actually translate into an entire FB
+    //needed to be fetched by MDP, thus needing more b/w rather than less.
+    if(fbBatchSize < 2 || fbBatchSize > numAppLayers) {
+        ALOGD_IF(isDebug(), "%s: Not attempting", __FUNCTION__);
+        return false;
+    }
+
+    //Top-most layers constitute FB batch
+    const int fbBatchStart = numAppLayers - fbBatchSize;
+
+    //Bottom-most layers constitute MDP batch
+    for(int i = 0; i < fbBatchStart; i++) {
+        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 = fbBatchStart;
+    mCurrentFrame.fbCount = fbBatchSize;
+    mCurrentFrame.mdpCount = mCurrentFrame.layerCount - fbBatchSize;
+
+    if(!resourceCheck(ctx, list)) {
+        ALOGD_IF(isDebug(), "%s: resource check failed", __FUNCTION__);
+        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
@@ -742,7 +796,6 @@
     mCurrentFrame.reset(numAppLayers);
     updateYUV(ctx, list, secureOnly);
     int mdpCount = mCurrentFrame.mdpCount;
-    int fbNeeded = (mCurrentFrame.fbCount != 0);
 
     if(!isYuvPresent(ctx, mDpy)) {
         return false;
@@ -757,18 +810,8 @@
     if(!mdpCount)
         return false;
 
-    if(mdpCount > (sMaxPipesPerMixer - fbNeeded)) {
-        ALOGD_IF(isDebug(), "%s: Exceeds MAX_PIPES_PER_MIXER",__FUNCTION__);
-        return false;
-    }
-
-    if(!arePipesAvailable(ctx, list)) {
-        return false;
-    }
-
-    uint32_t size = calcMDPBytesRead(ctx, list);
-    if(!bandwidthCheck(ctx, size)) {
-        ALOGD_IF(isDebug(), "%s: Exceeds bandwidth",__FUNCTION__);
+    if(!resourceCheck(ctx, list)) {
+        ALOGD_IF(isDebug(), "%s: resource check failed", __FUNCTION__);
         return false;
     }
 
@@ -984,7 +1027,6 @@
             mCurrentFrame.isFBComposed[i] = true;
         } else {
             mCurrentFrame.isFBComposed[i] = false;
-            mCachedFrame.hnd[i] = list->hwLayers[i].handle;
         }
     }
 
@@ -1092,6 +1134,27 @@
     return true;
 }
 
+bool MDPComp::resourceCheck(hwc_context_t *ctx,
+        hwc_display_contents_1_t *list) {
+    const bool fbUsed = mCurrentFrame.fbCount;
+    if(mCurrentFrame.mdpCount > sMaxPipesPerMixer - fbUsed) {
+        ALOGD_IF(isDebug(), "%s: Exceeds MAX_PIPES_PER_MIXER",__FUNCTION__);
+        return false;
+    }
+
+    if(!arePipesAvailable(ctx, list)) {
+        return false;
+    }
+
+    uint32_t size = calcMDPBytesRead(ctx, list);
+    if(!bandwidthCheck(ctx, size)) {
+        ALOGD_IF(isDebug(), "%s: Exceeds bandwidth",__FUNCTION__);
+        return false;
+    }
+
+    return true;
+}
+
 uint32_t MDPComp::calcMDPBytesRead(hwc_context_t *ctx,
         hwc_display_contents_1_t* list) {
     uint32_t size = 0;
@@ -1106,7 +1169,6 @@
             if (hnd) {
                 hwc_rect_t crop = integerizeSourceCrop(layer->sourceCropf);
                 hwc_rect_t dst = layer->displayFrame;
-                trimLayer(ctx, mDpy, layer->transform, crop, dst);
                 float bpp = ((float)hnd->size) / (hnd->width * hnd->height);
                 size += bpp * (crop.right - crop.left) *
                     (crop.bottom - crop.top) *
@@ -1129,10 +1191,10 @@
     //Will be added for other targets if we run into bandwidth issues and when
     //we have profiling data to set an upper limit.
     if(qdutils::MDPVersion::getInstance().is8x74v2()) {
-        const uint32_t ONE_GIG = 1024 * 1024 * 1024;
+        const uint32_t ONE_GIG = 1000 * 1000 * 1000;
         double panelRefRate =
                 1000000000.0 / ctx->dpyAttr[mDpy].vsync_period;
-        if((size + sCompBytesClaimed) > ((sMaxBw / panelRefRate) * ONE_GIG)) {
+        if((size * panelRefRate) > ((sMaxBw - sBwClaimed) * ONE_GIG)) {
             return false;
         }
     }
@@ -1152,7 +1214,7 @@
     //do not cache the information for next draw cycle.
     if(numLayers > MAX_NUM_APP_LAYERS) {
         mCachedFrame.updateCounts(mCurrentFrame);
-        ALOGE("%s: Number of App layers exceeded the limit ",
+        ALOGI("%s: Number of App layers exceeded the limit ",
         __FUNCTION__);
         ret = -1;
         return ret;
@@ -1192,7 +1254,7 @@
         } else { //Success
             //Any change in composition types needs an FB refresh
             mCurrentFrame.needsRedraw = false;
-            if(!mCachedFrame.isSameFrame(mCurrentFrame) ||
+            if(!mCachedFrame.isSameFrame(mCurrentFrame, list) ||
                      (list->flags & HWC_GEOMETRY_CHANGED) ||
                      isSkipPresent(ctx, mDpy)) {
                 mCurrentFrame.needsRedraw = true;
@@ -1228,10 +1290,11 @@
         }
     } else {
         reset(numLayers, list);
+        memset(&mCurrentFrame.drop, 0, sizeof(mCurrentFrame.drop));
+        mCurrentFrame.dropCount = 0;
         ret = -1;
         goto exit;
     }
-
     //UpdateLayerFlags
     setMDPCompLayerFlags(ctx, list);
     mCachedFrame.cacheAll(list);
@@ -1246,7 +1309,9 @@
     }
 
 exit:
-    sCompBytesClaimed += calcMDPBytesRead(ctx, list);
+    //gbps (bytes / nanosec = gigabytes / sec)
+    sBwClaimed += calcMDPBytesRead(ctx, list) /
+            (double)ctx->dpyAttr[mDpy].vsync_period;
     return ret;
 }
 
diff --git a/libhwcomposer/hwc_mdpcomp.h b/libhwcomposer/hwc_mdpcomp.h
index 1d5d715..adf74bb 100644
--- a/libhwcomposer/hwc_mdpcomp.h
+++ b/libhwcomposer/hwc_mdpcomp.h
@@ -52,7 +52,7 @@
     /* Initialize MDP comp*/
     static bool init(hwc_context_t *ctx);
     static void resetIdleFallBack() { sIdleFallBack = false; }
-    static void reset() { sCompBytesClaimed = 0; };
+    static void reset() { sBwClaimed = 0.0; };
 
 protected:
     enum { MAX_SEC_LAYERS = 1 }; //TODO add property support
@@ -118,7 +118,8 @@
         void reset();
         void cacheAll(hwc_display_contents_1_t* list);
         void updateCounts(const FrameInfo&);
-        bool isSameFrame(const FrameInfo& curFrame);
+        bool isSameFrame(const FrameInfo& curFrame,
+                         hwc_display_contents_1_t* list);
     };
 
     /* allocates pipe from pipe book */
@@ -146,8 +147,16 @@
     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);
+    /* Partial MDP comp that prefers GPU perf-wise. Since the GPU's
+     * perf is proportional to the pixels it processes, we use the number of
+     * pixels as a heuristic */
+    bool loadBasedCompPreferGPU(hwc_context_t *ctx,
+            hwc_display_contents_1_t* list);
+    /* Partial MDP comp that prefers MDP perf-wise. Since the MDP's perf is
+     * proportional to the bandwidth, overlaps it sees, we use that as a
+     * heuristic */
+    bool loadBasedCompPreferMDP(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);
@@ -192,6 +201,7 @@
     bool programYUV(hwc_context_t *ctx, hwc_display_contents_1_t* list);
     void reset(const int& numAppLayers, hwc_display_contents_1_t* list);
     bool isSupportedForMDPComp(hwc_context_t *ctx, hwc_layer_1_t* layer);
+    bool resourceCheck(hwc_context_t *ctx, hwc_display_contents_1_t *list);
 
     int mDpy;
     static bool sEnabled;
@@ -203,9 +213,9 @@
     static int sMaxPipesPerMixer;
     //Max bandwidth. Value is in GBPS. For ex: 2.3 means 2.3GBPS
     static float sMaxBw;
-    //Tracks composition bytes claimed. Represented as the total w*h*bpp
-    //going to MDP mixers
-    static uint32_t sCompBytesClaimed;
+    //Tracks composition bandwidth claimed. Represented as the total
+    //w*h*bpp*fps (gigabytes-per-second) going to MDP mixers.
+    static double sBwClaimed;
     static IdleInvalidator *idleInvalidator;
     struct FrameInfo mCurrentFrame;
     struct LayerCache mCachedFrame;
diff --git a/libhwcomposer/hwc_qclient.cpp b/libhwcomposer/hwc_qclient.cpp
index a17565b..3b98788 100644
--- a/libhwcomposer/hwc_qclient.cpp
+++ b/libhwcomposer/hwc_qclient.cpp
@@ -51,57 +51,28 @@
     ALOGD_IF(QCLIENT_DEBUG,"QClient Destructor invoked");
 }
 
-status_t QClient::notifyCallback(uint32_t msg, uint32_t value) {
-
-    if (msg > IQService::VPU_COMMAND_LIST_START &&
-        msg < IQService::VPU_COMMAND_LIST_END) {
-        return vpuCommand(msg, value);
-    }
-
-    switch(msg) {
-        case IQService::SECURING:
-            securing(value);
-            break;
-        case IQService::UNSECURING:
-            unsecuring(value);
-            break;
-        case IQService::SCREEN_REFRESH:
-            return screenRefresh();
-            break;
-        case IQService::EXTERNAL_ORIENTATION:
-            setExtOrientation(value);
-            break;
-        case IQService::BUFFER_MIRRORMODE:
-            setBufferMirrorMode(value);
-            break;
-        default:
-            return NO_ERROR;
-    }
-    return NO_ERROR;
-}
-
-void QClient::securing(uint32_t startEnd) {
-    Locker::Autolock _sl(mHwcContext->mDrawLock);
+static void securing(hwc_context_t *ctx, uint32_t startEnd) {
+    Locker::Autolock _sl(ctx->mDrawLock);
     //The only way to make this class in this process subscribe to media
     //player's death.
     IMediaDeathNotifier::getMediaPlayerService();
 
-    mHwcContext->mSecuring = startEnd;
+    ctx->mSecuring = startEnd;
     //We're done securing
     if(startEnd == IQService::END)
-        mHwcContext->mSecureMode = true;
-    if(mHwcContext->proc)
-        mHwcContext->proc->invalidate(mHwcContext->proc);
+        ctx->mSecureMode = true;
+    if(ctx->proc)
+        ctx->proc->invalidate(ctx->proc);
 }
 
-void QClient::unsecuring(uint32_t startEnd) {
-    Locker::Autolock _sl(mHwcContext->mDrawLock);
-    mHwcContext->mSecuring = startEnd;
+static void unsecuring(hwc_context_t *ctx, uint32_t startEnd) {
+    Locker::Autolock _sl(ctx->mDrawLock);
+    ctx->mSecuring = startEnd;
     //We're done unsecuring
     if(startEnd == IQService::END)
-        mHwcContext->mSecureMode = false;
-    if(mHwcContext->proc)
-        mHwcContext->proc->invalidate(mHwcContext->proc);
+        ctx->mSecureMode = false;
+    if(ctx->proc)
+        ctx->proc->invalidate(ctx->proc);
 }
 
 void QClient::MPDeathNotifier::died() {
@@ -113,33 +84,68 @@
         mHwcContext->proc->invalidate(mHwcContext->proc);
 }
 
-android::status_t QClient::screenRefresh() {
+static android::status_t screenRefresh(hwc_context_t *ctx) {
     status_t result = NO_INIT;
 #ifdef QCOM_BSP
-    if(mHwcContext->proc) {
-        mHwcContext->proc->invalidate(mHwcContext->proc);
+    if(ctx->proc) {
+        ctx->proc->invalidate(ctx->proc);
         result = NO_ERROR;
     }
 #endif
     return result;
 }
 
-android::status_t QClient::vpuCommand(uint32_t command, uint32_t setting) {
+static android::status_t vpuCommand(hwc_context_t *ctx,
+        uint32_t command,
+        const Parcel* inParcel,
+        Parcel* outParcel) {
     status_t result = NO_INIT;
 #ifdef QCOM_BSP
 #ifdef VPU_TARGET
-    result = mHwcContext->mVPUClient->processCommand(command, setting);
+    result = ctx->mVPUClient->processCommand(command, inParcel, outParcel);
 #endif
 #endif
     return result;
 }
 
-void QClient::setExtOrientation(uint32_t orientation) {
-    mHwcContext->mExtOrientation = orientation;
+static void setExtOrientation(hwc_context_t *ctx, uint32_t orientation) {
+    ctx->mExtOrientation = orientation;
 }
 
-void QClient::setBufferMirrorMode(uint32_t enable) {
-    mHwcContext->mBufferMirrorMode = enable;
+static void setBufferMirrorMode(hwc_context_t *ctx, uint32_t enable) {
+    ctx->mBufferMirrorMode = enable;
 }
 
+status_t QClient::notifyCallback(uint32_t command, const Parcel* inParcel,
+        Parcel* outParcel) {
+
+    if (command > IQService::VPU_COMMAND_LIST_START &&
+        command < IQService::VPU_COMMAND_LIST_END) {
+        return vpuCommand(mHwcContext, command, inParcel, outParcel);
+    }
+
+    switch(command) {
+        case IQService::SECURING:
+            securing(mHwcContext, inParcel->readInt32());
+            break;
+        case IQService::UNSECURING:
+            unsecuring(mHwcContext, inParcel->readInt32());
+            break;
+        case IQService::SCREEN_REFRESH:
+            return screenRefresh(mHwcContext);
+            break;
+        case IQService::EXTERNAL_ORIENTATION:
+            setExtOrientation(mHwcContext, inParcel->readInt32());
+            break;
+        case IQService::BUFFER_MIRRORMODE:
+            setBufferMirrorMode(mHwcContext, inParcel->readInt32());
+            break;
+        default:
+            return NO_ERROR;
+    }
+    return NO_ERROR;
+}
+
+
+
 }
diff --git a/libhwcomposer/hwc_qclient.h b/libhwcomposer/hwc_qclient.h
index fa1d6b0..d955377 100644
--- a/libhwcomposer/hwc_qclient.h
+++ b/libhwcomposer/hwc_qclient.h
@@ -39,6 +39,7 @@
 
 struct hwc_context_t;
 
+class Params;
 namespace qClient {
 // ----------------------------------------------------------------------------
 
@@ -46,7 +47,9 @@
 public:
     QClient(hwc_context_t *ctx);
     virtual ~QClient();
-    virtual android::status_t notifyCallback(uint32_t msg, uint32_t value);
+    virtual android::status_t notifyCallback(uint32_t command,
+            const android::Parcel* inParcel,
+            android::Parcel* outParcel);
 
 private:
     //Notifies of Media Player death
@@ -57,13 +60,6 @@
         hwc_context_t *mHwcContext;
     };
 
-    void securing(uint32_t startEnd);
-    void unsecuring(uint32_t startEnd);
-    android::status_t screenRefresh();
-    void setExtOrientation(uint32_t orientation);
-    void setBufferMirrorMode(uint32_t enable);
-    android::status_t vpuCommand(uint32_t command, uint32_t setting);
-
     hwc_context_t *mHwcContext;
     const android::sp<android::IMediaDeathNotifier> mMPDeathNotifier;
 };
diff --git a/libhwcomposer/hwc_uevents.cpp b/libhwcomposer/hwc_uevents.cpp
index 926f425..5cb87f8 100644
--- a/libhwcomposer/hwc_uevents.cpp
+++ b/libhwcomposer/hwc_uevents.cpp
@@ -92,7 +92,7 @@
         while(((iter_str - strUdata) <= len) && (*iter_str)) {
             char* pstr = strstr(iter_str, "PANEL_ALIVE=0");
             if (pstr != NULL) {
-                ALOGE("%s: got change event in fb0 with PANEL_ALIVE=0",
+                ALOGI("%s: got change event in fb0 with PANEL_ALIVE=0",
                                                            __FUNCTION__);
                 ctx->mPanelResetStatus = true;
                 return true;
diff --git a/libhwcomposer/hwc_utils.cpp b/libhwcomposer/hwc_utils.cpp
index 477fe90..eed6e9d 100644
--- a/libhwcomposer/hwc_utils.cpp
+++ b/libhwcomposer/hwc_utils.cpp
@@ -612,7 +612,6 @@
 
     hwc_rect_t displayFrame  = layer->displayFrame;
     hwc_rect_t sourceCrop = integerizeSourceCrop(layer->sourceCropf);
-    trimLayer(ctx, dpy, layer->transform, sourceCrop, displayFrame);
 
     dst_w = displayFrame.right - displayFrame.left;
     dst_h = displayFrame.bottom - displayFrame.top;
@@ -640,7 +639,6 @@
     hwc_rect_t sourceCrop = integerizeSourceCrop(layer->sourceCropf);
     hwc_rect_t displayFrame  = layer->displayFrame;
     private_handle_t *hnd = (private_handle_t *)layer->handle;
-    trimLayer(ctx, dpy, layer->transform, sourceCrop, displayFrame);
 
     cropL = sourceCrop;
     dstL = displayFrame;
@@ -701,8 +699,35 @@
     return false;
 }
 
+static void trimLayer(hwc_context_t *ctx, const int& dpy, const int& transform,
+        hwc_rect_t& crop, hwc_rect_t& dst) {
+    int hw_w = ctx->dpyAttr[dpy].xres;
+    int hw_h = ctx->dpyAttr[dpy].yres;
+    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 };
+        qhwc::calculate_crop_rects(crop, dst, scissor, transform);
+    }
+}
+
+static void trimList(hwc_context_t *ctx, hwc_display_contents_1_t *list,
+        const int& dpy) {
+    for(uint32_t i = 0; i < list->numHwLayers - 1; i++) {
+        hwc_layer_1_t *layer = &list->hwLayers[i];
+        hwc_rect_t crop = integerizeSourceCrop(layer->sourceCropf);
+        trimLayer(ctx, dpy,
+                list->hwLayers[i].transform,
+                (hwc_rect_t&)crop,
+                (hwc_rect_t&)list->hwLayers[i].displayFrame);
+        layer->sourceCropf.left = crop.left;
+        layer->sourceCropf.right = crop.right;
+        layer->sourceCropf.top = crop.top;
+        layer->sourceCropf.bottom = crop.bottom;
+    }
+}
+
 void setListStats(hwc_context_t *ctx,
-        const hwc_display_contents_1_t *list, int dpy) {
+        hwc_display_contents_1_t *list, int dpy) {
     const int prevYuvCount = ctx->listStats[dpy].yuvCount;
     memset(&ctx->listStats[dpy], 0, sizeof(ListStats));
     ctx->listStats[dpy].numAppLayers = list->numHwLayers - 1;
@@ -719,6 +744,7 @@
                       (int)ctx->dpyAttr[dpy].xres, (int)ctx->dpyAttr[dpy].yres);
     ctx->listStats[dpy].secureUI = false;
 
+    trimList(ctx, list, dpy);
     optimizeLayerRects(ctx, list, dpy);
 
     for (size_t i = 0; i < (size_t)ctx->listStats[dpy].numAppLayers; i++) {
@@ -1223,17 +1249,6 @@
     return ret;
 }
 
-void trimLayer(hwc_context_t *ctx, const int& dpy, const int& transform,
-        hwc_rect_t& crop, hwc_rect_t& dst) {
-    int hw_w = ctx->dpyAttr[dpy].xres;
-    int hw_h = ctx->dpyAttr[dpy].yres;
-    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 };
-        qhwc::calculate_crop_rects(crop, dst, scissor, transform);
-    }
-}
-
 void setMdpFlags(hwc_layer_1_t *layer,
         ovutils::eMdpFlags &mdpFlags,
         int rotDownscale, int transform) {
@@ -1483,7 +1498,6 @@
     }
 
     setMdpFlags(layer, mdpFlags, downscale, transform);
-    trimLayer(ctx, dpy, transform, crop, dst);
 
     if(isYuvBuffer(hnd) && //if 90 component or downscale, use rot
             ((transform & HWC_TRANSFORM_ROT_90) || downscale)) {
@@ -1600,7 +1614,6 @@
         }
     }
 
-
     setMdpFlags(layer, mdpFlagsL, 0, transform);
 
     if(lDest != OV_INVALID && rDest != OV_INVALID) {
@@ -1608,8 +1621,6 @@
         setMdpFlags(mdpFlagsL, OV_MDSS_MDP_DUAL_PIPE);
     }
 
-    trimLayer(ctx, dpy, transform, crop, dst);
-
     //Will do something only if feature enabled and conditions suitable
     //hollow call otherwise
     if(ctx->mAD->prepare(ctx, crop, whf, hnd)) {
diff --git a/libhwcomposer/hwc_utils.h b/libhwcomposer/hwc_utils.h
index 3d8b1e4..6288057 100644
--- a/libhwcomposer/hwc_utils.h
+++ b/libhwcomposer/hwc_utils.h
@@ -187,7 +187,7 @@
 // -----------------------------------------------------------------------------
 // Utility functions - implemented in hwc_utils.cpp
 void dumpLayer(hwc_layer_1_t const* l);
-void setListStats(hwc_context_t *ctx, const hwc_display_contents_1_t *list,
+void setListStats(hwc_context_t *ctx, hwc_display_contents_1_t *list,
         int dpy);
 void initContext(hwc_context_t *ctx);
 void closeContext(hwc_context_t *ctx);
@@ -254,10 +254,6 @@
 int hwc_sync(hwc_context_t *ctx, hwc_display_contents_1_t* list, int dpy,
         int fd);
 
-//Trims a layer's source crop which is outside of screen boundary.
-void trimLayer(hwc_context_t *ctx, const int& dpy, const int& transform,
-        hwc_rect_t& crop, hwc_rect_t& dst);
-
 //Sets appropriate mdp flags for a layer.
 void setMdpFlags(hwc_layer_1_t *layer,
         ovutils::eMdpFlags &mdpFlags,
diff --git a/libhwcomposer/hwc_vpuclient.cpp b/libhwcomposer/hwc_vpuclient.cpp
index bdfeae5..23c6841 100644
--- a/libhwcomposer/hwc_vpuclient.cpp
+++ b/libhwcomposer/hwc_vpuclient.cpp
@@ -31,9 +31,11 @@
 #include "hwc_vpuclient.h"
 #include "hwc_utils.h"
 #include <vpu/vpu.h>
+#include <binder/Parcel.h>
 
 
 using namespace vpu;
+using namespace android;
 namespace qhwc {
 
 VPUClient::VPUClient()
@@ -78,11 +80,14 @@
     return err;
 }
 
-int VPUClient::processCommand(uint32_t command, uint32_t setting)
+int VPUClient::processCommand(uint32_t command,
+        const Parcel* inParcel, Parcel* outParcel)
 {
     if(!mVPU)
         return 0;
-    return mVPU->processCommand(command, setting);
+    //XXX: Enable when VPU enables it
+    //return mVPU->processCommand(command, inParcel, outParcel);
+    return 0;
 }
 
 }; // namespace qhwc
diff --git a/libhwcomposer/hwc_vpuclient.h b/libhwcomposer/hwc_vpuclient.h
index 8cc7137..9985517 100644
--- a/libhwcomposer/hwc_vpuclient.h
+++ b/libhwcomposer/hwc_vpuclient.h
@@ -39,6 +39,9 @@
 namespace vpu {
 class VPU;
 };
+namespace android {
+class Parcel;
+};
 
 namespace qhwc {
 
@@ -52,7 +55,8 @@
 
     int draw(hwc_context_t *ctx, hwc_display_contents_1_t* list);
 
-    int processCommand(uint32_t command, uint32_t setting);
+    int processCommand(uint32_t command,
+            const android::Parcel* inParcel, android::Parcel* outParcel);
 
 private:
     vpu::VPU *mVPU;
diff --git a/liboverlay/Android.mk b/liboverlay/Android.mk
index 560b57f..d8c2ab5 100644
--- a/liboverlay/Android.mk
+++ b/liboverlay/Android.mk
@@ -6,8 +6,12 @@
 LOCAL_MODULE_PATH             := $(TARGET_OUT_SHARED_LIBRARIES)
 LOCAL_MODULE_TAGS             := optional
 LOCAL_C_INCLUDES              := $(common_includes) $(kernel_includes)
-LOCAL_SHARED_LIBRARIES        := $(common_libs) libqdutils libmemalloc libsync
+LOCAL_SHARED_LIBRARIES        := $(common_libs) libqdutils libmemalloc \
+                                 libsync libdl
 LOCAL_CFLAGS                  := $(common_flags) -DLOG_TAG=\"qdoverlay\"
+ifeq ($(TARGET_USES_QSEED_SCALAR),true)
+    LOCAL_CFLAGS += -DUSES_QSEED_SCALAR
+endif
 LOCAL_ADDITIONAL_DEPENDENCIES := $(common_deps)
 LOCAL_SRC_FILES := \
       overlay.cpp \
diff --git a/liboverlay/overlay.cpp b/liboverlay/overlay.cpp
index 6aaf236..f9d87c7 100644
--- a/liboverlay/overlay.cpp
+++ b/liboverlay/overlay.cpp
@@ -27,16 +27,23 @@
 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
+#include <dlfcn.h>
 #include "overlay.h"
 #include "pipes/overlayGenPipe.h"
 #include "mdp_version.h"
 #include "qdMetaData.h"
 
+#ifdef USES_QSEED_SCALAR
+#include <scale/scale.h>
+using namespace scale;
+#endif
+
 #define PIPE_DEBUG 0
 
 namespace overlay {
 using namespace utils;
 
+
 Overlay::Overlay() {
     PipeBook::NUM_PIPES = qdutils::MDPVersion::getInstance().getTotalPipes();
     for(int i = 0; i < PipeBook::NUM_PIPES; i++) {
@@ -44,12 +51,14 @@
     }
 
     mDumpStr[0] = '\0';
+    initScalar();
 }
 
 Overlay::~Overlay() {
     for(int i = 0; i < PipeBook::NUM_PIPES; i++) {
         mPipeBook[i].destroy();
     }
+    destroyScalar();
 }
 
 void Overlay::configBegin() {
@@ -60,6 +69,13 @@
     }
     sForceSetBitmap = 0;
     mDumpStr[0] = '\0';
+
+#ifdef USES_QSEED_SCALAR
+    Scale *scalar = getScalar();
+    if(scalar) {
+        scalar->configBegin();
+    }
+#endif
 }
 
 void Overlay::configDone() {
@@ -81,6 +97,13 @@
     }
     dump();
     PipeBook::save();
+
+#ifdef USES_QSEED_SCALAR
+    Scale *scalar = getScalar();
+    if(scalar) {
+        scalar->configDone();
+    }
+#endif
 }
 
 eDest Overlay::nextPipe(eMdpPipeType type, int dpy, int mixer) {
@@ -388,6 +411,42 @@
     }
 }
 
+void Overlay::initScalar() {
+#ifdef USES_QSEED_SCALAR
+    if(sLibScaleHandle == NULL) {
+        sLibScaleHandle = dlopen("libscale.so", RTLD_NOW);
+    }
+
+    if(sLibScaleHandle) {
+        if(sScale == NULL) {
+            Scale* (*getInstance)();
+            *(void **) &getInstance = dlsym(sLibScaleHandle, "getInstance");
+            if(getInstance) {
+                sScale = getInstance();
+            }
+        }
+    }
+#endif
+}
+
+void Overlay::destroyScalar() {
+#ifdef USES_QSEED_SCALAR
+    if(sLibScaleHandle) {
+        if(sScale) {
+            void (*destroyInstance)(Scale*);
+            *(void **) &destroyInstance = dlsym(sLibScaleHandle,
+                    "destroyInstance");
+            if(destroyInstance) {
+                destroyInstance(sScale);
+                sScale = NULL;
+            }
+        }
+        dlclose(sLibScaleHandle);
+        sLibScaleHandle = NULL;
+    }
+#endif
+}
+
 void Overlay::PipeBook::init() {
     mPipe = NULL;
     mDisplay = DPY_UNUSED;
@@ -413,5 +472,7 @@
 int Overlay::PipeBook::sAllocatedBitmap = 0;
 utils::eMdpPipeType Overlay::PipeBook::pipeTypeLUT[utils::OV_MAX] =
     {utils::OV_MDP_PIPE_ANY};
+void *Overlay::sLibScaleHandle = NULL;
+scale::Scale *Overlay::sScale = NULL;
 
 }; // namespace overlay
diff --git a/liboverlay/overlay.h b/liboverlay/overlay.h
index 295e123..8519ad2 100644
--- a/liboverlay/overlay.h
+++ b/liboverlay/overlay.h
@@ -34,6 +34,9 @@
 #include "utils/threads.h"
 
 struct MetaData_t;
+namespace scale {
+class Scale;
+};
 
 namespace overlay {
 class GenericPipe;
@@ -112,6 +115,8 @@
     static int getFbForDpy(const int& dpy);
     static bool displayCommit(const int& fd, const utils::Dim& roi);
     static bool displayCommit(const int& fd);
+    /* Returns the scalar object */
+    static scale::Scale *getScalar();
 
 private:
     /* Ctor setup */
@@ -119,6 +124,10 @@
     /*Validate index range, abort if invalid */
     void validate(int index);
     void dump() const;
+    /* Creates a scalar object using libscale.so */
+    static void initScalar();
+    /* Destroys the scalar object using libscale.so */
+    static void destroyScalar();
 
     /* Just like a Facebook for pipes, but much less profile info */
     struct PipeBook {
@@ -178,6 +187,8 @@
     static int sDpyFbMap[DPY_MAX];
     static int sDMAMode;
     static int sForceSetBitmap;
+    static void *sLibScaleHandle;
+    static scale::Scale *sScale;
 };
 
 inline void Overlay::validate(int index) {
@@ -250,6 +261,10 @@
     sForceSetBitmap |= (1 << dpy);
 }
 
+inline scale::Scale *Overlay::getScalar() {
+    return sScale;
+}
+
 inline bool Overlay::PipeBook::valid() {
     return (mPipe != NULL);
 }
diff --git a/liboverlay/overlayCtrlData.h b/liboverlay/overlayCtrlData.h
index d34fd2d..18ef5e6 100644
--- a/liboverlay/overlayCtrlData.h
+++ b/liboverlay/overlayCtrlData.h
@@ -53,7 +53,7 @@
     /* dtor close */
     ~Ctrl();
     /* init fd etc*/
-    bool init(uint32_t fbnum);
+    bool init(uint32_t dpy);
     /* close underlying mdp */
     bool close();
 
@@ -102,7 +102,7 @@
     /* calls close */
     ~Data();
     /* init fd etc */
-    bool init(uint32_t fbnum);
+    bool init(uint32_t dpy);
     /* calls underlying mdp close */
     bool close();
     /* set overlay pipe id in the mdp struct */
@@ -147,10 +147,10 @@
     return true;
 }
 
-inline bool Ctrl::init(uint32_t fbnum) {
+inline bool Ctrl::init(uint32_t dpy) {
     // MDP/FD init
-    if(!mMdp.init(fbnum)) {
-        ALOGE("Ctrl failed to init fbnum=%d", fbnum);
+    if(!mMdp.init(dpy)) {
+        ALOGE("Ctrl failed to init dpy=%d", dpy);
         return false;
     }
     return true;
@@ -246,8 +246,8 @@
 
 inline int Data::getPipeId() const { return mMdp.getPipeId(); }
 
-inline bool Data::init(uint32_t fbnum) {
-    if(!mMdp.init(fbnum)) {
+inline bool Data::init(uint32_t dpy) {
+    if(!mMdp.init(dpy)) {
         ALOGE("Data cannot init mdp");
         return false;
     }
diff --git a/liboverlay/overlayMdp.cpp b/liboverlay/overlayMdp.cpp
index 5da8b55..fbb173e 100644
--- a/liboverlay/overlayMdp.cpp
+++ b/liboverlay/overlayMdp.cpp
@@ -20,6 +20,12 @@
 #include "overlayUtils.h"
 #include "overlayMdp.h"
 #include "mdp_version.h"
+#include <overlay.h>
+
+#ifdef USES_QSEED_SCALAR
+#include <scale/scale.h>
+using namespace scale;
+#endif
 
 #define HSIC_SETTINGS_DEBUG 0
 
@@ -39,13 +45,20 @@
 namespace ovutils = overlay::utils;
 namespace overlay {
 
-bool MdpCtrl::init(uint32_t fbnum) {
+bool MdpCtrl::init(uint32_t dpy) {
+    int fbnum = Overlay::getFbForDpy(dpy);
+    if( fbnum < 0 ) {
+        ALOGE("%s: Invalid FB for the display: %d",__FUNCTION__, dpy);
+        return false;
+    }
+
     // FD init
     if(!utils::openDev(mFd, fbnum,
                 Res::fbPath, O_RDWR)){
         ALOGE("Ctrl failed to init fbnum=%d", fbnum);
         return false;
     }
+    mDpy = dpy;
     return true;
 }
 
@@ -57,6 +70,7 @@
     mOrientation = utils::OVERLAY_TRANSFORM_0;
     mDownscale = 0;
     mForceSet = false;
+    mDpy = 0;
 #ifdef USES_POST_PROCESSING
     mPPChanged = false;
     memset(&mParams, 0, sizeof(struct compute_params));
@@ -205,11 +219,22 @@
             mdp_wrapper::dump("== Bad OVInfo is: ", mOVInfo);
             mdp_wrapper::dump("== Last good known OVInfo is: ", mLkgo);
             this->restore();
+#ifdef USES_QSEED_SCALAR
+            if(Overlay::getScalar()) {
+                Overlay::getScalar()->configAbort(mDpy);
+            }
+#endif
             return false;
         }
         this->save();
     }
 
+#ifdef USES_QSEED_SCALAR
+    if(Overlay::getScalar()) {
+        Overlay::getScalar()->configSet(mOVInfo, mDpy, mFd.getFD());
+    }
+#endif
+
     return true;
 }
 
@@ -375,4 +400,21 @@
     return true;
 }
 
+
+//// MdpData ////////////
+bool MdpData::init(uint32_t dpy) {
+    int fbnum = Overlay::getFbForDpy(dpy);
+    if( fbnum < 0 ) {
+        ALOGE("%s: Invalid FB for the display: %d",__FUNCTION__, dpy);
+        return false;
+    }
+
+    // FD init
+    if(!utils::openDev(mFd, fbnum, Res::fbPath, O_RDWR)){
+        ALOGE("Ctrl failed to init fbnum=%d", fbnum);
+        return false;
+    }
+    return true;
+}
+
 } // overlay
diff --git a/liboverlay/overlayMdp.h b/liboverlay/overlayMdp.h
index 4a648ef..6dd3976 100644
--- a/liboverlay/overlayMdp.h
+++ b/liboverlay/overlayMdp.h
@@ -39,8 +39,8 @@
     explicit MdpCtrl();
     /* dtor close */
     ~MdpCtrl();
-    /* init underlying device using fbnum */
-    bool init(uint32_t fbnum);
+    /* init underlying device using fbnum for dpy */
+    bool init(uint32_t dpy);
     /* unset overlay, reset and close fd */
     bool close();
     /* reset and set ov id to -1 / MSMFB_NEW_REQUEST */
@@ -134,6 +134,7 @@
     OvFD          mFd;
     int mDownscale;
     bool mForceSet;
+    int mDpy;
 
 #ifdef USES_POST_PROCESSING
     /* PP Compute Params */
@@ -176,7 +177,7 @@
     /* dtor close*/
     ~MdpData();
     /* init FD */
-    bool init(uint32_t fbnum);
+    bool init(uint32_t dpy);
     /* memset0 the underlying mdp object */
     void reset();
     /* close fd, and reset */
@@ -397,15 +398,6 @@
 
 inline MdpData::~MdpData() { close(); }
 
-inline bool MdpData::init(uint32_t fbnum) {
-    // FD init
-    if(!utils::openDev(mFd, fbnum, Res::fbPath, O_RDWR)){
-        ALOGE("Ctrl failed to init fbnum=%d", fbnum);
-        return false;
-    }
-    return true;
-}
-
 inline void MdpData::reset() {
     overlay::utils::memset0(mOvData);
     mOvData.data.memory_id = -1;
diff --git a/liboverlay/pipes/overlayGenPipe.cpp b/liboverlay/pipes/overlayGenPipe.cpp
index 2bf2369..fd62cd6 100644
--- a/liboverlay/pipes/overlayGenPipe.cpp
+++ b/liboverlay/pipes/overlayGenPipe.cpp
@@ -28,7 +28,6 @@
 */
 
 #include "overlayGenPipe.h"
-#include "overlay.h"
 #include "mdp_version.h"
 
 namespace overlay {
@@ -47,20 +46,12 @@
     ALOGE_IF(DEBUG_OVERLAY, "GenericPipe init");
     mRotDownscaleOpt = false;
 
-    int fbNum = Overlay::getFbForDpy(mDpy);
-    if( fbNum < 0 ) {
-        ALOGE("%s: Invalid FB for the display: %d",__FUNCTION__, mDpy);
-        return false;
-    }
-
-    ALOGD_IF(DEBUG_OVERLAY,"%s: mFbNum:%d",__FUNCTION__, fbNum);
-
-    if(!mCtrlData.ctrl.init(fbNum)) {
+    if(!mCtrlData.ctrl.init(mDpy)) {
         ALOGE("GenericPipe failed to init ctrl");
         return false;
     }
 
-    if(!mCtrlData.data.init(fbNum)) {
+    if(!mCtrlData.data.init(mDpy)) {
         ALOGE("GenericPipe failed to init data");
         return false;
     }
diff --git a/libqdutils/Android.mk b/libqdutils/Android.mk
index b6bbc47..d514405 100644
--- a/libqdutils/Android.mk
+++ b/libqdutils/Android.mk
@@ -4,13 +4,14 @@
 
 LOCAL_MODULE                  := libqdutils
 LOCAL_MODULE_TAGS             := optional
-LOCAL_SHARED_LIBRARIES        := $(common_libs)
+LOCAL_SHARED_LIBRARIES        := $(common_libs) libui
 LOCAL_C_INCLUDES              := $(common_includes) $(kernel_includes)
 LOCAL_CFLAGS                  := $(common_flags) -DLOG_TAG=\"qdutils\"
 LOCAL_ADDITIONAL_DEPENDENCIES := $(common_deps)
 LOCAL_SRC_FILES               := profiler.cpp mdp_version.cpp \
                                  idle_invalidator.cpp \
-                                 comptype.cpp qd_utils.cpp
+                                 comptype.cpp qd_utils.cpp \
+                                 cb_utils.cpp
 include $(BUILD_SHARED_LIBRARY)
 
 include $(CLEAR_VARS)
diff --git a/libqdutils/cb_utils.cpp b/libqdutils/cb_utils.cpp
new file mode 100644
index 0000000..bc7e5b1
--- /dev/null
+++ b/libqdutils/cb_utils.cpp
@@ -0,0 +1,79 @@
+/* Copyright (c) 2013, 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
+* met:
+*   * Redistributions of source code must retain the above copyrigh
+*     notice, this list of conditions and the following disclaimer
+*   * Redistributions in binary form must reproduce the above
+*     copyright notice, this list of conditions and the following
+*     disclaimer in the documentation and/or other materials provided
+*     with the distribution.
+*   * Neither the name of The Linux Foundation nor the names of its
+*     contributors may be used to endorse or promote products derived
+*     from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include "cb_utils.h"
+
+/* get union of two rects into 3rd rect */
+void getUnion(hwc_rect_t& rect1,hwc_rect_t& rect2, hwc_rect_t& irect) {
+    irect.left   = min(rect1.left, rect2.left);
+    irect.top    = min(rect1.top, rect2.top);
+    irect.right  = max(rect1.right, rect2.right);
+    irect.bottom = max(rect1.bottom, rect2.bottom);
+}
+
+using namespace android;
+using namespace qhwc;
+namespace qdutils {
+
+int CBUtils::getuiClearRegion(hwc_display_contents_1_t* list,
+          hwc_rect_t &clearWormholeRect, LayerProp *layerProp) {
+
+    uint32_t last = list->numHwLayers - 1;
+    hwc_rect_t fbFrame = list->hwLayers[last].displayFrame;
+
+    Rect fbFrameRect(fbFrame.left,fbFrame.top,fbFrame.right,fbFrame.bottom);
+    Region wormholeRegion(fbFrameRect);
+
+    for (uint32_t i = 0 ; i < last; i++) {
+        // need to take care only in per pixel blending.
+        // Restrict calculation only for copybit layers.
+        if((list->hwLayers[i].blending != HWC_BLENDING_NONE) ||
+           !(layerProp[i].mFlags & HWC_COPYBIT))
+            continue ;
+        hwc_rect_t displayFrame = list->hwLayers[i].displayFrame;
+        Rect tmpRect(displayFrame.left,displayFrame.top,displayFrame.right,
+        displayFrame.bottom);
+        Region tmpRegion(tmpRect);
+        wormholeRegion.subtractSelf(wormholeRegion.intersect(tmpRegion));
+    }
+    if (wormholeRegion.isEmpty()) {
+        return 0;
+    }
+    //TO DO :- 1. remove union and call clear for each rect.
+    //      :- 2. support swap ract feature.
+    Region::const_iterator it = wormholeRegion.begin();
+    Region::const_iterator const end = wormholeRegion.end();
+    while (it != end) {
+        const Rect& r = *it++;
+        hwc_rect_t tmpWormRect = {r.left,r.top,r.right,r.bottom};
+        getUnion(clearWormholeRect, tmpWormRect, clearWormholeRect);
+
+    }
+    return 1;
+}
+
+}//namespace qdutils
diff --git a/libqdutils/cb_utils.h b/libqdutils/cb_utils.h
new file mode 100644
index 0000000..85dd78f
--- /dev/null
+++ b/libqdutils/cb_utils.h
@@ -0,0 +1,45 @@
+/* Copyright (c) 2013, 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
+* met:
+*   * Redistributions of source code must retain the above copyrigh
+*     notice, this list of conditions and the following disclaimer
+*   * Redistributions in binary form must reproduce the above
+*     copyright notice, this list of conditions and the following
+*     disclaimer in the documentation and/or other materials provided
+*     with the distribution.
+*   * Neither the name of The Linux Foundation nor the names of its
+*     contributors may be used to endorse or promote products derived
+*     from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+#ifndef CB_UTIL_H
+#define CB_UTIL_H
+
+#include <ui/Region.h>
+#include "hwc_utils.h"
+
+using namespace qhwc;
+namespace qdutils {
+class CBUtils {
+public:
+static int getuiClearRegion(hwc_display_contents_1_t* list,
+                              hwc_rect_t &clearWormholeRec,
+                                      LayerProp *layerProp);
+};
+}//namespace qdutils
+#endif /* end of include guard: CB_UTIL_H*/
+
diff --git a/libqdutils/mdp_version.cpp b/libqdutils/mdp_version.cpp
index 259d078..0809fd0 100644
--- a/libqdutils/mdp_version.cpp
+++ b/libqdutils/mdp_version.cpp
@@ -27,9 +27,6 @@
  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 #include <cutils/log.h>
-#include <fcntl.h>
-#include <sys/ioctl.h>
-#include <linux/fb.h>
 #include <linux/msm_mdp.h>
 #include "mdp_version.h"
 
@@ -42,81 +39,33 @@
 
 MDPVersion::MDPVersion()
 {
-    int fb_fd = open("/dev/graphics/fb0", O_RDWR);
-    char panel_type = 0;
-    struct fb_fix_screeninfo fb_finfo;
-
-    mMDPVersion = MDP_V_UNKNOWN;
+    mMDPVersion = MDSS_V5;
     mMdpRev = 0;
     mRGBPipes = 0;
     mVGPipes = 0;
     mDMAPipes = 0;
     mFeatures = 0;
     mMDPUpscale = 0;
-    //TODO get this from driver, default for A-fam to 8
-    mMDPDownscale = 8;
-    mFd = fb_fd;
+    mMDPDownscale = 0;
+    mPanelType = NO_PANEL;
 
-    if (ioctl(fb_fd, FBIOGET_FSCREENINFO, &fb_finfo) < 0) {
-        ALOGE("FBIOGET_FSCREENINFO failed");
-    } else {
-        if(!strncmp(fb_finfo.id, "msmfb", 5)) {
-            char str_ver[4] = { 0 };
-            memcpy(str_ver, &fb_finfo.id[5], 3);
-            str_ver[3] = '\0';
-            mMDPVersion = atoi(str_ver);
-            //Normalize MDP version to ease comparison.
-            //This is needed only because
-            //MDP 3.0.3 reports value as 303 which
-            //is more than all the others
-            if (mMDPVersion < 100)
-                mMDPVersion *= 10;
-
-            mRGBPipes = mVGPipes = 2;
-
-        } else if (!strncmp(fb_finfo.id, "mdssfb", 6)) {
-            mMDPVersion = MDSS_V5;
-            if(!updateSysFsInfo()) {
-                ALOGE("Unable to read updateSysFsInfo");
-            }
-            if (mMdpRev == MDP_V3_0_4){
-                mMDPVersion = MDP_V3_0_4;
-            }
-        }
-
-        /* Assumes panel type is 2nd element in '_' delimited id string */
-        char * ptype = strstr(fb_finfo.id, "_");
-        if (!ptype || (*(++ptype) == '\0')) {
-            ALOGE("Invalid framebuffer info string: %s", fb_finfo.id);
-            ptype = fb_finfo.id;
-        }
-        panel_type = *ptype;
+    if(!updatePanelInfo()) {
+        ALOGE("Unable to read Primary Panel Information");
     }
-    mPanelType = panel_type;
+    if(!updateSysFsInfo()) {
+        ALOGE("Unable to read display sysfs node");
+    }
+    if (mMdpRev == MDP_V3_0_4){
+        mMDPVersion = MDP_V3_0_4;
+    }
+
     mHasOverlay = false;
     if((mMDPVersion >= MDP_V4_0) ||
        (mMDPVersion == MDP_V_UNKNOWN) ||
        (mMDPVersion == MDP_V3_0_4))
         mHasOverlay = true;
-    if(mMDPVersion >= MDSS_V5) {
-        char split[64] = {0};
-        FILE* fp = fopen("/sys/class/graphics/fb0/msm_fb_split", "r");
-        if(fp){
-            //Format "left right" space as delimiter
-            if(fread(split, sizeof(char), 64, fp)) {
-                mSplit.mLeft = atoi(split);
-                ALOGI_IF(mSplit.mLeft, "Left Split=%d", mSplit.mLeft);
-                char *rght = strpbrk(split, " ");
-                if(rght)
-                    mSplit.mRight = atoi(rght + 1);
-                ALOGI_IF(rght, "Right Split=%d", mSplit.mRight);
-            }
-        } else {
-            ALOGE("Failed to open mdss_fb_split node");
-        }
-
-        if(fp)
-            fclose(fp);
+    if(!updateSplitInfo()) {
+        ALOGE("Unable to read display split node");
     }
 }
 
@@ -140,7 +89,39 @@
     *idx = index;
     return 0;
 }
+// This function reads the sysfs node to read the primary panel type
+// and updates information accordingly
+bool MDPVersion::updatePanelInfo() {
+    FILE *displayDeviceFP = NULL;
+    const int MAX_FRAME_BUFFER_NAME_SIZE = 128;
+    char fbType[MAX_FRAME_BUFFER_NAME_SIZE];
+    const char *strCmdPanel = "mipi dsi cmd panel";
+    const char *strVideoPanel = "mipi dsi video panel";
+    const char *strLVDSPanel = "lvds panel";
+    const char *strEDPPanel = "edp panel";
 
+    displayDeviceFP = fopen("/sys/class/graphics/fb0/msm_fb_type", "r");
+    if(displayDeviceFP){
+        fread(fbType, sizeof(char), MAX_FRAME_BUFFER_NAME_SIZE,
+                displayDeviceFP);
+        if(strncmp(fbType, strCmdPanel, strlen(strCmdPanel)) == 0) {
+            mPanelType = MIPI_CMD_PANEL;
+        }
+        else if(strncmp(fbType, strVideoPanel, strlen(strVideoPanel)) == 0) {
+            mPanelType = MIPI_VIDEO_PANEL;
+        }
+        else if(strncmp(fbType, strLVDSPanel, strlen(strLVDSPanel)) == 0) {
+            mPanelType = LVDS_PANEL;
+        }
+        else if(strncmp(fbType, strEDPPanel, strlen(strEDPPanel)) == 0) {
+            mPanelType = EDP_PANEL;
+        }
+        fclose(displayDeviceFP);
+        return true;
+    }else {
+        return false;
+    }
+}
 
 // This function reads the sysfs node to read MDP capabilities
 // and parses and updates information accordingly.
@@ -213,6 +194,33 @@
     return true;
 }
 
+// This function reads the sysfs node to read MDP capabilities
+// and parses and updates information accordingly.
+bool MDPVersion::updateSplitInfo() {
+    if(mMDPVersion >= MDSS_V5) {
+        char split[64] = {0};
+        FILE* fp = fopen("/sys/class/graphics/fb0/msm_fb_split", "r");
+        if(fp){
+            //Format "left right" space as delimiter
+            if(fread(split, sizeof(char), 64, fp)) {
+                mSplit.mLeft = atoi(split);
+                ALOGI_IF(mSplit.mLeft, "Left Split=%d", mSplit.mLeft);
+                char *rght = strpbrk(split, " ");
+                if(rght)
+                    mSplit.mRight = atoi(rght + 1);
+                ALOGI_IF(mSplit.mRight, "Right Split=%d", mSplit.mRight);
+            }
+        } else {
+            ALOGE("Failed to open mdss_fb_split node");
+            return false;
+        }
+        if(fp)
+            fclose(fp);
+    }
+    return true;
+}
+
+
 bool MDPVersion::supportsDecimation() {
     return mFeatures & MDP_DECIMATION_EN;
 }
@@ -241,11 +249,17 @@
 }
 
 bool MDPVersion::is8x74v2() {
-    if( mMdpRev >= MDSS_MDP_HW_REV_102 && mMdpRev < MDSS_MDP_HW_REV_103) {
+    if( mMdpRev >= MDSS_MDP_HW_REV_102 && mMdpRev < MDSS_MDP_HW_REV_200) {
         return true;
     }
     return false;
 }
 
+bool MDPVersion::is8x92() {
+    if( mMdpRev >= MDSS_MDP_HW_REV_200 && mMdpRev < MDSS_MDP_HW_REV_206) {
+        return true;
+    }
+    return false;
+}
 }; //namespace qdutils
 
diff --git a/libqdutils/mdp_version.h b/libqdutils/mdp_version.h
index a14592b..1e1e35e 100644
--- a/libqdutils/mdp_version.h
+++ b/libqdutils/mdp_version.h
@@ -38,6 +38,10 @@
 */
 using namespace android;
 namespace qdutils {
+// These panel definitions are available at mdss_mdp.h which is internal header
+// file and is not available at <linux/mdss_mdp.h>.
+// ToDo: once it is available at linux/mdss_mdp.h, these below definitions can
+// be removed.
 enum mdp_version {
     MDP_V_UNKNOWN = 0,
     MDP_V2_2    = 220,
@@ -57,13 +61,15 @@
     MDSS_MDP_HW_REV_100 = 0x10000000, //8974 v1
     MDSS_MDP_HW_REV_101 = 0x10010000, //8x26
     MDSS_MDP_HW_REV_102 = 0x10020000, //8974 v2
-    MDSS_MDP_HW_REV_103 = 0x10030000, //Future
+    MDSS_MDP_HW_REV_200 = 0x20000000, //8092
+    MDSS_MDP_HW_REV_206 = 0x20060000, //Future
 };
 
 enum {
     MAX_DISPLAY_DIM = 2048,
 };
 
+#define NO_PANEL         '0'
 #define MDDI_PANEL       '1'
 #define EBI2_PANEL       '2'
 #define LCDC_PANEL       '3'
@@ -74,6 +80,7 @@
 #define MIPI_CMD_PANEL   '9'
 #define WRITEBACK_PANEL  'a'
 #define LVDS_PANEL       'b'
+#define EDP_PANEL        'c'
 
 class MDPVersion;
 
@@ -103,10 +110,13 @@
     bool supportsBWC();
     bool is8x26();
     bool is8x74v2();
+    bool is8x92();
     int getLeftSplit() { return mSplit.left(); }
     int getRightSplit() { return mSplit.right(); }
 private:
     bool updateSysFsInfo();
+    bool updatePanelInfo();
+    bool updateSplitInfo();
     int tokenizeParams(char *inputParams, const char *delim,
                         char* tokenStr[], int *idx);
     int mFd;
diff --git a/libqdutils/qdMetaData.cpp b/libqdutils/qdMetaData.cpp
index 89ca92e..f39eef9 100644
--- a/libqdutils/qdMetaData.cpp
+++ b/libqdutils/qdMetaData.cpp
@@ -81,6 +81,26 @@
         case UPDATE_BUFFER_GEOMETRY:
             memcpy((void *)&data->bufferDim, param, sizeof(BufferDim_t));
             break;
+        case PP_PARAM_VFM_DATA:
+        {
+            int32_t     indx = 0;
+            VfmData_t*  pVfmData = reinterpret_cast <VfmData_t *>(param);
+            int32_t     dataType = pVfmData->dataType;
+
+            if(dataType > 0){
+                indx = getVfmDataIdx(dataType);
+                if(indx < MAX_VFM_DATA_COUNT){
+                    data->vfmDataBitMap |= dataType;
+                    memcpy((void *)&data->vfmData[indx], param,
+                        sizeof(VfmData_t));
+                }else{
+                    ALOGE("unknown dataType %d", dataType);
+                }
+            }else{
+                ALOGE("invalid dataType in PP_PARAM_VFM_DATA %d", dataType);
+            }
+        }
+        break;
         default:
             ALOGE("Unknown paramType %d", paramType);
             break;
diff --git a/libqdutils/qdMetaData.h b/libqdutils/qdMetaData.h
index d5354a4..4b6e678 100644
--- a/libqdutils/qdMetaData.h
+++ b/libqdutils/qdMetaData.h
@@ -31,6 +31,19 @@
 #define _QDMETADATA_H
 
 #define MAX_IGC_LUT_ENTRIES 256
+#define MAX_VFM_DATA_SIZE   64 //bytes per data buffer
+#define MAX_VFM_DATA_COUNT  16 //number of data buffers
+
+/* This macro finds the index corresponding to a type */
+/* This is equivalent to indx = LOG_2(type) */
+inline int32_t getVfmDataIdx(int32_t type){
+    int32_t indx = 0, x = type;
+    while( x >> 1) {
+        x = (x >> 1);
+        indx++;
+    }
+    return indx;
+}
 
 struct HSICData_t {
     int32_t hue;
@@ -57,6 +70,11 @@
     int32_t sliceHeight;
 };
 
+struct VfmData_t {
+    int32_t dataType;
+    char    data[MAX_VFM_DATA_SIZE];
+};
+
 struct MetaData_t {
     int32_t operation;
     int32_t interlaced;
@@ -67,6 +85,8 @@
     IGCData_t igcData;
     Sharp2Data_t Sharp2Data;
     int64_t timestamp;
+    int32_t vfmDataBitMap;
+    VfmData_t vfmData[MAX_VFM_DATA_COUNT];
 };
 
 typedef enum {
@@ -78,6 +98,7 @@
     PP_PARAM_SHARP2     = 0x0020,
     PP_PARAM_TIMESTAMP  = 0x0040,
     UPDATE_BUFFER_GEOMETRY = 0x0080,
+    PP_PARAM_VFM_DATA   = 0x0100,
 } DispParamType;
 
 int setMetaData(private_handle_t *handle, DispParamType paramType, void *param);
diff --git a/libqservice/IQClient.cpp b/libqservice/IQClient.cpp
index 30fbb64..a6251c8 100644
--- a/libqservice/IQClient.cpp
+++ b/libqservice/IQClient.cpp
@@ -28,6 +28,9 @@
 using namespace android;
 
 // ---------------------------------------------------------------------------
+// XXX: Since qservice currently runs as part of hwc instead of a standalone
+// process, the implementation below is overridden and the notifyCallback in
+// hwc_qclient is directly called.
 
 namespace qClient {
 
@@ -41,13 +44,17 @@
     BpQClient(const sp<IBinder>& impl)
         : BpInterface<IQClient>(impl) {}
 
-    virtual status_t notifyCallback(uint32_t msg, uint32_t value) {
-        Parcel data, reply;
+    virtual status_t notifyCallback(uint32_t command,
+            const Parcel* inParcel,
+            Parcel* outParcel) {
+        Parcel data;
+        Parcel *reply = outParcel;
         data.writeInterfaceToken(IQClient::getInterfaceDescriptor());
-        data.writeInt32(msg);
-        data.writeInt32(value);
-        remote()->transact(NOTIFY_CALLBACK, data, &reply);
-        status_t result = reply.readInt32();
+        data.writeInt32(command);
+        if (inParcel->dataAvail())
+            data.appendFrom(inParcel, inParcel->dataPosition(),
+                    inParcel->dataAvail());
+        status_t result = remote()->transact(NOTIFY_CALLBACK, data, reply);
         return result;
     }
 };
@@ -55,21 +62,21 @@
 IMPLEMENT_META_INTERFACE(QClient, "android.display.IQClient");
 
 // ----------------------------------------------------------------------
-
+//Stub implementation - nothing needed here
 status_t BnQClient::onTransact(
     uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
 {
     switch(code) {
         case NOTIFY_CALLBACK: {
             CHECK_INTERFACE(IQClient, data, reply);
-            uint32_t msg = data.readInt32();
-            uint32_t value = data.readInt32();
-            notifyCallback(msg, value);
+            uint32_t command = data.readInt32();
+            notifyCallback(command, &data, reply);
             return NO_ERROR;
         } break;
         default:
             return BBinder::onTransact(code, data, reply, flags);
     }
+
 }
 
 }; // namespace qClient
diff --git a/libqservice/IQClient.h b/libqservice/IQClient.h
index a28f826..7d816d2 100644
--- a/libqservice/IQClient.h
+++ b/libqservice/IQClient.h
@@ -33,7 +33,9 @@
 {
 public:
     DECLARE_META_INTERFACE(QClient);
-    virtual android::status_t notifyCallback(uint32_t msg, uint32_t value) = 0;
+    virtual android::status_t notifyCallback(uint32_t command,
+            const android::Parcel* inParcel,
+            android::Parcel* outParcel) = 0;
 };
 
 // ----------------------------------------------------------------------------
diff --git a/libqservice/IQService.cpp b/libqservice/IQService.cpp
index 33f79c6..d2180bb 100644
--- a/libqservice/IQService.cpp
+++ b/libqservice/IQService.cpp
@@ -27,9 +27,10 @@
 #include <binder/IPCThreadState.h>
 #include <utils/Errors.h>
 #include <private/android_filesystem_config.h>
-
 #include <IQService.h>
 
+#define QSERVICE_DEBUG 0
+
 using namespace android;
 using namespace qClient;
 
@@ -43,56 +44,25 @@
     BpQService(const sp<IBinder>& impl)
         : BpInterface<IQService>(impl) {}
 
-    virtual void securing(uint32_t startEnd) {
-        Parcel data, reply;
-        data.writeInterfaceToken(IQService::getInterfaceDescriptor());
-        data.writeInt32(startEnd);
-        remote()->transact(SECURING, data, &reply);
-    }
-
-    virtual void unsecuring(uint32_t startEnd) {
-        Parcel data, reply;
-        data.writeInterfaceToken(IQService::getInterfaceDescriptor());
-        data.writeInt32(startEnd);
-        remote()->transact(UNSECURING, data, &reply);
-    }
-
     virtual void connect(const sp<IQClient>& client) {
+        ALOGD_IF(QSERVICE_DEBUG, "%s: connect client", __FUNCTION__);
         Parcel data, reply;
         data.writeInterfaceToken(IQService::getInterfaceDescriptor());
         data.writeStrongBinder(client->asBinder());
         remote()->transact(CONNECT, data, &reply);
     }
 
-    virtual status_t screenRefresh() {
-        Parcel data, reply;
+    virtual android::status_t dispatch(uint32_t command, const Parcel* inParcel,
+            Parcel* outParcel) {
+        ALOGD_IF(QSERVICE_DEBUG, "%s: dispatch in:%p", __FUNCTION__, inParcel);
+        status_t err = android::FAILED_TRANSACTION;
+        Parcel data;
+        Parcel *reply = outParcel;
         data.writeInterfaceToken(IQService::getInterfaceDescriptor());
-        remote()->transact(SCREEN_REFRESH, data, &reply);
-        status_t result = reply.readInt32();
-        return result;
-    }
-
-    virtual void setExtOrientation(uint32_t orientation) {
-        Parcel data, reply;
-        data.writeInterfaceToken(IQService::getInterfaceDescriptor());
-        data.writeInt32(orientation);
-        remote()->transact(EXTERNAL_ORIENTATION, data, &reply);
-    }
-
-    virtual void setBufferMirrorMode(uint32_t enable) {
-        Parcel data, reply;
-        data.writeInterfaceToken(IQService::getInterfaceDescriptor());
-        data.writeInt32(enable);
-        remote()->transact(BUFFER_MIRRORMODE, data, &reply);
-    }
-
-    virtual status_t vpuCommand(uint32_t command, uint32_t setting) {
-        Parcel data, reply;
-        data.writeInterfaceToken(IQService::getInterfaceDescriptor());
-        data.writeInt32(setting);
-        remote()->transact(command, data, &reply);
-        status_t result = reply.readInt32();
-        return result;
+        if (inParcel && inParcel->dataSize() > 0)
+            data.appendFrom(inParcel, 0, inParcel->dataSize());
+        err = remote()->transact(command, data, reply);
+        return err;
     }
 };
 
@@ -105,7 +75,8 @@
 status_t BnQService::onTransact(
     uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
 {
-    // IPC should be from mediaserver only
+    ALOGD_IF(QSERVICE_DEBUG, "%s: code: %d", __FUNCTION__, code);
+    // IPC should be from certain processes only
     IPCThreadState* ipc = IPCThreadState::self();
     const int callerPid = ipc->getCallingPid();
     const int callerUid = ipc->getCallingUid();
@@ -114,94 +85,35 @@
 
     getProcName(callerPid, callingProcName, MAX_BUF_SIZE);
 
-    const bool permission = (callerUid == AID_MEDIA);
+    const bool permission = (callerUid == AID_MEDIA ||
+            callerUid == AID_GRAPHICS ||
+            callerUid == AID_ROOT ||
+            callerUid == AID_SYSTEM);
 
-    if (code > VPU_COMMAND_LIST_START && code < VPU_COMMAND_LIST_END) {
-        if(callerUid != AID_SYSTEM && callerUid != AID_ROOT) {
-            ALOGE("display.qservice VPU command access denied: \
-                  pid=%d uid=%d process=%s",callerPid,
+    if (code == CONNECT) {
+        CHECK_INTERFACE(IQService, data, reply);
+        if(callerUid != AID_GRAPHICS) {
+            ALOGE("display.qservice CONNECT access denied: \
+                    pid=%d uid=%d process=%s",
+                    callerPid, callerUid, callingProcName);
+            return PERMISSION_DENIED;
+        }
+        sp<IQClient> client =
+                interface_cast<IQClient>(data.readStrongBinder());
+        connect(client);
+        return NO_ERROR;
+    } else if (code > COMMAND_LIST_START && code < COMMAND_LIST_END) {
+        if(!permission) {
+            ALOGE("display.qservice access denied: command=%d\
+                  pid=%d uid=%d process=%s", code, callerPid,
                   callerUid, callingProcName);
             return PERMISSION_DENIED;
         }
         CHECK_INTERFACE(IQService, data, reply);
-        int32_t setting = data.readInt32();
-        return vpuCommand(code, setting);
-    }
-
-    switch(code) {
-        case SECURING: {
-            if(!permission) {
-                ALOGE("display.qservice SECURING access denied: \
-                      pid=%d uid=%d process=%s",
-                      callerPid, callerUid, callingProcName);
-                return PERMISSION_DENIED;
-            }
-            CHECK_INTERFACE(IQService, data, reply);
-            uint32_t startEnd = data.readInt32();
-            securing(startEnd);
-            return NO_ERROR;
-        } break;
-        case UNSECURING: {
-            if(!permission) {
-                ALOGE("display.qservice UNSECURING access denied: \
-                      pid=%d uid=%d process=%s",
-                      callerPid, callerUid, callingProcName);
-                return PERMISSION_DENIED;
-            }
-            CHECK_INTERFACE(IQService, data, reply);
-            uint32_t startEnd = data.readInt32();
-            unsecuring(startEnd);
-            return NO_ERROR;
-        } break;
-        case CONNECT: {
-            CHECK_INTERFACE(IQService, data, reply);
-            if(callerUid != AID_GRAPHICS) {
-                ALOGE("display.qservice CONNECT access denied: \
-                      pid=%d uid=%d process=%s",
-                      callerPid, callerUid, callingProcName);
-                return PERMISSION_DENIED;
-            }
-            sp<IQClient> client =
-                interface_cast<IQClient>(data.readStrongBinder());
-            connect(client);
-            return NO_ERROR;
-        } break;
-        case SCREEN_REFRESH: {
-            CHECK_INTERFACE(IQService, data, reply);
-            if(callerUid != AID_SYSTEM) {
-                ALOGE("display.qservice SCREEN_REFRESH access denied: \
-                      pid=%d uid=%d process=%s",callerPid,
-                      callerUid, callingProcName);
-                return PERMISSION_DENIED;
-            }
-            return screenRefresh();
-        } break;
-        case EXTERNAL_ORIENTATION: {
-            CHECK_INTERFACE(IQService, data, reply);
-            if(callerUid != AID_SYSTEM) {
-                ALOGE("display.qservice EXTERNAL_ORIENTATION access denied: \
-                      pid=%d uid=%d process=%s",callerPid,
-                      callerUid, callingProcName);
-                return PERMISSION_DENIED;
-            }
-            uint32_t orientation = data.readInt32();
-            setExtOrientation(orientation);
-            return NO_ERROR;
-        } break;
-        case BUFFER_MIRRORMODE: {
-            CHECK_INTERFACE(IQService, data, reply);
-            if(callerUid != AID_SYSTEM) {
-                ALOGE("display.qservice BUFFER_MIRRORMODE access denied: \
-                      pid=%d uid=%d process=%s",callerPid,
-                      callerUid, callingProcName);
-                return PERMISSION_DENIED;
-            }
-            uint32_t enable = data.readInt32();
-            setBufferMirrorMode(enable);
-            return NO_ERROR;
-        } break;
-        default:
-            return BBinder::onTransact(code, data, reply, flags);
+        dispatch(code, &data, reply);
+        return NO_ERROR;
+    } else {
+        return BBinder::onTransact(code, data, reply, flags);
     }
 }
 
diff --git a/libqservice/IQService.h b/libqservice/IQService.h
index 9cd122e..7ad443d 100644
--- a/libqservice/IQService.h
+++ b/libqservice/IQService.h
@@ -29,35 +29,39 @@
 #include <binder/IBinder.h>
 #include <IQClient.h>
 
+
 namespace qService {
 // ----------------------------------------------------------------------------
+
 class IQService : public android::IInterface
 {
 public:
     DECLARE_META_INTERFACE(QService);
     enum {
-        // Hardware securing start/end notification
-        SECURING = android::IBinder::FIRST_CALL_TRANSACTION,
-        UNSECURING, // Hardware unsecuring start/end notification
-        CONNECT,
-        SCREEN_REFRESH,
-        EXTERNAL_ORIENTATION,
-        BUFFER_MIRRORMODE,
-        //VPU command codes - list is defined in vpu.h
-        VPU_COMMAND_LIST_START = 100,
-        VPU_COMMAND_LIST_END = 200,
+        COMMAND_LIST_START = android::IBinder::FIRST_CALL_TRANSACTION,
+        SECURING,                // Hardware securing start/end notification
+        UNSECURING,              // Hardware unsecuring start/end notification
+        CONNECT,                 // Connect to qservice
+        SCREEN_REFRESH,          // Refresh screen through SF invalidate
+        EXTERNAL_ORIENTATION,    // Set external orientation
+        BUFFER_MIRRORMODE,       // Buffer mirrormode
+        VPU_COMMAND_LIST_START = 100, //Reserved block for VPU commands
+        VPU_COMMAND_LIST_END   = 200,
+        COMMAND_LIST_END = 400,
     };
+
     enum {
         END = 0,
         START,
     };
-    virtual void securing(uint32_t startEnd) = 0;
-    virtual void unsecuring(uint32_t startEnd) = 0;
+
+    // Register a client that can be notified
     virtual void connect(const android::sp<qClient::IQClient>& client) = 0;
-    virtual android::status_t screenRefresh() = 0;
-    virtual void setExtOrientation(uint32_t orientation) = 0;
-    virtual void setBufferMirrorMode(uint32_t enable) = 0;
-    virtual android::status_t vpuCommand(uint32_t command, uint32_t setting) = 0;
+    // Generic function to dispatch binder commands
+    // The type of command decides how the data is parceled
+    virtual android::status_t dispatch(uint32_t command,
+            const android::Parcel* inParcel,
+            android::Parcel* outParcel) = 0;
 };
 
 // ----------------------------------------------------------------------------
diff --git a/libqservice/QService.cpp b/libqservice/QService.cpp
index 327888c..aac5788 100644
--- a/libqservice/QService.cpp
+++ b/libqservice/QService.cpp
@@ -47,49 +47,19 @@
     ALOGD_IF(QSERVICE_DEBUG,"QService Destructor invoked");
 }
 
-void QService::securing(uint32_t startEnd) {
-    if(mClient.get()) {
-        mClient->notifyCallback(SECURING, startEnd);
-    }
-}
-
-void QService::unsecuring(uint32_t startEnd) {
-    if(mClient.get()) {
-        mClient->notifyCallback(UNSECURING, startEnd);
-    }
-}
-
 void QService::connect(const sp<qClient::IQClient>& client) {
+    ALOGD_IF(QSERVICE_DEBUG,"client connected");
     mClient = client;
 }
 
-android::status_t QService::screenRefresh() {
-    status_t result = NO_ERROR;
-    if(mClient.get()) {
-        result = mClient->notifyCallback(SCREEN_REFRESH, 0);
+status_t QService::dispatch(uint32_t command, const Parcel* inParcel,
+        Parcel* outParcel) {
+    status_t err = FAILED_TRANSACTION;
+    if (mClient.get()) {
+        ALOGD_IF(QSERVICE_DEBUG, "Dispatching command: %d", command);
+        err = mClient->notifyCallback(command, inParcel, outParcel);
     }
-    return result;
-}
-
-android::status_t QService::vpuCommand(uint32_t command, uint32_t setting ) {
-    status_t result = NO_ERROR;
-    if(mClient.get()) {
-        result = mClient->notifyCallback(command, setting);
-    }
-    return result;
-}
-
-
-void QService::setExtOrientation(uint32_t orientation) {
-    if(mClient.get()) {
-        mClient->notifyCallback(EXTERNAL_ORIENTATION, orientation);
-    }
-}
-
-void QService::setBufferMirrorMode(uint32_t enable) {
-    if(mClient.get()) {
-        mClient->notifyCallback(BUFFER_MIRRORMODE, enable);
-    }
+    return err;
 }
 
 void QService::init()
diff --git a/libqservice/QService.h b/libqservice/QService.h
index de18b59..a8e4cdb 100644
--- a/libqservice/QService.h
+++ b/libqservice/QService.h
@@ -45,13 +45,10 @@
 class QService : public BnQService {
 public:
     virtual ~QService();
-    virtual void securing(uint32_t startEnd);
-    virtual void unsecuring(uint32_t startEnd);
     virtual void connect(const android::sp<qClient::IQClient>& client);
-    virtual android::status_t screenRefresh();
-    virtual void setExtOrientation(uint32_t orientation);
-    virtual void setBufferMirrorMode(uint32_t enable);
-    virtual android::status_t vpuCommand(uint32_t command, uint32_t setting);
+    virtual android::status_t dispatch(uint32_t command,
+            const android::Parcel* data,
+            android::Parcel* reply);
     static void init();
 private:
     QService();
diff --git a/libqservice/QServiceUtils.h b/libqservice/QServiceUtils.h
new file mode 100644
index 0000000..3d1adc0
--- /dev/null
+++ b/libqservice/QServiceUtils.h
@@ -0,0 +1,86 @@
+/*
+* Copyright (c) 2013 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
+* met:
+*    * Redistributions of source code must retain the above copyright
+*      notice, this list of conditions and the following disclaimer.
+*    * Redistributions in binary form must reproduce the above
+*      copyright notice, this list of conditions and the following
+*      disclaimer in the documentation and/or other materials provided
+*      with the distribution.
+*    * Neither the name of The Linux Foundation. nor the names of its
+*      contributors may be used to endorse or promote products derived
+*      from this software without specific prior written permission.
+*
+* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+* ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef QSERVICEUTILS_H
+#define QSERVICEUTILS_H
+#include <binder/Parcel.h>
+#include <binder/IServiceManager.h>
+#include <utils/RefBase.h>
+#include <IQService.h>
+
+// ----------------------------------------------------------------------------
+// Helpers
+// ----------------------------------------------------------------------------
+inline android::sp<qService::IQService> getBinder() {
+    android::sp<android::IServiceManager> sm = android::defaultServiceManager();
+    android::sp<qService::IQService> binder =
+            android::interface_cast<qService::IQService>
+            (sm->getService(android::String16("display.qservice")));
+    if (binder == NULL) {
+        ALOGE("%s: invalid binder object", __FUNCTION__);
+    }
+    return binder;
+}
+
+inline android::status_t sendSingleParam(uint32_t command, uint32_t value) {
+    android::status_t err = android::FAILED_TRANSACTION;
+    android::sp<qService::IQService> binder = getBinder();
+    android::Parcel inParcel, outParcel;
+    inParcel.writeInt32(value);
+    if(binder != NULL) {
+        err = binder->dispatch(command, &inParcel , &outParcel);
+    }
+    return err;
+}
+
+// ----------------------------------------------------------------------------
+// Convenience wrappers that clients can call
+// ----------------------------------------------------------------------------
+inline android::status_t securing(uint32_t startEnd) {
+    return sendSingleParam(qService::IQService::SECURING, startEnd);
+}
+
+inline android::status_t unsecuring(uint32_t startEnd) {
+    return sendSingleParam(qService::IQService::UNSECURING, startEnd);
+}
+
+inline android::status_t screenRefresh() {
+    return sendSingleParam(qService::IQService::SCREEN_REFRESH, 1);
+}
+
+inline android::status_t setExtOrientation(uint32_t orientation) {
+    return sendSingleParam(qService::IQService::EXTERNAL_ORIENTATION,
+            orientation);
+}
+
+inline android::status_t setBufferMirrorMode(uint32_t enable) {
+    return sendSingleParam(qService::IQService::BUFFER_MIRRORMODE, enable);
+}
+
+#endif /* end of include guard: QSERVICEUTILS_H */