1、Vsync簡介:android
屏幕的刷新過程是每一行從左到右(行刷新,水平刷新,Horizontal Scanning),從上到下(屏幕刷新,垂直刷新,Vertical Scanning)。當整個屏幕刷新完畢,即一個垂直刷新週期完成,會有短暫的空白期,此時發出 VSync 信號。因此,VSync 中的 V 指的是垂直刷新中的垂直-Vertical。app
Android系統每隔16ms發出VSYNC信號,觸發對UI進行渲染,VSync是Vertical Synchronization(垂直同步)的縮寫,是一種在PC上很早就普遍使用的技術,能夠簡單的把它認爲是一種定時中斷。而在Android 4.1(JB)中已經開始引入VSync機制,用來同步渲染,讓AppUI和SurfaceFlinger能夠按硬件產生的VSync節奏進行工做。composer
2、黃油計劃:三個方法改進顯示系統框架
1.Vsync同步:函數
可見vsync信號沒有提醒CPU/GPU工做的狀況下,第二次vsync到來須要顯示內容時,CPU和GPU尚未來得及準備好下一幀的數據,因此只能接着顯示上一幀的數據,產生Jank!oop
CPU/GPU接收vsync信號提早準備下一幀要顯示的內容,因此可以及時準備好每一幀的數據,保證畫面的流程。post
2.多級緩衝:性能
除了Vsync的機制,Android還使用了多級緩衝的手段以優化UI流程度,例如雙緩衝(A+B),在顯示buffer A的數據時,CPU/GPU就開始在buffer B中準備下一幀數據:優化
可是不能保證每一幀CPU、GPU都運行狀態良好,可能因爲資源搶佔等性能問題致使某一幀GPU掉鏈子,vsync信號到來時buffer B的數據還沒準備好,而此時Display又在顯示buffer A的數據,致使後面CPU/GPU沒有新的buffer着手準備數據,空白時間無事可作,後面Jank頻出:ui
所以用三級緩衝來提升系統對性能波動的容忍度:
雖然GPU在準備buffer B的數據耗時過長,第二幀Jank,可是新增1個buffer能夠減小CPU和GPU在vsync同步間的空白間隙,此時CPU/GPU可以利用buffer C繼續工做,因此後面就不會再產生Jank了,固然具體使用多少個buffer要根據實際硬件性能狀況調整,最終目的就是解決Display的Jank產生。
3.Vsync虛擬化(Vsync App + Vsync SurfaceFlinger):
雖然vsync使得CPU/GPU/Display同步了,但App UI和SurfaceFlinger的工做顯然是一個流水線的模型。即對於一幀內容,先等App UI畫完了,SurfaceFlinger再出場對其進行合併渲染後放入framebuffer,最後整到屏幕上。而現有的VSync模型是讓你們一塊兒開始幹活,這樣對於同一幀內容,第一個VSync信號時App UI的數據開始準備,第二個VSync信號時SurfaceFlinger工做,第三個VSync信號時用戶看到Display內容,這樣就兩個VSync period(每一個16ms)過去了,影響用戶體驗。
解決思路:SurfaceFlinger在App UI準備好數據後及時開工作合成。
Android 4.4(KitKat)引入了VSync的虛擬化,即把硬件的VSync信號先同步到一個本地VSync模型中,再從中一分爲二,引出兩條VSync時間與之有固定偏移的線程。示意圖以下:
這樣,你們工做既保持必定的節拍,又能夠相互錯開,一前一後保持着流水節奏。
注意其中兩個Phase offset參數(即VSYNC_EVENT_PHASE_OFFSET_NS和SF_VSYNC_EVENT_PHASE_OFFSET_NS)是可調的。
處理流程:
類型DispSync表示了一個基於硬件VSync信號的同步模型,它會根據從HWComposer來的硬件VSync信號的採樣來進行同步。其它兩個EventThread分別用了兩個不一樣的虛擬VSync信號源(用DispSyncSource表示,其中包含了與真實VSync信號的偏移值),這兩個VSync信號源就是被虛擬出來分別用於控制App UI和SurfaceFlinger渲染。在EventThread的線程循環中,若是有須要就會向DispSync註冊相應的listener。DispSyncThread就像樂隊鼓手同樣控制着你們的節奏。它在主循環中會先經過已經向DispSync註冊的listener計算下一個要產生的虛擬VSync信號還要多久,等待相應時間後就會調用相應listener的callback函數。這樣,對於那些註冊了listener的監聽者來講,就好像被真實的VSync信號控制着同樣。至於EventControlThread是用來向真實的VSync硬件發命令。
3、Vsync框架
1.硬件或者軟件建立vsyncThread產生vsync。
2.DispSyncThread處理vsync,把vsync虛擬化成vsync-app和vsync-sf。
3.vsync-app/sf按需產生(若是App和SurfaceFlinger都沒有更新請求,則休眠省電):
APP端:APP須要更新界面時發出vsync請求給EventThread(設置connection.count>=0),DispSyncThread收到vsync信號後休眠offset,而後喚醒EventThread通知APP開始渲染。
SF端:sf請求EventThread-sf,EventThread-sf收到vsync後通知SF能夠開始合成。
(vsync框架圖)
4.代碼分析:
4.1 建立五個線程:SurfaceFlingerThread、DispSyncThread、EventThead-App、EventThead-SF、VsyncThread,都屬於SurfaceFlinger進程:
(1)啓動SurfaceFlinger主線程:android-8.0.0_r4\frameworks\native\services\surfaceflinger\main_surfaceflinger.cpp
int main(int, char**) { startHidlServices(); signal(SIGPIPE, SIG_IGN); // When SF is launched in its own process, limit the number of // binder threads to 4. ProcessState::self()->setThreadPoolMaxThreadCount(4); // start the thread pool sp<ProcessState> ps(ProcessState::self()); ps->startThreadPool(); // instantiate surfaceflinger sp<SurfaceFlinger> flinger = new SurfaceFlinger(); //其中建立了 mPrimaryDispSync 成員變量 setpriority(PRIO_PROCESS, 0, PRIORITY_URGENT_DISPLAY); set_sched_policy(0, SP_FOREGROUND); // Put most SurfaceFlinger threads in the system-background cpuset // Keeps us from unnecessarily using big cores // Do this after the binder thread pool init if (cpusets_enabled()) set_cpuset_policy(0, SP_SYSTEM); // initialize before clients can connect flinger->init(); //傳入mPrimaryDispSync並建立EventThread(app/sf)、HWComposer // publish surface flinger sp<IServiceManager> sm(defaultServiceManager()); sm->addService(String16(SurfaceFlinger::getServiceName()), flinger, false); // publish GpuService sp<GpuService> gpuservice = new GpuService(); sm->addService(String16(GpuService::SERVICE_NAME), gpuservice, false); struct sched_param param = {0}; param.sched_priority = 2; if (sched_setscheduler(0, SCHED_FIFO, ¶m) != 0) { ALOGE("Couldn't set SCHED_FIFO"); } // run surface flinger in this thread (SF的主線程) flinger->run(); return 0; }
(2)new SurfaceFlinger() 時建立了成員變量 DispSync mPrimaryDispSync; android-8.0.0_r4\frameworks\native\services\surfaceflinger\SurfaceFlinger.h
其中 DispSync 的構造函數會啓動DispSyncThread線程:
DispSync::DispSync(const char* name) : mName(name), mRefreshSkipCount(0), mThread(new DispSyncThread(name)), //建立了DispSyncThread mIgnorePresentFences(!SurfaceFlinger::hasSyncFramework){ mPresentTimeOffset = SurfaceFlinger::dispSyncPresentTimeOffset; mThread->run("DispSync", PRIORITY_URGENT_DISPLAY + PRIORITY_MORE_FAVORABLE); // set DispSync to SCHED_FIFO to minimize jitter struct sched_param param = {0}; param.sched_priority = 2; if (sched_setscheduler(mThread->getTid(), SCHED_FIFO, ¶m) != 0) { ALOGE("Couldn't set SCHED_FIFO for DispSyncThread"); } 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 (!mIgnorePresentFences && kEnableZeroPhaseTracer) { addEventListener("ZeroPhaseTracer", 0, new ZeroPhaseTracer()); } } }
(3)接着分析SurfaceFlinger對象,它是一個strong point,在引用時會調用其onFirstRef()方法:
void SurfaceFlinger::onFirstRef() {
//初始化消息隊列,其中建立了loop和handle mEventQueue.init(this); }
flinger->run()的實現: android-8.0.0_r4\frameworks\native\services\surfaceflinger\SurfaceFlinger_hwc1.cpp
void SurfaceFlinger::run() { do { waitForEvent(); //其中就是調用mEventQueue.waitMessage() } while (true); }
waitMessage中等待AP和EventTHread給它發數據:
void MessageQueue::waitMessage() { do { IPCThreadState::self()->flushCommands(); int32_t ret = mLooper->pollOnce(-1); switch (ret) { case Looper::POLL_WAKE: case Looper::POLL_CALLBACK: continue; case Looper::POLL_ERROR: ALOGE("Looper::POLL_ERROR"); continue; case Looper::POLL_TIMEOUT: // timeout (should not happen) continue; default: // should not happen ALOGE("Looper::pollOnce() returned unknown status %d", ret); continue; } } while (true); }
SurfaceFlinger初始化最重要的函數是init():
void SurfaceFlinger::init() { ALOGI( "SurfaceFlinger's main thread ready to run. " "Initializing graphics H/W..."); ALOGI("Phase offest NS: %" PRId64 "", vsyncPhaseOffsetNs); { // Autolock scope Mutex::Autolock _l(mStateLock); // initialize EGL for the default display mEGLDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY); eglInitialize(mEGLDisplay, NULL, NULL); // start the EventThread (建立了兩個EventThread,他們的名字和offset不一樣) sp<VSyncSource> vsyncSrc = new DispSyncSource(&mPrimaryDispSync, vsyncPhaseOffsetNs, true, "app"); mEventThread = new EventThread(vsyncSrc, *this, false); sp<VSyncSource> sfVsyncSrc = new DispSyncSource(&mPrimaryDispSync, sfVsyncPhaseOffsetNs, true, "sf"); mSFEventThread = new EventThread(sfVsyncSrc, *this, true);
// 建立sf與EventThread之間的connection mEventQueue.setEventThread(mSFEventThread); // set EventThread and SFEventThread to SCHED_FIFO to minimize jitter struct sched_param param = {0}; param.sched_priority = 2; if (sched_setscheduler(mSFEventThread->getTid(), SCHED_FIFO, ¶m) != 0) { ALOGE("Couldn't set SCHED_FIFO for SFEventThread"); } if (sched_setscheduler(mEventThread->getTid(), SCHED_FIFO, ¶m) != 0) { ALOGE("Couldn't set SCHED_FIFO for EventThread"); } // Get a RenderEngine for the given display / config (can't fail) mRenderEngine = RenderEngine::create(mEGLDisplay, HAL_PIXEL_FORMAT_RGBA_8888); }
其中 mEventQueue.setEventThread(mSFEventThread) 的實現:
//sufaceflinger/MessageQueue.cpp void MessageQueue::setEventThread(const sp<EventThread>& eventThread) { mEventThread = eventThread; //建立鏈接,從鏈接得到dataChannel,把它的Fd添加到Looper, //也就是把EventThread裏的一個fd傳給了SF線程, //之後EventThread與SF就能夠經過這個fd通訊, mEvents = eventTHread->createEnvetConnection(); mEventTube = mEvents->getDataChannel(); mLooper->addFd(mEventTube->getFd(), 0, Looper::EVENT_INPUT, MessageQueue::cb_eventReceiver, this); //這個cb_eventRecevier很重要,它負責處理EventThread發過來的信號 }
(4)hwcomposer的構造函數:android-8.0.0_r4\frameworks\native\services\surfaceflinger\DisplayHardware\HWComposer_hwc1.cpp
HWComposer::HWComposer( const sp<SurfaceFlinger>& flinger, EventHandler& handler) : mFlinger(flinger), mFbDev(0), mHwc(0), mNumDisplays(1), mCBContext(new cb_context), mEventHandler(handler), mDebugForceFakeVSync(false) { for (size_t i =0 ; i<MAX_HWC_DISPLAYS ; i++) { mLists[i] = 0; } for (size_t i=0 ; i<HWC_NUM_PHYSICAL_DISPLAY_TYPES ; i++) { mLastHwVSync[i] = 0; mVSyncCounts[i] = 0; } char value[PROPERTY_VALUE_MAX]; property_get("debug.sf.no_hw_vsync", value, "0"); mDebugForceFakeVSync = atoi(value); bool needVSyncThread = true; // Note: some devices may insist that the FB HAL be opened before HWC. int fberr = loadFbHalModule(); loadHwcModule(); if (mFbDev && mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) { // close FB HAL if we don't needed it. // FIXME: this is temporary until we're not forced to open FB HAL // before HWC. framebuffer_close(mFbDev); mFbDev = NULL; } // If we have no HWC, or a pre-1.1 HWC, an FB dev is mandatory. if ((!mHwc || !hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) && !mFbDev) { ALOGE("ERROR: failed to open framebuffer (%s), aborting", strerror(-fberr)); abort(); } // these display IDs are always reserved for (size_t i=0 ; i<NUM_BUILTIN_DISPLAYS ; i++) { mAllocatedDisplayIDs.markBit(i); } if (mHwc) { ALOGI("Using %s version %u.%u", HWC_HARDWARE_COMPOSER, (hwcApiVersion(mHwc) >> 24) & 0xff, (hwcApiVersion(mHwc) >> 16) & 0xff); if (mHwc->registerProcs) { mCBContext->hwc = this; mCBContext->procs.invalidate = &hook_invalidate; mCBContext->procs.vsync = &hook_vsync; if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) mCBContext->procs.hotplug = &hook_hotplug; else mCBContext->procs.hotplug = NULL; memset(mCBContext->procs.zero, 0, sizeof(mCBContext->procs.zero)); mHwc->registerProcs(mHwc, &mCBContext->procs); } // don't need a vsync thread if we have a hardware composer needVSyncThread = false; // always turn vsync off when we start eventControl(HWC_DISPLAY_PRIMARY, HWC_EVENT_VSYNC, 0); // the number of displays we actually have depends on the // hw composer version if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_3)) { // 1.3 adds support for virtual displays mNumDisplays = MAX_HWC_DISPLAYS; } else if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) { // 1.1 adds support for multiple displays mNumDisplays = NUM_BUILTIN_DISPLAYS; } else { mNumDisplays = 1; } } if (mFbDev) { ALOG_ASSERT(!(mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)), "should only have fbdev if no hwc or hwc is 1.0"); DisplayData& disp(mDisplayData[HWC_DISPLAY_PRIMARY]); disp.connected = true; disp.format = mFbDev->format; DisplayConfig config = DisplayConfig(); config.width = mFbDev->width; config.height = mFbDev->height; config.xdpi = mFbDev->xdpi; config.ydpi = mFbDev->ydpi; config.refresh = nsecs_t(1e9 / mFbDev->fps); disp.configs.push_back(config); disp.currentConfig = 0; } else if (mHwc) { // here we're guaranteed to have at least HWC 1.1 for (size_t i =0 ; i<NUM_BUILTIN_DISPLAYS ; i++) { queryDisplayProperties(i); } } if (needVSyncThread) { // we don't have VSYNC support, we need to fake it
// 若是不支持硬件Vsync則建立軟件vysnc線程,它是一個sp<>,其onFirstRef()真正建立運行這個線程 mVSyncThread = new VSyncThread(*this); } }
加載並準備hw composer模塊。Sets mHwc
void HWComposer::loadHwcModule() { hw_module_t const* module; if (hw_get_module(HWC_HARDWARE_MODULE_ID, &module) != 0) { ALOGE("%s module not found", HWC_HARDWARE_MODULE_ID); return; } int err = hwc_open_1(module, &mHwc); if (err) { ALOGE("%s device failed to initialize (%s)", HWC_HARDWARE_COMPOSER, strerror(-err)); return; } if (!hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_0) || hwcHeaderVersion(mHwc) < MIN_HWC_HEADER_VERSION || hwcHeaderVersion(mHwc) > HWC_HEADER_VERSION) { ALOGE("%s device version %#x unsupported, will not be used", HWC_HARDWARE_COMPOSER, mHwc->common.version); hwc_close_1(mHwc); mHwc = NULL; return; } }
4.2 SurfaceFLinger使用vsync過程
(1)App發數據給sf,sf發請求給EventThread-sf:AP是Producer,它經過listener->onFrameAvailable() ->進入消費者 -> mFrameAvailableListener(就是Layer對象) -> 進入SF線程-> mFlinger->signalLayerUpdate() -> mEventQueue.invalidate();
//surfaceflinger/MessageQueue.cpp void MessageQueue::invalidate() { //mEvents是sp<IDisplayEventConnection> //也就是sf線程使用connection向EventThread線程請求下一個vsync信號 mEvents->requestNextVsync(); } ---> //surfaceFlinger/EventThread.cpp void EventThread::Connection::requestNextVsync() { mEventThread->requestrNextVsync(this); } ---> void EventTHread::requestNextVysnc( const sp<EventTHread::Connection>& connection) { if(connection->count < 0){ //若cnt小於0,則cnt=0,而後發出廣播,來喚醒某個線程, //當connection的cnt >= 0怎麼它須要從EventThread獲得vsync //這個函數得代碼在EventThread,可是它執行在SF線程 //也就是說,SF線程使用EventThread的函數向EventThread發出廣播來喚醒EventThread線程 connection->count = 0; mCondition.boradcast(); } }
(2)EventThread-sf發請求給DispSyncThread,EventThread裏面必定有一個threadLoop: android-8.0.0_r4\frameworks\native\services\surfaceflinger\EventThread.cpp
bool EventThread::threadLoop() { DisplayEventReceiver::Event event; Vector< sp<EventThread::Connection> > signalConnections;
//1,EventThread向DispSyncThread發出vsync請求
//2,等待vsync signalConnections = waitForEvent(&event); // dispatch events to listeners...
const size_t count = signalConnections.size(); for (size_t i=0 ; i<count ; i++) { const sp<Connection>& conn(signalConnections[i]); // now see if we still need to report this event
// 當EventThread收到Vsync,把它轉交給SF線程 status_t err = conn->postEvent(event); if (err == -EAGAIN || err == -EWOULDBLOCK) { // The destination doesn't accept events anymore, it's probably // full. For now, we just drop the events on the floor. // FIXME: Note that some events cannot be dropped and would have // to be re-sent later. // Right-now we don't have the ability to do this. ALOGW("EventThread: dropping event (%08x) for connection %p", event.header.type, conn.get()); } else if (err < 0) { // handle any other error on the pipe as fatal. the only // reasonable thing to do is to clean-up this connection. // The most common error we'll get here is -EPIPE. removeDisplayEventConnection(signalConnections[i]); } } return true; }
分析waitForEvent():
//this will return when //1, a vsync event has benn recevied //2,there was as least one connection interested in receiving it when we started waiting Vector< sp<EventThread::Connection > >EventThread::waitForEvent( DisplayEventReceiver::Event* event) { //find out connections waitting for events size_t count = mDisplayEventConnections.size(); ofr(size_t i=0; i<count; i++) { if(connection->count >= 0) { //we need vsync events because at least //one connnection is waiting for it waitForVSync = true; } ...... if(waitFOrVSync){ enableVSyncLocked(); //若是上面的count >= 0,表明須要獲得vsync信號,而後調用enableVSyncLocked() } if(waitForVSync){ ...... } else { //EventThread以後就會休眠等待vsync mCondition.wait(mLock); } } }
enableVSyncLocked中給DisplaySyncThread設置回調,在DisplaySyncThread收到vsync信號後就調用這個回調函數:
void EventThread::enableVSyncLocked() { if(!mVsyncEnabled) { mVsyncEnabled = true; mVSyncSource->setCallback(static_cast<VSyncSource::Callback*)(this)); mVSYncSource->setVSyncEnabled(true); } }
(3)H/S vsync喚醒DispSyncThread:
//surfaceFlinger/DIsplayHardware/HWComposer_hwc1.cpp bool HWComposer::VSyncThread::threadLoop() { clock_nanosleep(); //休眠 完成後,調用它,發出vsync信號 //mEventHanlder就是SurfaceFlinger, mHwc.mEventHandler.onVSyncReceived(0, next_vsync); } ---> //surfaceflinger/SurafceFLinger.cpp void SurfaceFLinger::onVSyncReceived(type, nescs_t timestamp){ if(type == 0 && mPrimaryHWVsyncEnabled) { //DispSync::addResyncSample => updateModelLocked() => //mThread->updateModel => mCond.signal()來喚醒某個線程, //mCond.signal()在DispSync.cpp,屬於DispSYncThread, //仍是以前說的套路,swVsyncThread使用DispSync的函數喚醒DispSYncThread needsHwVsync = mPrimaryDIspSync.addResyncSample(timestamp); } if(needsHwVsync) { enableHardwareVsync(); } }
(4)DispSyncThread發信號給EventThread,EventThread發信號給SF線程。
//surfaceflinger/DispSync.cpp class DispSyncThread : public Thread { virtual bool threadLoop() { //計算最近的eventThread的時間,EventThread是Listener, // =>computeListenerNextEventTimeLocked targetTime = computeNextEventTimeLocked(now); //休眠 if(now < targetTime) { mCond.waitRelative(mMutex, targetrTime-now); } //以後被vsync信號喚醒,獲取callback callbackInvacations = gatherCallbackInvocationsLocked(now); if(callbackInvocations.size() > 0) { //執行callback,致使EventThread的onVsyncEvent函數被調用 fireCallbackInvocations(callbackInvovcations); } } }
若是EventThread發現Connection的cnt >= 0,就會向DispSyncThread註冊回調函數,最後會經過callback構造出Listener,並且EventThread運行時間是收到vsync以後加一個offset,fireCallbackInvocations()調用EventThread類的onVSyncEvent來喚醒EventThread線程:
//surfaceFlinger/EventThread.cpp void EventThread::onVSyncEvent(nsecs_t timestamp) { Mutex::Autolock _l(mLock); mVSyncEvent[0].header.id = 0; mVsyncEvent[0].vsync.count++; //發出廣播,喚醒EvenThread::threadLoop()向app或sf發出信號 mCondition.broadcast(); }
EventThread::threadLoop()在waitForEvent裏面休眠(mCondition.wait),收到廣播後被喚醒,而後調用conn->postEvent(event)向SF線程或者AP發出信號,並經過connection的fd把數據寫到SF線程,一樣SF線程經過fd得到數據,而後調用SF線程的處理函數。
status_t EventThread::Connection::postEvent( const DisplayEventReceiver::Event& event) { ssize_t size = DisplayEventReceiver::sendEvents(&mChannel, &event, 1); return size < 0 ? status_t(size) : status_t(NO_ERROR); }
(5)sf線程對vsync的處理:在flinger->init()建立connection時,獲得了一個fd,而後會檢測fd。
flinger->init() => MessageQueue::setEventThread:
mEventTube = mEvent->getDataChannel(); //檢測fd,從fd獲得數據,會調用MessageQueue::cb_eventRecevier函數 mLooper->addFd(mEventTube0>getFd(),....,MessageQueue::cb_eventRecevier, this);
--->
//surfaceflinger/MessageQueue.cpp int MessageQueue::cb_eventRecevier(int fd, int event, void* data) { return queue->eventRecevier(fd, events); }
---> int MessageQueue::eventReceiver(int fd, int events) { mHanlder->displatchInvalidate(); } ---> void MessageQueue::Handler::displayInvaliadate() { mQueue.mLooper->sendMessage(this, Message(MessageQueue::INVALIDATE)); }
SurfaceFlinger中接收並處理消息:
void MessageQueue::Handler::handleMessage(const Message& message) { switch(message.what) { ... case INVALIDATE: mQueue.mFlinger->onMessageReceived(message.what); } } ---> // android-8.0.0_r4\frameworks\native\services\surfaceflinger\SurfaceFlinger_hwc1.cpp void SurfaceFlinger::onMessageReceived(int32_t what) { ATRACE_CALL(); switch (what) { case MessageQueue::INVALIDATE: { bool refreshNeeded = handleMessageTransaction(); //處理事務(設置flag,並未實際操做各個buffer):
//①在handleTransactionLocked()中遍歷每一個Layer,執行layer->doTransaction(0)
//②處理Display事務(add/remove)
//③Layer角度發生了變化
//④處理sf自己事務: Layer的增長或者刪除
refreshNeeded |= handleMessageInvalidate(); //處理各Layer的buffer更換,使原來的界面無效,並準備好新數據用來更新:
//①accquire next buffer
//②release previous buffer
//③bindTextureImageLocked() ---> glEGLImageTargetTexture2DOES()
refreshNeeded |= mRepaintEverything; if (refreshNeeded) { // Signal a refresh if a transaction modified the window state, // a new buffer was latched, or if HWC has requested a full // repaint signalRefresh(); //發出Refresh信號,致使下面的 handleMessageRefresh()函數被調用 } break; } case MessageQueue::REFRESH: { handleMessageRefresh(); //①計算各Layer的可視區域
//②合成顯示:a.調用opengl把各個Layer的可視區域在一個內存上描繪出來
// b.使用hw composer硬件合成
break; } } }
(Vsync時序圖)