標籤:star remove 產生 ref rate 面具 turned cto disable
HWComposer模組產生VSync訊號後要經過分發才能送達到關心VSync事件的模組中去。VSync訊號分發大致流程為HWComposer->SurfaceFlinger->DispSync->DispSyncSource->各個具體模組。下面具體分析下這個流程。
在上一篇文章中分析到硬體或者軟體VSync訊號產生時,會回調SurfaceFlinger的onVSyncReceived函數,來看看這個函數:
void SurfaceFlinger::onVSyncReceived(int type, nsecs_t timestamp) { bool needsHwVsync = false; { // Scope for the lock Mutex::Autolock _l(mHWVsyncLock); if (type == 0 && mPrimaryHWVsyncEnabled) { needsHwVsync = mPrimaryDispSync.addResyncSample(timestamp); } } if (needsHwVsync) { enableHardwareVsync(); } else { disableHardwareVsync(false); } }
- mPrimaryDispSync類型為DispSync,在構造的時候會建立DispSyncThread
DispSync::DispSync() : mRefreshSkipCount(0), mThread(new DispSyncThread()) { mThread->run("DispSync", PRIORITY_URGENT_DISPLAY + PRIORITY_MORE_FAVORABLE); reset(); beginResync(); if (kTraceDetailedInfo) { // If we‘re not getting present fences then the ZeroPhaseTracer // would prevent HW vsync event from ever being turned off. // Even if we‘re just ignoring the fences, the zero-phase tracing is // not needed because any time there is an event registered we will // turn on the HW vsync events. if (!kIgnorePresentFences) { addEventListener(0, new ZeroPhaseTracer()); } }}
- 調用DispSync的addResyncSample方法,最終會去喚醒DispSyncThread線程
bool DispSync::addResyncSample(nsecs_t timestamp) { Mutex::Autolock lock(mMutex); size_t idx = (mFirstResyncSample + mNumResyncSamples) % MAX_RESYNC_SAMPLES; mResyncSamples[idx] = timestamp; if (mNumResyncSamples < MAX_RESYNC_SAMPLES) { mNumResyncSamples++; } else { mFirstResyncSample = (mFirstResyncSample + 1) % MAX_RESYNC_SAMPLES; } updateModelLocked(); if (mNumResyncSamplesSincePresent++ > MAX_RESYNC_SAMPLES_WITHOUT_PRESENT) { resetErrorLocked(); } if (kIgnorePresentFences) { // If we don‘t have the sync framework we will never have // addPresentFence called. This means we have no way to know whether // or not we‘re synchronized with the HW vsyncs, so we just request // that the HW vsync events be turned on whenever we need to generate // SW vsync events. return mThread->hasAnyEventListeners(); } return mPeriod == 0 || mError > kErrorThreshold;}
- 調用updateModelLocked函數
- 計算是否需要開啟硬體VSync,進行同步
void DispSync::updateModelLocked() { if (mNumResyncSamples >= MIN_RESYNC_SAMPLES_FOR_UPDATE) { ...... mThread->updateModel(mPeriod, mPhase); }}
- 成員變數mThread為DispSyncThread類的對象
- 調用DispSyncThread類pdateModel方法
void updateModel(nsecs_t period, nsecs_t phase) { Mutex::Autolock lock(mMutex); mPeriod = period; mPhase = phase; mCond.signal(); }
- 該方法主要設定成員變數mPeriod、mPhase
- 然後在喚醒線程迴圈
virtual bool threadLoop() { status_t err; nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC); nsecs_t nextEventTime = 0; while (true) { Vector<CallbackInvocation> callbackInvocations; nsecs_t targetTime = 0; { // Scope for lock Mutex::Autolock lock(mMutex); ...... callbackInvocations = gatherCallbackInvocationsLocked(now); } if (callbackInvocations.size() > 0) { fireCallbackInvocations(callbackInvocations); } } return false; }
- 通過gatherCallbackInvocationsLocked得到監聽者集合
- 通過fireCallbackInvocations調用監聽者回呼函數
DispSync的回呼函數在哪裡註冊,我們在看看DispSyncSource的setVSyncEnabled函數
virtual void setVSyncEnabled(bool enable) { Mutex::Autolock lock(mVsyncMutex); if (enable) { status_t err = mDispSync->addEventListener(mPhaseOffset, static_cast<DispSync::Callback*>(this)); if (err != NO_ERROR) { ALOGE("error registering vsync callback: %s (%d)", strerror(-err), err); } //ATRACE_INT(mVsyncOnLabel.string(), 1); } else { status_t err = mDispSync->removeEventListener( static_cast<DispSync::Callback*>(this)); if (err != NO_ERROR) { ALOGE("error unregistering vsync callback: %s (%d)", strerror(-err), err); } //ATRACE_INT(mVsyncOnLabel.string(), 0); } mEnabled = enable; }
- DispSyncSource類繼承於DispSync::Callback
- 調用DispSync->addEventListener註冊回調,當DispSyncSource收到DispSync的VSync訊號時,會回調整onDispSyncEvent函數
virtual void onDispSyncEvent(nsecs_t when) { sp<VSyncSource::Callback> callback; { Mutex::Autolock lock(mCallbackMutex); callback = mCallback; if (mTraceVsync) { mValue = (mValue + 1) % 2; ATRACE_INT(mVsyncEventLabel.string(), mValue); } } if (callback != NULL) { callback->onVSyncEvent(when); } }
- 這個函數最終還是調用VSyncSource::Callback的onVSyncEvent函數。
- VSyncSource::Callback函數的註冊是通過調用DispSyncSource的setCallback註冊。
DispSyncSource的setCallback函數在哪裡調用的呢,要解答這個問題,還是得回到SurfaceFlinger的init函數裡,以sfVsyncSrc為例。
void SurfaceFlinger::init() { ...... // start the EventThread sp<VSyncSource> vsyncSrc = new DispSyncSource(&mPrimaryDispSync, vsyncPhaseOffsetNs, true, "app"); mEventThread = new EventThread(vsyncSrc); sp<VSyncSource> sfVsyncSrc = new DispSyncSource(&mPrimaryDispSync, sfVsyncPhaseOffsetNs, true, "sf"); mSFEventThread = new EventThread(sfVsyncSrc); mEventQueue.setEventThread(mSFEventThread); ......}
- 以sfVsyncSrc為參數建立EventThread對象
- 在EventThread的線程迴圈中會去調用enableVSyncLocked函數
void EventThread::enableVSyncLocked() { if (!mUseSoftwareVSync) { // never enable h/w VSYNC when screen is off if (!mVsyncEnabled) { mVsyncEnabled = true; mVSyncSource->setCallback(static_cast<VSyncSource::Callback*>(this)); mVSyncSource->setVSyncEnabled(true); } } mDebugVsyncEnabled = true; sendVsyncHintOnLocked();}
- EventThread繼承VSyncSource::Callback介面,實現了onVSyncEvent函數
- 調用mVSyncSource的setCallback函數設定回調
- 調用mVSyncSource的setVSyncEnabled函數使能VSync訊號的監聽
void EventThread::onVSyncEvent(nsecs_t timestamp) { Mutex::Autolock _l(mLock); mVSyncEvent[0].header.type = DisplayEventReceiver::DISPLAY_EVENT_VSYNC; mVSyncEvent[0].header.id = 0; mVSyncEvent[0].header.timestamp = timestamp; mVSyncEvent[0].vsync.count++; mCondition.broadcast();}
- EventThread收到VSync訊號後,發送廣播訊息,喚醒相關線程
- 最終EventThread將VSnc訊號傳遞給MessageQueue
Android SurfaceFlinger服務(六) ----- VSync訊號的分發