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:
committed by
Iliyan Malchev
parent
0a03dd8b11
commit
2dd04a873b
@@ -21,6 +21,12 @@ common_libs := liblog libutils libcutils libhardware
|
||||
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
|
||||
|
||||
@@ -209,6 +209,10 @@ static int hwc_set(hwc_composer_device_1 *dev,
|
||||
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);
|
||||
|
||||
@@ -16,7 +16,10 @@
|
||||
*/
|
||||
|
||||
#include <gralloc_priv.h>
|
||||
|
||||
#ifndef USE_FENCE_SYNC
|
||||
#include <genlock.h>
|
||||
#endif
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// QueuedBufferStore
|
||||
@@ -56,12 +59,15 @@ class QueuedBufferStore {
|
||||
|
||||
//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 @@ inline void QueuedBufferStore::unlockAllPrevious() {
|
||||
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 @@ inline void QueuedBufferStore::unlockBuffer(private_handle_t *hnd) {
|
||||
ALOGE("%s: genlock_unlock_buffer failed", __func__);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
// -----------------------------------------------------------------------------
|
||||
};//namespace
|
||||
|
||||
@@ -238,4 +238,61 @@ void wait4Pan(hwc_context_t* ctx) {
|
||||
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
|
||||
|
||||
@@ -87,6 +87,9 @@ void wait4fbPost(hwc_context_t* ctx);
|
||||
// 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)));
|
||||
|
||||
Reference in New Issue
Block a user