Merge "libexternal: prefix the property name with hw"
diff --git a/libgralloc/alloc_controller.cpp b/libgralloc/alloc_controller.cpp
index ebd7e98..20f7973 100644
--- a/libgralloc/alloc_controller.cpp
+++ b/libgralloc/alloc_controller.cpp
@@ -76,8 +76,7 @@
 static bool useUncached(int usage)
 {
     // System heaps cannot be uncached
-    if(usage & (GRALLOC_USAGE_PRIVATE_SYSTEM_HEAP |
-                GRALLOC_USAGE_PRIVATE_IOMMU_HEAP))
+    if(usage & GRALLOC_USAGE_PRIVATE_SYSTEM_HEAP)
         return false;
     if (usage & GRALLOC_USAGE_PRIVATE_UNCACHED)
         return true;
diff --git a/libhwcomposer/hwc.cpp b/libhwcomposer/hwc.cpp
index c2688b5..dfae893 100644
--- a/libhwcomposer/hwc.cpp
+++ b/libhwcomposer/hwc.cpp
@@ -17,13 +17,14 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
+#define ATRACE_TAG ATRACE_TAG_GRAPHICS
 #include <fcntl.h>
 #include <errno.h>
 
 #include <cutils/log.h>
 #include <cutils/atomic.h>
 #include <EGL/egl.h>
+#include <utils/Trace.h>
 
 #include <overlay.h>
 #include <fb_priv.h>
@@ -124,9 +125,8 @@
         hwc_display_contents_1_t *list) {
     hwc_context_t* ctx = (hwc_context_t*)(dev);
     const int dpy = HWC_DISPLAY_PRIMARY;
-    if (LIKELY(list && list->numHwLayers > 1) &&
-        ctx->dpyAttr[dpy].isActive) {
-
+    if (LIKELY(list && list->numHwLayers > 1 &&
+        list->numHwLayers <= MAX_NUM_LAYERS) && ctx->dpyAttr[dpy].isActive) {
         uint32_t last = list->numHwLayers - 1;
         hwc_layer_1_t *fbLayer = &list->hwLayers[last];
         if(fbLayer->handle) {
@@ -136,7 +136,7 @@
             if(!ret) {
                 // IF MDPcomp fails use this route
                 VideoOverlay::prepare(ctx, list, dpy);
-                ctx->mFBUpdate[dpy]->prepare(ctx, fbLayer);
+                ctx->mFBUpdate[dpy]->prepare(ctx, list);
             }
             ctx->mLayerCache[dpy]->updateLayerCache(list);
             // Use Copybit, when MDP comp fails
@@ -151,7 +151,8 @@
         hwc_display_contents_1_t *list, int dpy) {
     hwc_context_t* ctx = (hwc_context_t*)(dev);
 
-    if (LIKELY(list && list->numHwLayers > 1) &&
+    if (LIKELY(list && list->numHwLayers > 1 &&
+        list->numHwLayers <= MAX_NUM_LAYERS) &&
         ctx->dpyAttr[dpy].isActive &&
         ctx->dpyAttr[dpy].connected) {
         uint32_t last = list->numHwLayers - 1;
@@ -161,7 +162,7 @@
                 setListStats(ctx, list, dpy);
                 reset_layer_prop(ctx, dpy);
                 VideoOverlay::prepare(ctx, list, dpy);
-                ctx->mFBUpdate[dpy]->prepare(ctx, fbLayer);
+                ctx->mFBUpdate[dpy]->prepare(ctx, list);
                 ctx->mLayerCache[dpy]->updateLayerCache(list);
                 if(ctx->mCopyBit[dpy])
                     ctx->mCopyBit[dpy]->prepare(ctx, list, dpy);
@@ -234,6 +235,7 @@
 
 static int hwc_blank(struct hwc_composer_device_1* dev, int dpy, int blank)
 {
+    ATRACE_CALL();
     hwc_context_t* ctx = (hwc_context_t*)(dev);
     private_module_t* m = reinterpret_cast<private_module_t*>(
         ctx->mFbDev->common.module);
@@ -309,6 +311,7 @@
 }
 
 static int hwc_set_primary(hwc_context_t *ctx, hwc_display_contents_1_t* list) {
+    ATRACE_CALL();
     int ret = 0;
     const int dpy = HWC_DISPLAY_PRIMARY;
 
@@ -316,8 +319,9 @@
         uint32_t last = list->numHwLayers - 1;
         hwc_layer_1_t *fbLayer = &list->hwLayers[last];
         int fd = -1; //FenceFD from the Copybit(valid in async mode)
+        bool copybitDone = false;
         if(ctx->mCopyBit[dpy])
-            ctx->mCopyBit[dpy]->draw(ctx, list, dpy, &fd);
+            copybitDone = ctx->mCopyBit[dpy]->draw(ctx, list, dpy, &fd);
         if(list->numHwLayers > 1)
             hwc_sync(ctx, list, dpy, fd);
         if (!VideoOverlay::draw(ctx, list, dpy)) {
@@ -331,11 +335,16 @@
 
         //TODO We dont check for SKIP flag on this layer because we need PAN
         //always. Last layer is always FB
-        private_handle_t *hnd = (private_handle_t *)fbLayer->handle;
+        private_handle_t *hnd = NULL;
+        if(copybitDone) {
+            hnd = ctx->mCopyBit[dpy]->getCurrentRenderBuffer();
+        } else {
+            hnd = (private_handle_t *)fbLayer->handle;
+        }
         if(fbLayer->compositionType == HWC_FRAMEBUFFER_TARGET && hnd) {
             if(!(fbLayer->flags & HWC_SKIP_LAYER) &&
                 (list->numHwLayers > 1)) {
-                if (!ctx->mFBUpdate[dpy]->draw(ctx, fbLayer)) {
+                if (!ctx->mFBUpdate[dpy]->draw(ctx, hnd)) {
                     ALOGE("%s: FBUpdate::draw fail!", __FUNCTION__);
                     ret = -1;
                 }
@@ -352,7 +361,9 @@
 }
 
 static int hwc_set_external(hwc_context_t *ctx,
-        hwc_display_contents_1_t* list, int dpy) {
+                            hwc_display_contents_1_t* list, int dpy)
+{
+    ATRACE_CALL();
     int ret = 0;
     Locker::Autolock _l(ctx->mExtSetLock);
 
@@ -362,8 +373,9 @@
         uint32_t last = list->numHwLayers - 1;
         hwc_layer_1_t *fbLayer = &list->hwLayers[last];
         int fd = -1; //FenceFD from the Copybit(valid in async mode)
+        bool copybitDone = false;
         if(ctx->mCopyBit[dpy])
-            ctx->mCopyBit[dpy]->draw(ctx, list, dpy, &fd);
+            copybitDone = ctx->mCopyBit[dpy]->draw(ctx, list, dpy, &fd);
 
         if(list->numHwLayers > 1)
             hwc_sync(ctx, list, dpy, fd);
@@ -373,11 +385,17 @@
             ret = -1;
         }
 
-        private_handle_t *hnd = (private_handle_t *)fbLayer->handle;
+        private_handle_t *hnd = NULL;
+        if(copybitDone) {
+            hnd = ctx->mCopyBit[dpy]->getCurrentRenderBuffer();
+        } else {
+            hnd = (private_handle_t *)fbLayer->handle;
+        }
+
         if(fbLayer->compositionType == HWC_FRAMEBUFFER_TARGET &&
                 !(fbLayer->flags & HWC_SKIP_LAYER) && hnd &&
                 (list->numHwLayers > 1)) {
-            if (!ctx->mFBUpdate[dpy]->draw(ctx, fbLayer)) {
+            if (!ctx->mFBUpdate[dpy]->draw(ctx, hnd)) {
                 ALOGE("%s: FBUpdate::draw fail!", __FUNCTION__);
                 ret = -1;
             }
diff --git a/libhwcomposer/hwc_copybit.cpp b/libhwcomposer/hwc_copybit.cpp
index 8ce9f0d..4549dcf 100644
--- a/libhwcomposer/hwc_copybit.cpp
+++ b/libhwcomposer/hwc_copybit.cpp
@@ -23,11 +23,7 @@
 #include <utils/Timers.h>
 #include "hwc_copybit.h"
 #include "comptype.h"
-
-//XXX: Remove HWC_BLIT
-#ifndef QCOM_BSP
-#define HWC_BLIT 4
-#endif
+#include "gr.h"
 
 namespace qhwc {
 
@@ -164,27 +160,42 @@
 
     bool useCopybitForYUV = canUseCopybitForYUV(ctx);
     bool useCopybitForRGB = canUseCopybitForRGB(ctx, list, dpy);
+    LayerProp *layerProp = ctx->layerProp[dpy];
+    size_t fbLayerIndex = ctx->listStats[dpy].fbLayerIndex;
+    hwc_layer_1_t *fbLayer = &list->hwLayers[fbLayerIndex];
+    private_handle_t *fbHnd = (private_handle_t *)fbLayer->handle;
+
+
+
+    //Allocate render buffers if they're not allocated
+    if (useCopybitForYUV || useCopybitForRGB) {
+        int ret = allocRenderBuffers(fbHnd->width,
+                                     fbHnd->height,
+                                     fbHnd->format);
+        if (ret < 0) {
+            return false;
+        } else {
+            mCurRenderBufferIndex = (mCurRenderBufferIndex + 1) %
+                NUM_RENDER_BUFFERS;
+        }
+    }
+
 
     // numAppLayers-1, as we iterate till 0th layer index
     for (int i = ctx->listStats[dpy].numAppLayers-1; i >= 0 ; i--) {
         private_handle_t *hnd = (private_handle_t *)list->hwLayers[i].handle;
 
-        if (hnd->bufferType == BUFFER_TYPE_VIDEO) {
-            //YUV layer, check, if copybit can be used
-            // mark the video layer to gpu when all layer is
-            // going to gpu in case of dynamic composition.
-            if (useCopybitForYUV) {
-                list->hwLayers[i].compositionType = HWC_BLIT;
-                mCopyBitDraw = true;
-            }
-        } else if (hnd->bufferType == BUFFER_TYPE_UI) {
-            //RGB layer, check, if copybit can be used
-            if (useCopybitForRGB) {
-                ALOGD_IF(DEBUG_COPYBIT, "%s: Marking layer[%d] for copybit for"
-                                "dpy[%d] ", __FUNCTION__, i, dpy);
-                list->hwLayers[i].compositionType = HWC_BLIT;
-                mCopyBitDraw = true;
-            }
+        if ((hnd->bufferType == BUFFER_TYPE_VIDEO && useCopybitForYUV) ||
+            (hnd->bufferType == BUFFER_TYPE_UI && useCopybitForRGB)) {
+            layerProp[i].mFlags |= HWC_COPYBIT;
+            list->hwLayers[i].compositionType = HWC_OVERLAY;
+            mCopyBitDraw = true;
+        } else {
+            // We currently cannot mix copybit layers with layers marked to
+            // be drawn on the framebuffer or that are on the layer cache.
+            mCopyBitDraw = false;
+            //There is no need to reset layer properties here as we return in
+            //draw if mCopyBitDraw is false
         }
     }
     return true;
@@ -195,23 +206,29 @@
     // draw layers marked for COPYBIT
     int retVal = true;
     int copybitLayerCount = 0;
+    LayerProp *layerProp = ctx->layerProp[dpy];
 
     if(mCopyBitDraw == false) // there is no layer marked for copybit
-        return true ;
+        return false ;
 
-    size_t fbLayerIndex = ctx->listStats[dpy].fbLayerIndex;
-    hwc_layer_1_t *fbLayer = &list->hwLayers[fbLayerIndex];
     //render buffer
-    private_handle_t *renderBuffer = (private_handle_t *)fbLayer->handle;
+    private_handle_t *renderBuffer = getCurrentRenderBuffer();
     if (!renderBuffer) {
-        ALOGE("%s: HWC_FRAMEBUFFER_TARGET layer handle is NULL", __FUNCTION__);
+        ALOGE("%s: Render buffer layer handle is NULL", __FUNCTION__);
         return false;
     }
-    // numAppLayers-1, as we iterate from 0th layer index with HWC_BLIT flag
+
+    //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;
+    }
+    // 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];
-        if(!list->hwLayers[i].compositionType == HWC_BLIT) {
-            ALOGD_IF(DEBUG_COPYBIT, "%s: Not Marked for C2D", __FUNCTION__);
+        if(!(layerProp[i].mFlags & HWC_COPYBIT)) {
+            ALOGD_IF(DEBUG_COPYBIT, "%s: Not Marked for copybit", __FUNCTION__);
             continue;
         }
         int ret = -1;
@@ -372,7 +389,7 @@
        }
        ALOGE("%s:%d::tmp_w = %d,tmp_h = %d",__FUNCTION__,__LINE__,tmp_w,tmp_h);
 
-       int usage = GRALLOC_USAGE_PRIVATE_MM_HEAP;
+       int usage = GRALLOC_USAGE_PRIVATE_IOMMU_HEAP;
 
        if (0 == alloc_buffer(&tmpHnd, tmp_w, tmp_h, fbHandle->format, usage)){
             copybit_image_t tmp_dst;
@@ -463,12 +480,55 @@
 }
 
 
+int CopyBit::allocRenderBuffers(int w, int h, int f)
+{
+    int ret = 0;
+    for (int i = 0; i < NUM_RENDER_BUFFERS; i++) {
+        if (mRenderBuffer[i] == NULL) {
+            ret = alloc_buffer(&mRenderBuffer[i],
+                               w, h, f,
+                               GRALLOC_USAGE_PRIVATE_IOMMU_HEAP);
+        }
+        if(ret < 0) {
+            freeRenderBuffers();
+            break;
+        }
+    }
+    return ret;
+}
+
+void CopyBit::freeRenderBuffers()
+{
+    for (int i = 0; i < NUM_RENDER_BUFFERS; i++) {
+        if(mRenderBuffer[i]) {
+            free_buffer(mRenderBuffer[i]);
+            mRenderBuffer[i] = NULL;
+        }
+    }
+}
+
+private_handle_t * CopyBit::getCurrentRenderBuffer() {
+    return mRenderBuffer[mCurRenderBufferIndex];
+}
+
+void CopyBit::setReleaseFd(int fd) {
+    if(mRelFd[0] >=0)
+        close(mRelFd[0]);
+    mRelFd[0] = mRelFd[1];
+    mRelFd[1] = dup(fd);
+}
+
 struct copybit_device_t* CopyBit::getCopyBitDevice() {
     return mEngine;
 }
 
-CopyBit::CopyBit():mIsModeOn(false), mCopyBitDraw(false){
+CopyBit::CopyBit():mIsModeOn(false), mCopyBitDraw(false),
+    mCurRenderBufferIndex(0){
     hw_module_t const *module;
+    for (int i = 0; i < NUM_RENDER_BUFFERS; i++)
+        mRenderBuffer[i] = NULL;
+    mRelFd[0] = -1;
+    mRelFd[1] = -1;
     if (hw_get_module(COPYBIT_HARDWARE_MODULE_ID, &module) == 0) {
         if(copybit_open(module, &mEngine) < 0) {
             ALOGE("FATAL ERROR: copybit open failed.");
@@ -480,6 +540,11 @@
 
 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 015d85a..45d254a 100644
--- a/libhwcomposer/hwc_copybit.h
+++ b/libhwcomposer/hwc_copybit.h
@@ -21,8 +21,7 @@
 #define HWC_COPYBIT_H
 #include "hwc_utils.h"
 
-#define LIKELY( exp )       (__builtin_expect( (exp) != 0, true  ))
-#define UNLIKELY( exp )     (__builtin_expect( (exp) != 0, false ))
+#define NUM_RENDER_BUFFERS 2
 
 namespace qhwc {
 
@@ -40,6 +39,11 @@
                                                         int dpy, int* fd);
     // resets the values
     void reset();
+
+    private_handle_t * getCurrentRenderBuffer();
+
+    void setReleaseFd(int fd);
+
 private:
     // holds the copybit device
     struct copybit_device_t *mEngine;
@@ -61,6 +65,19 @@
 
     void getLayerResolution(const hwc_layer_1_t* layer,
                                    unsigned int &width, unsigned int& height);
+
+    int allocRenderBuffers(int w, int h, int f);
+
+    void freeRenderBuffers();
+
+    private_handle_t* mRenderBuffer[NUM_RENDER_BUFFERS];
+
+    // 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];
 };
 
 }; //namespace qhwc
diff --git a/libhwcomposer/hwc_fbupdate.cpp b/libhwcomposer/hwc_fbupdate.cpp
index a0dbbe3..f9161a3 100644
--- a/libhwcomposer/hwc_fbupdate.cpp
+++ b/libhwcomposer/hwc_fbupdate.cpp
@@ -46,21 +46,24 @@
     mDest = ovutils::OV_INVALID;
 }
 
-bool FBUpdateLowRes::prepare(hwc_context_t *ctx, hwc_layer_1_t *fblayer) {
+bool FBUpdateLowRes::prepare(hwc_context_t *ctx, hwc_display_contents_1 *list)
+{
     if(!ctx->mMDP.hasOverlay) {
         ALOGD_IF(DEBUG_FBUPDATE, "%s, this hw doesnt support overlays",
                 __FUNCTION__);
        return false;
     }
-    mModeOn = configure(ctx, fblayer);
+    mModeOn = configure(ctx, list);
     ALOGD_IF(DEBUG_FBUPDATE, "%s, mModeOn = %d", __FUNCTION__, mModeOn);
     return mModeOn;
 }
 
 // Configure
-bool FBUpdateLowRes::configure(hwc_context_t *ctx, hwc_layer_1_t *layer)
+bool FBUpdateLowRes::configure(hwc_context_t *ctx,
+                               hwc_display_contents_1 *list)
 {
     bool ret = false;
+    hwc_layer_1_t *layer = &list->hwLayers[list->numHwLayers - 1];
     if (LIKELY(ctx->mOverlay)) {
         overlay::Overlay& ov = *(ctx->mOverlay);
         private_handle_t *hnd = (private_handle_t *)layer->handle;
@@ -87,7 +90,8 @@
                 ovutils::ROT_FLAGS_NONE);
         ov.setSource(parg, dest);
 
-        hwc_rect_t sourceCrop = layer->sourceCrop;
+        hwc_rect_t sourceCrop;
+        getNonWormholeRegion(list, sourceCrop);
         // x,y,w,h
         ovutils::Dim dcrop(sourceCrop.left, sourceCrop.top,
                 sourceCrop.right - sourceCrop.left,
@@ -99,7 +103,7 @@
                 static_cast<ovutils::eTransform>(transform);
         ov.setTransform(orient, dest);
 
-        hwc_rect_t displayFrame = layer->displayFrame;
+        hwc_rect_t displayFrame = sourceCrop;
         ovutils::Dim dpos(displayFrame.left,
                 displayFrame.top,
                 displayFrame.right - displayFrame.left,
@@ -118,7 +122,7 @@
     return ret;
 }
 
-bool FBUpdateLowRes::draw(hwc_context_t *ctx, hwc_layer_1_t *layer)
+bool FBUpdateLowRes::draw(hwc_context_t *ctx, private_handle_t *hnd)
 {
     if(!mModeOn) {
         return true;
@@ -126,7 +130,6 @@
     bool ret = true;
     overlay::Overlay& ov = *(ctx->mOverlay);
     ovutils::eDest dest = mDest;
-    private_handle_t *hnd = (private_handle_t *)layer->handle;
     if (!ov.queueBuffer(hnd->fd, hnd->offset, dest)) {
         ALOGE("%s: queueBuffer failed for FBUpdate", __FUNCTION__);
         ret = false;
@@ -143,21 +146,24 @@
     mDestRight = ovutils::OV_INVALID;
 }
 
-bool FBUpdateHighRes::prepare(hwc_context_t *ctx, hwc_layer_1_t *fblayer) {
+bool FBUpdateHighRes::prepare(hwc_context_t *ctx, hwc_display_contents_1 *list)
+{
     if(!ctx->mMDP.hasOverlay) {
         ALOGD_IF(DEBUG_FBUPDATE, "%s, this hw doesnt support overlays",
                 __FUNCTION__);
        return false;
     }
     ALOGD_IF(DEBUG_FBUPDATE, "%s, mModeOn = %d", __FUNCTION__, mModeOn);
-    mModeOn = configure(ctx, fblayer);
+    mModeOn = configure(ctx, list);
     return mModeOn;
 }
 
 // Configure
-bool FBUpdateHighRes::configure(hwc_context_t *ctx, hwc_layer_1_t *layer)
+bool FBUpdateHighRes::configure(hwc_context_t *ctx,
+                                hwc_display_contents_1 *list)
 {
     bool ret = false;
+    hwc_layer_1_t *layer = &list->hwLayers[list->numHwLayers - 1];
     if (LIKELY(ctx->mOverlay)) {
         overlay::Overlay& ov = *(ctx->mOverlay);
         private_handle_t *hnd = (private_handle_t *)layer->handle;
@@ -199,7 +205,8 @@
                 ovutils::ROT_FLAGS_NONE);
         ov.setSource(pargR, destR);
 
-        hwc_rect_t sourceCrop = layer->sourceCrop;
+        hwc_rect_t sourceCrop;
+        getNonWormholeRegion(list, sourceCrop);
         ovutils::Dim dcropL(sourceCrop.left, sourceCrop.top,
                 (sourceCrop.right - sourceCrop.left) / 2,
                 sourceCrop.bottom - sourceCrop.top);
@@ -217,7 +224,7 @@
         ov.setTransform(orient, destL);
         ov.setTransform(orient, destR);
 
-        hwc_rect_t displayFrame = layer->displayFrame;
+        hwc_rect_t displayFrame = sourceCrop;
         //For FB left, top will always be 0
         //That should also be the case if using 2 mixers for single display
         ovutils::Dim dpos(displayFrame.left,
@@ -240,7 +247,7 @@
     return ret;
 }
 
-bool FBUpdateHighRes::draw(hwc_context_t *ctx, hwc_layer_1_t *layer)
+bool FBUpdateHighRes::draw(hwc_context_t *ctx, private_handle_t *hnd)
 {
     if(!mModeOn) {
         return true;
@@ -249,7 +256,6 @@
     overlay::Overlay& ov = *(ctx->mOverlay);
     ovutils::eDest destL = mDestLeft;
     ovutils::eDest destR = mDestRight;
-    private_handle_t *hnd = (private_handle_t *)layer->handle;
     if (!ov.queueBuffer(hnd->fd, hnd->offset, destL)) {
         ALOGE("%s: queue failed for left of dpy = %d",
                 __FUNCTION__, mDpy);
diff --git a/libhwcomposer/hwc_fbupdate.h b/libhwcomposer/hwc_fbupdate.h
index a30a3af..5fc7708 100644
--- a/libhwcomposer/hwc_fbupdate.h
+++ b/libhwcomposer/hwc_fbupdate.h
@@ -34,9 +34,9 @@
     explicit IFBUpdate(const int& dpy) : mDpy(dpy) {}
     virtual ~IFBUpdate() {};
     // Sets up members and prepares overlay if conditions are met
-    virtual bool prepare(hwc_context_t *ctx, hwc_layer_1_t *fblayer) = 0;
+    virtual bool prepare(hwc_context_t *ctx, hwc_display_contents_1 *list) = 0;
     // Draws layer
-    virtual bool draw(hwc_context_t *ctx, hwc_layer_1_t *fblayer) = 0;
+    virtual bool draw(hwc_context_t *ctx, private_handle_t *hnd) = 0;
     //Reset values
     virtual void reset();
     //Factory method that returns a low-res or high-res version
@@ -52,11 +52,12 @@
 public:
     explicit FBUpdateLowRes(const int& dpy);
     virtual ~FBUpdateLowRes() {};
-    bool prepare(hwc_context_t *ctx, hwc_layer_1_t *fblayer);
-    bool draw(hwc_context_t *ctx, hwc_layer_1_t *fblayer);
+    bool prepare(hwc_context_t *ctx, hwc_display_contents_1 *list);
+
+    bool draw(hwc_context_t *ctx, private_handle_t *hnd);
     void reset();
 private:
-    bool configure(hwc_context_t *ctx, hwc_layer_1_t *fblayer);
+    bool configure(hwc_context_t *ctx, hwc_display_contents_1 *list);
     ovutils::eDest mDest; //pipe to draw on
 };
 
@@ -65,11 +66,11 @@
 public:
     explicit FBUpdateHighRes(const int& dpy);
     virtual ~FBUpdateHighRes() {};
-    bool prepare(hwc_context_t *ctx, hwc_layer_1_t *fblayer);
-    bool draw(hwc_context_t *ctx, hwc_layer_1_t *fblayer);
+    bool prepare(hwc_context_t *ctx, hwc_display_contents_1 *list);
+    bool draw(hwc_context_t *ctx, private_handle_t *hnd);
     void reset();
 private:
-    bool configure(hwc_context_t *ctx, hwc_layer_1_t *fblayer);
+    bool configure(hwc_context_t *ctx, hwc_display_contents_1 *list);
     ovutils::eDest mDestLeft; //left pipe to draw on
     ovutils::eDest mDestRight; //right pipe to draw on
 };
diff --git a/libhwcomposer/hwc_qclient.cpp b/libhwcomposer/hwc_qclient.cpp
index ee31e6c..c130208 100644
--- a/libhwcomposer/hwc_qclient.cpp
+++ b/libhwcomposer/hwc_qclient.cpp
@@ -54,7 +54,7 @@
     ALOGD_IF(QCLIENT_DEBUG,"QClient Destructor invoked");
 }
 
-void QClient::notifyCallback(uint32_t msg, uint32_t value) {
+status_t QClient::notifyCallback(uint32_t msg, uint32_t value) {
     switch(msg) {
         case IQService::SECURING:
             securing(value);
@@ -62,9 +62,13 @@
         case IQService::UNSECURING:
             unsecuring(value);
             break;
+        case IQService::SCREEN_REFRESH:
+            return screenRefresh();
+            break;
         default:
-            return;
+            return NO_ERROR;
     }
+    return NO_ERROR;
 }
 
 void QClient::securing(uint32_t startEnd) {
@@ -93,4 +97,14 @@
         mHwcContext->proc->invalidate(mHwcContext->proc);
 }
 
+android::status_t QClient::screenRefresh() {
+    status_t result = NO_INIT;
+#ifdef QCOM_BSP
+    if(mHwcContext->proc) {
+        mHwcContext->proc->invalidate(mHwcContext->proc);
+        result = NO_ERROR;
+    }
+#endif
+    return result;
+}
 }
diff --git a/libhwcomposer/hwc_qclient.h b/libhwcomposer/hwc_qclient.h
index 0ee6de1..9cb2680 100644
--- a/libhwcomposer/hwc_qclient.h
+++ b/libhwcomposer/hwc_qclient.h
@@ -46,7 +46,7 @@
 public:
     QClient(hwc_context_t *ctx);
     virtual ~QClient();
-    virtual void notifyCallback(uint32_t msg, uint32_t value);
+    virtual android::status_t notifyCallback(uint32_t msg, uint32_t value);
 
 private:
     //Notifies of Media Player death
@@ -59,6 +59,7 @@
 
     void securing(uint32_t startEnd);
     void unsecuring(uint32_t startEnd);
+    android::status_t screenRefresh();
 
     hwc_context_t *mHwcContext;
     const android::sp<android::IMediaDeathNotifier> mMPDeathNotifier;
diff --git a/libhwcomposer/hwc_utils.cpp b/libhwcomposer/hwc_utils.cpp
index 82ab25c..5193644 100644
--- a/libhwcomposer/hwc_utils.cpp
+++ b/libhwcomposer/hwc_utils.cpp
@@ -364,6 +364,33 @@
     crop_b -= crop_h * bottomCutRatio;
 }
 
+void getNonWormholeRegion(hwc_display_contents_1_t* list,
+                              hwc_rect_t& nwr)
+{
+    uint32_t last = list->numHwLayers - 1;
+    hwc_rect_t fbDisplayFrame = list->hwLayers[last].displayFrame;
+    //Initiliaze nwr to first frame
+    nwr.left =  list->hwLayers[0].displayFrame.left;
+    nwr.top =  list->hwLayers[0].displayFrame.top;
+    nwr.right =  list->hwLayers[0].displayFrame.right;
+    nwr.bottom =  list->hwLayers[0].displayFrame.bottom;
+
+    for (uint32_t i = 1; i < last; i++) {
+        hwc_rect_t displayFrame = list->hwLayers[i].displayFrame;
+        nwr.left   = min(nwr.left, displayFrame.left);
+        nwr.top    = min(nwr.top, displayFrame.top);
+        nwr.right  = max(nwr.right, displayFrame.right);
+        nwr.bottom = max(nwr.bottom, displayFrame.bottom);
+    }
+
+    //Intersect with the framebuffer
+    nwr.left   = max(nwr.left, fbDisplayFrame.left);
+    nwr.top    = max(nwr.top, fbDisplayFrame.top);
+    nwr.right  = min(nwr.right, fbDisplayFrame.right);
+    nwr.bottom = min(nwr.bottom, fbDisplayFrame.bottom);
+
+}
+
 bool isExternalActive(hwc_context_t* ctx) {
     return ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].isActive;
 }
@@ -452,6 +479,8 @@
         fd = -1;
     }
 
+    if (ctx->mCopyBit[dpy])
+        ctx->mCopyBit[dpy]->setReleaseFd(releaseFd);
     if(UNLIKELY(swapzero)){
         list->retireFenceFd = -1;
         close(releaseFd);
diff --git a/libhwcomposer/hwc_utils.h b/libhwcomposer/hwc_utils.h
index 671fbba..187c43a 100644
--- a/libhwcomposer/hwc_utils.h
+++ b/libhwcomposer/hwc_utils.h
@@ -56,6 +56,7 @@
 class MDPComp;
 class CopyBit;
 
+
 struct MDPInfo {
     int version;
     char panel;
@@ -97,6 +98,7 @@
 // LayerProp::flag values
 enum {
     HWC_MDPCOMP = 0x00000001,
+    HWC_COPYBIT = 0x00000002,
 };
 
 class LayerCache {
@@ -132,6 +134,8 @@
 //Crops source buffer against destination and FB boundaries
 void calculate_crop_rects(hwc_rect_t& crop, hwc_rect_t& dst,
                          const hwc_rect_t& scissor, int orient);
+void getNonWormholeRegion(hwc_display_contents_1_t* list,
+                              hwc_rect_t& nwr);
 bool isSecuring(hwc_context_t* ctx);
 bool isSecureModePolicy(int mdpVersion);
 bool isExternalActive(hwc_context_t* ctx);
@@ -185,6 +189,9 @@
     return (hnd && (hnd->flags & private_handle_t::PRIV_FLAGS_EXTERNAL_CC));
 }
 
+template<typename T> inline T max(T a, T b) { return (a > b) ? a : b; }
+template<typename T> inline T min(T a, T b) { return (a < b) ? a : b; }
+
 // Initialize uevent thread
 void init_uevent_thread(hwc_context_t* ctx);
 // Initialize vsync thread
diff --git a/libqservice/IQClient.cpp b/libqservice/IQClient.cpp
index 4ff67dc..30fbb64 100644
--- a/libqservice/IQClient.cpp
+++ b/libqservice/IQClient.cpp
@@ -41,12 +41,14 @@
     BpQClient(const sp<IBinder>& impl)
         : BpInterface<IQClient>(impl) {}
 
-    virtual void notifyCallback(uint32_t msg, uint32_t value) {
+    virtual status_t notifyCallback(uint32_t msg, uint32_t value) {
         Parcel data, reply;
         data.writeInterfaceToken(IQClient::getInterfaceDescriptor());
         data.writeInt32(msg);
         data.writeInt32(value);
         remote()->transact(NOTIFY_CALLBACK, data, &reply);
+        status_t result = reply.readInt32();
+        return result;
     }
 };
 
diff --git a/libqservice/IQClient.h b/libqservice/IQClient.h
index 68d8275..a28f826 100644
--- a/libqservice/IQClient.h
+++ b/libqservice/IQClient.h
@@ -33,7 +33,7 @@
 {
 public:
     DECLARE_META_INTERFACE(QClient);
-    virtual void notifyCallback(uint32_t msg, uint32_t value) = 0;
+    virtual android::status_t notifyCallback(uint32_t msg, uint32_t value) = 0;
 };
 
 // ----------------------------------------------------------------------------
diff --git a/libqservice/IQService.cpp b/libqservice/IQService.cpp
index 7a88bdf..6c6f7b6 100644
--- a/libqservice/IQService.cpp
+++ b/libqservice/IQService.cpp
@@ -63,6 +63,14 @@
         data.writeStrongBinder(client->asBinder());
         remote()->transact(CONNECT, data, &reply);
     }
+
+    virtual status_t screenRefresh() {
+        Parcel data, reply;
+        data.writeInterfaceToken(IQService::getInterfaceDescriptor());
+        remote()->transact(SCREEN_REFRESH, data, &reply);
+        status_t result = reply.readInt32();
+        return result;
+    }
 };
 
 IMPLEMENT_META_INTERFACE(QService, "android.display.IQService");
@@ -88,7 +96,8 @@
     switch(code) {
         case SECURING: {
             if(!permission) {
-                ALOGE("display.qservice SECURING access denied: pid=%d uid=%d process=%s",
+                ALOGE("display.qservice SECURING access denied: \
+                      pid=%d uid=%d process=%s",
                       callerPid, callerUid, callingProcName);
                 return PERMISSION_DENIED;
             }
@@ -99,7 +108,8 @@
         } break;
         case UNSECURING: {
             if(!permission) {
-                ALOGE("display.qservice UNSECURING access denied: pid=%d uid=%d process=%s",
+                ALOGE("display.qservice UNSECURING access denied: \
+                      pid=%d uid=%d process=%s",
                       callerPid, callerUid, callingProcName);
                 return PERMISSION_DENIED;
             }
@@ -111,7 +121,8 @@
         case CONNECT: {
             CHECK_INTERFACE(IQService, data, reply);
             if(callerUid != AID_GRAPHICS) {
-                ALOGE("display.qservice CONNECT access denied: pid=%d uid=%d process=%s",
+                ALOGE("display.qservice CONNECT access denied: \
+                      pid=%d uid=%d process=%s",
                       callerPid, callerUid, callingProcName);
                 return PERMISSION_DENIED;
             }
@@ -120,6 +131,16 @@
             connect(client);
             return NO_ERROR;
         } break;
+        case SCREEN_REFRESH: {
+            CHECK_INTERFACE(IQService, data, reply);
+            if(callerUid != AID_GRAPHICS) {
+                ALOGE("display.qservice SCREEN_REFRESH access denied: \
+                      pid=%d uid=%d process=%s",callerPid,
+                      callerUid, callingProcName);
+                return PERMISSION_DENIED;
+            }
+            return screenRefresh();
+        } break;
         default:
             return BBinder::onTransact(code, data, reply, flags);
     }
diff --git a/libqservice/IQService.h b/libqservice/IQService.h
index 70e6c64..79e831d 100644
--- a/libqservice/IQService.h
+++ b/libqservice/IQService.h
@@ -40,6 +40,7 @@
         SECURING = android::IBinder::FIRST_CALL_TRANSACTION,
         UNSECURING, // Hardware unsecuring start/end notification
         CONNECT,
+        SCREEN_REFRESH,
     };
     enum {
         END = 0,
@@ -48,6 +49,7 @@
     virtual void securing(uint32_t startEnd) = 0;
     virtual void unsecuring(uint32_t startEnd) = 0;
     virtual void connect(const android::sp<qClient::IQClient>& client) = 0;
+    virtual android::status_t screenRefresh() = 0;
 };
 
 // ----------------------------------------------------------------------------
diff --git a/libqservice/QService.cpp b/libqservice/QService.cpp
index 8fc7319..54e285c 100644
--- a/libqservice/QService.cpp
+++ b/libqservice/QService.cpp
@@ -63,6 +63,14 @@
     mClient = client;
 }
 
+android::status_t QService::screenRefresh() {
+    status_t result = NO_ERROR;
+    if(mClient.get()) {
+        result = mClient->notifyCallback(SCREEN_REFRESH, 0);
+    }
+    return result;
+}
+
 void QService::init()
 {
     if(!sQService) {
diff --git a/libqservice/QService.h b/libqservice/QService.h
index 4f7e570..268bf81 100644
--- a/libqservice/QService.h
+++ b/libqservice/QService.h
@@ -48,6 +48,7 @@
     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();
     static void init();
 private:
     QService();