Merge "hwc: Add support for Macro Tile feature"
diff --git a/libcopybit/copybit.cpp b/libcopybit/copybit.cpp
index 9558f69..c0246e3 100644
--- a/libcopybit/copybit.cpp
+++ b/libcopybit/copybit.cpp
@@ -573,7 +573,9 @@
     int rel_fen_fd = -1;
     int my_tmp_get_fence = -1;
 
+    list1.sync.acq_fen_fd  =  ctx->acqFence;
     list1.sync.rel_fen_fd  =  &my_tmp_get_fence;
+    list1.sync.acq_fen_fd_cnt = ctx->list.sync.acq_fen_fd_cnt;
     mdp_blit_req* req = &list1.req[0];
 
     if(!req) {
@@ -607,6 +609,7 @@
     req->flags = MDP_SOLID_FILL | MDP_MEMORY_ID_TYPE_FB | MDP_BLEND_FG_PREMULT;
     int status = msm_copybit(ctx, &list1);
 
+    ctx->list.sync.acq_fen_fd_cnt = 0;
     if (my_tmp_get_fence !=  -1)
         close(my_tmp_get_fence);
 
diff --git a/libgralloc/gralloc_priv.h b/libgralloc/gralloc_priv.h
index b00a95e..66a67d3 100644
--- a/libgralloc/gralloc_priv.h
+++ b/libgralloc/gralloc_priv.h
@@ -114,6 +114,9 @@
     HAL_PIXEL_FORMAT_INTERLACE              = 0x180,
     //v4l2_fourcc('Y', 'U', 'Y', 'L'). 24 bpp YUYV 4:2:2 10 bit per component
     HAL_PIXEL_FORMAT_YCbCr_422_I_10BIT      = 0x4C595559,
+    //v4l2_fourcc('Y', 'B', 'W', 'C'). 10 bit per component. This compressed
+    //format reduces the memory access bandwidth
+    HAL_PIXEL_FORMAT_YCbCr_422_I_10BIT_COMPRESSED = 0x43574259,
 };
 
 /* possible formats for 3D content*/
diff --git a/libhwcomposer/hwc_copybit.cpp b/libhwcomposer/hwc_copybit.cpp
index 47b9225..38d8d5d 100644
--- a/libhwcomposer/hwc_copybit.cpp
+++ b/libhwcomposer/hwc_copybit.cpp
@@ -188,8 +188,15 @@
             dst_h = layer->displayFrame.bottom - layer->displayFrame.top;
             dst_w = layer->displayFrame.right - layer->displayFrame.left;
 
+            if(src_w <=0 || src_h<=0 ||dst_w<=0 || dst_h<=0 ) {
+              ALOGE("%s: wrong params for display screen_w=%d \
+                         src_crop_width=%d screen_h=%d src_crop_height=%d",
+                         __FUNCTION__, dst_w,src_w,dst_h,src_h);
+              return false;
+            }
             dx = (float)dst_w/src_w;
             dy = (float)dst_h/src_h;
+
             if (dx > MAX_SCALE_FACTOR || dx < MIN_SCALE_FACTOR)
                 return false;
 
@@ -448,8 +455,8 @@
 
     if(screen_w <=0 || screen_h<=0 ||src_crop_width<=0 || src_crop_height<=0 ) {
         ALOGE("%s: wrong params for display screen_w=%d src_crop_width=%d \
-        screen_w=%d src_crop_width=%d", __FUNCTION__, screen_w,
-                                src_crop_width,screen_w,src_crop_width);
+        screen_h=%d src_crop_height=%d", __FUNCTION__, screen_w,
+                                src_crop_width,screen_h,src_crop_height);
         return -1;
     }
 
diff --git a/libhwcomposer/hwc_mdpcomp.cpp b/libhwcomposer/hwc_mdpcomp.cpp
index 0b4cbe0..9221b71 100644
--- a/libhwcomposer/hwc_mdpcomp.cpp
+++ b/libhwcomposer/hwc_mdpcomp.cpp
@@ -541,6 +541,13 @@
         return false;
     }
 
+    // check for action safe flag and downscale mode which requires scaling.
+    if(ctx->dpyAttr[mDpy].mActionSafePresent
+            || ctx->dpyAttr[mDpy].mDownScaleMode) {
+        ALOGD_IF(isDebug(), "%s: Scaling needed for this frame",__FUNCTION__);
+        return false;
+    }
+
     for(int i = 0; i < numAppLayers; ++i) {
         hwc_layer_1_t* layer = &list->hwLayers[i];
         private_handle_t *hnd = (private_handle_t *)layer->handle;
diff --git a/libhwcomposer/hwc_qclient.cpp b/libhwcomposer/hwc_qclient.cpp
index 50e94c9..8c99d64 100644
--- a/libhwcomposer/hwc_qclient.cpp
+++ b/libhwcomposer/hwc_qclient.cpp
@@ -1,5 +1,5 @@
 /*
- *  Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *  Copyright (c) 2013-14, 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
@@ -36,6 +36,7 @@
 
 using namespace android;
 using namespace qService;
+using namespace qhwc;
 
 namespace qClient {
 
@@ -165,6 +166,17 @@
     }
 }
 
+static void pauseWFD(hwc_context_t *ctx, uint32_t pause) {
+    int dpy = HWC_DISPLAY_VIRTUAL;
+    if(pause) {
+        //WFD Pause
+        handle_pause(ctx, dpy);
+    } else {
+        //WFD Resume
+        handle_resume(ctx, dpy);
+    }
+}
+
 status_t QClient::notifyCallback(uint32_t command, const Parcel* inParcel,
         Parcel* outParcel) {
     status_t ret = NO_ERROR;
@@ -202,6 +214,8 @@
             break;
         case IQService::SET_HSIC_DATA:
             setHSIC(mHwcContext, inParcel);
+        case IQService::PAUSE_WFD:
+            pauseWFD(mHwcContext, inParcel->readInt32());
             break;
         default:
             ret = NO_ERROR;
diff --git a/libhwcomposer/hwc_uevents.cpp b/libhwcomposer/hwc_uevents.cpp
index 51e5526..83586ac 100644
--- a/libhwcomposer/hwc_uevents.cpp
+++ b/libhwcomposer/hwc_uevents.cpp
@@ -1,7 +1,7 @@
 
 /*
  * Copyright (C) 2010 The Android Open Source Project
- * Copyright (C) 2012, The Linux Foundation. All rights reserved.
+ * Copyright (C) 2012-14, The Linux Foundation. All rights reserved.
  *
  * Not a Contribution, Apache license notifications and license are
  * retained for attribution purposes only.
@@ -50,13 +50,6 @@
 {
     ctx->mFBUpdate[dpy] = IFBUpdate::getObject(ctx, dpy);
     ctx->mMDPComp[dpy] =  MDPComp::getObject(ctx, dpy);
-    int compositionType =
-                qdutils::QCCompositionType::getInstance().getCompositionType();
-    if (compositionType & (qdutils::COMPOSITION_TYPE_DYN |
-                           qdutils::COMPOSITION_TYPE_MDP |
-                           qdutils::COMPOSITION_TYPE_C2D)) {
-        ctx->mCopyBit[dpy] = new CopyBit(ctx, dpy);
-    }
 }
 
 static void clear(hwc_context_t* ctx, int dpy)
@@ -65,10 +58,6 @@
         delete ctx->mFBUpdate[dpy];
         ctx->mFBUpdate[dpy] = NULL;
     }
-    if(ctx->mCopyBit[dpy]){
-        delete ctx->mCopyBit[dpy];
-        ctx->mCopyBit[dpy] = NULL;
-    }
     if(ctx->mMDPComp[dpy]) {
         delete ctx->mMDPComp[dpy];
         ctx->mMDPComp[dpy] = NULL;
@@ -117,6 +106,58 @@
     return -1;
 }
 
+void handle_pause(hwc_context_t* ctx, int dpy) {
+    {
+        Locker::Autolock _l(ctx->mDrawLock);
+        ctx->dpyAttr[dpy].isActive = true;
+        ctx->dpyAttr[dpy].isPause = true;
+        ctx->proc->invalidate(ctx->proc);
+    }
+    usleep(ctx->dpyAttr[HWC_DISPLAY_PRIMARY].vsync_period
+           * 2 / 1000);
+    // At this point all the pipes used by External have been
+    // marked as UNSET.
+    {
+        Locker::Autolock _l(ctx->mDrawLock);
+        // Perform commit to unstage the pipes.
+        if (!Overlay::displayCommit(ctx->dpyAttr[dpy].fd)) {
+            ALOGE("%s: display commit fail! for %d dpy",
+                  __FUNCTION__, dpy);
+        }
+    }
+    return;
+}
+
+void handle_resume(hwc_context_t* ctx, int dpy) {
+    //Treat Resume as Online event
+    //Since external didnt have any pipes, force primary to give up
+    //its pipes; we don't allow inter-mixer pipe transfers.
+    {
+        Locker::Autolock _l(ctx->mDrawLock);
+
+        // A dynamic resolution change (DRC) can be made for a WiFi
+        // display. In order to support the resolution change, we
+        // need to reconfigure the corresponding display attributes.
+        // Since DRC is only on WiFi display, we only need to call
+        // configure() on the VirtualDisplay device.
+        if(dpy == HWC_DISPLAY_VIRTUAL)
+            ctx->mVirtualDisplay->configure();
+
+        ctx->dpyAttr[dpy].isConfiguring = true;
+        ctx->dpyAttr[dpy].isActive = true;
+        ctx->proc->invalidate(ctx->proc);
+    }
+    usleep(ctx->dpyAttr[HWC_DISPLAY_PRIMARY].vsync_period
+           * 2 / 1000);
+    //At this point external has all the pipes it would need.
+    {
+        Locker::Autolock _l(ctx->mDrawLock);
+        ctx->dpyAttr[dpy].isPause = false;
+        ctx->proc->invalidate(ctx->proc);
+    }
+    return;
+}
+
 static void handle_uevent(hwc_context_t* ctx, const char* udata, int len)
 {
     bool bpanelReset = getPanelResetStatus(ctx, udata, len);
@@ -267,25 +308,8 @@
         case EXTERNAL_PAUSE:
             {   // pause case
                 ALOGD("%s Received Pause event",__FUNCTION__);
-                 {
-                     Locker::Autolock _l(ctx->mDrawLock);
-                     ctx->dpyAttr[dpy].isActive = true;
-                     ctx->dpyAttr[dpy].isPause = true;
-                     ctx->proc->invalidate(ctx->proc);
-                 }
-                 usleep(ctx->dpyAttr[HWC_DISPLAY_PRIMARY].vsync_period
-                         * 2 / 1000);
-                 // At this point all the pipes used by External have been
-                 // marked as UNSET.
-                 {
-                     Locker::Autolock _l(ctx->mDrawLock);
-                     // Perform commit to unstage the pipes.
-                     if (!Overlay::displayCommit(ctx->dpyAttr[dpy].fd)) {
-                         ALOGE("%s: display commit fail! for %d dpy",
-                                 __FUNCTION__, dpy);
-                     }
-                 }
-                 break;
+                handle_pause(ctx, dpy);
+                break;
             }
         case EXTERNAL_RESUME:
             {  // resume case
@@ -293,29 +317,7 @@
                 //Treat Resume as Online event
                 //Since external didnt have any pipes, force primary to give up
                 //its pipes; we don't allow inter-mixer pipe transfers.
-                {
-                    Locker::Autolock _l(ctx->mDrawLock);
-
-                    // A dynamic resolution change (DRC) can be made for a WiFi
-                    // display. In order to support the resolution change, we
-                    // need to reconfigure the corresponding display attributes.
-                    // Since DRC is only on WiFi display, we only need to call
-                    // configure() on the VirtualDisplay device.
-                    if(dpy == HWC_DISPLAY_VIRTUAL)
-                        ctx->mVirtualDisplay->configure();
-
-                    ctx->dpyAttr[dpy].isConfiguring = true;
-                    ctx->dpyAttr[dpy].isActive = true;
-                    ctx->proc->invalidate(ctx->proc);
-                }
-                usleep(ctx->dpyAttr[HWC_DISPLAY_PRIMARY].vsync_period
-                        * 2 / 1000);
-                //At this point external has all the pipes it would need.
-                {
-                    Locker::Autolock _l(ctx->mDrawLock);
-                    ctx->dpyAttr[dpy].isPause = false;
-                    ctx->proc->invalidate(ctx->proc);
-                }
+                handle_resume(ctx, dpy);
                 break;
             }
     default:
diff --git a/libhwcomposer/hwc_utils.cpp b/libhwcomposer/hwc_utils.cpp
index bb12c4e..ed3454a 100644
--- a/libhwcomposer/hwc_utils.cpp
+++ b/libhwcomposer/hwc_utils.cpp
@@ -142,16 +142,18 @@
     ctx->mFBUpdate[HWC_DISPLAY_PRIMARY] =
         IFBUpdate::getObject(ctx, HWC_DISPLAY_PRIMARY);
 
-    // Check if the target supports copybit compostion (dyn/mdp/c2d) to
+    // Check if the target supports copybit compostion (dyn/mdp) to
     // decide if we need to open the copybit module.
     int compositionType =
         qdutils::QCCompositionType::getInstance().getCompositionType();
 
-    if (compositionType & (qdutils::COMPOSITION_TYPE_DYN |
-                           qdutils::COMPOSITION_TYPE_MDP |
-                           qdutils::COMPOSITION_TYPE_C2D)) {
-            ctx->mCopyBit[HWC_DISPLAY_PRIMARY] = new CopyBit(ctx,
-                    HWC_DISPLAY_PRIMARY);
+    // Only MDP copybit is used
+    if ((compositionType & (qdutils::COMPOSITION_TYPE_DYN |
+            qdutils::COMPOSITION_TYPE_MDP)) &&
+            (qdutils::MDPVersion::getInstance().getMDPVersion() ==
+            qdutils::MDP_V3_0_4)) {
+        ctx->mCopyBit[HWC_DISPLAY_PRIMARY] = new CopyBit(ctx,
+                                                         HWC_DISPLAY_PRIMARY);
     }
 
     ctx->mExtDisplay = new ExternalDisplay(ctx);
@@ -173,6 +175,9 @@
         ctx->mHwcDebug[i] = new HwcDebug(i);
         ctx->mLayerRotMap[i] = new LayerRotMap();
         ctx->mAnimationState[i] = ANIMATION_STOPPED;
+        ctx->dpyAttr[i].mActionSafePresent = false;
+        ctx->dpyAttr[i].mAsWidthRatio = 0;
+        ctx->dpyAttr[i].mAsHeightRatio = 0;
     }
 
     MDPComp::init(ctx);
@@ -285,22 +290,11 @@
     int w = rect.right - rect.left;
     int h = rect.bottom - rect.top;
 
-    // if external supports underscan, do nothing
-    // it will be taken care in the driver
-    if(ctx->mExtDisplay->isCEUnderscanSupported())
+    if(!ctx->dpyAttr[dpy].mActionSafePresent)
         return;
-
-    char value[PROPERTY_VALUE_MAX];
-    // Read action safe properties
-    property_get("persist.sys.actionsafe.width", value, "0");
-    int asWidthRatio = atoi(value);
-    property_get("persist.sys.actionsafe.height", value, "0");
-    int asHeightRatio = atoi(value);
-
-    if(!asWidthRatio && !asHeightRatio) {
-        //No action safe ratio set, return
-        return;
-    }
+   // Read action safe properties
+    int asWidthRatio = ctx->dpyAttr[dpy].mAsWidthRatio;
+    int asHeightRatio = ctx->dpyAttr[dpy].mAsHeightRatio;
 
     float wRatio = 1.0;
     float hRatio = 1.0;
@@ -626,7 +620,6 @@
 }
 bool needsScaling(hwc_layer_1_t const* layer) {
     int dst_w, dst_h, src_w, src_h;
-
     hwc_rect_t displayFrame  = layer->displayFrame;
     hwc_rect_t sourceCrop = integerizeSourceCrop(layer->sourceCropf);
 
@@ -763,6 +756,7 @@
     ctx->listStats[dpy].secureUI = false;
     ctx->listStats[dpy].yuv4k2kCount = 0;
     ctx->mViewFrame[dpy] = (hwc_rect_t){0, 0, 0, 0};
+    ctx->dpyAttr[dpy].mActionSafePresent = isActionSafePresent(ctx, dpy);
 
     trimList(ctx, list, dpy);
     optimizeLayerRects(ctx, list, dpy);
@@ -920,6 +914,27 @@
         return false;
 }
 
+// returns true if Action safe dimensions are set and target supports Actionsafe
+bool isActionSafePresent(hwc_context_t *ctx, int dpy) {
+    // if external supports underscan, do nothing
+    // it will be taken care in the driver
+    if(!dpy || ctx->mExtDisplay->isCEUnderscanSupported())
+        return false;
+
+    char value[PROPERTY_VALUE_MAX];
+    // Read action safe properties
+    property_get("persist.sys.actionsafe.width", value, "0");
+    ctx->dpyAttr[dpy].mAsWidthRatio = atoi(value);
+    property_get("persist.sys.actionsafe.height", value, "0");
+    ctx->dpyAttr[dpy].mAsHeightRatio = atoi(value);
+
+    if(!ctx->dpyAttr[dpy].mAsWidthRatio && !ctx->dpyAttr[dpy].mAsHeightRatio) {
+        //No action safe ratio set, return
+        return false;
+    }
+    return true;
+}
+
 int getBlending(int blending) {
     switch(blending) {
     case HWC_BLENDING_NONE:
diff --git a/libhwcomposer/hwc_utils.h b/libhwcomposer/hwc_utils.h
index 0b41a02..4a20d47 100644
--- a/libhwcomposer/hwc_utils.h
+++ b/libhwcomposer/hwc_utils.h
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2010 The Android Open Source Project
- * Copyright (C)2012-2013, The Linux Foundation. All rights reserved.
+ * Copyright (C)2012-2014, The Linux Foundation. All rights reserved.
  *
  * Not a Contribution, Apache license notifications and license are retained
  * for attribution purposes only.
@@ -89,6 +89,11 @@
     bool mDownScaleMode;
     // Ext dst Rect
     hwc_rect_t mDstRect;
+    //Action safe attributes
+    // Flag to indicate the presence of action safe dimensions for external
+    bool mActionSafePresent;
+    int mAsWidthRatio;
+    int mAsHeightRatio;
 };
 
 struct ListStats {
@@ -230,6 +235,9 @@
 bool areLayersIntersecting(const hwc_layer_1_t* layer1,
         const hwc_layer_1_t* layer2);
 
+// returns true if Action safe dimensions are set and target supports Actionsafe
+bool isActionSafePresent(hwc_context_t *ctx, int dpy);
+
 /* Calculates the destination position based on the action safe rectangle */
 void getActionSafePosition(hwc_context_t *ctx, int dpy, hwc_rect_t& dst);
 
@@ -255,6 +263,10 @@
 // BufferMirrirMode(Sidesync)
 int getMirrorModeOrientation(hwc_context_t *ctx);
 
+// Handles wfd Pause and resume events
+void handle_pause(hwc_context_t *ctx, int dpy);
+void handle_resume(hwc_context_t *ctx, int dpy);
+
 //Close acquireFenceFds of all layers of incoming list
 void closeAcquireFds(hwc_display_contents_1_t* list);
 
diff --git a/liboverlay/overlayCtrlData.h b/liboverlay/overlayCtrlData.h
index 1b26b66..dbf328a 100644
--- a/liboverlay/overlayCtrlData.h
+++ b/liboverlay/overlayCtrlData.h
@@ -49,13 +49,9 @@
 public:
 
     /* ctor */
-    explicit Ctrl();
+    explicit Ctrl(const int& dpy);
     /* dtor close */
     ~Ctrl();
-    /* init fd etc*/
-    bool init(uint32_t dpy);
-    /* close underlying mdp */
-    bool close();
 
     /* set source using whf, orient and wait flag */
     void setSource(const utils::PipeArgs& args);
@@ -90,20 +86,16 @@
 
 private:
     // mdp ctrl struct(info e.g.)
-    MdpCtrl mMdp;
+    MdpCtrl *mMdp;
 };
 
 
 class Data : utils::NoCopy {
 public:
     /* init, reset */
-    explicit Data();
+    explicit Data(const int& dpy);
     /* calls close */
     ~Data();
-    /* init fd etc */
-    bool init(uint32_t dpy);
-    /* calls underlying mdp close */
-    bool close();
     /* set overlay pipe id in the mdp struct */
     void setPipeId(int id);
     /* get overlay id in the mdp struct */
@@ -117,72 +109,46 @@
 
 private:
     // mdp data struct
-    MdpData mMdp;
-};
-
-/* This class just creates a Ctrl Data pair to be used by a pipe.
- * Although this was legacy design, this separation still makes sense, since we
- * need to use the Ctrl channel in hwc_prepare (i.e config stage) and Data
- * channel in hwc_set (i.e draw stage)
- */
-struct CtrlData {
-    Ctrl ctrl;
-    Data data;
+    MdpData *mMdp;
 };
 
 //-------------Inlines-------------------------------
 
-inline Ctrl::Ctrl() {
-    mMdp.reset();
+inline Ctrl::Ctrl(const int& dpy) : mMdp(new MdpCtrl(dpy)) {
 }
 
 inline Ctrl::~Ctrl() {
-    close();
-}
-
-inline bool Ctrl::close() {
-    if(!mMdp.close())
-        return false;
-    return true;
-}
-
-inline bool Ctrl::init(uint32_t dpy) {
-    // MDP/FD init
-    if(!mMdp.init(dpy)) {
-        ALOGE("Ctrl failed to init dpy=%d", dpy);
-        return false;
-    }
-    return true;
+    delete mMdp;
 }
 
 inline void Ctrl::setSource(const utils::PipeArgs& args)
 {
-    mMdp.setSource(args);
+    mMdp->setSource(args);
 }
 
 inline void Ctrl::setPosition(const utils::Dim& dim)
 {
-    mMdp.setPosition(dim);
+    mMdp->setPosition(dim);
 }
 
 inline void Ctrl::setTransform(const utils::eTransform& orient)
 {
-    mMdp.setTransform(orient);
+    mMdp->setTransform(orient);
 }
 
 inline void Ctrl::setCrop(const utils::Dim& d)
 {
-    mMdp.setCrop(d);
+    mMdp->setCrop(d);
 }
 
 inline void Ctrl::setColor(const uint32_t color)
 {
-    mMdp.setColor(color);
+    mMdp->setColor(color);
 }
 
 inline bool Ctrl::setVisualParams(const MetaData_t &metadata)
 {
-    if (!mMdp.setVisualParams(metadata)) {
+    if (!mMdp->setVisualParams(metadata)) {
         ALOGE("Ctrl setVisualParams failed in MDP setVisualParams");
         return false;
     }
@@ -191,12 +157,12 @@
 
 inline void Ctrl::dump() const {
     ALOGE("== Dump Ctrl start ==");
-    mMdp.dump();
+    mMdp->dump();
     ALOGE("== Dump Ctrl end ==");
 }
 
 inline bool Ctrl::commit() {
-    if(!mMdp.set()) {
+    if(!mMdp->set()) {
         ALOGE("Ctrl commit failed set overlay");
         return false;
     }
@@ -204,71 +170,56 @@
 }
 
 inline int Ctrl::getPipeId() const {
-    return mMdp.getPipeId();
+    return mMdp->getPipeId();
 }
 
 inline int Ctrl::getFd() const {
-    return mMdp.getFd();
+    return mMdp->getFd();
 }
 
 inline void Ctrl::updateSrcFormat(const uint32_t& rotDstFmt) {
-    mMdp.updateSrcFormat(rotDstFmt);
+    mMdp->updateSrcFormat(rotDstFmt);
 }
 
 inline utils::Dim Ctrl::getCrop() const {
-    return mMdp.getSrcRectDim();
+    return mMdp->getSrcRectDim();
 }
 
 inline utils::Dim Ctrl::getPosition() const {
-    return mMdp.getDstRectDim();
+    return mMdp->getDstRectDim();
 }
 
 inline void Ctrl::setDownscale(int dscale_factor) {
-    mMdp.setDownscale(dscale_factor);
+    mMdp->setDownscale(dscale_factor);
 }
 
 inline void Ctrl::getDump(char *buf, size_t len) {
-    mMdp.getDump(buf, len);
+    mMdp->getDump(buf, len);
 }
 
-inline Data::Data() {
-    mMdp.reset();
+inline Data::Data(const int& dpy) : mMdp(new MdpData(dpy)) {
 }
 
-inline Data::~Data() { close(); }
-
-inline void Data::setPipeId(int id) { mMdp.setPipeId(id); }
-
-inline int Data::getPipeId() const { return mMdp.getPipeId(); }
-
-inline bool Data::init(uint32_t dpy) {
-    if(!mMdp.init(dpy)) {
-        ALOGE("Data cannot init mdp");
-        return false;
-    }
-    return true;
+inline Data::~Data() {
+    delete mMdp;
 }
 
-inline bool Data::close() {
-    if(!mMdp.close()) {
-        ALOGE("Data close failed");
-        return false;
-    }
-    return true;
-}
+inline void Data::setPipeId(int id) { mMdp->setPipeId(id); }
+
+inline int Data::getPipeId() const { return mMdp->getPipeId(); }
 
 inline bool Data::queueBuffer(int fd, uint32_t offset) {
-    return mMdp.play(fd, offset);
+    return mMdp->play(fd, offset);
 }
 
 inline void Data::dump() const {
     ALOGE("== Dump Data MDP start ==");
-    mMdp.dump();
+    mMdp->dump();
     ALOGE("== Dump Data MDP end ==");
 }
 
 inline void Data::getDump(char *buf, size_t len) {
-    mMdp.getDump(buf, len);
+    mMdp->getDump(buf, len);
 }
 
 } // overlay
diff --git a/liboverlay/overlayMdp.cpp b/liboverlay/overlayMdp.cpp
index 006e05d..b278ce4 100644
--- a/liboverlay/overlayMdp.cpp
+++ b/liboverlay/overlayMdp.cpp
@@ -45,7 +45,7 @@
 namespace ovutils = overlay::utils;
 namespace overlay {
 
-bool MdpCtrl::init(uint32_t dpy) {
+bool MdpCtrl::init(const int& dpy) {
     int fbnum = Overlay::getFbForDpy(dpy);
     if( fbnum < 0 ) {
         ALOGE("%s: Invalid FB for the display: %d",__FUNCTION__, dpy);
@@ -64,14 +64,11 @@
 
 void MdpCtrl::reset() {
     utils::memset0(mOVInfo);
-    utils::memset0(mLkgo);
     mOVInfo.id = MSMFB_NEW_REQUEST;
-    mLkgo.id = MSMFB_NEW_REQUEST;
     mOrientation = utils::OVERLAY_TRANSFORM_0;
     mDownscale = 0;
     mDpy = 0;
 #ifdef USES_POST_PROCESSING
-    mPPChanged = false;
     memset(&mParams, 0, sizeof(struct compute_params));
     mParams.params.conv_params.order = hsic_order_hsc_i;
     mParams.params.conv_params.interface = interface_rec601;
@@ -210,21 +207,15 @@
 
     doDownscale();
 
-    if(this->ovChanged()) {
-        if(!mdp_wrapper::setOverlay(mFd.getFD(), mOVInfo)) {
-            ALOGE("MdpCtrl failed to setOverlay, restoring last known "
-                  "good ov info");
-            mdp_wrapper::dump("== Bad OVInfo is: ", mOVInfo);
-            mdp_wrapper::dump("== Last good known OVInfo is: ", mLkgo);
-            this->restore();
+    if(!mdp_wrapper::setOverlay(mFd.getFD(), mOVInfo)) {
+        ALOGE("MdpCtrl failed to setOverlay");
+        mdp_wrapper::dump("== Bad OVInfo is: ", mOVInfo);
 #ifdef USES_QSEED_SCALAR
-            if(Overlay::getScalar()) {
-                Overlay::getScalar()->configAbort(mDpy);
-            }
-#endif
-            return false;
+        if(Overlay::getScalar()) {
+            Overlay::getScalar()->configAbort(mDpy);
         }
-        this->save();
+#endif
+        return false;
     }
 
 #ifdef USES_QSEED_SCALAR
@@ -392,7 +383,6 @@
 
     if (needUpdate) {
         display_pp_compute_params(&mParams, &mOVInfo.overlay_pp_cfg);
-        mPPChanged = true;
     }
 #endif
     return true;
@@ -400,7 +390,7 @@
 
 
 //// MdpData ////////////
-bool MdpData::init(uint32_t dpy) {
+bool MdpData::init(const int& dpy) {
     int fbnum = Overlay::getFbForDpy(dpy);
     if( fbnum < 0 ) {
         ALOGE("%s: Invalid FB for the display: %d",__FUNCTION__, dpy);
diff --git a/liboverlay/overlayMdp.h b/liboverlay/overlayMdp.h
index 3cb6a41..daaeaf2 100644
--- a/liboverlay/overlayMdp.h
+++ b/liboverlay/overlayMdp.h
@@ -36,11 +36,11 @@
 class MdpCtrl {
 public:
     /* ctor reset */
-    explicit MdpCtrl();
+    explicit MdpCtrl(const int& dpy);
     /* dtor close */
     ~MdpCtrl();
     /* init underlying device using fbnum for dpy */
-    bool init(uint32_t dpy);
+    bool init(const int& dpy);
     /* unset overlay, reset and close fd */
     bool close();
     /* reset and set ov id to -1 / MSMFB_NEW_REQUEST */
@@ -116,17 +116,8 @@
     int getUserData() const;
     /* sets user_data[0] */
     void setUserData(int v);
-    /* return true if current overlay is different
-     * than last known good overlay */
-    bool ovChanged() const;
-    /* save mOVInfo to be last known good ov*/
-    void save();
-    /* restore last known good ov to be the current */
-    void restore();
 
     utils::eTransform mOrientation; //Holds requested orientation
-    /* last good known ov info */
-    mdp_overlay   mLkgo;
     /* Actual overlay mdp structure */
     mdp_overlay   mOVInfo;
     /* FD for the mdp fbnum */
@@ -137,8 +128,6 @@
 #ifdef USES_POST_PROCESSING
     /* PP Compute Params */
     struct compute_params mParams;
-    /* indicate if PP params have been changed */
-    bool mPPChanged;
 #endif
 };
 
@@ -171,11 +160,11 @@
 class MdpData {
 public:
     /* ctor reset data */
-    explicit MdpData();
+    explicit MdpData(const int& dpy);
     /* dtor close*/
     ~MdpData();
     /* init FD */
-    bool init(uint32_t dpy);
+    bool init(const int& dpy);
     /* memset0 the underlying mdp object */
     void reset();
     /* close fd, and reset */
@@ -207,8 +196,9 @@
 
 /////   MdpCtrl  //////
 
-inline MdpCtrl::MdpCtrl() {
+inline MdpCtrl::MdpCtrl(const int& dpy) {
     reset();
+    init(dpy);
 }
 
 inline MdpCtrl::~MdpCtrl() {
@@ -265,37 +255,6 @@
     }
 }
 
-inline bool MdpCtrl::ovChanged() const {
-#ifdef USES_POST_PROCESSING
-    // Some pp params are stored as pointer address,
-    // so can't compare their content directly.
-    if (mPPChanged) {
-        return true;
-    }
-#endif
-    // 0 means same
-    if(0 == ::memcmp(&mOVInfo, &mLkgo, sizeof (mdp_overlay))) {
-        return false;
-    }
-    return true;
-}
-
-inline void MdpCtrl::save() {
-    if(static_cast<ssize_t>(mOVInfo.id) == MSMFB_NEW_REQUEST) {
-        ALOGE("MdpCtrl current ov has id -1, will not save");
-        return;
-    }
-    mLkgo = mOVInfo;
-}
-
-inline void MdpCtrl::restore() {
-    if(static_cast<ssize_t>(mLkgo.id) == MSMFB_NEW_REQUEST) {
-        ALOGE("MdpCtrl Lkgo ov has id -1, will not restore");
-        return;
-    }
-    mOVInfo = mLkgo;
-}
-
 inline overlay::utils::Whf MdpCtrl::getSrcWhf() const {
     return utils::Whf(  mOVInfo.src.width,
                         mOVInfo.src.height,
@@ -388,7 +347,10 @@
 
 ///////    MdpData   //////
 
-inline MdpData::MdpData() { reset(); }
+inline MdpData::MdpData(const int& dpy) {
+    reset();
+    init(dpy);
+}
 
 inline MdpData::~MdpData() { close(); }
 
diff --git a/liboverlay/pipes/overlayGenPipe.cpp b/liboverlay/pipes/overlayGenPipe.cpp
index e0b580b..394a56e 100644
--- a/liboverlay/pipes/overlayGenPipe.cpp
+++ b/liboverlay/pipes/overlayGenPipe.cpp
@@ -32,73 +32,40 @@
 
 namespace overlay {
 
-GenericPipe::GenericPipe(int dpy) : mDpy(dpy), mRotDownscaleOpt(false),
-    pipeState(CLOSED) {
-    init();
+GenericPipe::GenericPipe(const int& dpy) : mDpy(dpy), mRotDownscaleOpt(false),
+    pipeState(CLOSED), mCtrl(new Ctrl(dpy)), mData(new Data(dpy)) {
 }
 
 GenericPipe::~GenericPipe() {
-    close();
-}
-
-bool GenericPipe::init()
-{
-    ALOGE_IF(DEBUG_OVERLAY, "GenericPipe init");
-    mRotDownscaleOpt = false;
-
-    if(!mCtrlData.ctrl.init(mDpy)) {
-        ALOGE("GenericPipe failed to init ctrl");
-        return false;
-    }
-
-    if(!mCtrlData.data.init(mDpy)) {
-        ALOGE("GenericPipe failed to init data");
-        return false;
-    }
-
-    return true;
-}
-
-bool GenericPipe::close() {
-    bool ret = true;
-
-    if(!mCtrlData.ctrl.close()) {
-        ALOGE("GenericPipe failed to close ctrl");
-        ret = false;
-    }
-    if (!mCtrlData.data.close()) {
-        ALOGE("GenericPipe failed to close data");
-        ret = false;
-    }
-
+    delete mCtrl;
+    delete mData;
     setClosed();
-    return ret;
 }
 
 void GenericPipe::setSource(const utils::PipeArgs& args) {
     mRotDownscaleOpt = args.rotFlags & utils::ROT_DOWNSCALE_ENABLED;
-    mCtrlData.ctrl.setSource(args);
+    mCtrl->setSource(args);
 }
 
 void GenericPipe::setCrop(const overlay::utils::Dim& d) {
-    mCtrlData.ctrl.setCrop(d);
+    mCtrl->setCrop(d);
 }
 
 void GenericPipe::setColor(const uint32_t color) {
-    mCtrlData.ctrl.setColor(color);
+    mCtrl->setColor(color);
 }
 
 void GenericPipe::setTransform(const utils::eTransform& orient) {
-    mCtrlData.ctrl.setTransform(orient);
+    mCtrl->setTransform(orient);
 }
 
 void GenericPipe::setPosition(const utils::Dim& d) {
-    mCtrlData.ctrl.setPosition(d);
+    mCtrl->setPosition(d);
 }
 
 bool GenericPipe::setVisualParams(const MetaData_t &metadata)
 {
-        return mCtrlData.ctrl.setVisualParams(metadata);
+        return mCtrl->setVisualParams(metadata);
 }
 
 bool GenericPipe::commit() {
@@ -106,14 +73,14 @@
     int downscale_factor = utils::ROT_DS_NONE;
 
     if(mRotDownscaleOpt) {
-        ovutils::Dim src(mCtrlData.ctrl.getCrop());
-        ovutils::Dim dst(mCtrlData.ctrl.getPosition());
+        ovutils::Dim src(mCtrl->getCrop());
+        ovutils::Dim dst(mCtrl->getPosition());
         downscale_factor = ovutils::getDownscaleFactor(
                 src.w, src.h, dst.w, dst.h);
     }
 
-    mCtrlData.ctrl.setDownscale(downscale_factor);
-    ret = mCtrlData.ctrl.commit();
+    mCtrl->setDownscale(downscale_factor);
+    ret = mCtrl->commit();
 
     pipeState = ret ? OPEN : CLOSED;
     return ret;
@@ -122,36 +89,35 @@
 bool GenericPipe::queueBuffer(int fd, uint32_t offset) {
     //TODO Move pipe-id transfer to CtrlData class. Make ctrl and data private.
     OVASSERT(isOpen(), "State is closed, cannot queueBuffer");
-    int pipeId = mCtrlData.ctrl.getPipeId();
+    int pipeId = mCtrl->getPipeId();
     OVASSERT(-1 != pipeId, "Ctrl ID should not be -1");
     // set pipe id from ctrl to data
-    mCtrlData.data.setPipeId(pipeId);
+    mData->setPipeId(pipeId);
 
-    return mCtrlData.data.queueBuffer(fd, offset);
+    return mData->queueBuffer(fd, offset);
 }
 
 int GenericPipe::getCtrlFd() const {
-    return mCtrlData.ctrl.getFd();
+    return mCtrl->getFd();
 }
 
 utils::Dim GenericPipe::getCrop() const
 {
-    return mCtrlData.ctrl.getCrop();
+    return mCtrl->getCrop();
 }
 
 void GenericPipe::dump() const
 {
     ALOGE("== Dump Generic pipe start ==");
     ALOGE("pipe state = %d", (int)pipeState);
-    mCtrlData.ctrl.dump();
-    mCtrlData.data.dump();
-
+    mCtrl->dump();
+    mData->dump();
     ALOGE("== Dump Generic pipe end ==");
 }
 
 void GenericPipe::getDump(char *buf, size_t len) {
-    mCtrlData.ctrl.getDump(buf, len);
-    mCtrlData.data.getDump(buf, len);
+    mCtrl->getDump(buf, len);
+    mData->getDump(buf, len);
 }
 
 bool GenericPipe::isClosed() const  {
@@ -168,7 +134,7 @@
 }
 
 int GenericPipe::getPipeId() {
-    return mCtrlData.ctrl.getPipeId();
+    return mCtrl->getPipeId();
 }
 
 } //namespace overlay
diff --git a/liboverlay/pipes/overlayGenPipe.h b/liboverlay/pipes/overlayGenPipe.h
index ecdd001..57e1758 100644
--- a/liboverlay/pipes/overlayGenPipe.h
+++ b/liboverlay/pipes/overlayGenPipe.h
@@ -38,11 +38,9 @@
 class GenericPipe : utils::NoCopy {
 public:
     /* ctor */
-    explicit GenericPipe(int dpy);
+    explicit GenericPipe(const int& dpy);
     /* dtor */
     ~GenericPipe();
-    bool init();
-    bool close();
     /* Control APIs */
     /* set source using whf, orient and wait flag */
     void setSource(const utils::PipeArgs& args);
@@ -82,8 +80,6 @@
     bool setClosed();
 
     int mDpy;
-    /* Ctrl/Data aggregator */
-    CtrlData mCtrlData;
     //Whether we will do downscale opt. This is just a request. If the frame is
     //not a candidate, we might not do it.
     bool mRotDownscaleOpt;
@@ -93,6 +89,8 @@
         OPEN
     };
     ePipeState pipeState;
+    Ctrl *mCtrl;
+    Data *mData;
 };
 
 } //namespace overlay
diff --git a/libqdutils/cb_utils.cpp b/libqdutils/cb_utils.cpp
index d8eec2a..bc7e5b1 100644
--- a/libqdutils/cb_utils.cpp
+++ b/libqdutils/cb_utils.cpp
@@ -49,10 +49,6 @@
     Region wormholeRegion(fbFrameRect);
 
     for (uint32_t i = 0 ; i < last; i++) {
-        //TODO Work on using hwc clear instead of gpu for HWC_BLIT
-        //If layer is marked for HWC_BLIT clear is done by GPU
-        if(list->hwLayers[i].compositionType == HWC_BLIT)
-            return 0;
         // need to take care only in per pixel blending.
         // Restrict calculation only for copybit layers.
         if((list->hwLayers[i].blending != HWC_BLENDING_NONE) ||
diff --git a/libqservice/IQService.h b/libqservice/IQService.h
index f8e58ab..33c3ca0 100644
--- a/libqservice/IQService.h
+++ b/libqservice/IQService.h
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2010 The Android Open Source Project
- * Copyright (C) 2012-2013, The Linux Foundation. All rights reserved.
+ * Copyright (C) 2012-2014, The Linux Foundation. All rights reserved.
  *
  * Not a Contribution, Apache license notifications and license are
  * retained for attribution purposes only.
@@ -49,6 +49,7 @@
         GET_DISPLAY_ATTRIBUTES,  // Get display attributes
         SET_HSIC_DATA,           // Set HSIC on dspp
         GET_DISPLAY_VISIBLE_REGION,  // Get the visibleRegion for dpy
+        PAUSE_WFD,               // Pause/Resume WFD
         VPU_COMMAND_LIST_START = 100, //Reserved block for VPU commands
         VPU_COMMAND_LIST_END   = 200,
         COMMAND_LIST_END = 400,
diff --git a/libqservice/QServiceUtils.h b/libqservice/QServiceUtils.h
index 3d1adc0..2817429 100644
--- a/libqservice/QServiceUtils.h
+++ b/libqservice/QServiceUtils.h
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2013 The Linux Foundation. All rights reserved.
+* Copyright (c) 2013-14 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
@@ -83,4 +83,8 @@
     return sendSingleParam(qService::IQService::BUFFER_MIRRORMODE, enable);
 }
 
+inline android::status_t pauseWFD(uint32_t pause) {
+    return sendSingleParam(qService::IQService::PAUSE_WFD, pause);
+}
+
 #endif /* end of include guard: QSERVICEUTILS_H */