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)));