diff --git a/libhwcomposer/hwc.cpp b/libhwcomposer/hwc.cpp index 2b34be7..205e5e7 100644 --- a/libhwcomposer/hwc.cpp +++ b/libhwcomposer/hwc.cpp @@ -36,6 +36,7 @@ #include "hwc_extonly.h" #include "qcom_ui.h" +#define VSYNC_DEBUG 0 using namespace qhwc; static int hwc_device_open(const struct hw_module_t* module, @@ -130,19 +131,46 @@ static int hwc_eventControl(struct hwc_composer_device* dev, int event, int value) { int ret = 0; + static int prev_value, temp; + hwc_context_t* ctx = (hwc_context_t*)(dev); private_module_t* m = reinterpret_cast( ctx->mFbDev->common.module); switch(event) { #ifndef NO_HW_VSYNC case HWC_EVENT_VSYNC: + if (value == prev_value){ + //TODO see why HWC gets repeated events + ALOGD_IF(VSYNC_DEBUG, "%s - VSYNC is already %s", + __FUNCTION__, (value)?"ENABLED":"DISABLED"); + } + temp = ctx->vstate.enable; if(ioctl(m->framebuffer->fd, MSMFB_OVERLAY_VSYNC_CTRL, &value) < 0) ret = -errno; - if(ctx->mExtDisplay->isHDMIConfigured() && - (ctx->mExtDisplay->getExternalDisplay()==EXTERN_DISPLAY_FB1)) { - ret = ctx->mExtDisplay->enableHDMIVsync(value); + /* vsync state change logic */ + if (value == 1) { + //unblock vsync thread + pthread_mutex_lock(&ctx->vstate.lock); + ctx->vstate.enable = true; + pthread_cond_signal(&ctx->vstate.cond); + pthread_mutex_unlock(&ctx->vstate.lock); } + if (value == 0 && temp) { + //vsync thread will block + pthread_mutex_lock(&ctx->vstate.lock); + ctx->vstate.enable = false; + pthread_mutex_unlock(&ctx->vstate.lock); + } + ALOGD_IF (VSYNC_DEBUG, "VSYNC state changed from %s to %s", + (prev_value)?"ENABLED":"DISABLED", (value)?"ENABLED":"DISABLED"); + prev_value = value; + /* vsync state change logic - end*/ + + if(ctx->mExtDisplay->isHDMIConfigured() && + (ctx->mExtDisplay->getExternalDisplay()==EXTERN_DISPLAY_FB1)) { + ret = ctx->mExtDisplay->enableHDMIVsync(value); + } break; #endif case HWC_EVENT_ORIENTATION: diff --git a/libhwcomposer/hwc_utils.cpp b/libhwcomposer/hwc_utils.cpp index c952a46..ac6e428 100644 --- a/libhwcomposer/hwc_utils.cpp +++ b/libhwcomposer/hwc_utils.cpp @@ -66,6 +66,10 @@ void initContext(hwc_context_t *ctx) property_get("debug.hwc.dynThreshold", value, "2"); ctx->dynThreshold = atof(value); + pthread_mutex_init(&(ctx->vstate.lock), NULL); + pthread_cond_init(&(ctx->vstate.cond), NULL); + ctx->vstate.enable = false; + ALOGI("Initializing Qualcomm Hardware Composer"); ALOGI("MDP version: %d", ctx->mMDP.version); ALOGI("DYN composition threshold : %f", ctx->dynThreshold); @@ -98,6 +102,8 @@ void closeContext(hwc_context_t *ctx) ctx->mExtDisplay = NULL; } + pthread_mutex_destroy(&(ctx->vstate.lock)); + pthread_cond_destroy(&(ctx->vstate.cond)); free(const_cast(ctx->device.methods)); diff --git a/libhwcomposer/hwc_utils.h b/libhwcomposer/hwc_utils.h index 774810f..fa1cdf0 100644 --- a/libhwcomposer/hwc_utils.h +++ b/libhwcomposer/hwc_utils.h @@ -133,6 +133,12 @@ inline void getLayerResolution(const hwc_layer_t* layer, } }; //qhwc namespace +struct vsync_state { + pthread_mutex_t lock; + pthread_cond_t cond; + bool enable; +}; + // ----------------------------------------------------------------------------- // HWC context // This structure contains overall state @@ -164,6 +170,9 @@ struct hwc_context_t { qhwc::MDPInfo mMDP; + //Vsync + struct vsync_state vstate; + }; #endif //HWC_UTILS_H diff --git a/libhwcomposer/hwc_vsync.cpp b/libhwcomposer/hwc_vsync.cpp index 4e4eb44..cc86312 100644 --- a/libhwcomposer/hwc_vsync.cpp +++ b/libhwcomposer/hwc_vsync.cpp @@ -42,7 +42,8 @@ static void *vsync_loop(void *param) char thread_name[64] = "hwcVsyncThread"; prctl(PR_SET_NAME, (unsigned long) &thread_name, 0, 0, 0); - setpriority(PRIO_PROCESS, 0, HAL_PRIORITY_URGENT_DISPLAY); + setpriority(PRIO_PROCESS, 0, + HAL_PRIORITY_URGENT_DISPLAY + ANDROID_PRIORITY_MORE_FAVORABLE); static char vdata[PAGE_SIZE]; @@ -51,12 +52,17 @@ static void *vsync_loop(void *param) bool fb1_vsync = false; /* Currently read vsync timestamp from drivers - VSYNC=41800875994 + e.g. VSYNC=41800875994 */ hwc_procs* proc = (hwc_procs*)ctx->device.reserved_proc[0]; do { + pthread_mutex_lock(&ctx->vstate.lock); + if(ctx->vstate.enable == false) { + pthread_cond_wait(&ctx->vstate.cond, &ctx->vstate.lock); + } + pthread_mutex_unlock(&ctx->vstate.lock); int hdmiconnected = ctx->mExtDisplay->getExternalDisplay(); @@ -78,15 +84,15 @@ static void *vsync_loop(void *param) ALOGE ("FATAL:%s:not able to open file:%s, %s", __FUNCTION__, (fb1_vsync) ? vsync_timestamp_fb1 : vsync_timestamp_fb0, strerror(errno)); - return NULL; + return NULL; } - // Open success - read now len = read(fd_timestamp, vdata, PAGE_SIZE); if (len < 0){ ALOGE ("FATAL:%s:not able to read file:%s, %s", __FUNCTION__, (fb1_vsync) ? vsync_timestamp_fb1 : vsync_timestamp_fb0, strerror(errno)); + fd_timestamp = -1; return NULL; }