author | sky zhou <sky.zhou@amlogic.com> | 2020-02-18 07:03:47 (GMT) |
---|---|---|
committer | sky zhou <sky.zhou@amlogic.com> | 2020-05-21 12:02:32 (GMT) |
commit | 9288fb90c35bfda32c456f0aecee31622e75c1f6 (patch) | |
tree | 681e1931de00e2f3f27dc0153c613fd271ed1eac | |
parent | 7c74f94ec896b8ef70231d98e5f939c2efb87fbb (diff) | |
download | hwcomposer-9288fb90c35bfda32c456f0aecee31622e75c1f6.zip hwcomposer-9288fb90c35bfda32c456f0aecee31622e75c1f6.tar.gz hwcomposer-9288fb90c35bfda32c456f0aecee31622e75c1f6.tar.bz2 |
hwc: improve hw vsync to return accurate timestamp. [1/1]
PD#SWPL-20748
Problem:
vsync timestamp cannot match nts requirment.
Solution:
add change flag in drmfb, and avoid return fence when
no osd changed.
Verify:
Verify on newton.
Change-Id: I5e779fc1a0a7d3b8da2959397fb044cfcdb70322
Signed-off-by: sky zhou <sky.zhou@amlogic.com>
-rw-r--r-- | common/hwc/HwcConfig.cpp | 2 | ||||
-rw-r--r-- | common/hwc/HwcDisplayPipe.cpp | 10 | ||||
-rw-r--r-- | common/hwc/HwcVsync.cpp | 64 | ||||
-rw-r--r-- | common/hwc/include/HwcVsync.h | 11 | ||||
-rw-r--r-- | hwc2/Hwc2Display.cpp | 2 |
5 files changed, 60 insertions, 29 deletions
diff --git a/common/hwc/HwcConfig.cpp b/common/hwc/HwcConfig.cpp index 31d3ec4..717cce5 100644 --- a/common/hwc/HwcConfig.cpp +++ b/common/hwc/HwcConfig.cpp @@ -140,7 +140,7 @@ int32_t HwcConfig::headlessRefreshRate() { } bool HwcConfig::softwareVsyncEnabled() { -#ifdef HWC_ENABLE_SOFTWARE_VSYNC +#if 1//def HWC_ENABLE_SOFTWARE_VSYNC return true; #else return false; diff --git a/common/hwc/HwcDisplayPipe.cpp b/common/hwc/HwcDisplayPipe.cpp index c4d8b08..d95e7d0 100644 --- a/common/hwc/HwcDisplayPipe.cpp +++ b/common/hwc/HwcDisplayPipe.cpp @@ -236,6 +236,10 @@ int32_t HwcDisplayPipe::updatePipe(std::shared_ptr<PipeStat> & stat) { } else { stat->hwcVsync->setHwMode(stat->modeCrtc); } + drm_mode_info_t mode; + if (0 == stat->modeMgr->getDisplayMode(mode)) { + stat->hwcVsync->setPeriod(1e9 / mode.refreshRate); + } drm_mode_info_t mode; if (0 == stat->modeMgr->getDisplayMode(mode)) { @@ -312,10 +316,8 @@ void HwcDisplayPipe::handleEvent(drm_display_event event, int val) { statIt.second->hwcDisplay->onModeChanged(val); /*update display dynamic info.*/ drm_mode_info_t mode; - if (HwcConfig::softwareVsyncEnabled()) { - if (0 == statIt.second->modeMgr->getDisplayMode(mode)) { - statIt.second->hwcVsync->setPeriod(1e9 / mode.refreshRate); - } + if (0 == statIt.second->modeMgr->getDisplayMode(mode)) { + statIt.second->hwcVsync->setPeriod(1e9 / mode.refreshRate); } } } diff --git a/common/hwc/HwcVsync.cpp b/common/hwc/HwcVsync.cpp index bc7545b..b3f758b 100644 --- a/common/hwc/HwcVsync.cpp +++ b/common/hwc/HwcVsync.cpp @@ -17,9 +17,8 @@ HwcVsync::HwcVsync() { mSoftVsync = true; mEnabled = false; mPreTimeStamp = 0; - mPeriod = 0; - mExit = false; - mObserver = NULL; + mReqPeriod = 0; + mVsyncTime = 0; int ret; ret = pthread_create(&hw_vsync_thread, NULL, vsyncThread, this); @@ -61,8 +60,10 @@ int32_t HwcVsync::setHwMode(std::shared_ptr<HwDisplayCrtc> & crtc) { } int32_t HwcVsync::setPeriod(nsecs_t period) { - if (mSoftVsync) - mPeriod = period; + if (mReqPeriod != period) { + MESON_LOGD("Update period %llx->%llx", period, mReqPeriod); + mReqPeriod = period; + } return 0; } @@ -97,17 +98,15 @@ void * HwcVsync::vsyncThread(void * data) { if (pThis->mSoftVsync) { ret = pThis->waitSoftwareVsync(timestamp); } else { - ret = pThis->mCrtc->waitVBlank(timestamp); + ret = pThis->waitHwVsync(timestamp); } bool debug = true; if (debug) { nsecs_t period = timestamp - pThis->mPreTimeStamp; UNUSED(period); - print_cnt --; - if (pThis->mPreTimeStamp != 0 && print_cnt <= 0) { - MESON_LOGD("wait for vsync success, (%p) peroid: %lld", pThis, period); - print_cnt = 10; - } + if (pThis->mPreTimeStamp != 0) + MESON_LOGD("wait for vsync success, peroid: %lld, timestmap (%lld)", + period, timestamp); pThis->mPreTimeStamp = timestamp; } @@ -121,29 +120,53 @@ void * HwcVsync::vsyncThread(void * data) { return NULL; } +int32_t HwcVsync::waitHwVsync(nsecs_t& vsync_timestamp) { + static nsecs_t cur_vsync_period = 0; + if (cur_vsync_period != mReqPeriod) { + mCrtc->waitVBlank(mVsyncTime); + cur_vsync_period = mReqPeriod; + } else { + nsecs_t now = systemTime(CLOCK_MONOTONIC); + mVsyncTime = mVsyncTime + cur_vsync_period + + (now - mVsyncTime ) /cur_vsync_period * cur_vsync_period; + MESON_LOGE("Wait hw vsync %lld - %lld", mVsyncTime, now); + + struct timespec spec; + spec.tv_sec = mVsyncTime / 1000000000; + spec.tv_nsec = mVsyncTime % 1000000000; + + int err; + do { + err = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &spec, NULL); + } while (err<0 && errno == EINTR); + } + + vsync_timestamp = mVsyncTime; + return 0; +} + int32_t HwcVsync::waitSoftwareVsync(nsecs_t& vsync_timestamp) { static nsecs_t vsync_time = 0; static nsecs_t old_vsync_period = 0; nsecs_t now = systemTime(CLOCK_MONOTONIC); - - mPeriod = (mPeriod == 0) ? 1e9/SF_VSYNC_DFT_PERIOD : mPeriod; + mReqPeriod = (mReqPeriod == 0) ? (1e9/SF_VSYNC_DFT_PERIOD) : mReqPeriod; //cal the last vsync time with old period - if (mPeriod != old_vsync_period) { + if (mReqPeriod != old_vsync_period) { if (old_vsync_period > 0) { vsync_time = vsync_time + ((now - vsync_time) / old_vsync_period) * old_vsync_period; } - old_vsync_period = mPeriod; + old_vsync_period = mReqPeriod; } //set to next vsync time - vsync_time += mPeriod; + vsync_time += mReqPeriod; // we missed, find where the next vsync should be if (vsync_time - now < 0) { - vsync_time = now + (mPeriod - - ((now - vsync_time) % mPeriod)); + vsync_time = now + (mReqPeriod - + ((now - vsync_time) % mReqPeriod)); } struct timespec spec; @@ -159,3 +182,8 @@ int32_t HwcVsync::waitSoftwareVsync(nsecs_t& vsync_timestamp) { return err; } +void HwcVsync::dump(String8 & dumpstr) { + dumpstr.appendFormat("HwcVsync mode(%s) period(%lld) \n", + mSoftVsync ? "soft":"hw", mReqPeriod); +} + diff --git a/common/hwc/include/HwcVsync.h b/common/hwc/include/HwcVsync.h index 9bc5081..4c52602 100644 --- a/common/hwc/include/HwcVsync.h +++ b/common/hwc/include/HwcVsync.h @@ -32,23 +32,22 @@ public: int32_t setObserver(HwcVsyncObserver * observer); int32_t setSoftwareMode(); int32_t setHwMode(std::shared_ptr<HwDisplayCrtc> & crtc); - - int32_t setEnabled(bool enabled); - - /*for software vsync.*/ int32_t setPeriod(nsecs_t period); + int32_t setEnabled(bool enabled); - void dump(); + void dump(String8 & dumpstr); protected: static void * vsyncThread(void * data); int32_t waitSoftwareVsync(nsecs_t& vsync_timestamp); + int32_t waitHwVsync(nsecs_t& vsync_timestamp); protected: bool mSoftVsync; bool mEnabled; bool mExit; - nsecs_t mPeriod; + nsecs_t mVsyncTime; + nsecs_t mReqPeriod; nsecs_t mPreTimeStamp; HwcVsyncObserver * mObserver; diff --git a/hwc2/Hwc2Display.cpp b/hwc2/Hwc2Display.cpp index 45a82d5..3a5ceaa 100644 --- a/hwc2/Hwc2Display.cpp +++ b/hwc2/Hwc2Display.cpp @@ -1132,6 +1132,8 @@ void Hwc2Display::dump(String8 & dumpstr) { /* dump display configs*/ mModeMgr->dump(dumpstr); dumpstr.append("\n"); + mVsync->dump(dumpstr); + dumpstr.append("\n"); /*dump detail debug info*/ if (DebugHelper::getInstance().dumpDetailInfo()) { |