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>
This commit is contained in:
Kinjal Bhavsar
2012-09-18 18:27:59 -07:00
committed by Iliyan Malchev
parent 0a03dd8b11
commit 2dd04a873b
5 changed files with 89 additions and 0 deletions

View File

@@ -21,6 +21,12 @@ common_libs := liblog libutils libcutils libhardware
common_flags := -DDEBUG_CALC_FPS -Wno-missing-field-initializers common_flags := -DDEBUG_CALC_FPS -Wno-missing-field-initializers
common_flags += -Werror 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) ifeq ($(ARCH_ARM_HAVE_NEON),true)
common_flags += -D__ARM_HAVE_NEON common_flags += -D__ARM_HAVE_NEON
endif endif

View File

@@ -209,6 +209,10 @@ static int hwc_set(hwc_composer_device_1 *dev,
VideoOverlay::draw(ctx, list); VideoOverlay::draw(ctx, list);
ExtOnly::draw(ctx, list); ExtOnly::draw(ctx, list);
MDPComp::draw(ctx, list); MDPComp::draw(ctx, list);
//Sync TODO better error handling.
hwc_sync(list);
EGLBoolean success = eglSwapBuffers((EGLDisplay)list->dpy, EGLBoolean success = eglSwapBuffers((EGLDisplay)list->dpy,
(EGLSurface)list->sur); (EGLSurface)list->sur);
wait4fbPost(ctx); wait4fbPost(ctx);

View File

@@ -16,7 +16,10 @@
*/ */
#include <gralloc_priv.h> #include <gralloc_priv.h>
#ifndef USE_FENCE_SYNC
#include <genlock.h> #include <genlock.h>
#endif
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// QueuedBufferStore // QueuedBufferStore
@@ -56,12 +59,15 @@ class QueuedBufferStore {
//Store and lock current drawing round buffers //Store and lock current drawing round buffers
inline void QueuedBufferStore::lockAndAdd(private_handle_t *hnd) { inline void QueuedBufferStore::lockAndAdd(private_handle_t *hnd) {
#ifndef USE_FENCE_SYNC
if(lockBuffer(hnd)) if(lockBuffer(hnd))
current[curCount++] = hnd; current[curCount++] = hnd;
#endif
} }
//Unlock all previous drawing round buffers //Unlock all previous drawing round buffers
inline void QueuedBufferStore::unlockAllPrevious() { inline void QueuedBufferStore::unlockAllPrevious() {
#ifndef USE_FENCE_SYNC
//Unlock //Unlock
for(int i = 0; i < prevCount; i++) { for(int i = 0; i < prevCount; i++) {
unlockBuffer(previous[i]); unlockBuffer(previous[i]);
@@ -71,46 +77,58 @@ inline void QueuedBufferStore::unlockAllPrevious() {
mvCurrToPrev(); mvCurrToPrev();
//Clear current //Clear current
clearCurrent(); clearCurrent();
#endif
} }
inline void QueuedBufferStore::unlockAll() { inline void QueuedBufferStore::unlockAll() {
#ifndef USE_FENCE_SYNC
//Unlocks prev and moves current to prev //Unlocks prev and moves current to prev
unlockAllPrevious(); unlockAllPrevious();
//Unlocks the newly populated prev if any. //Unlocks the newly populated prev if any.
unlockAllPrevious(); unlockAllPrevious();
#endif
} }
//Clear currentbuf store //Clear currentbuf store
inline void QueuedBufferStore::clearCurrent() { inline void QueuedBufferStore::clearCurrent() {
#ifndef USE_FENCE_SYNC
for(int i = 0; i < MAX_QUEUED_BUFS; i++) for(int i = 0; i < MAX_QUEUED_BUFS; i++)
current[i] = NULL; current[i] = NULL;
curCount = 0; curCount = 0;
#endif
} }
//Clear previousbuf store //Clear previousbuf store
inline void QueuedBufferStore::clearPrevious() { inline void QueuedBufferStore::clearPrevious() {
#ifndef USE_FENCE_SYNC
for(int i = 0; i < MAX_QUEUED_BUFS; i++) for(int i = 0; i < MAX_QUEUED_BUFS; i++)
previous[i] = NULL; previous[i] = NULL;
prevCount = 0; prevCount = 0;
#endif
} }
//Copy from current to previous //Copy from current to previous
inline void QueuedBufferStore::mvCurrToPrev() { inline void QueuedBufferStore::mvCurrToPrev() {
#ifndef USE_FENCE_SYNC
for(int i = 0; i < curCount; i++) for(int i = 0; i < curCount; i++)
previous[i] = current[i]; previous[i] = current[i];
prevCount = curCount; prevCount = curCount;
#endif
} }
inline bool QueuedBufferStore::lockBuffer(private_handle_t *hnd) { inline bool QueuedBufferStore::lockBuffer(private_handle_t *hnd) {
#ifndef USE_FENCE_SYNC
if (GENLOCK_FAILURE == genlock_lock_buffer(hnd, GENLOCK_READ_LOCK, if (GENLOCK_FAILURE == genlock_lock_buffer(hnd, GENLOCK_READ_LOCK,
GENLOCK_MAX_TIMEOUT)) { GENLOCK_MAX_TIMEOUT)) {
ALOGE("%s: genlock_lock_buffer(READ) failed", __func__); ALOGE("%s: genlock_lock_buffer(READ) failed", __func__);
return false; return false;
} }
#endif
return true; return true;
} }
inline void QueuedBufferStore::unlockBuffer(private_handle_t *hnd) { inline void QueuedBufferStore::unlockBuffer(private_handle_t *hnd) {
#ifndef USE_FENCE_SYNC
//Check if buffer is still around //Check if buffer is still around
if(private_handle_t::validate(hnd) != 0) { if(private_handle_t::validate(hnd) != 0) {
ALOGE("%s Invalid Handle", __func__); ALOGE("%s Invalid Handle", __func__);
@@ -121,6 +139,7 @@ inline void QueuedBufferStore::unlockBuffer(private_handle_t *hnd) {
ALOGE("%s: genlock_unlock_buffer failed", __func__); ALOGE("%s: genlock_unlock_buffer failed", __func__);
return; return;
} }
#endif
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
};//namespace };//namespace

View File

@@ -238,4 +238,61 @@ void wait4Pan(hwc_context_t* ctx) {
pthread_mutex_unlock(&m->fbPanLock); 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 };//namespace

View File

@@ -87,6 +87,9 @@ void wait4fbPost(hwc_context_t* ctx);
// Waits for the fb_post to finish PAN (primary commit) // Waits for the fb_post to finish PAN (primary commit)
void wait4Pan(hwc_context_t* ctx); void wait4Pan(hwc_context_t* ctx);
//Sync point impl.
int hwc_sync(hwc_display_contents_1_t* list);
// Inline utility functions // Inline utility functions
static inline bool isSkipLayer(const hwc_layer_1_t* l) { static inline bool isSkipLayer(const hwc_layer_1_t* l) {
return (UNLIKELY(l && (l->flags & HWC_SKIP_LAYER))); return (UNLIKELY(l && (l->flags & HWC_SKIP_LAYER)));