summaryrefslogtreecommitdiff
authorsky 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)
commit9288fb90c35bfda32c456f0aecee31622e75c1f6 (patch)
tree681e1931de00e2f3f27dc0153c613fd271ed1eac
parent7c74f94ec896b8ef70231d98e5f939c2efb87fbb (diff)
downloadhwcomposer-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>
Diffstat
-rw-r--r--common/hwc/HwcConfig.cpp2
-rw-r--r--common/hwc/HwcDisplayPipe.cpp10
-rw-r--r--common/hwc/HwcVsync.cpp64
-rw-r--r--common/hwc/include/HwcVsync.h11
-rw-r--r--hwc2/Hwc2Display.cpp2
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()) {