hwc: Add support for copybit(C2D) composition

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

Change-Id: I052da015cd031f7abd6411d83d7944c335caeff7
diff --git a/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;