hwc: Add support for copybit(C2D) composition

- Add CopybitEngine to hwc_context
- draw the layer on the HWC_FRAMEBUFFER_TARGET using
  copybit(c2d) if it qualifies for C2D composition.
- use fence returned from the copybit during c2d
  composition

Change-Id: I052da015cd031f7abd6411d83d7944c335caeff7
diff --git a/libgralloc/Android.mk b/libgralloc/Android.mk
index 159a252..f4e3834 100644
--- a/libgralloc/Android.mk
+++ b/libgralloc/Android.mk
@@ -35,7 +35,7 @@
 LOCAL_MODULE                  := libmemalloc
 LOCAL_MODULE_TAGS             := optional
 LOCAL_C_INCLUDES              := $(common_includes) $(kernel_includes)
-LOCAL_SHARED_LIBRARIES        := $(common_libs) libgenlock
+LOCAL_SHARED_LIBRARIES        := $(common_libs) libgenlock libqdutils
 LOCAL_CFLAGS                  := $(common_flags) -DLOG_TAG=\"qdmemalloc\"
 LOCAL_ADDITIONAL_DEPENDENCIES := $(common_deps) $(kernel_deps)
 LOCAL_SRC_FILES               :=  ionalloc.cpp alloc_controller.cpp
diff --git a/libhwcomposer/Android.mk b/libhwcomposer/Android.mk
index 543efd9..a9ada35 100644
--- a/libhwcomposer/Android.mk
+++ b/libhwcomposer/Android.mk
@@ -8,7 +8,7 @@
 LOCAL_C_INCLUDES              := $(common_includes) $(kernel_includes)
 LOCAL_SHARED_LIBRARIES        := $(common_libs) libEGL liboverlay libgenlock \
                                  libexternal libqdutils libhardware_legacy \
-                                 libdl libmemalloc libqservice
+                                 libdl libmemalloc libqservice libsync
 LOCAL_CFLAGS                  := $(common_flags) -DLOG_TAG=\"qdhwcomposer\"
 LOCAL_ADDITIONAL_DEPENDENCIES := $(common_deps)
 LOCAL_SRC_FILES               := hwc.cpp          \
@@ -17,6 +17,7 @@
                                  hwc_uevents.cpp  \
                                  hwc_vsync.cpp    \
                                  hwc_fbupdate.cpp \
-                                 hwc_mdpcomp.cpp
+                                 hwc_mdpcomp.cpp  \
+                                 hwc_copybit.cpp
 
 include $(BUILD_SHARED_LIBRARY)
diff --git a/libhwcomposer/hwc.cpp b/libhwcomposer/hwc.cpp
index ac1be19..ba84580 100644
--- a/libhwcomposer/hwc.cpp
+++ b/libhwcomposer/hwc.cpp
@@ -2,6 +2,9 @@
  * 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.
+ *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
@@ -30,6 +33,7 @@
 #include "hwc_fbupdate.h"
 #include "hwc_mdpcomp.h"
 #include "external.h"
+#include "hwc_copybit.h"
 
 using namespace qhwc;
 #define VSYNC_DEBUG 0
@@ -96,6 +100,9 @@
 
         if(ctx->mFBUpdate[i])
             ctx->mFBUpdate[i]->reset();
+
+        if(ctx->mCopyBit[i])
+            ctx->mCopyBit[i]->reset();
     }
     VideoOverlay::reset();
 }
@@ -127,11 +134,16 @@
         if(fbLayer->handle) {
             setListStats(ctx, list, dpy);
             reset_layer_prop(ctx, dpy);
-            if(!ctx->mMDPComp->prepare(ctx, list)) {
+            int ret = ctx->mMDPComp->prepare(ctx, list);
+            if(!ret) {
+                // IF MDPcomp fails use this route
                 VideoOverlay::prepare(ctx, list, dpy);
                 ctx->mFBUpdate[dpy]->prepare(ctx, fbLayer);
             }
             ctx->mLayerCache[dpy]->updateLayerCache(list);
+            // Use Copybit, when MDP comp fails
+            if(!ret && ctx->mCopyBit[dpy])
+                ctx->mCopyBit[dpy]->prepare(ctx, list, dpy);
         }
     }
     return 0;
@@ -154,6 +166,8 @@
             VideoOverlay::prepare(ctx, list, dpy);
             ctx->mFBUpdate[dpy]->prepare(ctx, fbLayer);
             ctx->mLayerCache[dpy]->updateLayerCache(list);
+            if(ctx->mCopyBit[dpy])
+                ctx->mCopyBit[dpy]->prepare(ctx, list, dpy);
             ctx->mExtDispConfiguring = false;
         }
     }
@@ -296,8 +310,10 @@
         ctx->dpyAttr[dpy].isActive) {
         uint32_t last = list->numHwLayers - 1;
         hwc_layer_1_t *fbLayer = &list->hwLayers[last];
-
-        hwc_sync(ctx, list, dpy);
+        int fd = -1; //FenceFD from the Copybit(valid in async mode)
+        if(ctx->mCopyBit[dpy])
+            ctx->mCopyBit[dpy]->draw(ctx, list, dpy, &fd);
+        hwc_sync(ctx, list, dpy, fd);
         if (!VideoOverlay::draw(ctx, list, dpy)) {
             ALOGE("%s: VideoOverlay::draw fail!", __FUNCTION__);
             ret = -1;
@@ -338,8 +354,11 @@
         ctx->dpyAttr[dpy].connected) {
         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)
+        if(ctx->mCopyBit[dpy])
+            ctx->mCopyBit[dpy]->draw(ctx, list, dpy, &fd);
 
-        hwc_sync(ctx, list, dpy);
+        hwc_sync(ctx, list, dpy, fd);
 
         if (!VideoOverlay::draw(ctx, list, dpy)) {
             ALOGE("%s: VideoOverlay::draw fail!", __FUNCTION__);
@@ -369,7 +388,6 @@
     int ret = 0;
     hwc_context_t* ctx = (hwc_context_t*)(dev);
     Locker::Autolock _l(ctx->mBlankLock);
-
     for (uint32_t i = 0; i < numDisplays; i++) {
         hwc_display_contents_1_t* list = displays[i];
         switch(i) {
diff --git a/libhwcomposer/hwc_copybit.cpp b/libhwcomposer/hwc_copybit.cpp
index 1249e84..e764c69 100644
--- a/libhwcomposer/hwc_copybit.cpp
+++ b/libhwcomposer/hwc_copybit.cpp
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2010 The Android Open Source Project
- * Copyright (C) 2012, Code Aurora Forum. All rights reserved.
+ * Copyright (C) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * Not a Contribution, Apache license notifications and license are retained
  * for attribution purposes only.
@@ -20,14 +20,12 @@
 
 #define DEBUG_COPYBIT 0
 #include <copybit.h>
-#include <genlock.h>
-#include "hwc_copybit.h"
+#include <utils/Timers.h>
 #include "hwc_copybit.h"
 #include "comptype.h"
 
 namespace qhwc {
 
-
 struct range {
     int current;
     int end;
@@ -65,44 +63,9 @@
     mutable range r;
 };
 
-// Initialize CopyBit Class Static Mmembers.
-functype_eglGetRenderBufferANDROID CopyBit::LINK_eglGetRenderBufferANDROID
-                                                                   = NULL;
-functype_eglGetCurrentSurface CopyBit::LINK_eglGetCurrentSurface = NULL;
-int CopyBit::sYuvCount = 0;
-int CopyBit::sYuvLayerIndex = -1;
-bool CopyBit::sIsModeOn = false;
-bool CopyBit::sIsLayerSkip = false;
-void* CopyBit::egl_lib = NULL;
-
-void CopyBit::openEglLibAndGethandle()
-{
-    egl_lib = ::dlopen("libEGL_adreno200.so", RTLD_GLOBAL | RTLD_LAZY);
-    if (!egl_lib) {
-        return;
-    }
-    updateEglHandles(egl_lib);
-}
-void CopyBit::closeEglLib()
-{
-    if(egl_lib)
-        ::dlclose(egl_lib);
-
-    egl_lib = NULL;
-    updateEglHandles(NULL);
-}
-
-void CopyBit::updateEglHandles(void* egl_lib)
-{
-    if(egl_lib != NULL) {
-        *(void **)&CopyBit::LINK_eglGetRenderBufferANDROID =
-                             ::dlsym(egl_lib, "eglGetRenderBufferANDROID");
-        *(void **)&CopyBit::LINK_eglGetCurrentSurface =
-                                  ::dlsym(egl_lib, "eglGetCurrentSurface");
-   }else {
-        LINK_eglGetCurrentSurface = NULL;
-        LINK_eglGetCurrentSurface = NULL;
-   }
+void CopyBit::reset() {
+    mIsModeOn = false;
+    mCopyBitDraw = false;
 }
 
 bool CopyBit::canUseCopybitForYUV(hwc_context_t *ctx) {
@@ -113,15 +76,16 @@
     return true;
 }
 
-bool CopyBit::canUseCopybitForRGB(hwc_context_t *ctx, hwc_display_contents_1_t *list) {
-    int compositionType =
-        qdutils::QCCompositionType::getInstance().getCompositionType();
+bool CopyBit::canUseCopybitForRGB(hwc_context_t *ctx,
+                                        hwc_display_contents_1_t *list,
+                                        int dpy) {
+    int compositionType = qdutils::QCCompositionType::
+                                    getInstance().getCompositionType();
 
     if ((compositionType & qdutils::COMPOSITION_TYPE_C2D) ||
         (compositionType & qdutils::COMPOSITION_TYPE_DYN)) {
-         if (sYuvCount) {
+         if(ctx->listStats[dpy].yuvCount) {
              //Overlay up & running. Dont use COPYBIT for RGB layers.
-             // TODO need to implement blending with C2D
              return false;
          }
     }
@@ -131,17 +95,13 @@
         // use copybit, if (TotalRGBRenderArea < 2 * FB Area)
         // this is done based on perf inputs in ICS
         // TODO: Above condition needs to be re-evaluated in JB
-
-        framebuffer_device_t *fbDev = ctx->mFbDev;
-        if (!fbDev) {
-            ALOGE("%s:Invalid FB device", __FUNCTION__);
-            return false;
-        }
-        unsigned int fbArea = (fbDev->width * fbDev->height);
+        int fbWidth =  ctx->dpyAttr[dpy].xres;
+        int fbHeight =  ctx->dpyAttr[dpy].yres;
+        unsigned int fbArea = (fbWidth * fbHeight);
         unsigned int renderArea = getRGBRenderingArea(list);
             ALOGD_IF (DEBUG_COPYBIT, "%s:renderArea %u, fbArea %u",
                                   __FUNCTION__, renderArea, fbArea);
-        if (renderArea < (2 * fbArea)) {
+        if (renderArea <= (2 * fbArea)) {
             return true;
         }
     } else if ((compositionType & qdutils::COMPOSITION_TYPE_MDP)) {
@@ -154,7 +114,8 @@
     return false;
 }
 
-unsigned int CopyBit::getRGBRenderingArea(const hwc_display_contents_1_t *list) {
+unsigned int CopyBit::getRGBRenderingArea
+                                    (const hwc_display_contents_1_t *list) {
     //Calculates total rendering area for RGB layers
     unsigned int renderArea = 0;
     unsigned int w=0, h=0;
@@ -170,71 +131,116 @@
     return renderArea;
 }
 
-bool CopyBit::prepare(hwc_context_t *ctx, hwc_display_contents_1_t *list) {
+bool CopyBit::prepare(hwc_context_t *ctx, hwc_display_contents_1_t *list,
+                                                            int dpy) {
 
-    int compositionType =
-        qdutils::QCCompositionType::getInstance().getCompositionType();
+    if(mEngine == NULL) {
+        // No copybit device found - cannot use copybit
+        return false;
+    }
+    int compositionType = qdutils::QCCompositionType::
+                                    getInstance().getCompositionType();
 
-    if ((compositionType & qdutils::COMPOSITION_TYPE_GPU) ||
-        (compositionType & qdutils::COMPOSITION_TYPE_CPU))   {
+    if ((compositionType == qdutils::COMPOSITION_TYPE_GPU) ||
+        (compositionType == qdutils::COMPOSITION_TYPE_CPU))   {
         //GPU/CPU composition, don't change layer composition type
         return true;
     }
 
-    bool useCopybitForYUV = canUseCopybitForYUV(ctx);
-    bool useCopybitForRGB = canUseCopybitForRGB(ctx, list);
-
     if(!(validateParams(ctx, list))) {
-       ALOGE("%s:Invalid Params", __FUNCTION__);
-       return false;
+        ALOGE("%s:Invalid Params", __FUNCTION__);
+        return false;
     }
 
-    for (int i=list->numHwLayers-1; i >= 0 ; i--) {
+    if(ctx->listStats[dpy].skipCount) {
+        //GPU will be anyways used
+        return false;
+    }
+
+    bool useCopybitForYUV = canUseCopybitForYUV(ctx);
+    bool useCopybitForRGB = canUseCopybitForRGB(ctx, list, dpy);
+
+    // 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 (isSkipLayer(&list->hwLayers[i])) {
-            return true;
-        } else if (hnd->bufferType == BUFFER_TYPE_VIDEO) {
-          //YUV layer, check, if copybit can be used
-          if (useCopybitForYUV) {
-              list->hwLayers[i].compositionType = HWC_USE_COPYBIT;
-          }
-       } else if (hnd->bufferType == BUFFER_TYPE_UI) {
-          //RGB layer, check, if copybit can be used
-          if (useCopybitForRGB) {
-              list->hwLayers[i].compositionType = HWC_USE_COPYBIT;
-          }
-       }
-    }
-    return true;
-}
-
-bool CopyBit::draw(hwc_context_t *ctx, hwc_display_contents_1_t *list, EGLDisplay dpy,
-                                                               EGLSurface sur){
-    // draw layers marked for COPYBIT
-    int retVal = true;
-    for (size_t i=0; i<list->numHwLayers; i++) {
-        if (list->hwLayers[i].compositionType == HWC_USE_COPYBIT) {
-            retVal = drawLayerUsingCopybit(ctx, &(list->hwLayers[i]),
-                                                     (EGLDisplay)dpy,
-                                                     (EGLSurface)sur,
-                                      LINK_eglGetRenderBufferANDROID,
-                                          LINK_eglGetCurrentSurface);
-           if(retVal<0) {
-              ALOGE("%s : drawLayerUsingCopybit failed", __FUNCTION__);
-           }
+        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;
+            }
         }
     }
     return true;
 }
 
+bool CopyBit::draw(hwc_context_t *ctx, hwc_display_contents_1_t *list,
+                                                        int dpy, int32_t *fd) {
+    // draw layers marked for COPYBIT
+    int retVal = true;
+    int copybitLayerCount = 0;
+
+    if(mCopyBitDraw == false) // there is no layer marked for copybit
+        return true ;
+
+    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;
+    if (!renderBuffer) {
+        ALOGE("%s: HWC_FRAMEBUFFER_TARGET layer handle is NULL", __FUNCTION__);
+        return false;
+    }
+    // numAppLayers-1, as we iterate from 0th layer index with HWC_BLIT 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__);
+            continue;
+        }
+        int ret = -1;
+        if (list->hwLayers[i].acquireFenceFd != -1 ) {
+            // Wait for acquire Fence on the App buffers.
+            ret = sync_wait(list->hwLayers[i].acquireFenceFd, 1000);
+            if(ret < 0) {
+                ALOGE("%s: sync_wait error!! error no = %d err str = %s",
+                                    __FUNCTION__, errno, strerror(errno));
+            }
+            close(list->hwLayers[i].acquireFenceFd);
+            list->hwLayers[i].acquireFenceFd = -1;
+        }
+        retVal = drawLayerUsingCopybit(ctx, &(list->hwLayers[i]),
+                                                    renderBuffer, dpy);
+        copybitLayerCount++;
+        if(retVal < 0) {
+            ALOGE("%s : drawLayerUsingCopybit failed", __FUNCTION__);
+        }
+    }
+
+    if (copybitLayerCount) {
+        copybit_device_t *copybit = getCopyBitDevice();
+        // Async mode
+        copybit->flush_get_fence(copybit, fd);
+    }
+    return true;
+}
+
 int  CopyBit::drawLayerUsingCopybit(hwc_context_t *dev, hwc_layer_1_t *layer,
-                                                            EGLDisplay dpy,
-                                                        EGLSurface surface,
-        functype_eglGetRenderBufferANDROID& LINK_eglGetRenderBufferANDROID,
-                    functype_eglGetCurrentSurface LINK_eglGetCurrentSurface)
+                                     private_handle_t *renderBuffer, int dpy)
 {
     hwc_context_t* ctx = (hwc_context_t*)(dev);
+    int err = 0;
     if(!ctx) {
          ALOGE("%s: null context ", __FUNCTION__);
          return -1;
@@ -246,26 +252,9 @@
         return -1;
     }
 
-    // Lock this buffer for read.
-    genlock_lock_type lockType = GENLOCK_READ_LOCK;
-    int err = genlock_lock_buffer(hnd, lockType, GENLOCK_MAX_TIMEOUT);
-    if (GENLOCK_FAILURE == err) {
-        ALOGE("%s: genlock_lock_buffer(READ) failed", __FUNCTION__);
-        return -1;
-    }
-    //render buffer
-    EGLSurface eglSurface = LINK_eglGetCurrentSurface(EGL_DRAW);
-    android_native_buffer_t *renderBuffer =
-     (android_native_buffer_t *)LINK_eglGetRenderBufferANDROID(dpy, eglSurface);
-    if (!renderBuffer) {
-        ALOGE("%s: eglGetRenderBuffer returned NULL buffer", __FUNCTION__);
-        genlock_unlock_buffer(hnd);
-        return -1;
-    }
-    private_handle_t *fbHandle = (private_handle_t *)renderBuffer->handle;
+    private_handle_t *fbHandle = (private_handle_t *)renderBuffer;
     if(!fbHandle) {
         ALOGE("%s: Framebuffer handle is NULL", __FUNCTION__);
-        genlock_unlock_buffer(hnd);
         return -1;
     }
 
@@ -281,8 +270,6 @@
     // this needs to change to accomodate vertical stride
     // if needed in the future
     src.vert_padding = 0;
-    // Remove the srcBufferTransform if any
-    layer->transform = (layer->transform & FINAL_TRANSFORM_MASK);
 
     // Copybit source rect
     hwc_rect_t sourceCrop = layer->sourceCrop;
@@ -302,9 +289,9 @@
     dst.h = fbHandle->height;
     dst.format = fbHandle->format;
     dst.base = (void *)fbHandle->base;
-    dst.handle = (native_handle_t *)renderBuffer->handle;
+    dst.handle = (native_handle_t *)fbHandle;
 
-    copybit_device_t *copybit = ctx->mCopybitEngine->getEngine();
+    copybit_device_t *copybit = mEngine;
 
     int32_t screen_w        = displayFrame.right - displayFrame.left;
     int32_t screen_h        = displayFrame.bottom - displayFrame.top;
@@ -330,7 +317,6 @@
         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);
-        genlock_unlock_buffer(hnd);
         return -1;
     }
 
@@ -346,7 +332,6 @@
         ALOGE("%s: greater than max supported size dsdx=%f dtdy=%f \
               scaleLimitMax=%f scaleLimitMin=%f", __FUNCTION__,dsdx,dtdy,
                                           scaleLimitMax,1/scaleLimitMin);
-        genlock_unlock_buffer(hnd);
         return -1;
     }
     if(dsdx > copybitsMaxScale ||
@@ -411,7 +396,6 @@
                                                              __LINE__);
                 if(tmpHnd)
                     free_buffer(tmpHnd);
-                genlock_unlock_buffer(hnd);
                 return err;
             }
             // copy new src and src rect crop
@@ -431,9 +415,8 @@
                                               layer->transform);
     //TODO: once, we are able to read layer alpha, update this
     copybit->set_parameter(copybit, COPYBIT_PLANE_ALPHA, 255);
-    copybit->set_parameter(copybit, COPYBIT_PREMULTIPLIED_ALPHA,
-                      (layer->blending == HWC_BLENDING_PREMULT)?
-                                             COPYBIT_ENABLE : COPYBIT_DISABLE);
+    copybit->set_parameter(copybit, COPYBIT_BLEND_MODE,
+                                              layer->blending);
     copybit->set_parameter(copybit, COPYBIT_DITHER,
                              (dst.format == HAL_PIXEL_FORMAT_RGB_565)?
                                              COPYBIT_ENABLE : COPYBIT_DISABLE);
@@ -449,13 +432,6 @@
 
     if(err < 0)
         ALOGE("%s: copybit stretch failed",__FUNCTION__);
-
-    // Unlock this buffer since copybit is done with it.
-    err = genlock_unlock_buffer(hnd);
-    if (GENLOCK_FAILURE == err) {
-        ALOGE("%s: genlock_unlock_buffer failed", __FUNCTION__);
-    }
-
     return err;
 }
 
@@ -468,62 +444,41 @@
     height = displayFrame.bottom - displayFrame.top;
 }
 
-bool CopyBit::validateParams(hwc_context_t *ctx, const hwc_display_contents_1_t *list) {
-   //Validate parameters
-   if (!ctx) {
-       ALOGE("%s:Invalid HWC context", __FUNCTION__);
-       return false;
-   } else if (!list) {
-       ALOGE("%s:Invalid HWC layer list", __FUNCTION__);
-       return false;
-   }
-
-   framebuffer_device_t *fbDev = ctx->mFbDev;
-
-   if (!fbDev) {
-       ALOGE("%s:Invalid FB device", __FUNCTION__);
-       return false;
-   }
-
-   if (LINK_eglGetRenderBufferANDROID == NULL ||
-            LINK_eglGetCurrentSurface == NULL) {
-       ALOGE("%s:Not able to link to ADRENO", __FUNCTION__);
-       return false;
-   }
-
-   return true;
+bool CopyBit::validateParams(hwc_context_t *ctx,
+                                        const hwc_display_contents_1_t *list) {
+    //Validate parameters
+    if (!ctx) {
+        ALOGE("%s:Invalid HWC context", __FUNCTION__);
+        return false;
+    } else if (!list) {
+        ALOGE("%s:Invalid HWC layer list", __FUNCTION__);
+        return false;
+    }
+    return true;
 }
 
-//CopybitEngine Class functions
-CopybitEngine* CopybitEngine::sInstance = 0;
 
-struct copybit_device_t* CopybitEngine::getEngine() {
-   return sEngine;
-}
-CopybitEngine* CopybitEngine::getInstance() {
-   if(sInstance == NULL)
-       sInstance = new CopybitEngine();
-   return sInstance;
+struct copybit_device_t* CopyBit::getCopyBitDevice() {
+    return mEngine;
 }
 
-CopybitEngine::CopybitEngine(){
+CopyBit::CopyBit():mIsModeOn(false), mCopyBitDraw(false){
     hw_module_t const *module;
     if (hw_get_module(COPYBIT_HARDWARE_MODULE_ID, &module) == 0) {
-        copybit_open(module, &sEngine);
-        CopyBit::openEglLibAndGethandle();
+        if(copybit_open(module, &mEngine) < 0) {
+            ALOGE("FATAL ERROR: copybit open failed.");
+        }
     } else {
-       ALOGE("FATAL ERROR: copybit open failed.");
+        ALOGE("FATAL ERROR: copybit hw module not found");
     }
 }
 
-CopybitEngine::~CopybitEngine()
+CopyBit::~CopyBit()
 {
-    if(sEngine)
+    if(mEngine)
     {
-        CopyBit::closeEglLib();
-        copybit_close(sEngine);
-        sEngine = NULL;
+        copybit_close(mEngine);
+        mEngine = NULL;
     }
 }
-
 }; //namespace qhwc
diff --git a/libhwcomposer/hwc_copybit.h b/libhwcomposer/hwc_copybit.h
index ae82b6c..015d85a 100644
--- a/libhwcomposer/hwc_copybit.h
+++ b/libhwcomposer/hwc_copybit.h
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2010 The Android Open Source Project
- * Copyright (C) 2012, Code Aurora Forum. All rights reserved.
+ * Copyright (C) 2012-2013, The Linux Foundation. All rights reserved.
  *
  * Not a Contribution, Apache license notifications and license are retained
  * for attribution purposes only.
@@ -20,94 +20,49 @@
 #ifndef HWC_COPYBIT_H
 #define HWC_COPYBIT_H
 #include "hwc_utils.h"
-#include <EGL/egl.h>
-#include <EGL/eglext.h>
-#include <gralloc_priv.h>
-#include <gr.h>
-#include <dlfcn.h>
 
 #define LIKELY( exp )       (__builtin_expect( (exp) != 0, true  ))
 #define UNLIKELY( exp )     (__builtin_expect( (exp) != 0, false ))
 
 namespace qhwc {
-//Feature for using Copybit to display RGB layers.
-typedef EGLClientBuffer (*functype_eglGetRenderBufferANDROID) (
-                                              EGLDisplay dpy,
-                                              EGLSurface draw);
-typedef EGLSurface (*functype_eglGetCurrentSurface)(EGLint readdraw);
 
 class CopyBit {
 public:
+    CopyBit();
+    ~CopyBit();
+    // API to get copybit engine(non static)
+    struct copybit_device_t *getCopyBitDevice();
     //Sets up members and prepares copybit if conditions are met
-    static bool prepare(hwc_context_t *ctx, hwc_display_contents_1_t *list);
+    bool prepare(hwc_context_t *ctx, hwc_display_contents_1_t *list,
+                                                                   int dpy);
     //Draws layer if the layer is set for copybit in prepare
-    static bool draw(hwc_context_t *ctx, hwc_display_contents_1_t *list, EGLDisplay dpy,
-                                                                EGLSurface sur);
-    //Receives data from hwc
-    static void setStats(int yuvCount, int yuvLayerIndex, bool isYuvLayerSkip);
-
-    static void updateEglHandles(void*);
-    static int  drawLayerUsingCopybit(hwc_context_t *dev, hwc_layer_1_t *layer,
-                                        EGLDisplay dpy, EGLSurface surface,
-        functype_eglGetRenderBufferANDROID& LINK_eglGetRenderBufferANDROID,
-                  functype_eglGetCurrentSurface LINK_eglGetCurrentSurface);
-    static bool canUseCopybitForYUV (hwc_context_t *ctx);
-    static bool canUseCopybitForRGB (hwc_context_t *ctx,
-                                     hwc_display_contents_1_t *list);
-    static bool validateParams (hwc_context_t *ctx,
-                                const hwc_display_contents_1_t *list);
-    static void closeEglLib();
-    static void openEglLibAndGethandle();
+    bool draw(hwc_context_t *ctx, hwc_display_contents_1_t *list,
+                                                        int dpy, int* fd);
+    // resets the values
+    void reset();
 private:
-    //Marks layer flags if this feature is used
-    static void markFlags(hwc_layer_1_t *layer);
-    //returns yuv count
-    static int getYuvCount();
-
-    //Number of yuv layers in this drawing round
-    static int sYuvCount;
-    //Index of YUV layer, relevant only if count is 1
-    static int sYuvLayerIndex;
-    //Flags if a yuv layer is animating or below something that is animating
-    static bool sIsLayerSkip;
+    // holds the copybit device
+    struct copybit_device_t *mEngine;
+    // Helper functions for copybit composition
+    int  drawLayerUsingCopybit(hwc_context_t *dev, hwc_layer_1_t *layer,
+                                       private_handle_t *renderBuffer, int dpy);
+    bool canUseCopybitForYUV (hwc_context_t *ctx);
+    bool canUseCopybitForRGB (hwc_context_t *ctx,
+                                     hwc_display_contents_1_t *list, int dpy);
+    bool validateParams (hwc_context_t *ctx,
+                                const hwc_display_contents_1_t *list);
     //Flags if this feature is on.
-    static bool sIsModeOn;
-    //handle for adreno lib
-    static void* egl_lib;
+    bool mIsModeOn;
+    // flag that indicates whether CopyBit composition is enabled for this cycle
+    bool mCopyBitDraw;
 
-    static functype_eglGetRenderBufferANDROID LINK_eglGetRenderBufferANDROID;
-    static functype_eglGetCurrentSurface LINK_eglGetCurrentSurface;
+    unsigned int getRGBRenderingArea
+                            (const hwc_display_contents_1_t *list);
 
-    static  unsigned int getRGBRenderingArea (const hwc_display_contents_1_t *list);
-
-    static void getLayerResolution(const hwc_layer_1_t* layer,
+    void getLayerResolution(const hwc_layer_1_t* layer,
                                    unsigned int &width, unsigned int& height);
 };
 
-class CopybitEngine {
-public:
-    ~CopybitEngine();
-    // API to get copybit engine(non static)
-    struct copybit_device_t *getEngine();
-    // API to get singleton
-    static CopybitEngine* getInstance();
-private:
-    CopybitEngine();
-    struct copybit_device_t *sEngine;
-    static CopybitEngine* sInstance; // singleton
-};
-
-
-inline void CopyBit::setStats(int yuvCount, int yuvLayerIndex,
-        bool isYuvLayerSkip) {
-    sYuvCount = yuvCount;
-    sYuvLayerIndex = yuvLayerIndex;
-    sIsLayerSkip = isYuvLayerSkip;
-}
-
-inline int CopyBit::getYuvCount() { return sYuvCount; }
-
-
 }; //namespace qhwc
 
 #endif //HWC_COPYBIT_H
diff --git a/libhwcomposer/hwc_uevents.cpp b/libhwcomposer/hwc_uevents.cpp
index 334df26..6b8f4e3 100644
--- a/libhwcomposer/hwc_uevents.cpp
+++ b/libhwcomposer/hwc_uevents.cpp
@@ -27,6 +27,8 @@
 #include <stdlib.h>
 #include "hwc_utils.h"
 #include "hwc_fbupdate.h"
+#include "hwc_copybit.h"
+#include "comptype.h"
 #include "external.h"
 
 namespace qhwc {
@@ -38,6 +40,16 @@
     int vsync = 0;
     int64_t timestamp = 0;
     const char *str = udata;
+    bool usecopybit = false;
+    int compositionType =
+        qdutils::QCCompositionType::getInstance().getCompositionType();
+
+    if (compositionType & (qdutils::COMPOSITION_TYPE_DYN |
+                           qdutils::COMPOSITION_TYPE_MDP |
+                           qdutils::COMPOSITION_TYPE_C2D)) {
+        usecopybit = true;
+
+    }
 
     if(!strcasestr("change@/devices/virtual/switch/hdmi", str) &&
        !strcasestr("change@/devices/virtual/switch/wfd", str)) {
@@ -72,6 +84,8 @@
             ctx->mFBUpdate[HWC_DISPLAY_EXTERNAL] =
                 IFBUpdate::getObject(ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].xres,
                 HWC_DISPLAY_EXTERNAL);
+            if(usecopybit)
+                ctx->mCopyBit[HWC_DISPLAY_EXTERNAL] = new CopyBit();
         } else {
             ctx->mExtDisplay->processUEventOffline(udata);
             if(ctx->mFBUpdate[HWC_DISPLAY_EXTERNAL]) {
@@ -79,6 +93,11 @@
                 delete ctx->mFBUpdate[HWC_DISPLAY_EXTERNAL];
                 ctx->mFBUpdate[HWC_DISPLAY_EXTERNAL] = NULL;
             }
+            if(ctx->mCopyBit[HWC_DISPLAY_EXTERNAL]){
+                Locker::Autolock _l(ctx->mExtSetLock);
+                delete ctx->mCopyBit[HWC_DISPLAY_EXTERNAL];
+                ctx->mCopyBit[HWC_DISPLAY_EXTERNAL] = NULL;
+            }
         }
         ALOGD("%s sending hotplug: connected = %d", __FUNCTION__, connected);
         Locker::Autolock _l(ctx->mExtSetLock); //hwc comp could be on
diff --git a/libhwcomposer/hwc_utils.cpp b/libhwcomposer/hwc_utils.cpp
index 76635d5..9cc5c24 100644
--- a/libhwcomposer/hwc_utils.cpp
+++ b/libhwcomposer/hwc_utils.cpp
@@ -1,6 +1,9 @@
 /*
  * Copyright (C) 2010 The Android Open Source Project
- * Copyright (C) 2012, The Linux Foundation All rights reserved.
+ * Copyright (C) 2012-2013, The Linux Foundation All rights reserved.
+ *
+ * Not a Contribution, Apache license notifications and license are retained
+ * for attribution purposes only.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,7 +17,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
+#define HWC_UTILS_DEBUG 0
 #include <sys/ioctl.h>
 #include <EGL/egl.h>
 #include <cutils/properties.h>
@@ -25,9 +28,10 @@
 #include "hwc_mdpcomp.h"
 #include "hwc_fbupdate.h"
 #include "mdp_version.h"
+#include "hwc_copybit.h"
 #include "external.h"
 #include "QService.h"
-
+#include "comptype.h"
 namespace qhwc {
 
 // Opens Framebuffer device
@@ -66,6 +70,19 @@
     ctx->mFBUpdate[HWC_DISPLAY_PRIMARY] =
         IFBUpdate::getObject(ctx->dpyAttr[HWC_DISPLAY_PRIMARY].xres,
         HWC_DISPLAY_PRIMARY);
+
+    char value[PROPERTY_VALUE_MAX];
+    // Check if the target supports copybit compostion (dyn/mdp/c2d) 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->mExtDisplay = new ExternalDisplay(ctx);
     for (uint32_t i = 0; i < HWC_NUM_DISPLAY_TYPES; i++)
         ctx->mLayerCache[i] = new LayerCache();
@@ -87,6 +104,13 @@
         ctx->mOverlay = NULL;
     }
 
+    for(int i = 0; i< HWC_NUM_DISPLAY_TYPES; i++) {
+        if(ctx->mCopyBit[i]) {
+            delete ctx->mCopyBit[i];
+            ctx->mCopyBit[i] = NULL;
+        }
+    }
+
     if(ctx->mFbDev) {
         framebuffer_close(ctx->mFbDev);
         ctx->mFbDev = NULL;
@@ -251,13 +275,15 @@
     return ctx->dpyAttr[HWC_DISPLAY_EXTERNAL].isActive;
 }
 
-int hwc_sync(hwc_context_t *ctx, hwc_display_contents_1_t* list, int dpy) {
+int hwc_sync(hwc_context_t *ctx, hwc_display_contents_1_t* list, int dpy,
+                                                        int fd) {
     int ret = 0;
     struct mdp_buf_sync data;
     int acquireFd[MAX_NUM_LAYERS];
     int count = 0;
     int releaseFd = -1;
     int fbFd = -1;
+    memset(&data, 0, sizeof(data));
     bool swapzero = false;
     data.flags = MDP_BUF_SYNC_FLAG_WAIT;
     data.acq_fen_fd = acquireFd;
@@ -270,35 +296,52 @@
 
     //Accumulate acquireFenceFds
     for(uint32_t i = 0; i < list->numHwLayers; i++) {
-        if((list->hwLayers[i].compositionType == HWC_OVERLAY ||
-            list->hwLayers[i].compositionType == HWC_FRAMEBUFFER_TARGET) &&
-            list->hwLayers[i].acquireFenceFd != -1 ){
+        if(list->hwLayers[i].compositionType == HWC_OVERLAY &&
+                        list->hwLayers[i].acquireFenceFd != -1) {
             if(UNLIKELY(swapzero))
                 acquireFd[count++] = -1;
             else
                 acquireFd[count++] = list->hwLayers[i].acquireFenceFd;
         }
+        if(list->hwLayers[i].compositionType == HWC_FRAMEBUFFER_TARGET) {
+            if(UNLIKELY(swapzero))
+                acquireFd[count++] = -1;
+            else if(fd != -1) {
+                //set the acquireFD from fd - which is coming from c2d
+                acquireFd[count++] = fd;
+                // Buffer sync IOCTL should be async when using c2d fence is
+                // used
+                data.flags &= ~MDP_BUF_SYNC_FLAG_WAIT;
+            } else if(list->hwLayers[i].acquireFenceFd != -1)
+                acquireFd[count++] = list->hwLayers[i].acquireFenceFd;
+        }
     }
 
     data.acq_fen_fd_cnt = count;
     fbFd = ctx->dpyAttr[dpy].fd;
-
     //Waits for acquire fences, returns a release fence
-    if(LIKELY(!swapzero))
+    if(LIKELY(!swapzero)) {
+        uint64_t start = systemTime();
         ret = ioctl(fbFd, MSMFB_BUFFER_SYNC, &data);
+        ALOGD_IF(HWC_UTILS_DEBUG, "%s: time taken for MSMFB_BUFFER_SYNC IOCTL = %d",
+                            __FUNCTION__, (size_t) ns2ms(systemTime() - start));
+    }
     if(ret < 0) {
         ALOGE("ioctl MSMFB_BUFFER_SYNC failed, err=%s",
                 strerror(errno));
     }
-
     for(uint32_t i = 0; i < list->numHwLayers; i++) {
-        if((list->hwLayers[i].compositionType == HWC_OVERLAY ||
-            list->hwLayers[i].compositionType == HWC_FRAMEBUFFER_TARGET)) {
+        if(list->hwLayers[i].compositionType == HWC_OVERLAY ||
+           list->hwLayers[i].compositionType == HWC_FRAMEBUFFER_TARGET) {
             //Close the acquireFenceFds
             if(list->hwLayers[i].acquireFenceFd > 0) {
                 close(list->hwLayers[i].acquireFenceFd);
                 list->hwLayers[i].acquireFenceFd = -1;
             }
+            if(fd > 0) {
+                close(fd);
+                fd = -1;
+            }
             //Populate releaseFenceFds.
             if(UNLIKELY(swapzero))
                 list->hwLayers[i].releaseFenceFd = -1;
diff --git a/libhwcomposer/hwc_utils.h b/libhwcomposer/hwc_utils.h
index 9541404..0005582 100644
--- a/libhwcomposer/hwc_utils.h
+++ b/libhwcomposer/hwc_utils.h
@@ -1,6 +1,9 @@
 /*
  * Copyright (C) 2010 The Android Open Source Project
- * Copyright (C) 2012, The Linux Foundation. All rights reserved.
+ * Copyright (C) 2012-2013, The Linux Foundation. All rights reserved.
+ *
+ * Not a Contribution, Apache license notifications and license are retained
+ * for attribution purposes only.
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -51,6 +54,7 @@
 class ExternalDisplay;
 class IFBUpdate;
 class MDPComp;
+class CopyBit;
 
 struct MDPInfo {
     int version;
@@ -82,7 +86,6 @@
     bool needsAlphaScale;
 };
 
-
 struct LayerProp {
     uint32_t mFlags; //qcom specific layer flags
     LayerProp():mFlags(0) {};
@@ -133,7 +136,8 @@
 void dumpsys_log(android::String8& buf, const char* fmt, ...);
 
 //Sync point impl.
-int hwc_sync(hwc_context_t *ctx, hwc_display_contents_1_t* list, int dpy);
+int hwc_sync(hwc_context_t *ctx, hwc_display_contents_1_t* list, int dpy,
+                                                    int fd);
 
 // Inline utility functions
 static inline bool isSkipLayer(const hwc_layer_1_t* l) {
@@ -214,6 +218,10 @@
     const hwc_procs_t* proc;
     //Framebuffer device
     framebuffer_device_t *mFbDev;
+
+    //CopyBit objects
+    qhwc::CopyBit *mCopyBit[HWC_NUM_DISPLAY_TYPES];
+
     //Overlay object - NULL for non overlay devices
     overlay::Overlay *mOverlay;
     //QService object
diff --git a/libqdutils/Android.mk b/libqdutils/Android.mk
index ecae273..eb04afb 100644
--- a/libqdutils/Android.mk
+++ b/libqdutils/Android.mk
@@ -9,8 +9,8 @@
 LOCAL_CFLAGS                  := $(common_flags) -DLOG_TAG=\"qdutils\"
 LOCAL_ADDITIONAL_DEPENDENCIES := $(common_deps)
 LOCAL_SRC_FILES               := profiler.cpp mdp_version.cpp \
-                                 idle_invalidator.cpp
-
+                                 idle_invalidator.cpp \
+                                 comptype.cpp
 include $(BUILD_SHARED_LIBRARY)
 
 include $(CLEAR_VARS)
diff --git a/libqdutils/comptype.cpp b/libqdutils/comptype.cpp
new file mode 100644
index 0000000..a29158a
--- /dev/null
+++ b/libqdutils/comptype.cpp
@@ -0,0 +1,33 @@
+/*
+ * 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 or 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<comptype.h>
+
+//Instanticate the QCCompositionType Singleton
+ANDROID_SINGLETON_STATIC_INSTANCE(qdutils::QCCompositionType);
diff --git a/libqdutils/comptype.h b/libqdutils/comptype.h
index a90f957..63c99d3 100644
--- a/libqdutils/comptype.h
+++ b/libqdutils/comptype.h
@@ -1,6 +1,6 @@
 /*
- * Copyright (c) 2012, Code Aurora Forum. All rights reserved.
-
+ * Copyright (C) 2012-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:
@@ -10,7 +10,7 @@
  *     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 Code Aurora Forum, Inc. nor the names of its
+ *   * Neither the name of The Linux Foundation or the names of its
  *     contributors may be used to endorse or promote products derived
  *     from this software without specific prior written permission.
  *
@@ -89,5 +89,4 @@
 
 }
 }; //namespace qdutils
-ANDROID_SINGLETON_STATIC_INSTANCE(qdutils::QCCompositionType);
 #endif //INCLUDE_LIBQCOM_COMPTYPES