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 := -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
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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)));
|
||||||
|
|||||||
Reference in New Issue
Block a user