Android圖形系統(tǒng)(十)-SurfaceFlinger啟動(dòng)及圖層合成送顯過程

這個(gè)系列最后一篇文章蓬网,簡單總結(jié)下SurfaceFlinger的啟動(dòng)流程及合成視圖過程瘸味。

一切端、SurfaceFlinger啟動(dòng)流程

SurfaceFlinger 進(jìn)程是由 init 進(jìn)程創(chuàng)建的型将,運(yùn)行在獨(dú)立進(jìn)程中寂祥。

//init.rc
service surfaceflinger /system/bin/surfaceflinger
    class core
    user system
    group graphics drmrpc
    onrestart restart zygote
    writepid /dev/cpuset/system-background/tasks

SurfaceFlinger 的創(chuàng)建會(huì)執(zhí)行 main() 方法:

//main_surfaceflinger.cpp
int main(int, char**) {
    ProcessState::self()->setThreadPoolMaxThreadCount(4);
    sp<ProcessState> ps(ProcessState::self());
    ps->startThreadPool();
    //實(shí)例化 surfaceflinger
    sp<SurfaceFlinger> flinger =  new SurfaceFlinger();
    setpriority(PRIO_PROCESS, 0, PRIORITY_URGENT_DISPLAY);
    set_sched_policy(0, SP_FOREGROUND);
    //初始化
    flinger->init();
    //發(fā)布 surface flinger,注冊到 ServiceManager
    sp<IServiceManager> sm(defaultServiceManager());
    sm->addService(String16(SurfaceFlinger::getServiceName()), flinger, false);
    // 運(yùn)行在當(dāng)前線程
    flinger->run();
    return 0;
}

事實(shí)上到這里七兜,SurfaceFlinger進(jìn)程就已經(jīng)啟動(dòng)了丸凭。之后我們再來了解下SurfaceFlinger的一些初始化操作:

首先SurfaceFlinger 的實(shí)例化會(huì)執(zhí)行到:onFirstRef()

//SurfaceFlinger.cpp
void SurfaceFlinger::onFirstRef() {
    mEventQueue.init(this); //初始化MessageQueue , mEventQueue.init中又會(huì)創(chuàng)建Looper與Handler。
}

然后會(huì)執(zhí)行到 SurfaceFlinger::init():

//SurfaceFlinger.cpp
void SurfaceFlinger::init() {
    Mutex::Autolock _l(mStateLock);
    //初始化 EGL腕铸,作為默認(rèn)的顯示
    mEGLDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
    eglInitialize(mEGLDisplay, NULL, NULL);
    // 初始化硬件 composer 對象
    mHwc = new HWComposer(this, *static_cast<HWComposer::EventHandler *>(this));
    //獲取 RenderEngine 引擎
    mRenderEngine = RenderEngine::create(mEGLDisplay, mHwc->getVisualID());
    //檢索創(chuàng)建的 EGL 上下文
    mEGLContext = mRenderEngine->getEGLContext();
    //初始化非虛擬顯示屏
    for (size_t i=0 ; i<DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES ; i++) {
        DisplayDevice::DisplayType type((DisplayDevice::DisplayType)i);
        //建立已連接的顯示設(shè)備
        if (mHwc->isConnected(i) || type==DisplayDevice::DISPLAY_PRIMARY) {
            bool isSecure = true;
            createBuiltinDisplayLocked(type);
            wp<IBinder> token = mBuiltinDisplays[i];
            sp<IGraphicBufferProducer> producer;
            sp<IGraphicBufferConsumer> consumer;
            //創(chuàng)建 BufferQueue 的生產(chǎn)者和消費(fèi)者
            BufferQueue::createBufferQueue(&producer, &consumer,
                    new GraphicBufferAlloc());
            sp<FramebufferSurface> fbs = new FramebufferSurface(*mHwc, i, consumer);
            int32_t hwcId = allocateHwcDisplayId(type);
            //創(chuàng)建顯示設(shè)備
            sp<DisplayDevice> hw = new DisplayDevice(this,
                    type, hwcId, mHwc->getFormat(hwcId), isSecure, token,
                    fbs, producer,
                    mRenderEngine->getEGLConfig());
            if (i > DisplayDevice::DISPLAY_PRIMARY) {
                hw->setPowerMode(HWC_POWER_MODE_NORMAL);
            }
            mDisplays.add(token, hw);
        }
    }
    getDefaultDisplayDevice()->makeCurrent(mEGLDisplay, mEGLContext);
    //當(dāng)應(yīng)用和 sf 的 vsync 偏移量一致時(shí)惜犀,則只創(chuàng)建一個(gè) EventThread 線程
    if (vsyncPhaseOffsetNs != sfVsyncPhaseOffsetNs) {
        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);
    } else {
        //創(chuàng)建 DispSyncSource 對象
        sp<VSyncSource> vsyncSrc = new DispSyncSource(&mPrimaryDispSync,
                vsyncPhaseOffsetNs, true, "sf-app");
        //創(chuàng)建線程 EventThread
        mEventThread = new EventThread(vsyncSrc);
        //設(shè)置 EventThread
        mEventQueue.setEventThread(mEventThread);
    }
    //創(chuàng)建 EventControl
    mEventControlThread = new EventControlThread(this);
    mEventControlThread->run("EventControl", PRIORITY_URGENT_DISPLAY);
    //當(dāng)不存在 HWComposer 時(shí),則設(shè)置軟件 vsync
    if (mHwc->initCheck() != NO_ERROR) {
        mPrimaryDispSync.setPeriod(16666667);
    }
    //初始化繪圖狀態(tài)
    mDrawingState = mCurrentState;
    //初始化顯示設(shè)備
    initializeDisplays();
    //啟動(dòng)開機(jī)動(dòng)畫
    startBootAnim();
}

該方法主要是執(zhí)行一些初始化工作狠裹,包括:EGL標(biāo)準(zhǔn)下OpenGL環(huán)境的創(chuàng)建虽界、創(chuàng)建 HWComposer、初始化非虛擬顯示屏涛菠、啟動(dòng) EventThread 線程莉御、啟動(dòng)開機(jī)動(dòng)畫等等撇吞。

在這里,有幾個(gè)比較重要的對象需要介紹下:

  1. EGL:OpenGL是一個(gè)操作GPU的API礁叔,它通過驅(qū)動(dòng)向GPU發(fā)送相關(guān)指令牍颈,控制圖形渲染管線狀態(tài)機(jī)的運(yùn)行狀態(tài)。但OpenGL需要本地視窗系統(tǒng)進(jìn)行交互琅关,這就需要一個(gè)中間控制層煮岁,最好與平臺(tái)無關(guān)。EGL正是這個(gè)中間控制層涣易,它作為OpenGL ES和本地窗口的橋梁画机,主要作用是:其主要作用是為OpenGL指令創(chuàng)建 Context 、繪制目標(biāo)Surface 都毒、配置Framebuffer屬性色罚、Swap提交繪制結(jié)果等。

  2. HWComposer: 硬件組合抽象層账劲,介于SurfaceFlinger和HAL之間戳护,具體到代碼級(jí)別就是一個(gè)類,封裝對于Hwcomposer HAL和Gralloc HAL的使用瀑焦。 主要作用是:一方面處理部分SurfaceFlinger委托過來的合成工作腌且,另一方面就是產(chǎn)生vsync信號(hào)

  3. EventThread: 它是Surfaceflinger中的一個(gè)線程 ,主要作用:接收VSync事件通知榛瓮,并分發(fā)VSync通知給系統(tǒng)中的每一個(gè)感興趣的注冊者铺董。

二、SurfaceFlinger圖層合成過程

2.1 什么是圖層合成

圖層合成就是把多個(gè)圖層按既定的顯示區(qū)域禀晓,展現(xiàn)到顯示屏上精续。

例如Android手機(jī)的Launcher主界面圖層合成如下:


adb shell dumpsys SurfaceFlinger

com.android.systemui.ImageWallpaper
com.miui.home/com.miui.home.launcher.Launcher
StatusBar
2.2 SurfaceFlinger合成消息

SurfaceFlinger合成圖層依賴于Android的異步消息處理機(jī)制。

首先粹懒,它包含了一個(gè)MessageQueue對象(消息隊(duì)列)用于處理各種異步消息重付,在onFirstRef()中對消息隊(duì)列進(jìn)行了初始化:

//SurfaceFlinger.cpp
SurfaceFlinger::onFirstRef()
{
    mEventQueue.init(this);
}

分析一下MessageQueue的實(shí)現(xiàn):

//MessageQueue.cpp
void MessageQueue::init(const sp<SurfaceFlinger>& flinger)
{
   mFlinger = flinger;//保存MessageQueue的擁有者SurfaceFlinger
   mLooper = new Looper(true);//創(chuàng)建Looper對象
   mHandler = new Handler(*this);//創(chuàng)建Handler對象
}

調(diào)用Handler::handleMessage()處理INVALIDATE和REFRESH消息,并將其轉(zhuǎn)發(fā)給SurfaceFlinger進(jìn)行處理凫乖,調(diào)用onMessageReceived():

void MessageQueue::Handler::handleMessage(const Message& message) {
   switch (message.what) {
       case INVALIDATE:
           android_atomic_and(~eventMaskInvalidate, &mEventMask);
           mQueue.mFlinger->onMessageReceived(message.what);
           break;
       case REFRESH:
           android_atomic_and(~eventMaskRefresh, &mEventMask);
           mQueue.mFlinger->onMessageReceived(message.what);
           break;
   }  
}

接下來看一下SurfaceFlinger對消息的處理:

void SurfaceFlinger::onMessageReceived(int32_t what) {
   ATRACE_CALL();
   switch (what) {
       case MessageQueue::INVALIDATE: {
           bool refreshNeeded = handleMessageTransaction();
           refreshNeeded |= handleMessageInvalidate();
           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();
           }
           break;
       }
       case MessageQueue::REFRESH: {
           handleMessageRefresh();
           break;
       }
   }    
}

SurfaceFlinger處理的消息分為兩種:

INVALIDATE消息:用于處理Layer或者display屬性的變化以及Layer對應(yīng)buffer的更新确垫。

 1) Layer或者Display屬性的更新通過調(diào)用handleMessageTransaction()處理;

 2) buffer的更新通過調(diào)用handleMessageInvalidate()處理。

REFRESH消息:表示SurfaceFlinger需要進(jìn)行一次合成操作(Refresh),通過handleMessageRefresh()實(shí)現(xiàn)帽芽;主要有三種情況:

 1) Layer屬性的變化導(dǎo)致window state發(fā)生變化;

 2) Layer有新的buffer到來;

 3) HWC請求進(jìn)行一次repaint删掀。

如果這三種情況之一發(fā)生,則置refreshNeeded為true导街,調(diào)用signalRefresh()發(fā)出MessageQueue::REFRESH消息;

當(dāng)VSync信號(hào)來之前披泪,Layer或者display屬性的變化會(huì)做本地保存,只有當(dāng)VSync信號(hào)到來時(shí)搬瑰,SurfaceFlinger才會(huì)通過INVALIDATE和REFRESH消息來做統(tǒng)一的合并渲染和輸出的處理工作付呕。

2.3 handleMessageTransaction()

處理之前對屏幕和應(yīng)用程序窗口的改動(dòng)计福。因這些改動(dòng)很有可能會(huì)改變圖層的可見區(qū)域,進(jìn)而影響臟區(qū)域的計(jì)算徽职。

主要處理以下幾個(gè)方面的transaction:

1)Layer屬性的變化;
2)Layer的增加和減少佩厚;
3)Display屬性的變化;
4)Display的增加和減少姆钉;
2.4 handleMessageInvalidate()

主要調(diào)用handlePageFlip()函數(shù)。這里Page Flip是指從BufferQueue中取下一個(gè)圖形緩沖區(qū)內(nèi)容抄瓦,就好像是“翻頁”一樣潮瓶。該函數(shù)主要是從各Layer對應(yīng)的BufferQueue中拿圖形緩沖區(qū)數(shù)據(jù),并根據(jù)內(nèi)容更新臟區(qū)域(注:臟區(qū)域是需要重繪的屏幕區(qū)域钙姊。)毯辅。并且把GraphicBuffer映射為OpenGL的texture 。

2.5 handleMessageRefresh()

合并和渲染輸出煞额。

void SurfaceFlinger::handleMessageRefresh() {
   ...
    preComposition(); //合成前的準(zhǔn)備
    rebuildLayerStacks();//重建layer堆棧
    setUpHWComposer();//hwcomposer的設(shè)定
    doComposition();//正式的合成處理
    postComposition(refreshStartTime);//合成后期的處理
   ...
}
2.5.1 void SurfaceFlinger::preComposition()

合成前準(zhǔn)備工作思恐。首先得到當(dāng)前所有l(wèi)ayer的集合,然后對所有的Layer調(diào)用其onPreComposition()檢查是否需要ExtralInvalidate,如果需要就調(diào)用一次signalLayerUpdate(),即通過EventThread安排一次vsync膊毁。

2.5.2 void SurfaceFlinger::rebuildLayerStacks()

計(jì)算可見layer及它們的可見區(qū)域胀莹。首先每個(gè)layer都有一個(gè)layerStack來區(qū)別它屬于哪個(gè)Display,系統(tǒng)的Display可能不止一個(gè)婚温,所以需要逐個(gè)處理Display描焰,根據(jù)所有l(wèi)ayers的當(dāng)前狀態(tài)通過SurfaceFlinger::computeVisibleRegions方法計(jì)算各個(gè)Layer在當(dāng)前display上的可見區(qū)域和臟區(qū)域等。最后把需要繪制的layer添加到layersSortedByZ中栅螟。

2.5.3 void SurfaceFlinger::setUpHWComposer()

為合成搭建環(huán)境荆秦。這個(gè)HWComposer并不是真正的Hal模塊,而是surfaceflinger為管理HWComposer模塊而設(shè)計(jì)的一個(gè)類力图,路徑是:frameworks/native/service/surfaceflinger/displayhardware/步绸。依次處理各個(gè)Display,構(gòu)造WorkList搪哪,合成過程既可以有Hwc模塊完成靡努,也可以通過OpengGlEs來完成,具體用哪種方式是有prepare()中的compositionType來決定的晓折。

2.5.4 void SurfaceFlinger::doComposition()

執(zhí)行合成操作惑朦。執(zhí)行openGl合成 or HWC合成。

2.5.5 void SurfaceFlinger::postComposition(refreshStartTime)

將圖像傳遞到物理屏幕漓概。

最后借用一張流程圖做最后的總結(jié):

from Jeanboydev

參考:
https://blog.csdn.net/jxt1234and2010/article/details/46057267
https://blog.csdn.net/freekiteyu/article/details/79483406
https://blog.csdn.net/u012878643/article/details/71104467

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
禁止轉(zhuǎn)載漾月,如需轉(zhuǎn)載請通過簡信或評論聯(lián)系作者。
  • 序言:七十年代末胃珍,一起剝皮案震驚了整個(gè)濱河市梁肿,隨后出現(xiàn)的幾起案子蜓陌,更是在濱河造成了極大的恐慌,老刑警劉巖吩蔑,帶你破解...
    沈念sama閱讀 206,968評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件钮热,死亡現(xiàn)場離奇詭異,居然都是意外死亡烛芬,警方通過查閱死者的電腦和手機(jī)隧期,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來赘娄,“玉大人仆潮,你說我怎么就攤上這事∏簿剩” “怎么了性置?”我有些...
    開封第一講書人閱讀 153,220評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長揍堰。 經(jīng)常有香客問我鹏浅,道長,這世上最難降的妖魔是什么个榕? 我笑而不...
    開封第一講書人閱讀 55,416評論 1 279
  • 正文 為了忘掉前任篡石,我火速辦了婚禮,結(jié)果婚禮上西采,老公的妹妹穿的比我還像新娘凰萨。我一直安慰自己,他們只是感情好械馆,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,425評論 5 374
  • 文/花漫 我一把揭開白布胖眷。 她就那樣靜靜地躺著,像睡著了一般霹崎。 火紅的嫁衣襯著肌膚如雪珊搀。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,144評論 1 285
  • 那天尾菇,我揣著相機(jī)與錄音境析,去河邊找鬼。 笑死派诬,一個(gè)胖子當(dāng)著我的面吹牛劳淆,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播默赂,決...
    沈念sama閱讀 38,432評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼沛鸵,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了缆八?” 一聲冷哼從身側(cè)響起曲掰,我...
    開封第一講書人閱讀 37,088評論 0 261
  • 序言:老撾萬榮一對情侶失蹤疾捍,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后栏妖,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體乱豆,經(jīng)...
    沈念sama閱讀 43,586評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,028評論 2 325
  • 正文 我和宋清朗相戀三年底哥,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了咙鞍。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,137評論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡趾徽,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出翰守,到底是詐尸還是另有隱情孵奶,我是刑警寧澤,帶...
    沈念sama閱讀 33,783評論 4 324
  • 正文 年R本政府宣布蜡峰,位于F島的核電站了袁,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏湿颅。R本人自食惡果不足惜载绿,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,343評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望油航。 院中可真熱鬧崭庸,春花似錦、人聲如沸谊囚。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,333評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽镰踏。三九已至函筋,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間奠伪,已是汗流浹背跌帐。 一陣腳步聲響...
    開封第一講書人閱讀 31,559評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留绊率,地道東北人谨敛。 一個(gè)月前我還...
    沈念sama閱讀 45,595評論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像即舌,于是被迫代替她去往敵國和親佣盒。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,901評論 2 345

推薦閱讀更多精彩內(nèi)容