hwc: sync-point implementation.

Add sync pt implementation.
Add genlock and sync pt under conditional compilation flags.

Change-Id: I32fb7f6051ccc706662152e90ac15b6b6743f897
Signed-off-by: Iliyan Malchev <malchev@google.com>
diff --git a/common.mk b/common.mk
index 30896a8..ed8edc3 100644
--- a/common.mk
+++ b/common.mk
@@ -21,6 +21,12 @@
 common_flags := -DDEBUG_CALC_FPS -Wno-missing-field-initializers
 common_flags += -Werror
 
+#TODO
+#ifeq ($(call is-vendor-board-platform,QCOM),true)
+ifeq ($(TARGET_BOARD_PLATFORM), msm8960)
+    common_flags += -DUSE_FENCE_SYNC
+endif
+
 ifeq ($(ARCH_ARM_HAVE_NEON),true)
     common_flags += -D__ARM_HAVE_NEON
 endif
diff --git a/libhwcomposer/hwc.cpp b/libhwcomposer/hwc.cpp
index ab55ea6..e688538 100644
--- a/libhwcomposer/hwc.cpp
+++ b/libhwcomposer/hwc.cpp
@@ -209,6 +209,10 @@
             VideoOverlay::draw(ctx, list);
             ExtOnly::draw(ctx, list);
             MDPComp::draw(ctx, list);
+
+            //Sync TODO better error handling.
+            hwc_sync(list);
+
             EGLBoolean success = eglSwapBuffers((EGLDisplay)list->dpy,
                                                 (EGLSurface)list->sur);
             wait4fbPost(ctx);
diff --git a/libhwcomposer/hwc_qbuf.h b/libhwcomposer/hwc_qbuf.h
index 0e639cf..90f7143 100644
--- a/libhwcomposer/hwc_qbuf.h
+++ b/libhwcomposer/hwc_qbuf.h
@@ -16,7 +16,10 @@
  */
 
 #include <gralloc_priv.h>
+
+#ifndef USE_FENCE_SYNC
 #include <genlock.h>
+#endif
 
 // -----------------------------------------------------------------------------
 // QueuedBufferStore
@@ -56,12 +59,15 @@
 
 //Store and lock current drawing round buffers
 inline void QueuedBufferStore::lockAndAdd(private_handle_t *hnd) {
+#ifndef USE_FENCE_SYNC
     if(lockBuffer(hnd))
         current[curCount++] = hnd;
+#endif
 }
 
 //Unlock all previous drawing round buffers
 inline void QueuedBufferStore::unlockAllPrevious() {
+#ifndef USE_FENCE_SYNC
     //Unlock
     for(int i = 0; i < prevCount; i++) {
         unlockBuffer(previous[i]);
@@ -71,46 +77,58 @@
     mvCurrToPrev();
     //Clear current
     clearCurrent();
+#endif
 }
 
 inline void QueuedBufferStore::unlockAll() {
+#ifndef USE_FENCE_SYNC
     //Unlocks prev and moves current to prev
     unlockAllPrevious();
     //Unlocks the newly populated prev if any.
     unlockAllPrevious();
+#endif
 }
 
 //Clear currentbuf store
 inline void QueuedBufferStore::clearCurrent() {
+#ifndef USE_FENCE_SYNC
     for(int i = 0; i < MAX_QUEUED_BUFS; i++)
         current[i] = NULL;
     curCount = 0;
+#endif
 }
 
 //Clear previousbuf store
 inline void QueuedBufferStore::clearPrevious() {
+#ifndef USE_FENCE_SYNC
     for(int i = 0; i < MAX_QUEUED_BUFS; i++)
         previous[i] = NULL;
     prevCount = 0;
+#endif
 }
 
 //Copy from current to previous
 inline void QueuedBufferStore::mvCurrToPrev() {
+#ifndef USE_FENCE_SYNC
     for(int i = 0; i < curCount; i++)
         previous[i] = current[i];
     prevCount = curCount;
+#endif
 }
 
 inline bool QueuedBufferStore::lockBuffer(private_handle_t *hnd) {
+#ifndef USE_FENCE_SYNC
     if (GENLOCK_FAILURE == genlock_lock_buffer(hnd, GENLOCK_READ_LOCK,
                                                GENLOCK_MAX_TIMEOUT)) {
         ALOGE("%s: genlock_lock_buffer(READ) failed", __func__);
         return false;
     }
+#endif
     return true;
 }
 
 inline void QueuedBufferStore::unlockBuffer(private_handle_t *hnd) {
+#ifndef USE_FENCE_SYNC
     //Check if buffer is still around
     if(private_handle_t::validate(hnd) != 0) {
         ALOGE("%s Invalid Handle", __func__);
@@ -121,6 +139,7 @@
         ALOGE("%s: genlock_unlock_buffer failed", __func__);
         return;
     }
+#endif
 }
 // -----------------------------------------------------------------------------
 };//namespace
diff --git a/libhwcomposer/hwc_utils.cpp b/libhwcomposer/hwc_utils.cpp
index 7c4ad27..b957721 100644
--- a/libhwcomposer/hwc_utils.cpp
+++ b/libhwcomposer/hwc_utils.cpp
@@ -238,4 +238,61 @@
         pthread_mutex_unlock(&m->fbPanLock);
     }
 }
+
+int hwc_sync(hwc_display_contents_1_t* list) {
+    int ret = 0;
+#ifdef USE_FENCE_SYNC
+    struct mdp_buf_sync data;
+    int acquireFd[10];
+    int count = 0;
+    int releaseFd = -1;
+    int fbFd = -1;
+    data.flags = 0;
+    data.acq_fen_fd = acquireFd;
+    data.rel_fen_fd = &releaseFd;
+    //Accumulate acquireFenceFds
+    for(uint32_t i = 0; i < list->numHwLayers; i++) {
+        if(list->hwLayers[i].compositionType == HWC_OVERLAY &&
+            list->hwLayers[i].acquireFenceFd != -1) {
+            acquireFd[count++] = list->hwLayers[i].acquireFenceFd;
+        }
+    }
+
+    if (count) {
+        data.acq_fen_fd_cnt = count;
+
+        //Open fb0 for ioctl
+        fbFd = open("/dev/graphics/fb0", O_RDWR);
+        if (fbFd < 0) {
+            ALOGE("%s: /dev/graphics/fb0 not available", __FUNCTION__);
+            return -1;
+        }
+
+        //Waits for acquire fences, returns a release fence
+        ret = ioctl(fbFd, MSMFB_BUFFER_SYNC, &data);
+        if(ret < 0) {
+            ALOGE("ioctl MSMFB_BUFFER_SYNC failed, err=%s",
+                    strerror(errno));
+        }
+        close(fbFd);
+
+        for(uint32_t i = 0; i < list->numHwLayers; i++) {
+            if(list->hwLayers[i].compositionType == HWC_OVERLAY) {
+                //Close the acquireFenceFds
+                if(list->hwLayers[i].acquireFenceFd > 0) {
+                    close(list->hwLayers[i].acquireFenceFd);
+                    list->hwLayers[i].acquireFenceFd = -1;
+                }
+                //Populate releaseFenceFds.
+                if (releaseFd != -1)
+                    list->hwLayers[i].releaseFenceFd = dup(releaseFd);
+            }
+        }
+        if (releaseFd != -1)
+            close(releaseFd);
+    }
+#endif
+    return ret;
+}
+
 };//namespace
diff --git a/libhwcomposer/hwc_utils.h b/libhwcomposer/hwc_utils.h
index 184d967..1153cc7 100644
--- a/libhwcomposer/hwc_utils.h
+++ b/libhwcomposer/hwc_utils.h
@@ -87,6 +87,9 @@
 // Waits for the fb_post to finish PAN (primary commit)
 void wait4Pan(hwc_context_t* ctx);
 
+//Sync point impl.
+int hwc_sync(hwc_display_contents_1_t* list);
+
 // Inline utility functions
 static inline bool isSkipLayer(const hwc_layer_1_t* l) {
     return (UNLIKELY(l && (l->flags & HWC_SKIP_LAYER)));