Merge "libgralloc: force 1M alignment for secure buffers"
diff --git a/libcopybit/c2d2.h b/libcopybit/c2d2.h
index 8c7d05b..886f38a 100644
--- a/libcopybit/c2d2.h
+++ b/libcopybit/c2d2.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-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
@@ -9,7 +9,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. nor the names of its
  *       contributors may be used to endorse or promote products derived
  *       from this software without specific prior written permission.
  *
@@ -232,6 +232,7 @@
     C2D_DRAW_LINE_NOLAST     = (1 << 17), /* disable last pixel draw for line */
 } C2D_SOURCE_CONFIG;
 
+
 /* Target configuration bits, defines rotation + mirroring.
  * Mirror is applied prior to rotation if enabled. */
 typedef enum {
@@ -273,6 +274,18 @@
     C2D_ALPHA_BLEND_NONE       = (1  << 25), /* disables alpha blending */
 } C2D_ALPHA_BLEND_MODE;
 
+/* Configuration bits, used in the config_mask field of C2D_OBJECT struct */
+typedef enum {
+    C2D_OVERRIDE_GLOBAL_TARGET_ROTATE_CONFIG = (1 << 27), /* Overrides TARGET Config */
+    C2D_OVERRIDE_TARGET_ROTATE_0             = (0 << 28), /* no rotation             */
+    C2D_OVERRIDE_TARGET_ROTATE_90            = (1 << 28), /* 90 degree rotation      */
+    C2D_OVERRIDE_TARGET_ROTATE_180           = (2 << 28), /* 180 degree rotation     */
+    C2D_OVERRIDE_TARGET_ROTATE_270           = (3 << 28), /* 270 degree rotation     */
+} C2D_SOURCE_TARGET_CONFIG;
+
+#define C2D_OVERRIDE_SOURCE_CONFIG_TARGET_ROTATION_SHIFT_MASK  28
+#define C2D_OVERRIDE_TARGET_CONFIG_TARGET_ROTATION_SHIFT_MASK  2
+
 
 /* Surface caps enumeration */
 typedef enum {
@@ -375,6 +388,51 @@
     struct C2D_OBJECT_STR *next; /* pointer to the next object or NULL */
 } C2D_OBJECT;
 
+/* Configuration bits, driver capabilities used by 2Dapplications */
+typedef enum {
+    C2D_DRIVER_SUPPORTS_GLOBAL_ALPHA_OP           = (1 << 0),
+    C2D_DRIVER_SUPPORTS_TILE_OP                   = (1 << 1),
+    C2D_DRIVER_SUPPORTS_COLOR_KEY_OP              = (1 << 2),
+    C2D_DRIVER_SUPPORTS_NO_PIXEL_ALPHA_OP         = (1 << 3),
+    C2D_DRIVER_SUPPORTS_TARGET_ROTATE_OP          = (1 << 4),
+    C2D_DRIVER_SUPPORTS_ANTI_ALIASING_OP          = (1 << 5), /* antialiasing */
+    C2D_DRIVER_SUPPORTS_BILINEAR_FILTER_OP        = (1 << 6),
+    C2D_DRIVER_SUPPORTS_LENS_CORRECTION_OP        = (1 << 7),
+    C2D_DRIVER_SUPPORTS_OVERRIDE_TARGET_ROTATE_OP = (1 << 8),
+    C2D_DRIVER_SUPPORTS_SHADER_BLOB_OP            = (1 << 9),
+    C2D_DRIVER_SUPPORTS_MASK_SURFACE_OP           = (1 << 10), /* mask surface */
+    C2D_DRIVER_SUPPORTS_MIRROR_H_OP               = (1 << 11), /* horizontal flip */
+    C2D_DRIVER_SUPPORTS_MIRROR_V_OP               = (1 << 12), /* vertical flip */
+    C2D_DRIVER_SUPPORTS_SCISSOR_RECT_OP           = (1 << 13),
+    C2D_DRIVER_SUPPORTS_SOURCE_RECT_OP            = (1 << 14),
+    C2D_DRIVER_SUPPORTS_TARGET_RECT_OP            = (1 << 15),
+    C2D_DRIVER_SUPPORTS_ROTATE_OP                 = (1 << 16), /* all rotations */
+    C2D_DRIVER_SUPPORTS_FLUSH_WITH_FENCE_FD_OP    = (1 << 17), /* all rotations */
+    C2D_DRIVER_SUPPORTS_ALL_CAPABILITIES_OP       = ((0xFFFFFFFF) >> (31 - 17)) /* mask for all capabilities supported */
+} C2D_DRIVER_CAPABILITIES;
+
+/* 2D driver workaround bits used by the 2D applications */
+typedef enum {
+    C2D_DRIVER_WORKAROUND_NONE  = 0, /* NO workaround */
+    C2D_DRIVER_WORKAROUND_SWAP_UV_FOR_YUV_TARGET  = (1 << 0), /* Swap UV when this flag set */
+} C2D_DRIVER_WORKAROUND;
+
+/* Structure to query Driver information */
+typedef struct {
+    uint32 capabilities_mask;
+    uint32 workaround_mask;
+    uint32 reserved1;
+    uint32 reserved2;
+    uint32 reserved3;
+} C2D_DRIVER_INFO;
+
+/* Structure to query Driver information */
+typedef struct {
+    uint32          max_surface_template_needed;
+    uint32          reserved1;
+    uint32          reserved2;
+    uint32          reserved3;
+} C2D_DRIVER_SETUP_INFO;
 
 /*****************************************************************************/
 /**************************** C2D API 2.0 ********************************/
@@ -609,6 +667,13 @@
  * gpaddr is the gpuaddr to unmap */
 C2D_API C2D_STATUS c2dUnMapAddr (void * gpuaddr);
 
+/* allows user to query driver capabilities.
+ * driver_info is the information about driver */
+C2D_API C2D_STATUS c2dGetDriverCapabilities( C2D_DRIVER_INFO * driver_info);
+
+/* create a fence fd for the timestamp */
+C2D_API C2D_STATUS c2dCreateFenceFD( uint32 target_id, c2d_ts_handle timestamp, int32 *fd);
+
 /*****************************************************************************/
 
 #ifdef __cplusplus
diff --git a/libcopybit/copybit.cpp b/libcopybit/copybit.cpp
index 773e9b8..ed302f1 100644
--- a/libcopybit/copybit.cpp
+++ b/libcopybit/copybit.cpp
@@ -1,6 +1,9 @@
 /*
  * Copyright (C) 2008 The Android Open Source Project
- * Copyright (c) 2010 - 2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010 - 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.
@@ -129,6 +132,7 @@
         case HAL_PIXEL_FORMAT_YCbCr_422_SP:  return MDP_Y_CRCB_H2V1;
         case HAL_PIXEL_FORMAT_YCbCr_420_SP:  return MDP_Y_CRCB_H2V2;
         case HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO: return MDP_Y_CBCR_H2V2_ADRENO;
+        case HAL_PIXEL_FORMAT_NV12_ENCODEABLE: return MDP_Y_CBCR_H2V2;
     }
     return -1;
 }
@@ -313,10 +317,10 @@
                     ctx->mFlags &= ~MDP_BLUR;
                 }
                 break;
-            case COPYBIT_PREMULTIPLIED_ALPHA:
-                if(value == COPYBIT_ENABLE) {
+            case COPYBIT_BLEND_MODE:
+                if(value == COPYBIT_BLENDING_PREMULT) {
                     ctx->mFlags |= MDP_BLEND_FG_PREMULT;
-                } else if (value == COPYBIT_DISABLE) {
+                } else {
                     ctx->mFlags &= ~MDP_BLEND_FG_PREMULT;
                 }
                 break;
@@ -403,8 +407,8 @@
             }
         }
 
-        if (src_rect->l < 0 || src_rect->r > (int)src->w ||
-            src_rect->t < 0 || src_rect->b > (int)src->h) {
+        if (src_rect->l < 0 || (uint32_t)src_rect->r > src->w ||
+            src_rect->t < 0 || (uint32_t)src_rect->b > src->h) {
             // this is always invalid
             ALOGE ("%s : Invalid source rectangle : src_rect l %d t %d r %d b %d",\
                    __FUNCTION__, src_rect->l, src_rect->t, src_rect->r, src_rect->b);
@@ -423,7 +427,8 @@
         }
 
         if(src->format ==  HAL_PIXEL_FORMAT_YV12) {
-            int usage = GRALLOC_USAGE_PRIVATE_MM_HEAP;
+            int usage =
+            GRALLOC_USAGE_PRIVATE_CAMERA_HEAP|GRALLOC_USAGE_PRIVATE_UNCACHED;
             if (0 == alloc_buffer(&yv12_handle,src->w,src->h,
                                   src->format, usage)){
                 if(0 == convertYV12toYCrCb420SP(src,yv12_handle)){
@@ -501,6 +506,11 @@
     return stretch_copybit(dev, dst, src, &dr, &sr, region);
 }
 
+static int finish_copybit(struct copybit_device_t *dev)
+{
+    // NOP for MDP copybit
+}
+
 /*****************************************************************************/
 
 /** Close the copybit device */
@@ -531,6 +541,7 @@
     ctx->device.get = get;
     ctx->device.blit = blit_copybit;
     ctx->device.stretch = stretch_copybit;
+    ctx->device.finish = finish_copybit;
     ctx->mAlpha = MDP_ALPHA_NOP;
     ctx->mFlags = 0;
     ctx->mFD = open("/dev/graphics/fb0", O_RDWR, 0);
diff --git a/libcopybit/copybit.h b/libcopybit/copybit.h
index c14af74..d57b84d 100644
--- a/libcopybit/copybit.h
+++ b/libcopybit/copybit.h
@@ -1,5 +1,9 @@
 /*
  * Copyright (C) 2008 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.
@@ -67,9 +71,8 @@
     /* blurs the copied bitmap. The amount of blurring cannot be changed
      * at this time. */
     COPYBIT_BLUR            = 5,
-    /* Informs the copybit that the source and destination contains
-       premultiplied alpha */
-    COPYBIT_PREMULTIPLIED_ALPHA  = 6,
+    /* Blend mode */
+    COPYBIT_BLEND_MODE  = 6,
     /* FB width */
     COPYBIT_FRAMEBUFFER_WIDTH = 7,
     /* FB height */
@@ -96,6 +99,20 @@
     COPYBIT_ENABLE  = 1
 };
 
+/*
+ * copybit blending values. same as HWC blending values
+ */
+enum {
+    /* no blending */
+    COPYBIT_BLENDING_NONE     = 0x0100,
+
+    /* ONE / ONE_MINUS_SRC_ALPHA */
+    COPYBIT_BLENDING_PREMULT  = 0x0105,
+
+    /* SRC_ALPHA / ONE_MINUS_SRC_ALPHA */
+    COPYBIT_BLENDING_COVERAGE = 0x0405
+};
+
 /* use get_static_info() to query static informations about the hardware */
 enum {
     /* Maximum amount of minification supported by the hardware*/
@@ -213,6 +230,26 @@
                    struct copybit_rect_t const *dst_rect,
                    struct copybit_rect_t const *src_rect,
                    struct copybit_region_t const *region);
+
+  /**
+    * Execute the completion of the copybit draw operation.
+    *
+    * @param dev from open
+    *
+    * @return 0 if successful
+    */
+  int (*finish)(struct copybit_device_t *dev);
+
+  /**
+    * Trigger the copybit draw operation(async).
+    *
+    * @param dev from open
+    *
+    * @param fd - gets the fencefd
+    *
+    * @return 0 if successful
+    */
+  int (*flush_get_fence)(struct copybit_device_t *dev, int* fd);
 };
 
 
diff --git a/libcopybit/copybit_c2d.cpp b/libcopybit/copybit_c2d.cpp
index ea5dd2a..2fa55cd 100644
--- a/libcopybit/copybit_c2d.cpp
+++ b/libcopybit/copybit_c2d.cpp
@@ -1,6 +1,9 @@
 /*
  * Copyright (C) 2008 The Android Open Source Project
- * Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-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,8 +17,9 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
 #include <cutils/log.h>
+#include <sys/resource.h>
+#include <sys/prctl.h>
 
 #include <stdint.h>
 #include <string.h>
@@ -76,10 +80,16 @@
 
 C2D_STATUS (*LINK_c2dDestroySurface)( uint32 surface_id );
 
-C2D_STATUS (*LINK_c2dMapAddr) ( int mem_fd, void * hostptr, uint32 len, uint32 offset, uint32 flags, void ** gpuaddr);
+C2D_STATUS (*LINK_c2dMapAddr) ( int mem_fd, void * hostptr, uint32 len,
+                                uint32 offset, uint32 flags, void ** gpuaddr);
 
 C2D_STATUS (*LINK_c2dUnMapAddr) ( void * gpuaddr);
 
+C2D_STATUS (*LINK_c2dGetDriverCapabilities) ( C2D_DRIVER_INFO * driver_info);
+
+/* create a fence fd for the timestamp */
+C2D_STATUS (*LINK_c2dCreateFenceFD) ( uint32 target_id, c2d_ts_handle timestamp,
+                                                            int32 *fd);
 /******************************************************************************/
 
 #if defined(COPYBIT_Z180)
@@ -89,7 +99,15 @@
 #error "Unsupported HW version"
 #endif
 
-#define NUM_SURFACES 3
+// The following defines can be changed as required i.e. as we encounter
+// complex use cases.
+#define MAX_RGB_SURFACES 8        // Max. RGB layers currently supported per draw
+#define MAX_YUV_2_PLANE_SURFACES 4// Max. 2-plane YUV layers currently supported per draw
+#define MAX_YUV_3_PLANE_SURFACES 1// Max. 3-plane YUV layers currently supported per draw
+// +1 for the destination surface. We cannot have multiple destination surfaces.
+#define MAX_SURFACES (MAX_RGB_SURFACES + MAX_YUV_2_PLANE_SURFACES + MAX_YUV_3_PLANE_SURFACES + 1)
+#define NUM_SURFACE_TYPES 3      // RGB_SURFACE + YUV_SURFACE_2_PLANES + YUV_SURFACE_3_PLANES
+#define MAX_BLIT_OBJECT_COUNT 50 // Max. blit objects that can be passed per draw
 
 enum {
     RGB_SURFACE,
@@ -103,8 +121,9 @@
 };
 
 enum eC2DFlags {
-    FLAGS_PREMULTIPLIED_ALPHA = 1<<0,
-    FLAGS_YUV_DESTINATION     = 1<<1
+    FLAGS_PREMULTIPLIED_ALPHA  = 1<<0,
+    FLAGS_YUV_DESTINATION      = 1<<1,
+    FLAGS_TEMP_SRC_DST         = 1<<2
 };
 
 static gralloc::IAllocController* sAlloc = 0;
@@ -113,22 +132,38 @@
 /** State information for each device instance */
 struct copybit_context_t {
     struct copybit_device_t device;
-    unsigned int src[NUM_SURFACES];  /* src surfaces */
-    unsigned int dst[NUM_SURFACES];  /* dst surfaces */
-    unsigned int trg_transform;      /* target transform */
-    C2D_OBJECT blitState;
+    // Templates for the various source surfaces. These templates are created
+    // to avoid the expensive create/destroy C2D Surfaces
+    C2D_OBJECT_STR blit_rgb_object[MAX_RGB_SURFACES];
+    C2D_OBJECT_STR blit_yuv_2_plane_object[MAX_YUV_2_PLANE_SURFACES];
+    C2D_OBJECT_STR blit_yuv_3_plane_object[MAX_YUV_3_PLANE_SURFACES];
+    C2D_OBJECT_STR blit_list[MAX_BLIT_OBJECT_COUNT]; // Z-ordered list of blit objects
+    C2D_DRIVER_INFO c2d_driver_info;
     void *libc2d2;
     alloc_data temp_src_buffer;
     alloc_data temp_dst_buffer;
+    unsigned int dst[NUM_SURFACE_TYPES]; // dst surfaces
+    unsigned int mapped_gpu_addr[MAX_SURFACES]; // GPU addresses mapped inside copybit
+    int blit_rgb_count;         // Total RGB surfaces being blit
+    int blit_yuv_2_plane_count; // Total 2 plane YUV surfaces being
+    int blit_yuv_3_plane_count; // Total 3 plane YUV  surfaces being blit
+    int blit_count;             // Total blit objects.
+    unsigned int trg_transform;      /* target transform */
     int fb_width;
     int fb_height;
-    bool isPremultipliedAlpha;
-    bool mBlitToFB;
-};
+    int src_global_alpha;
+    int config_mask;
+    int dst_surface_type;
+    bool is_premultiplied_alpha;
+    void* time_stamp;
 
-struct blitlist{
-    uint32_t count;
-    C2D_OBJECT blitObjects[12];
+    // used for signaling the wait thread
+    bool wait_timestamp;
+    pthread_t wait_thread_id;
+    bool stop_thread;
+    pthread_mutex_t wait_cleanup_lock;
+    pthread_cond_t wait_cleanup_cond;
+
 };
 
 struct bufferInfo {
@@ -172,6 +207,46 @@
 };
 
 
+/* thread function which waits on the timeStamp and cleans up the surfaces */
+static void* c2d_wait_loop(void* ptr) {
+    copybit_context_t* ctx = (copybit_context_t*)(ptr);
+    char thread_name[64] = "copybitWaitThr";
+    prctl(PR_SET_NAME, (unsigned long) &thread_name, 0, 0, 0);
+    setpriority(PRIO_PROCESS, 0, HAL_PRIORITY_URGENT_DISPLAY);
+
+    while(ctx->stop_thread == false) {
+        pthread_mutex_lock(&ctx->wait_cleanup_lock);
+        while(ctx->wait_timestamp == false && !ctx->stop_thread) {
+            pthread_cond_wait(&(ctx->wait_cleanup_cond),
+                              &(ctx->wait_cleanup_lock));
+        }
+        if(ctx->wait_timestamp) {
+            if(LINK_c2dWaitTimestamp(ctx->time_stamp)) {
+                ALOGE("%s: LINK_c2dWaitTimeStamp ERROR!!", __FUNCTION__);
+            }
+            ctx->wait_timestamp = false;
+            // Unmap any mapped addresses.
+            for (int i = 0; i < MAX_SURFACES; i++) {
+                if (ctx->mapped_gpu_addr[i]) {
+                    LINK_c2dUnMapAddr( (void*)ctx->mapped_gpu_addr[i]);
+                    ctx->mapped_gpu_addr[i] = 0;
+                }
+            }
+            // Reset the counts after the draw.
+            ctx->blit_rgb_count = 0;
+            ctx->blit_yuv_2_plane_count = 0;
+            ctx->blit_yuv_3_plane_count = 0;
+            ctx->blit_count = 0;
+        }
+        pthread_mutex_unlock(&ctx->wait_cleanup_lock);
+        if(ctx->stop_thread)
+            break;
+    }
+    pthread_exit(NULL);
+    return NULL;
+}
+
+
 /* convert COPYBIT_FORMAT to C2D format */
 static int get_format(int format) {
     switch (format) {
@@ -189,7 +264,9 @@
         case HAL_PIXEL_FORMAT_YCrCb_420_SP:   return C2D_COLOR_FORMAT_420_NV21;
         case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED: return C2D_COLOR_FORMAT_420_NV12 |
                                                   C2D_FORMAT_MACROTILED;
-        default:                              ALOGE("%s: invalid format (0x%x", __FUNCTION__, format); return -EINVAL;
+        default:                              ALOGE("%s: invalid format (0x%x",
+                                                     __FUNCTION__, format);
+                                              return -EINVAL;
     }
     return -EINVAL;
 }
@@ -201,7 +278,7 @@
         case HAL_PIXEL_FORMAT_RGBX_8888:      return C2D_COLOR_FORMAT_8888_ARGB |
                                               C2D_FORMAT_DISABLE_ALPHA;
         case HAL_PIXEL_FORMAT_RGBA_8888:      return C2D_COLOR_FORMAT_8888_ARGB;
-                                              // The U and V need to be interchanged when the target is YUV
+        // The U and V need to be interchanged when the target is YUV
         case HAL_PIXEL_FORMAT_YCbCr_420_SP:   return C2D_COLOR_FORMAT_420_NV21;
         case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:return C2D_COLOR_FORMAT_420_NV21;
         case HAL_PIXEL_FORMAT_YCrCb_420_SP:   return C2D_COLOR_FORMAT_420_NV12;
@@ -251,7 +328,8 @@
     return c2dBpp;
 }
 
-static uint32 c2d_get_gpuaddr( struct private_handle_t *handle)
+static uint32 c2d_get_gpuaddr(copybit_context_t* ctx, struct private_handle_t *handle,
+                              int &mapped_idx)
 {
     uint32 memtype, *gpuaddr;
     C2D_STATUS rc;
@@ -271,13 +349,36 @@
         return 0;
     }
 
-    rc = LINK_c2dMapAddr(handle->fd, (void*)handle->base, handle->size, handle->offset, memtype, (void**)&gpuaddr);
+    rc = LINK_c2dMapAddr(handle->fd, (void*)handle->base, handle->size,
+                                      handle->offset, memtype, (void**)&gpuaddr);
+
     if (rc == C2D_STATUS_OK) {
+        // We have mapped the GPU address inside copybit. We need to unmap this
+        // address after the blit. Store this address
+        for (int i = 0; i < MAX_SURFACES; i++) {
+            if (ctx->mapped_gpu_addr[i] == 0) {
+                ctx->mapped_gpu_addr[i] = (uint32) gpuaddr;
+                mapped_idx = i;
+                break;
+            }
+        }
+
         return (uint32) gpuaddr;
     }
     return 0;
 }
 
+static void unmap_gpuaddr(copybit_context_t* ctx, int mapped_idx)
+{
+    if (!ctx || (mapped_idx == -1))
+        return;
+
+    if (ctx->mapped_gpu_addr[mapped_idx]) {
+        LINK_c2dUnMapAddr( (void*)ctx->mapped_gpu_addr[mapped_idx]);
+        ctx->mapped_gpu_addr[mapped_idx] = 0;
+    }
+}
+
 static int is_supported_rgb_format(int format)
 {
     switch(format) {
@@ -379,20 +480,24 @@
 }
 
 /** create C2D surface from copybit image */
-static int set_image( uint32 surfaceId, const struct copybit_image_t *rhs,
-                      int *cformat, uint32_t *mapped, const eC2DFlags flags)
+static int set_image(copybit_context_t* ctx, uint32 surfaceId,
+                      const struct copybit_image_t *rhs,
+                      const eC2DFlags flags, int &mapped_idx)
 {
     struct private_handle_t* handle = (struct private_handle_t*)rhs->handle;
     C2D_SURFACE_TYPE surfaceType;
     int status = COPYBIT_SUCCESS;
+    uint32 gpuaddr = 0;
+    int c2d_format;
+    mapped_idx = -1;
 
     if (flags & FLAGS_YUV_DESTINATION) {
-        *cformat = get_c2d_format_for_yuv_destination(rhs->format);
+        c2d_format = get_c2d_format_for_yuv_destination(rhs->format);
     } else {
-        *cformat = get_format(rhs->format);
+        c2d_format = get_format(rhs->format);
     }
 
-    if(*cformat == -EINVAL) {
+    if(c2d_format == -EINVAL) {
         ALOGE("%s: invalid format", __FUNCTION__);
         return -EINVAL;
     }
@@ -403,12 +508,13 @@
     }
 
     if (handle->gpuaddr == 0) {
-        handle->gpuaddr = c2d_get_gpuaddr(handle);
-        if(!handle->gpuaddr) {
+        gpuaddr = c2d_get_gpuaddr(ctx, handle, mapped_idx);
+        if(!gpuaddr) {
             ALOGE("%s: c2d_get_gpuaddr failed", __FUNCTION__);
             return COPYBIT_FAILURE;
         }
-        *mapped = 1;
+    } else {
+        gpuaddr = handle->gpuaddr;
     }
 
     /* create C2D surface */
@@ -418,26 +524,27 @@
 
         surfaceType = (C2D_SURFACE_TYPE) (C2D_SURFACE_RGB_HOST | C2D_SURFACE_WITH_PHYS);
 
-        surfaceDef.phys = (void*) handle->gpuaddr;
+        surfaceDef.phys = (void*) gpuaddr;
         surfaceDef.buffer = (void*) (handle->base);
 
-        surfaceDef.format = *cformat |
+        surfaceDef.format = c2d_format |
             ((flags & FLAGS_PREMULTIPLIED_ALPHA) ? C2D_FORMAT_PREMULTIPLIED : 0);
         surfaceDef.width = rhs->w;
         surfaceDef.height = rhs->h;
         int aligned_width = ALIGN(surfaceDef.width,32);
         surfaceDef.stride = (aligned_width * c2diGetBpp(surfaceDef.format))>>3;
 
-        if(LINK_c2dUpdateSurface( surfaceId,C2D_TARGET | C2D_SOURCE, surfaceType, &surfaceDef)) {
+        if(LINK_c2dUpdateSurface( surfaceId,C2D_TARGET | C2D_SOURCE, surfaceType,
+                                  &surfaceDef)) {
             ALOGE("%s: RGB Surface c2dUpdateSurface ERROR", __FUNCTION__);
-            goto error;
+            unmap_gpuaddr(ctx, mapped_idx);
             status = COPYBIT_FAILURE;
         }
     } else if (is_supported_yuv_format(rhs->format) == COPYBIT_SUCCESS) {
         C2D_YUV_SURFACE_DEF surfaceDef;
         memset(&surfaceDef, 0, sizeof(surfaceDef));
         surfaceType = (C2D_SURFACE_TYPE)(C2D_SURFACE_YUV_HOST | C2D_SURFACE_WITH_PHYS);
-        surfaceDef.format = *cformat;
+        surfaceDef.format = c2d_format;
 
         bufferInfo info;
         info.width = rhs->w;
@@ -448,199 +555,116 @@
         status = calculate_yuv_offset_and_stride(info, yuvInfo);
         if(status != COPYBIT_SUCCESS) {
             ALOGE("%s: calculate_yuv_offset_and_stride error", __FUNCTION__);
-            goto error;
+            unmap_gpuaddr(ctx, mapped_idx);
         }
 
         surfaceDef.width = rhs->w;
         surfaceDef.height = rhs->h;
         surfaceDef.plane0 = (void*) (handle->base);
-        surfaceDef.phys0 = (void*) (handle->gpuaddr);
+        surfaceDef.phys0 = (void*) (gpuaddr);
         surfaceDef.stride0 = yuvInfo.yStride;
 
         surfaceDef.plane1 = (void*) (handle->base + yuvInfo.plane1_offset);
-        surfaceDef.phys1 = (void*) (handle->gpuaddr + yuvInfo.plane1_offset);
+        surfaceDef.phys1 = (void*) (gpuaddr + yuvInfo.plane1_offset);
         surfaceDef.stride1 = yuvInfo.plane1_stride;
         if (3 == get_num_planes(rhs->format)) {
             surfaceDef.plane2 = (void*) (handle->base + yuvInfo.plane2_offset);
-            surfaceDef.phys2 = (void*) (handle->gpuaddr + yuvInfo.plane2_offset);
+            surfaceDef.phys2 = (void*) (gpuaddr + yuvInfo.plane2_offset);
             surfaceDef.stride2 = yuvInfo.plane2_stride;
         }
 
         if(LINK_c2dUpdateSurface( surfaceId,C2D_TARGET | C2D_SOURCE, surfaceType,
                                   &surfaceDef)) {
             ALOGE("%s: YUV Surface c2dUpdateSurface ERROR", __FUNCTION__);
-            goto error;
+            unmap_gpuaddr(ctx, mapped_idx);
             status = COPYBIT_FAILURE;
         }
     } else {
         ALOGE("%s: invalid format 0x%x", __FUNCTION__, rhs->format);
-        goto error;
+        unmap_gpuaddr(ctx, mapped_idx);
         status = COPYBIT_FAILURE;
     }
 
     return status;
-
-error:
-    if(*mapped == 1) {
-        LINK_c2dUnMapAddr( (void*) handle->gpuaddr);
-        handle->gpuaddr = 0;
-        *mapped = 0;
-    }
-    return status;
 }
 
-static int set_src_image( uint32 *surfaceId, const struct copybit_image_t *rhs,
-                          int *cformat, uint32 *mapped)
+/** copy the bits */
+static int msm_copybit(struct copybit_context_t *ctx, unsigned int target)
 {
-    struct private_handle_t* handle = (struct private_handle_t*)rhs->handle;
-    *cformat  = get_format(rhs->format);
-    C2D_SURFACE_TYPE surfaceType;
-    uint32 gpuaddr = (uint32)handle->gpuaddr;
-    int status = COPYBIT_SUCCESS;
+    if (ctx->blit_count == 0) {
+        return COPYBIT_SUCCESS;
+    }
 
-    if (handle->gpuaddr == 0)
+    for (int i = 0; i < ctx->blit_count; i++)
     {
-        handle->gpuaddr = c2d_get_gpuaddr( handle);
-        if(!handle->gpuaddr)
-            return COPYBIT_FAILURE;
-
-        *mapped = 1;
+        ctx->blit_list[i].next = &(ctx->blit_list[i+1]);
     }
+    ctx->blit_list[ctx->blit_count-1].next = NULL;
+    if(LINK_c2dDraw(target,ctx->trg_transform, 0x0, 0, 0, ctx->blit_list,
+                    ctx->blit_count)) {
+        ALOGE("%s: LINK_c2dDraw ERROR", __FUNCTION__);
+        return COPYBIT_FAILURE;
+    }
+    return COPYBIT_SUCCESS;
+}
 
-    /* create C2D surface */
-    if(is_supported_rgb_format(rhs->format) == COPYBIT_SUCCESS) {
-        /* RGB */
-        C2D_RGB_SURFACE_DEF surfaceDef;
-        surfaceType = (C2D_SURFACE_TYPE) (C2D_SURFACE_RGB_HOST | C2D_SURFACE_WITH_PHYS | C2D_SURFACE_WITH_PHYS_DUMMY);
 
-        surfaceDef.phys = (void*) handle->gpuaddr;
-        surfaceDef.buffer = (void*) (handle->base);
-        surfaceDef.buffer = (void*) (handle->base + handle->offset);
 
-        surfaceDef.format = get_format(rhs->format);
-        surfaceDef.width = rhs->w;
-        surfaceDef.height = rhs->h;
-        surfaceDef.stride = ALIGN(((surfaceDef.width * c2diGetBpp(surfaceDef.format))>>3), 32);
+static int flush_get_fence_copybit (struct copybit_device_t *dev, int* fd)
+{
+    struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
+    int status = COPYBIT_FAILURE;
+    if (!ctx)
+        return COPYBIT_FAILURE;
+    pthread_mutex_lock(&ctx->wait_cleanup_lock);
+    status = msm_copybit(ctx, ctx->dst[ctx->dst_surface_type]);
 
-        if(LINK_c2dCreateSurface( surfaceId, C2D_TARGET, surfaceType,(void*)&surfaceDef)) {
-            ALOGE("%s: LINK_c2dCreateSurface error", __FUNCTION__);
-            status = COPYBIT_FAILURE;
-            goto error;
-        }
-    } else if(is_supported_yuv_format(rhs->format) == COPYBIT_SUCCESS) {
-        /* YUV */
-        C2D_YUV_SURFACE_DEF surfaceDef;
-        int offset = 0;
-        int yStride = 0;
-        int uvStride = 0;
-        memset(&surfaceDef, 0, sizeof(surfaceDef));
-
-        surfaceType = (C2D_SURFACE_TYPE)(C2D_SURFACE_YUV_HOST | C2D_SURFACE_WITH_PHYS | C2D_SURFACE_WITH_PHYS_DUMMY);
-        surfaceDef.format = get_format(rhs->format);
-        bufferInfo info;
-        info.width = rhs->w;
-        info.height = rhs->h;
-        info.format = rhs->format;
-
-        yuvPlaneInfo yuvInfo;
-        status = calculate_yuv_offset_and_stride(info, yuvInfo);
-        if(status != COPYBIT_SUCCESS) {
-            ALOGE("%s: calculate_yuv_offset_and_stride error", __FUNCTION__);
-            goto error;
-        }
-
-        surfaceDef.width = rhs->w;
-        surfaceDef.height = rhs->h;
-        surfaceDef.plane0 = (void*) (handle->base);
-        surfaceDef.phys0 = (void*) handle->gpuaddr;
-        surfaceDef.stride0 = yuvInfo.yStride;
-
-        surfaceDef.plane1 = (void*) (handle->base + yuvInfo.plane1_offset);
-        surfaceDef.phys1 = (void*) (handle->gpuaddr + yuvInfo.plane1_offset);
-        surfaceDef.stride1 = yuvInfo.plane1_stride;
-
-        if(LINK_c2dCreateSurface( surfaceId, C2D_TARGET | C2D_SOURCE, surfaceType,
-                                  (void*)&surfaceDef)) {
-            ALOGE("%s: YUV surface LINK_c2dCreateSurface error", __func__);
-            status = COPYBIT_FAILURE;
-            goto error;
-        }
-    } else {
-        ALOGE("%s: Invalid format 0x%x", __FUNCTION__, rhs->format);
+    if(LINK_c2dFlush(ctx->dst[ctx->dst_surface_type], &ctx->time_stamp)) {
+        ALOGE("%s: LINK_c2dFlush ERROR", __FUNCTION__);
+        // unlock the mutex and return failure
+        pthread_mutex_unlock(&ctx->wait_cleanup_lock);
+        return COPYBIT_FAILURE;
+    }
+    if(LINK_c2dCreateFenceFD(ctx->dst[ctx->dst_surface_type], ctx->time_stamp,
+                                                                        fd)) {
+        ALOGE("%s: LINK_c2dCreateFenceFD ERROR", __FUNCTION__);
         status = COPYBIT_FAILURE;
     }
-
-    return COPYBIT_SUCCESS;
-
-error:
-    if(*mapped == 1) {
-        LINK_c2dUnMapAddr( (void*) handle->gpuaddr);
-        handle->gpuaddr = 0;
-        *mapped = 0;
+    if(status == COPYBIT_SUCCESS) {
+        //signal the wait_thread
+        ctx->wait_timestamp = true;
+        pthread_cond_signal(&ctx->wait_cleanup_cond);
     }
+    pthread_mutex_unlock(&ctx->wait_cleanup_lock);
     return status;
 }
 
-void unset_image( uint32 surfaceId, const struct copybit_image_t *rhs,
-                  uint32 mmapped)
+static int finish_copybit(struct copybit_device_t *dev)
 {
-    struct private_handle_t* handle = (struct private_handle_t*)rhs->handle;
+    struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
+    if (!ctx)
+        return COPYBIT_FAILURE;
 
-    if (mmapped && handle->gpuaddr) {
-        // Unmap this gpuaddr
-        LINK_c2dUnMapAddr( (void*) handle->gpuaddr);
-        handle->gpuaddr = 0;
-    }
-}
+   int status = msm_copybit(ctx, ctx->dst[ctx->dst_surface_type]);
 
-static int blit_to_target( uint32 surfaceId, const struct copybit_image_t *rhs)
-{
-    struct private_handle_t* handle = (struct private_handle_t*)rhs->handle;
-    uint32 cformat  = get_format(rhs->format);
-    C2D_SURFACE_TYPE surfaceType;
-    uint32 memoryMapped = 0;
-    int status = COPYBIT_SUCCESS;
-
-    if (!handle->gpuaddr) {
-        handle->gpuaddr = c2d_get_gpuaddr(handle);
-        if(!handle->gpuaddr)
-            return COPYBIT_FAILURE;
-
-        memoryMapped = 1;
+   if(LINK_c2dFinish(ctx->dst[ctx->dst_surface_type])) {
+        ALOGE("%s: LINK_c2dFinish ERROR", __FUNCTION__);
+        return COPYBIT_FAILURE;
     }
 
-    /* create C2D surface */
-
-    if(cformat) {
-        /* RGB */
-        C2D_RGB_SURFACE_DEF surfaceDef;
-        memset(&surfaceDef, 0, sizeof(surfaceDef));
-
-        surfaceDef.buffer = (void*) handle->base;
-        surfaceDef.phys = (void*) handle->gpuaddr;
-
-        surfaceType = C2D_SURFACE_RGB_HOST;
-        surfaceDef.format = get_format(rhs->format);
-        surfaceDef.width = rhs->w;
-        surfaceDef.height = rhs->h;
-        surfaceDef.stride = ALIGN(((surfaceDef.width * c2diGetBpp(surfaceDef.format))>>3), 32);
-
-        if(LINK_c2dReadSurface(surfaceId, surfaceType, (void*)&surfaceDef, 0, 0)) {
-            ALOGE("%s: LINK_c2dReadSurface ERROR", __func__);
-            status = COPYBIT_FAILURE;
-            goto done;
+    // Unmap any mapped addresses.
+    for (int i = 0; i < MAX_SURFACES; i++) {
+        if (ctx->mapped_gpu_addr[i]) {
+            LINK_c2dUnMapAddr( (void*)ctx->mapped_gpu_addr[i]);
+            ctx->mapped_gpu_addr[i] = 0;
         }
     }
-    else {
-        /* YUV */
-        /* TODO */
-    }
 
-done:
-    if (memoryMapped) {
-        LINK_c2dUnMapAddr( (void*) handle->gpuaddr);
-        handle->gpuaddr = 0;
-    }
+    // Reset the counts after the draw.
+    ctx->blit_rgb_count = 0;
+    ctx->blit_yuv_2_plane_count = 0;
+    ctx->blit_yuv_3_plane_count = 0;
+    ctx->blit_count = 0;
     return status;
 }
 
@@ -696,24 +720,6 @@
     c2dObject->config_mask |= C2D_SCISSOR_RECT_BIT;
 }
 
-/** copy the bits */
-static int msm_copybit(struct copybit_context_t *dev, blitlist *list, uint32 target)
-{
-    unsigned int objects;
-
-    for(objects = 0; objects < list->count; objects++) {
-        list->blitObjects[objects].next = &(list->blitObjects[objects+1]);
-    }
-
-    if(LINK_c2dDraw(target,dev->trg_transform, 0x0, 0, 0, list->blitObjects,
-                    list->count)) {
-        ALOGE("%s: LINK_c2dDraw ERROR", __FUNCTION__);
-        return COPYBIT_FAILURE;
-    }
-
-    return COPYBIT_SUCCESS;
-}
-
 /*****************************************************************************/
 
 /** Set a parameter to value */
@@ -723,81 +729,95 @@
     int value)
 {
     struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
+    int status = COPYBIT_SUCCESS;
     if (!ctx) {
         ALOGE("%s: null context", __FUNCTION__);
         return -EINVAL;
     }
 
+    pthread_mutex_lock(&ctx->wait_cleanup_lock);
     switch(name) {
-        case COPYBIT_ROTATION_DEG:
-            ctx->blitState.rotation = value<<16;
-            /* SRC rotation */
-            if(!value)
-                ctx->blitState.config_mask &=~C2D_ROTATE_BIT;;
-            break;
         case COPYBIT_PLANE_ALPHA:
+        {
             if (value < 0)      value = 0;
             if (value >= 256)   value = 255;
 
-            ctx->blitState.global_alpha = value;
-
-            if(ctx->blitState.global_alpha<255)
-                ctx->blitState.config_mask |= C2D_GLOBAL_ALPHA_BIT;
+            ctx->src_global_alpha = value;
+            if (value < 255)
+                ctx->config_mask |= C2D_GLOBAL_ALPHA_BIT;
             else
-                ctx->blitState.config_mask &=~C2D_GLOBAL_ALPHA_BIT;
-            break;
-        case COPYBIT_DITHER:
-            /* TODO */
-            break;
-        case COPYBIT_BLUR:
-            /* TODO */
-            break;
-        case COPYBIT_TRANSFORM:
-            ctx->blitState.config_mask &=~C2D_ROTATE_BIT;
-            ctx->blitState.config_mask &=~C2D_MIRROR_H_BIT;
-            ctx->blitState.config_mask &=~C2D_MIRROR_V_BIT;
-            ctx->trg_transform = C2D_TARGET_ROTATE_0;
-
-            if((value&0x7) == COPYBIT_TRANSFORM_ROT_180)
-                ctx->trg_transform = C2D_TARGET_ROTATE_180;
-            else if((value&0x7) == COPYBIT_TRANSFORM_ROT_270)
-                ctx->trg_transform = C2D_TARGET_ROTATE_90;
-            else {
-                if(value&COPYBIT_TRANSFORM_FLIP_H)
-                    ctx->blitState.config_mask |= C2D_MIRROR_H_BIT;
-                if(value&COPYBIT_TRANSFORM_FLIP_V)
-                    ctx->blitState.config_mask |= C2D_MIRROR_V_BIT;
-                if(value&COPYBIT_TRANSFORM_ROT_90)
-                    ctx->trg_transform = C2D_TARGET_ROTATE_270;
+                ctx->config_mask &= ~C2D_GLOBAL_ALPHA_BIT;
+        }
+        break;
+        case COPYBIT_BLEND_MODE:
+        {
+            if (value == COPYBIT_BLENDING_NONE) {
+                ctx->config_mask |= C2D_ALPHA_BLEND_NONE;
+                ctx->is_premultiplied_alpha = true;
+            } else if (value == COPYBIT_BLENDING_PREMULT) {
+                ctx->is_premultiplied_alpha = true;
+            } else {
+                ctx->config_mask &= ~C2D_ALPHA_BLEND_NONE;
             }
-            break;
-        case COPYBIT_PREMULTIPLIED_ALPHA:
-            (value == COPYBIT_ENABLE) ? ctx->isPremultipliedAlpha = true :
-                ctx->isPremultipliedAlpha = false;
-            break;
+        }
+        break;
+        case COPYBIT_TRANSFORM:
+        {
+            unsigned int transform = 0;
+            uint32 config_mask = 0;
+            config_mask |= C2D_OVERRIDE_GLOBAL_TARGET_ROTATE_CONFIG;
+            if((value & 0x7) == COPYBIT_TRANSFORM_ROT_180) {
+                transform = C2D_TARGET_ROTATE_180;
+                config_mask |= C2D_OVERRIDE_TARGET_ROTATE_180;
+            } else if((value & 0x7) == COPYBIT_TRANSFORM_ROT_270) {
+                transform = C2D_TARGET_ROTATE_90;
+                config_mask |= C2D_OVERRIDE_TARGET_ROTATE_90;
+            } else if(value == COPYBIT_TRANSFORM_ROT_90) {
+                transform = C2D_TARGET_ROTATE_270;
+                config_mask |= C2D_OVERRIDE_TARGET_ROTATE_270;
+            } else {
+                config_mask |= C2D_OVERRIDE_TARGET_ROTATE_0;
+                if(value & COPYBIT_TRANSFORM_FLIP_H) {
+                    config_mask |= C2D_MIRROR_H_BIT;
+                } else if(value & COPYBIT_TRANSFORM_FLIP_V) {
+                    config_mask |= C2D_MIRROR_V_BIT;
+                }
+            }
+
+            if (transform != ctx->trg_transform) {
+                if (ctx->c2d_driver_info.capabilities_mask &
+                    C2D_DRIVER_SUPPORTS_OVERRIDE_TARGET_ROTATE_OP) {
+                    ctx->config_mask |= config_mask;
+                } else {
+                    // The transform for this surface does not match the current
+                    // target transform. Draw all previous surfaces. This will be
+                    // changed once we have a new mechanism to send different
+                    // target rotations to c2d.
+                    finish_copybit(dev);
+                }
+            }
+            ctx->trg_transform = transform;
+        }
+        break;
         case COPYBIT_FRAMEBUFFER_WIDTH:
             ctx->fb_width = value;
             break;
         case COPYBIT_FRAMEBUFFER_HEIGHT:
             ctx->fb_height = value;
             break;
+        case COPYBIT_ROTATION_DEG:
+        case COPYBIT_DITHER:
+        case COPYBIT_BLUR:
         case COPYBIT_BLIT_TO_FRAMEBUFFER:
-            if (COPYBIT_ENABLE == value) {
-                ctx->mBlitToFB = value;
-            } else if (COPYBIT_DISABLE == value) {
-                ctx->mBlitToFB = value;
-            } else {
-              ALOGE ("%s:Invalid input for COPYBIT_BLIT_TO_FRAMEBUFFER : %d",
-                                                         __FUNCTION__, value);
-            }
+            // Do nothing
             break;
         default:
             ALOGE("%s: default case param=0x%x", __FUNCTION__, name);
-            return -EINVAL;
+            status = -EINVAL;
             break;
     }
-
-    return COPYBIT_SUCCESS;
+    pthread_mutex_unlock(&ctx->wait_cleanup_lock);
+    return status;
 }
 
 /** Get a static info value */
@@ -898,14 +918,14 @@
             {
                 // Chroma for this format is aligned to 2K.
                 size = ALIGN((aligned_w*h), 2048) +
-                    ALIGN(w/2, 32) * h/2 *2;
+                        ALIGN(aligned_w/2, 32) * (h/2) *2;
                 size = ALIGN(size, 4096);
             } break;
         case HAL_PIXEL_FORMAT_YCbCr_420_SP:
         case HAL_PIXEL_FORMAT_YCrCb_420_SP:
             {
-                size = aligned_w*h +
-                    ALIGN(w/2, 32) * h/2 *2;
+                size = aligned_w * h +
+                       ALIGN(aligned_w/2, 32) * (h/2) * 2;
                 size = ALIGN(size, 4096);
             } break;
         default: break;
@@ -998,6 +1018,19 @@
         handle = 0;
     }
 }
+
+static bool need_to_execute_draw(struct copybit_context_t* ctx,
+                                          eC2DFlags flags)
+{
+    if (flags & FLAGS_TEMP_SRC_DST) {
+        return true;
+    }
+    if (flags & FLAGS_YUV_DESTINATION) {
+        return true;
+    }
+    return false;
+}
+
 /** do a stretch blit type operation */
 static int stretch_copybit_internal(
     struct copybit_device_t *dev,
@@ -1010,14 +1043,10 @@
 {
     struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
     int status = COPYBIT_SUCCESS;
-    uint32 maxCount;
-    uint32 src_mapped = 0, trg_mapped = 0;
-    blitlist list;
-    C2D_OBJECT *req;
-    memset(&list, 0, sizeof(list));
-    int cformat;
-    c2d_ts_handle timestamp;
-    uint32 src_surface_index = 0, dst_surface_index = 0;
+    int flags = 0;
+    int src_surface_type;
+    int mapped_src_idx = -1, mapped_dst_idx = -1;
+    C2D_OBJECT_STR src_surface;
 
     if (!ctx) {
         ALOGE("%s: null context error", __FUNCTION__);
@@ -1030,40 +1059,54 @@
     }
 
     if (dst->w > MAX_DIMENSION || dst->h > MAX_DIMENSION) {
-        ALOGE("%s : dst dimension error dst w %d h %d",  __FUNCTION__, dst->w, dst->h);
+        ALOGE("%s : dst dimension error dst w %d h %d",  __FUNCTION__, dst->w,
+                                                         dst->h);
         return -EINVAL;
     }
 
-    maxCount = sizeof(list.blitObjects)/sizeof(C2D_OBJECT);
-
-    struct copybit_rect_t clip;
-    list.count = 0;
-
     if (is_valid_destination_format(dst->format) == COPYBIT_FAILURE) {
-        ALOGE("%s: Invalid destination format format = 0x%x", __FUNCTION__, dst->format);
+        ALOGE("%s: Invalid destination format format = 0x%x", __FUNCTION__,
+                                                              dst->format);
         return COPYBIT_FAILURE;
     }
 
-    bool isYUVDestination = false;
+    int dst_surface_type;
     if (is_supported_rgb_format(dst->format) == COPYBIT_SUCCESS) {
-        dst_surface_index = RGB_SURFACE;
+        dst_surface_type = RGB_SURFACE;
+        flags |= FLAGS_PREMULTIPLIED_ALPHA;
     } else if (is_supported_yuv_format(dst->format) == COPYBIT_SUCCESS) {
-        isYUVDestination = true;
         int num_planes = get_num_planes(dst->format);
+        flags |= FLAGS_YUV_DESTINATION;
         if (num_planes == 2) {
-            dst_surface_index = YUV_SURFACE_2_PLANES;
+            dst_surface_type = YUV_SURFACE_2_PLANES;
         } else if (num_planes == 3) {
-            dst_surface_index = YUV_SURFACE_3_PLANES;
+            dst_surface_type = YUV_SURFACE_3_PLANES;
         } else {
             ALOGE("%s: dst number of YUV planes is invalid dst format = 0x%x",
                   __FUNCTION__, dst->format);
             return COPYBIT_FAILURE;
         }
     } else {
-        ALOGE("%s: Invalid dst surface format 0x%x", __FUNCTION__, dst->format);
+        ALOGE("%s: Invalid dst surface format 0x%x", __FUNCTION__,
+                                                     dst->format);
         return COPYBIT_FAILURE;
     }
 
+    if (ctx->blit_rgb_count == MAX_RGB_SURFACES ||
+        ctx->blit_yuv_2_plane_count == MAX_YUV_2_PLANE_SURFACES ||
+        ctx->blit_yuv_3_plane_count == MAX_YUV_2_PLANE_SURFACES ||
+        ctx->blit_count == MAX_BLIT_OBJECT_COUNT ||
+        ctx->dst_surface_type != dst_surface_type) {
+        // we have reached the max. limits of our internal structures or
+        // changed the target.
+        // Draw the remaining surfaces. We need to do the finish here since
+        // we need to free up the surface templates.
+        finish_copybit(dev);
+    }
+
+    ctx->dst_surface_type = dst_surface_type;
+
+    // Update the destination
     copybit_image_t dst_image;
     dst_image.w = dst->w;
     dst_image.h = dst->h;
@@ -1072,7 +1115,7 @@
     // Check if we need a temp. copy for the destination. We'd need this the destination
     // width is not aligned to 32. This case occurs for YUV formats. RGB formats are
     // aligned to 32.
-    bool needTempDestination = need_temp_buffer(dst);
+    bool need_temp_dst = need_temp_buffer(dst);
     bufferInfo dst_info;
     populate_buffer_info(dst, dst_info);
     private_handle_t* dst_hnd = new private_handle_t(-1, 0, 0, 0, dst_info.format,
@@ -1081,7 +1124,7 @@
         ALOGE("%s: dst_hnd is null", __FUNCTION__);
         return COPYBIT_FAILURE;
     }
-    if (needTempDestination) {
+    if (need_temp_dst) {
         if (get_size(dst_info) != ctx->temp_dst_buffer.size) {
             free_temp_buffer(ctx->temp_dst_buffer);
             // Create a temp buffer and set that as the destination.
@@ -1100,35 +1143,40 @@
         dst_image.handle = dst_hnd;
     }
 
-    int flags = 0;
-    flags |= (ctx->isPremultipliedAlpha) ? FLAGS_PREMULTIPLIED_ALPHA : 0;
-    flags |= (isYUVDestination) ? FLAGS_YUV_DESTINATION : 0;
-
-    status = set_image( ctx->dst[dst_surface_index], &dst_image,
-                        &cformat, &trg_mapped, (eC2DFlags)flags);
+    status = set_image(ctx, ctx->dst[ctx->dst_surface_type], &dst_image,
+                       (eC2DFlags)flags, mapped_dst_idx);
     if(status) {
         ALOGE("%s: dst: set_image error", __FUNCTION__);
         delete_handle(dst_hnd);
+        unmap_gpuaddr(ctx, mapped_dst_idx);
         return COPYBIT_FAILURE;
     }
 
+    // Update the source
+    flags = 0;
     if(is_supported_rgb_format(src->format) == COPYBIT_SUCCESS) {
-        src_surface_index = RGB_SURFACE;
+        src_surface_type = RGB_SURFACE;
+        src_surface = ctx->blit_rgb_object[ctx->blit_rgb_count];
     } else if (is_supported_yuv_format(src->format) == COPYBIT_SUCCESS) {
         int num_planes = get_num_planes(src->format);
         if (num_planes == 2) {
-            src_surface_index = YUV_SURFACE_2_PLANES;
+            src_surface_type = YUV_SURFACE_2_PLANES;
+            src_surface = ctx->blit_yuv_2_plane_object[ctx->blit_yuv_2_plane_count];
         } else if (num_planes == 3) {
-            src_surface_index = YUV_SURFACE_3_PLANES;
+            src_surface_type = YUV_SURFACE_3_PLANES;
+            src_surface = ctx->blit_yuv_3_plane_object[ctx->blit_yuv_2_plane_count];
         } else {
             ALOGE("%s: src number of YUV planes is invalid src format = 0x%x",
                   __FUNCTION__, src->format);
             delete_handle(dst_hnd);
+            unmap_gpuaddr(ctx, mapped_dst_idx);
             return -EINVAL;
         }
     } else {
-        ALOGE("%s: Invalid source surface format 0x%x", __FUNCTION__, src->format);
+        ALOGE("%s: Invalid source surface format 0x%x", __FUNCTION__,
+                                                        src->format);
         delete_handle(dst_hnd);
+        unmap_gpuaddr(ctx, mapped_dst_idx);
         return -EINVAL;
     }
 
@@ -1138,24 +1186,27 @@
     src_image.format = src->format;
     src_image.handle = src->handle;
 
-    bool needTempSource = need_temp_buffer(src);
+    bool need_temp_src = need_temp_buffer(src);
     bufferInfo src_info;
     populate_buffer_info(src, src_info);
     private_handle_t* src_hnd = new private_handle_t(-1, 0, 0, 0, src_info.format,
-                                                     src_info.width, src_info.height);
+                                                 src_info.width, src_info.height);
     if (NULL == src_hnd) {
         ALOGE("%s: src_hnd is null", __FUNCTION__);
         delete_handle(dst_hnd);
+        unmap_gpuaddr(ctx, mapped_dst_idx);
         return COPYBIT_FAILURE;
     }
-    if (needTempSource) {
+    if (need_temp_src) {
         if (get_size(src_info) != ctx->temp_src_buffer.size) {
             free_temp_buffer(ctx->temp_src_buffer);
             // Create a temp buffer and set that as the destination.
-            if (COPYBIT_SUCCESS != get_temp_buffer(src_info, ctx->temp_src_buffer)) {
+            if (COPYBIT_SUCCESS != get_temp_buffer(src_info,
+                                               ctx->temp_src_buffer)) {
                 ALOGE("%s: get_temp_buffer(src) failed", __FUNCTION__);
                 delete_handle(dst_hnd);
                 delete_handle(src_hnd);
+                unmap_gpuaddr(ctx, mapped_dst_idx);
                 return COPYBIT_FAILURE;
             }
         }
@@ -1168,7 +1219,15 @@
         src_image.handle = src_hnd;
 
         // Copy the source.
-        copy_image((private_handle_t *)src->handle, &src_image, CONVERT_TO_C2D_FORMAT);
+        status = copy_image((private_handle_t *)src->handle, &src_image,
+                                CONVERT_TO_C2D_FORMAT);
+        if (status == COPYBIT_FAILURE) {
+            ALOGE("%s:copy_image failed in temp source",__FUNCTION__);
+            delete_handle(dst_hnd);
+            delete_handle(src_hnd);
+            unmap_gpuaddr(ctx, mapped_dst_idx);
+            return status;
+        }
 
         // Flush the cache
         IMemAlloc* memalloc = sAlloc->getAllocator(src_hnd->flags);
@@ -1177,70 +1236,90 @@
             ALOGE("%s: clean_buffer failed", __FUNCTION__);
             delete_handle(dst_hnd);
             delete_handle(src_hnd);
+            unmap_gpuaddr(ctx, mapped_dst_idx);
             return COPYBIT_FAILURE;
         }
     }
 
-    status = set_image( ctx->src[src_surface_index], &src_image,
-                        &cformat, &src_mapped, (eC2DFlags)flags);
+    flags |= (ctx->is_premultiplied_alpha) ? FLAGS_PREMULTIPLIED_ALPHA : 0;
+    flags |= (ctx->dst_surface_type != RGB_SURFACE) ? FLAGS_YUV_DESTINATION : 0;
+    status = set_image(ctx, src_surface.surface_id, &src_image,
+                       (eC2DFlags)flags, mapped_src_idx);
     if(status) {
-        ALOGE("%s: set_src_image error", __FUNCTION__);
+        ALOGE("%s: set_image (src) error", __FUNCTION__);
         delete_handle(dst_hnd);
         delete_handle(src_hnd);
+        unmap_gpuaddr(ctx, mapped_dst_idx);
+        unmap_gpuaddr(ctx, mapped_src_idx);
         return COPYBIT_FAILURE;
     }
 
+    src_surface.config_mask = C2D_NO_BILINEAR_BIT | C2D_NO_ANTIALIASING_BIT |
+                              ctx->config_mask;
+    src_surface.global_alpha = ctx->src_global_alpha;
     if (enableBlend) {
-        if(ctx->blitState.config_mask & C2D_GLOBAL_ALPHA_BIT) {
-            ctx->blitState.config_mask &= ~C2D_ALPHA_BLEND_NONE;
-            if(!(ctx->blitState.global_alpha)) {
+        if(src_surface.config_mask & C2D_GLOBAL_ALPHA_BIT) {
+            src_surface.config_mask &= ~C2D_ALPHA_BLEND_NONE;
+            if(!(src_surface.global_alpha)) {
                 // src alpha is zero
-                unset_image( ctx->src[src_surface_index],
-                             &src_image, src_mapped);
-                unset_image( ctx->dst[dst_surface_index],
-                             &dst_image, trg_mapped);
                 delete_handle(dst_hnd);
                 delete_handle(src_hnd);
-                return status;
+                unmap_gpuaddr(ctx, mapped_dst_idx);
+                unmap_gpuaddr(ctx, mapped_src_idx);
+                return COPYBIT_FAILURE;
             }
         } else {
-            if(is_alpha(cformat))
-                ctx->blitState.config_mask &= ~C2D_ALPHA_BLEND_NONE;
+            int c2d_format = get_format(src->format);
+            if(is_alpha(c2d_format))
+                src_surface.config_mask &= ~C2D_ALPHA_BLEND_NONE;
             else
-                ctx->blitState.config_mask |= C2D_ALPHA_BLEND_NONE;
+                src_surface.config_mask |= C2D_ALPHA_BLEND_NONE;
         }
     } else {
-        ctx->blitState.config_mask |= C2D_ALPHA_BLEND_NONE;
+        src_surface.config_mask |= C2D_ALPHA_BLEND_NONE;
     }
 
-    ctx->blitState.surface_id = ctx->src[src_surface_index];
+    if (src_surface_type == RGB_SURFACE) {
+        ctx->blit_rgb_object[ctx->blit_rgb_count] = src_surface;
+        ctx->blit_rgb_count++;
+    } else if (src_surface_type == YUV_SURFACE_2_PLANES) {
+        ctx->blit_yuv_2_plane_object[ctx->blit_yuv_2_plane_count] = src_surface;
+        ctx->blit_yuv_2_plane_count++;
+    } else {
+        ctx->blit_yuv_3_plane_object[ctx->blit_yuv_3_plane_count] = src_surface;
+        ctx->blit_yuv_3_plane_count++;
+    }
 
+    struct copybit_rect_t clip;
     while ((status == 0) && region->next(region, &clip)) {
-        req = &(list.blitObjects[list.count]);
-        memcpy(req,&ctx->blitState,sizeof(C2D_OBJECT));
-
-        set_rects(ctx, req, dst_rect, src_rect, &clip);
-
-        if (++list.count == maxCount) {
-            status = msm_copybit(ctx, &list, ctx->dst[dst_surface_index]);
-            list.count = 0;
+        set_rects(ctx, &(src_surface), dst_rect, src_rect, &clip);
+        if (ctx->blit_count == MAX_BLIT_OBJECT_COUNT) {
+            ALOGW("Reached end of blit count");
+            finish_copybit(dev);
         }
-    }
-    if ((status == 0) && list.count) {
-        status = msm_copybit(ctx, &list, ctx->dst[dst_surface_index]);
+        ctx->blit_list[ctx->blit_count] = src_surface;
+        ctx->blit_count++;
     }
 
-    if(LINK_c2dFinish(ctx->dst[dst_surface_index])) {
-        ALOGE("%s: LINK_c2dFinish ERROR", __FUNCTION__);
+    // Check if we need to perform an early draw-finish.
+    flags |= (need_temp_dst || need_temp_src) ? FLAGS_TEMP_SRC_DST : 0;
+    if (need_to_execute_draw(ctx, (eC2DFlags)flags))
+    {
+        finish_copybit(dev);
     }
 
-    unset_image( ctx->src[src_surface_index], &src_image,
-                 src_mapped);
-    unset_image( ctx->dst[dst_surface_index], &dst_image,
-                 trg_mapped);
-    if (needTempDestination) {
-        // copy the temp. destination without the alignment to the actual destination.
-        copy_image(dst_hnd, dst, CONVERT_TO_ANDROID_FORMAT);
+    if (need_temp_dst) {
+        // copy the temp. destination without the alignment to the actual
+        // destination.
+        status = copy_image(dst_hnd, dst, CONVERT_TO_ANDROID_FORMAT);
+        if (status == COPYBIT_FAILURE) {
+            ALOGE("%s:copy_image failed in temp Dest",__FUNCTION__);
+            delete_handle(dst_hnd);
+            delete_handle(src_hnd);
+            unmap_gpuaddr(ctx, mapped_dst_idx);
+            unmap_gpuaddr(ctx, mapped_src_idx);
+            return status;
+        }
         // Invalidate the cache.
         IMemAlloc* memalloc = sAlloc->getAllocator(dst_hnd->flags);
         memalloc->clean_buffer((void *)(dst_hnd->base), dst_hnd->size,
@@ -1248,12 +1327,15 @@
     }
     delete_handle(dst_hnd);
     delete_handle(src_hnd);
-    ctx->isPremultipliedAlpha = false;
+
+    ctx->is_premultiplied_alpha = false;
     ctx->fb_width = 0;
     ctx->fb_height = 0;
+    ctx->config_mask = 0;
     return status;
 }
 
+
 static int stretch_copybit(
     struct copybit_device_t *dev,
     struct copybit_image_t const *dst,
@@ -1263,9 +1345,13 @@
     struct copybit_region_t const *region)
 {
     struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
-    bool needsBlending = (ctx->blitState.global_alpha != 0);
-    return stretch_copybit_internal(dev, dst, src, dst_rect, src_rect,
+    int status = COPYBIT_SUCCESS;
+    bool needsBlending = (ctx->src_global_alpha != 0);
+    pthread_mutex_lock(&ctx->wait_cleanup_lock);
+    status = stretch_copybit_internal(dev, dst, src, dst_rect, src_rect,
                                     region, needsBlending);
+    pthread_mutex_unlock(&ctx->wait_cleanup_lock);
+    return status;
 }
 
 /** Perform a blit type operation */
@@ -1282,26 +1368,60 @@
 
 /*****************************************************************************/
 
+static void clean_up(copybit_context_t* ctx)
+{
+    void* ret;
+    if (!ctx)
+        return;
+
+    // stop the wait_cleanup_thread
+    pthread_mutex_lock(&ctx->wait_cleanup_lock);
+    ctx->stop_thread = true;
+    // Signal waiting thread
+    pthread_cond_signal(&ctx->wait_cleanup_cond);
+    pthread_mutex_unlock(&ctx->wait_cleanup_lock);
+    // waits for the cleanup thread to exit
+    pthread_join(ctx->wait_thread_id, &ret);
+    pthread_mutex_destroy(&ctx->wait_cleanup_lock);
+    pthread_cond_destroy (&ctx->wait_cleanup_cond);
+
+    for (int i = 0; i < NUM_SURFACE_TYPES; i++) {
+        if (ctx->dst[i])
+            LINK_c2dDestroySurface(ctx->dst[i]);
+    }
+
+    for (int i = 0; i < MAX_RGB_SURFACES; i++) {
+        if (ctx->blit_rgb_object[i].surface_id)
+            LINK_c2dDestroySurface(ctx->blit_rgb_object[i].surface_id);
+    }
+
+    for (int i = 0; i < MAX_YUV_2_PLANE_SURFACES; i++) {
+        if (ctx->blit_yuv_2_plane_object[i].surface_id)
+            LINK_c2dDestroySurface(ctx->blit_yuv_2_plane_object[i].surface_id);
+    }
+
+    for (int i = 0; i < MAX_YUV_3_PLANE_SURFACES; i++) {
+        if (ctx->blit_yuv_3_plane_object[i].surface_id)
+            LINK_c2dDestroySurface(ctx->blit_yuv_3_plane_object[i].surface_id);
+    }
+
+    if (ctx->libc2d2) {
+        ::dlclose(ctx->libc2d2);
+        ALOGV("dlclose(libc2d2)");
+    }
+
+    free(ctx);
+}
+
 /** Close the copybit device */
 static int close_copybit(struct hw_device_t *dev)
 {
     struct copybit_context_t* ctx = (struct copybit_context_t*)dev;
     if (ctx) {
-        for(int i = 0; i <NUM_SURFACES; i++) {
-            LINK_c2dDestroySurface(ctx->dst[i]);
-            LINK_c2dDestroySurface(ctx->src[i]);
-        }
-
-        if (ctx->libc2d2) {
-            ::dlclose(ctx->libc2d2);
-            ALOGV("dlclose(libc2d2)");
-        }
-
         free_temp_buffer(ctx->temp_src_buffer);
         free_temp_buffer(ctx->temp_dst_buffer);
-        free(ctx);
     }
-
+    clean_up(ctx);
     return 0;
 }
 
@@ -1323,16 +1443,13 @@
 
     /* initialize drawstate */
     memset(ctx, 0, sizeof(*ctx));
-
-    for (int i=0; i< NUM_SURFACES; i++) {
-        ctx->dst[i] = -1;
-        ctx->src[i] = -1;
-    }
-
     ctx->libc2d2 = ::dlopen("libC2D2.so", RTLD_NOW);
     if (!ctx->libc2d2) {
         ALOGE("FATAL ERROR: could not dlopen libc2d2.so: %s", dlerror());
-        goto error;
+        clean_up(ctx);
+        status = COPYBIT_FAILURE;
+        *device = NULL;
+        return status;
     }
     *(void **)&LINK_c2dCreateSurface = ::dlsym(ctx->libc2d2,
                                                "c2dCreateSurface");
@@ -1351,12 +1468,20 @@
                                          "c2dMapAddr");
     *(void **)&LINK_c2dUnMapAddr = ::dlsym(ctx->libc2d2,
                                            "c2dUnMapAddr");
+    *(void **)&LINK_c2dGetDriverCapabilities = ::dlsym(ctx->libc2d2,
+                                           "c2dGetDriverCapabilities");
+    *(void **)&LINK_c2dCreateFenceFD = ::dlsym(ctx->libc2d2,
+                                           "c2dCreateFenceFD");
 
     if (!LINK_c2dCreateSurface || !LINK_c2dUpdateSurface || !LINK_c2dReadSurface
-        || !LINK_c2dDraw || !LINK_c2dFlush || !LINK_c2dWaitTimestamp || !LINK_c2dFinish
-        || !LINK_c2dDestroySurface) {
+        || !LINK_c2dDraw || !LINK_c2dFlush || !LINK_c2dWaitTimestamp ||
+        !LINK_c2dFinish  || !LINK_c2dDestroySurface ||
+        !LINK_c2dGetDriverCapabilities || !LINK_c2dCreateFenceFD) {
         ALOGE("%s: dlsym ERROR", __FUNCTION__);
-        goto error;
+        clean_up(ctx);
+        status = COPYBIT_FAILURE;
+        *device = NULL;
+        return status;
     }
 
     ctx->device.common.tag = HARDWARE_DEVICE_TAG;
@@ -1367,8 +1492,8 @@
     ctx->device.get = get;
     ctx->device.blit = blit_copybit;
     ctx->device.stretch = stretch_copybit;
-    ctx->blitState.config_mask = C2D_NO_BILINEAR_BIT | C2D_NO_ANTIALIASING_BIT;
-    ctx->trg_transform = C2D_TARGET_ROTATE_0;
+    ctx->device.finish = finish_copybit;
+    ctx->device.flush_get_fence = flush_get_fence_copybit;
 
     /* Create RGB Surface */
     surfDefinition.buffer = (void*)0xdddddddd;
@@ -1379,24 +1504,45 @@
     surfDefinition.format = C2D_COLOR_FORMAT_8888_ARGB;
     if (LINK_c2dCreateSurface(&(ctx->dst[RGB_SURFACE]), C2D_TARGET | C2D_SOURCE,
                               (C2D_SURFACE_TYPE)(C2D_SURFACE_RGB_HOST |
-                                                 C2D_SURFACE_WITH_PHYS | C2D_SURFACE_WITH_PHYS_DUMMY ), &surfDefinition)) {
-        ALOGE("%s: create ctx->dst[RGB_SURFACE] failed", __FUNCTION__);
-        ctx->dst[RGB_SURFACE] = -1;
-        goto error;
+                                                 C2D_SURFACE_WITH_PHYS |
+                                                 C2D_SURFACE_WITH_PHYS_DUMMY ),
+                                                 &surfDefinition)) {
+        ALOGE("%s: create ctx->dst_surface[RGB_SURFACE] failed", __FUNCTION__);
+        ctx->dst[RGB_SURFACE] = 0;
+        clean_up(ctx);
+        status = COPYBIT_FAILURE;
+        *device = NULL;
+        return status;
     }
 
-
-    if (LINK_c2dCreateSurface(&(ctx->src[RGB_SURFACE]), C2D_TARGET | C2D_SOURCE,
+    unsigned int surface_id = 0;
+    for (int i = 0; i < MAX_RGB_SURFACES; i++)
+    {
+        if (LINK_c2dCreateSurface(&surface_id, C2D_TARGET | C2D_SOURCE,
                               (C2D_SURFACE_TYPE)(C2D_SURFACE_RGB_HOST |
-                                                 C2D_SURFACE_WITH_PHYS | C2D_SURFACE_WITH_PHYS_DUMMY), &surfDefinition)) {
-        ALOGE("%s: create ctx->src[RGB_SURFACE] failed", __FUNCTION__);
-        ctx->src[RGB_SURFACE] = -1;
-        goto error;
+                                                 C2D_SURFACE_WITH_PHYS |
+                                                 C2D_SURFACE_WITH_PHYS_DUMMY ),
+                                                 &surfDefinition)) {
+            ALOGE("%s: create RGB source surface %d failed", __FUNCTION__, i);
+            ctx->blit_rgb_object[i].surface_id = 0;
+            status = COPYBIT_FAILURE;
+            break;
+        } else {
+            ctx->blit_rgb_object[i].surface_id = surface_id;
+            ALOGW("%s i = %d surface_id=%d",  __FUNCTION__, i,
+                                          ctx->blit_rgb_object[i].surface_id);
+        }
     }
 
-    /* Create YUV source surface */
-    yuvSurfaceDef.format = C2D_COLOR_FORMAT_420_NV12;
+    if (status == COPYBIT_FAILURE) {
+        clean_up(ctx);
+        status = COPYBIT_FAILURE;
+        *device = NULL;
+        return status;
+    }
 
+    // Create 2 plane YUV surfaces
+    yuvSurfaceDef.format = C2D_COLOR_FORMAT_420_NV12;
     yuvSurfaceDef.width = 4;
     yuvSurfaceDef.height = 4;
     yuvSurfaceDef.plane0 = (void*)0xaaaaaaaa;
@@ -1406,48 +1552,101 @@
     yuvSurfaceDef.plane1 = (void*)0xaaaaaaaa;
     yuvSurfaceDef.phys1 = (void*) 0xaaaaaaaa;
     yuvSurfaceDef.stride1 = 4;
-
-    if (LINK_c2dCreateSurface(&(ctx->src[YUV_SURFACE_2_PLANES]),
-                              C2D_TARGET | C2D_SOURCE,
-                              (C2D_SURFACE_TYPE)(C2D_SURFACE_YUV_HOST|C2D_SURFACE_WITH_PHYS | C2D_SURFACE_WITH_PHYS_DUMMY),
-                              &yuvSurfaceDef)) {
-        ALOGE("%s: create ctx->src[YUV_SURFACE_2_PLANES] failed", __FUNCTION__);
-        ctx->src[YUV_SURFACE_2_PLANES] = -1;
-        goto error;
-    }
-
     if (LINK_c2dCreateSurface(&(ctx->dst[YUV_SURFACE_2_PLANES]),
                               C2D_TARGET | C2D_SOURCE,
-                              (C2D_SURFACE_TYPE)(C2D_SURFACE_YUV_HOST | C2D_SURFACE_WITH_PHYS | C2D_SURFACE_WITH_PHYS_DUMMY),
+                              (C2D_SURFACE_TYPE)(C2D_SURFACE_YUV_HOST |
+                               C2D_SURFACE_WITH_PHYS |
+                               C2D_SURFACE_WITH_PHYS_DUMMY),
                               &yuvSurfaceDef)) {
         ALOGE("%s: create ctx->dst[YUV_SURFACE_2_PLANES] failed", __FUNCTION__);
-        ctx->dst[YUV_SURFACE_2_PLANES] = -1;
-        goto error;
+        ctx->dst[YUV_SURFACE_2_PLANES] = 0;
+        clean_up(ctx);
+        status = COPYBIT_FAILURE;
+        *device = NULL;
+        return status;
     }
 
+    for (int i=0; i < MAX_YUV_2_PLANE_SURFACES; i++)
+    {
+        if (LINK_c2dCreateSurface(&surface_id, C2D_TARGET | C2D_SOURCE,
+                              (C2D_SURFACE_TYPE)(C2D_SURFACE_YUV_HOST |
+                                                 C2D_SURFACE_WITH_PHYS |
+                                                 C2D_SURFACE_WITH_PHYS_DUMMY ),
+                              &yuvSurfaceDef)) {
+            ALOGE("%s: create YUV source %d failed", __FUNCTION__, i);
+            ctx->blit_yuv_2_plane_object[i].surface_id = 0;
+            status = COPYBIT_FAILURE;
+            break;
+        } else {
+            ctx->blit_yuv_2_plane_object[i].surface_id = surface_id;
+            ALOGW("%s: 2 Plane YUV i=%d surface_id=%d",  __FUNCTION__, i,
+                                   ctx->blit_yuv_2_plane_object[i].surface_id);
+        }
+    }
+
+    if (status == COPYBIT_FAILURE) {
+        clean_up(ctx);
+        status = COPYBIT_FAILURE;
+        *device = NULL;
+        return status;
+    }
+
+    // Create YUV 3 plane surfaces
     yuvSurfaceDef.format = C2D_COLOR_FORMAT_420_YV12;
     yuvSurfaceDef.plane2 = (void*)0xaaaaaaaa;
     yuvSurfaceDef.phys2 = (void*) 0xaaaaaaaa;
     yuvSurfaceDef.stride2 = 4;
 
-    if (LINK_c2dCreateSurface(&(ctx->src[YUV_SURFACE_3_PLANES]),
-                              C2D_TARGET | C2D_SOURCE,
-                              (C2D_SURFACE_TYPE)(C2D_SURFACE_YUV_HOST | C2D_SURFACE_WITH_PHYS | C2D_SURFACE_WITH_PHYS_DUMMY),
-                              &yuvSurfaceDef)) {
-        ALOGE("%s: create ctx->src[YUV_SURFACE_3_PLANES] failed", __FUNCTION__);
-        ctx->src[YUV_SURFACE_3_PLANES] = -1;
-        goto error;
-    }
-
     if (LINK_c2dCreateSurface(&(ctx->dst[YUV_SURFACE_3_PLANES]),
                               C2D_TARGET | C2D_SOURCE,
-                              (C2D_SURFACE_TYPE)(C2D_SURFACE_YUV_HOST | C2D_SURFACE_WITH_PHYS | C2D_SURFACE_WITH_PHYS_DUMMY),
+                              (C2D_SURFACE_TYPE)(C2D_SURFACE_YUV_HOST |
+                                                 C2D_SURFACE_WITH_PHYS |
+                                                 C2D_SURFACE_WITH_PHYS_DUMMY),
                               &yuvSurfaceDef)) {
         ALOGE("%s: create ctx->dst[YUV_SURFACE_3_PLANES] failed", __FUNCTION__);
-        ctx->dst[YUV_SURFACE_3_PLANES] = -1;
-        goto error;
+        ctx->dst[YUV_SURFACE_3_PLANES] = 0;
+        clean_up(ctx);
+        status = COPYBIT_FAILURE;
+        *device = NULL;
+        return status;
     }
 
+    for (int i=0; i < MAX_YUV_3_PLANE_SURFACES; i++)
+    {
+        if (LINK_c2dCreateSurface(&(surface_id),
+                              C2D_TARGET | C2D_SOURCE,
+                              (C2D_SURFACE_TYPE)(C2D_SURFACE_YUV_HOST |
+                                                 C2D_SURFACE_WITH_PHYS |
+                                                 C2D_SURFACE_WITH_PHYS_DUMMY),
+                              &yuvSurfaceDef)) {
+            ALOGE("%s: create 3 plane YUV surface %d failed", __FUNCTION__, i);
+            ctx->blit_yuv_3_plane_object[i].surface_id = 0;
+            status = COPYBIT_FAILURE;
+            break;
+        } else {
+            ctx->blit_yuv_3_plane_object[i].surface_id = surface_id;
+            ALOGW("%s: 3 Plane YUV i=%d surface_id=%d",  __FUNCTION__, i,
+                                   ctx->blit_yuv_3_plane_object[i].surface_id);
+        }
+    }
+
+    if (status == COPYBIT_FAILURE) {
+        clean_up(ctx);
+        status = COPYBIT_FAILURE;
+        *device = NULL;
+        return status;
+    }
+
+    if (LINK_c2dGetDriverCapabilities(&(ctx->c2d_driver_info))) {
+         ALOGE("%s: LINK_c2dGetDriverCapabilities failed", __FUNCTION__);
+         clean_up(ctx);
+         status = COPYBIT_FAILURE;
+        *device = NULL;
+        return status;
+    }
+    // Initialize context variables.
+    ctx->trg_transform = C2D_TARGET_ROTATE_0;
+
     ctx->temp_src_buffer.fd = -1;
     ctx->temp_src_buffer.base = 0;
     ctx->temp_src_buffer.size = 0;
@@ -1458,28 +1657,25 @@
 
     ctx->fb_width = 0;
     ctx->fb_height = 0;
-    ctx->isPremultipliedAlpha = false;
+
+    ctx->blit_rgb_count = 0;
+    ctx->blit_yuv_2_plane_count = 0;
+    ctx->blit_yuv_3_plane_count = 0;
+    ctx->blit_count = 0;
+
+    ctx->wait_timestamp = false;
+    ctx->stop_thread = false;
+    pthread_mutex_init(&(ctx->wait_cleanup_lock), NULL);
+    pthread_cond_init(&(ctx->wait_cleanup_cond), NULL);
+    /* Start the wait thread */
+    pthread_attr_t attr;
+    pthread_attr_init(&attr);
+    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
+
+    pthread_create(&ctx->wait_thread_id, &attr, &c2d_wait_loop,
+                                                            (void *)ctx);
+    pthread_attr_destroy(&attr);
 
     *device = &ctx->device.common;
     return status;
-
-error:
-    for (int i = 0; i<NUM_SURFACES; i++) {
-        if (-1 != (ctx->src[i])) {
-            LINK_c2dDestroySurface(ctx->src[i]);
-            ctx->src[i] = -1;
-        }
-        if (-1 != (ctx->dst[i])) {
-            LINK_c2dDestroySurface(ctx->dst[i]);
-            ctx->dst[i] = -1;
-        }
-    }
-    if (ctx->libc2d2)
-        ::dlclose(ctx->libc2d2);
-    if (ctx)
-        free(ctx);
-    status = COPYBIT_FAILURE;
-    *device = NULL;
-
-    return status;
 }
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/libgralloc/framebuffer.cpp b/libgralloc/framebuffer.cpp
index 1193a27..5293ca9 100644
--- a/libgralloc/framebuffer.cpp
+++ b/libgralloc/framebuffer.cpp
@@ -267,9 +267,20 @@
 
     float xdpi = (info.xres * 25.4f) / info.width;
     float ydpi = (info.yres * 25.4f) / info.height;
+#ifdef MSMFB_METADATA_GET
+    struct msmfb_metadata metadata;
+    memset(&metadata, 0 , sizeof(metadata));
+    metadata.op = metadata_op_frame_rate;
+    if (ioctl(fd, MSMFB_METADATA_GET, &metadata) == -1) {
+        ALOGE("Error retrieving panel frame rate");
+        return -errno;
+    }
+    float fps  = metadata.data.panel_frame_rate;
+#else
+    //XXX: Remove reserved field usage on all baselines
     //The reserved[3] field is used to store FPS by the driver.
     float fps  = info.reserved[3] & 0xFF;
-
+#endif
     ALOGI("using (fd=%d)\n"
           "id           = %s\n"
           "xres         = %d px\n"
diff --git a/libgralloc/gpu.cpp b/libgralloc/gpu.cpp
index 656df38..0d070f0 100644
--- a/libgralloc/gpu.cpp
+++ b/libgralloc/gpu.cpp
@@ -47,6 +47,7 @@
     common.module  = const_cast<hw_module_t*>(&module->base.common);
     common.close   = gralloc_close;
     alloc          = gralloc_alloc;
+    allocSize      = gralloc_alloc_size;
     free           = gralloc_free;
 
 }
@@ -246,7 +247,7 @@
 
     if ((ssize_t)size <= 0)
         return -EINVAL;
-    size = (bufferSize >= size)? bufferSize : size;
+    size = (bufferSize != 0)? bufferSize : size;
 
     // All buffers marked as protected or for external
     // display need to go to overlay
diff --git a/libgralloc/gralloc_priv.h b/libgralloc/gralloc_priv.h
index 6ccc7e0..dc755cb 100644
--- a/libgralloc/gralloc_priv.h
+++ b/libgralloc/gralloc_priv.h
@@ -84,7 +84,8 @@
 enum {
     /* Gralloc perform enums
     */
-    GRALLOC_MODULE_PERFORM_CREATE_HANDLE_FROM_BUFFER = 0x080000001,
+    GRALLOC_MODULE_PERFORM_CREATE_HANDLE_FROM_BUFFER =
+                                    GRALLOC_MODULE_PERFORM_PRIVATE_START,
 };
 
 #define GRALLOC_HEAP_MASK   (GRALLOC_USAGE_PRIVATE_UI_CONTIG_HEAP |\
diff --git a/libgralloc/mapper.cpp b/libgralloc/mapper.cpp
index 176a84e..197c372 100644
--- a/libgralloc/mapper.cpp
+++ b/libgralloc/mapper.cpp
@@ -348,6 +348,21 @@
                 break;
 
             }
+        case GRALLOC_MODULE_PERFORM_UPDATE_BUFFER_GEOMETRY:
+            {
+                int width = va_arg(args, int);
+                int height = va_arg(args, int);
+                int format = va_arg(args, int);
+                private_handle_t* hnd =  va_arg(args, private_handle_t*);
+                if (private_handle_t::validate(hnd)) {
+                    return res;
+                }
+                hnd->width = width;
+                hnd->height = height;
+                hnd->format = format;
+                res = 0;
+            }
+            break;
         default:
             break;
     }
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_mdpcomp.cpp b/libhwcomposer/hwc_mdpcomp.cpp
index 2c0a77a..2e58b93 100644
--- a/libhwcomposer/hwc_mdpcomp.cpp
+++ b/libhwcomposer/hwc_mdpcomp.cpp
@@ -215,7 +215,8 @@
     if(isSecureBuffer(hnd)) {
         ovutils::setMdpFlags(mdpFlags, ovutils::OV_MDP_SECURE_OVERLAY_SESSION);
     }
-    if((metadata->operation & PP_PARAM_INTERLACED) && metadata->interlaced) {
+    if(metadata && (metadata->operation & PP_PARAM_INTERLACED) &&
+                                              metadata->interlaced) {
         ovutils::setMdpFlags(mdpFlags, ovutils::OV_MDP_DEINTERLACE);
     }
 }
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/libhwcomposer/hwc_video.cpp b/libhwcomposer/hwc_video.cpp
index 1784593..16d0c89 100644
--- a/libhwcomposer/hwc_video.cpp
+++ b/libhwcomposer/hwc_video.cpp
@@ -108,7 +108,8 @@
     }
 
     MetaData_t *metadata = (MetaData_t *)hnd->base_metadata;
-    if ((metadata->operation & PP_PARAM_INTERLACED) && metadata->interlaced) {
+    if (metadata && (metadata->operation & PP_PARAM_INTERLACED) &&
+                                             metadata->interlaced) {
         ovutils::setMdpFlags(mdpFlags, ovutils::OV_MDP_DEINTERLACE);
     }
 
diff --git a/liboverlay/overlayMdssRot.cpp b/liboverlay/overlayMdssRot.cpp
index dedc396..071e9f2 100644
--- a/liboverlay/overlayMdssRot.cpp
+++ b/liboverlay/overlayMdssRot.cpp
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2008 The Android Open Source Project
- * Copyright (c) 2010-2012, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
  * Not a Contribution, Apache license notifications and license are retained
  * for attribution purposes only.
  *
@@ -95,10 +95,7 @@
 }
 
 void MdssRot::setFlags(const utils::eMdpFlags& flags) {
-    mRotInfo.flags &= ~utils::OV_MDP_SECURE_OVERLAY_SESSION;
-    if (flags & utils::OV_MDP_SECURE_OVERLAY_SESSION) {
-        mRotInfo.flags |= utils::OV_MDP_SECURE_OVERLAY_SESSION;
-    }
+    mRotInfo.flags |= flags;
 }
 
 void MdssRot::setTransform(const utils::eTransform& rot, const bool& rotUsed)
@@ -132,6 +129,8 @@
         return false;
     }
     mRotData.id = mRotInfo.id;
+    //reset flags to avoid stale orientation values
+    mRotInfo.flags = 0;
     return true;
 }
 
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