Android 顯示系統:Vsync機制


一、Vsync簡介:

  屏幕的刷新過程是每一行從左到右(行刷新,水平刷新,Horizontal Scanning),從上到下(屏幕刷新,垂直刷新,Vertical Scanning)。當整個屏幕刷新完畢,即一個垂直刷新周期完成,會有短暫的空白期,此時發出 VSync 信號。所以,VSync 中的 V 指的是垂直刷新中的垂直-Vertical。

  Android系統每隔16ms發出VSYNC信號,觸發對UI進行渲染,VSync是Vertical Synchronization(垂直同步)的縮寫,是一種在PC上很早就廣泛使用的技術,可以簡單的把它認為是一種定時中斷。而在Android 4.1(JB)中已經開始引入VSync機制,用來同步渲染,讓AppUI和SurfaceFlinger可以按硬件產生的VSync節奏進行工作。

 

二、黃油計划:三個方法改進顯示系統

 1.Vsync同步:

 

  

 

  可見vsync信號沒有提醒CPU/GPU工作的情況下,第二次vsync到來需要顯示內容時,CPU和GPU還沒有來得及准備好下一幀的數據,所以只能接着顯示上一幀的數據,產生Jank!

 

 

 

 

  CPU/GPU接收vsync信號提前准備下一幀要顯示的內容,所以能夠及時准備好每一幀的數據,保證畫面的流程。

 

 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頻出:

  

 

   因此用三級緩沖來提高系統對性能波動的容忍度:

  

 

   雖然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_NSSF_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硬件發命令。

 

三、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, &param) != 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, &param) != 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, &param) != 0) { ALOGE("Couldn't set SCHED_FIFO for SFEventThread"); } if (sched_setscheduler(mEventThread->getTid(), SCHED_FIFO, &param) != 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時序圖)

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM