Android SurfaceFlinger服務(六) ----- VSync訊號的分發

來源:互聯網
上載者:User

標籤: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訊號的分發

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.