一般OpenGL被認為是一個API(Application Programming Interface, 應用程序編程接口),包含了一系列可以操作圖形、圖像的函數。然而,OpenGL本身並不是一個API,它僅僅是一個由Khronos組織制定並維護的規範(Specification)。
OpenGL規範嚴格規定了每個函數該如何執行,以及它們的輸出值。至於內部具體每個函數是如何實現的,將由OpenGL庫的開發者自行決定
實際的OpenGL庫的開發者通常是顯卡的生產商
OpenGL ES(OpenGL for Embedded Systems) 是從OpenGL裁剪的定製而來的,去除了一些複雜圖元等許多非絕對必要的特性
OpenGL還是很值得學習的,大家可以參考:LearnOpenGL教程的中文翻譯
`EGL`我們知道OpenGL ES定義了一個渲染圖形的API,但沒有定義窗口系統。
為了讓OpenGL ES能夠適合各種平台,OpenGL ES需要與一個知道如何通過操作系統創建和訪問窗口的庫結合使用
在Android中的這個庫就是EGL。(沒有什麼問題是不能通過增加一個中間層來解決的,有的話那就再增加一個。。。。。)
整體結構如下(網上盜圖):

使用EGL繪製的一般步驟如下:
獲取 EGL Display 對象:eglGetDisplay()
初始化與 EGLDisplay 之間的連接:eglInitialize()
獲取 EGLConfig 對象:eglChooseConfig()
創建 EGLContext 實例:eglCreateContext()
創建 EGLSurface 實例:eglCreateWindowSurface()
連接 EGLContext 和 EGLSurface:eglMakeCurrent()
使用 OpenGL ES API 繪製圖形:gl_*()
切換 front buffer 和 back buffer 送顯:eglSwapBuffer()
斷開並釋放與 EGLSurface 關聯的 EGLContext 對象:eglRelease()
刪除 EGLSurface 對象
刪除 EGLContext 對象
終止與 EGLDisplay 之間的連接
`Android`中的封裝前面的章節我們介紹過,無論開發者使用什麼渲染API,一切內容都會渲染到Surface上
此處的Surface指的是framework/native/libs/gui/Surface.cpp對應的業務邏輯
當SurfaceFlinger以消費者的角色獲取到顯示數據後,會開始進行渲染操作,在過程中也存在一個Surface
定義在framework/native/services/surfaceflinger/RenderEngine/Surface.cpp
這個Surface便是對EGL接口的調用封裝,我們看下這個類的定義:
Surface::Surface(constRenderEngine&engine):mEGLDisplay(engine.getEGLDisplay()),mEGLConfig(engine.getEGLConfig()){...}Surface::~Surface(){setNativeWindow(nullptr);}voidSurface::setNativeWindow(ANativeWindow*window){...if(mWindow){mEGLSurface=eglCreateWindowSurface(mEGLDisplay,mEGLConfig,mWindow,nullptr);}}voidSurface::swapBuffers()const{if(!eglSwapBuffers(mEGLDisplay,mEGLSurface)){...}}EGLintSurface::queryConfig(EGLintattrib)const{EGLintvalue;if(!eglGetConfigAttrib(mEGLDisplay,mEGLConfig,attrib,&value)){value=0;}returnvalue;}EGLintSurface::querySurface(EGLintattrib)const{EGLintvalue;if(!eglQuerySurface(mEGLDisplay,mEGLSurface,attrib,&value)){value=0;}returnvalue;}接口定義結合上面EGL的知識應該很容易理解,下面我們開始SurfaceFlinger學習吧
`SurfaceFlinger`的啟動過程從Android 4.4開始SurfaceFlinger服務運行在一個獨立的守護進程中(以前在SystemServer中),這樣系統的圖像繪製性能會得到一定的提升。frameworks/native/services/surfaceflinger/surfaceflinger.rc中關於SurfaceFlinger的定義如下:
servicesurfaceflinger/system/bin/surfaceflingerclasscoreanimationusersystemgroupgraphicsdrmrpcreadproconrestartrestartzygote...可以看到surfaceflinger放到了core組裡,這個組的服務會在系統初始化時啟動。SurfaceFlinger啟動的入口函數main()代碼如下:
intmain(int,char**){...//啟動Gralloc服務startGraphicsAllocatorService();//設置當前Binder服務可連接最大線程數ProcessState::self()->setThreadPoolMaxThreadCount(4);//通過startThreadPool通知Binder驅動當前線程已準備完成sp<ProcessState>ps(ProcessState::self());ps->startThreadPool();//初始化SurfaceFlingersp<SurfaceFlinger>flinger=newSurfaceFlinger();//調整進程優先級為PRIORITY_URGENT_DISPLAYsetpriority(PRIO_PROCESS,0,PRIORITY_URGENT_DISPLAY);//調整調度策略,將其設置為前台進程//這兩種標誌涉及了內核的完全公平調度算法,感興趣的同學可以百度一下//在這裡的目的是保證SurfaceFlinger的較高優先級,方便快速響應更新圖像的請求set_sched_policy(0,SP_FOREGROUND);...//註冊Service前的初始化部分flinger->init();//註冊SurfaceFlinger服務sp<IServiceManager>sm(defaultServiceManager());sm->addService(String16(SurfaceFlinger::getServiceName()),flinger,false,IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL|IServiceManager::DUMP_FLAG_PROTO);//註冊GpuService服務sp<GpuService>gpuservice=newGpuService();sm->addService(String16(GpuService::SERVICE_NAME),gpuservice,false);//啟動DisplayService服務startDisplayService();//dependencyonSFgettingregisteredabove...//runsurfaceflingerinthisthreadflinger->run();return0;}main()方法中注釋比較詳細就不細說了,方法總結下來有三點:
初始化GraphicsAllocatorService、DisplayService和GpuService服務
set_sched_policy和sched_setscheduler設置進程優先級
SurfaceFlinger對象的初始化以及init和run方法的調用
SurfaceFlinger的初始化過程設計的模塊比較多,我們先簡單看下類關係圖:

SurfaceFlinger的類定義如下:
classSurfaceFlinger:publicBnSurfaceComposer,publicPriorityDumper,privateIBinder::DeathRecipient,privateHWC2::ComposerCallback{}BnSurfaceComposer類:類圖中該類實現的是ISurfaceComposer接口,而ISurfaceComposer又是一套定義好的Binder類
`Binder`篇提到過,當出現`Bn*`開頭的類就可以把它看做`Binder服務類`了,所以`SurfaceFlinger`這裡是作為一個`Binder`服務對象
上一篇在`SurfaceSession`初始化時,`SurfaceComposerClient`對象就是通過`ServiceManager`獲取了`SurfaceFlinger`服務
然後通過服務提供的`createConnection()`方法獲取了`ISurfaceComposerClient`對象,也就是上面類圖中提到的`Client`類
HWC2::ComposerCallback類:面向底層硬件狀態的監聽回調接口,包括
`onHotplugReceived`,顯示屏熱插拔事件回調
`onRefreshReceived`,通知刷新的回調
`onVsyncReceived`,`VSYNC`信號接收回調
SurfaceFlinger的構造方法如下:
SurfaceFlinger::SurfaceFlinger():SurfaceFlinger(SkipInitialization){ALOGI("SurfaceFlingerisstarting");//初始化vsync信號相關的offsetvsyncPhaseOffsetNs=getInt64<ISurfaceFlingerConfigs,&ISurfaceFlingerConfigs::vsyncEventPhaseOffsetNs>(1000000);sfVsyncPhaseOffsetNs=getInt64<ISurfaceFlingerConfigs,&ISurfaceFlingerConfigs::vsyncSfEventPhaseOffsetNs>(1000000);...//確認主屏幕方向V1_1::DisplayOrientationprimaryDisplayOrientation=getDisplayOrientation<V1_1::ISurfaceFlingerConfigs,&V1_1::ISurfaceFlingerConfigs::primaryDisplayOrientation>(V1_1::DisplayOrientation::ORIENTATION_0);switch(primaryDisplayOrientation){caseV1_1::DisplayOrientation::ORIENTATION_90:mPrimaryDisplayOrientation=DisplayState::eOrientation90;break;...}//初始化主屏幕的DispSync對象,這個對象與vsync信號分發有關係mPrimaryDispSync.init(SurfaceFlinger::hasSyncFramework,SurfaceFlinger::dispSyncPresentTimeOffset);...//讀取Prop進行一些基礎屬性的設置//是否啟動HWC虛擬顯示property_get("debug.sf.enable_hwc_vds",value,"0");mUseHwcVirtualDisplays=atoi(value);//是否開啟三級緩衝property_get("ro.sf.disable_triple_buffer",value,"1");mLayerTripleBufferingDisabled=atoi(value);...}構造方法中主要的動作是mPrimaryDispSync.init()操作,餘下基本都是對一些變量的初始化。mPrimaryDispSync的類型是DispSync,這個對象主要是對VSYNC信號進行調整,然後轉發給app或sf,等下完善。
隨着SurfaceFlinger對象創建後的初次引用,也會調用到對象的onFirstRef()方法:
voidSurfaceFlinger::onFirstRef(){mEventQueue->init(this);}方法中執行了MessageQueue對象的init()方法,這個MessageQueue是SurfaceFlinger自己定義的消息隊列,MessageQueue相關的知識對整個SurfaceFlinger業務邏輯的理解有着關鍵作用,下面細講
鋪墊內容了解這部分的內容有助於更好的理解SurfaceFlinger後面的init()和run()方法
消息和事件分發-`MessageQueue`MessageQueue是SurfaceFlinger中用與消息和事件分發的對象,先看下主要的成員變量:
classMessageQueue{...sp<SurfaceFlinger>mFlinger;//指向SurfaceFlinger對象sp<Looper>mLooper;//實現消息機制的Looper對象android::EventThread*mEventThread;//關聯的EventThread對象sp<IDisplayEventConnection>mEvents;gui::BitTubemEventTube;sp<Handler>mHandler;//消息處理Handler...}MessageQueue的成員變量中
mLooper是一個指向Looper類的指針,它實現了一套完整的消息處理機制
mEventThread指向一個EventThread對象,主要作用是分發VSYNC信號
前面提到在SurfaceFlinger中會調用MessageQueue對象的init()方法,代碼如下:
voidMessageQueue::init(constsp<SurfaceFlinger>&flinger){mFlinger=flinger;mLooper=newLooper(true);mHandler=newHandler(*this);}init()方法中
創建了Handler對象。此處的Handler是MessageQueue中定義的一個內部類,定義如下:
classMessageQueuefinal:publicandroid::MessageQueue{classHandler:publicMessageHandler{enum{eventMaskInvalidate=0x1,eventMaskRefresh=0x2,eventMaskTransaction=0x4};MessageQueue&mQueue;int32_tmEventMask;...};}Handler對象中主要處理三種消息:eventMaskInvalidate、eventMaskRefresh、eventMaskTransaction
創建了Looper對象。關於native層的Looper對象在Android 消息機制中已經介紹過,會通過epoll開啟一個消息監聽,具體可以看這個直達入口
init()完成後,MessageQueue就可以通過waitMessage()來等待消息,代碼如下:
voidMessageQueue::waitMessage(){do{IPCThreadState::self()->flushCommands();int32_tret=mLooper->pollOnce(-1);//嘗試讀取消息,-1表示永遠阻塞switch(ret){caseLooper::POLL_WAKE://poll被喚醒caseLooper::POLL_CALLBACK:continue;caseLooper::POLL_ERROR://poll發送錯誤ALOGE("Looper::POLL_ERROR");continue;caseLooper::POLL_TIMEOUT://poll超時//timeout(shouldnothappen)continue;default://shouldnothappenALOGE("Looper::pollOnce()returnedunknownstatus%d",ret);continue;}}while(true);}waitMessage()是一個無限循環,它的主要作用是循環調用Looper類的pollOnce()從消息隊列中讀取消息
需要注意的是waitMessage()中並沒有消息的處理過程,而且沒有明顯的消息處理方法的調用,那麼具體的消息處理在哪裡? 消息的處理涉及EventThread類,在MessageQueue中通過setEventThread()方法進行關聯,代碼如下:
voidMessageQueue::setEventThread(android::EventThread*eventThread){if(mEventThread==eventThread){return;}if(mEventTube.getFd()>=0){mLooper->removeFd(mEventTube.getFd());}mEventThread=eventThread;//創建連接mEvents=eventThread->createEventConnection();mEvents->stealReceiveChannel(&mEventTube);//重點是這個方法mLooper->addFd(mEventTube.getFd(),0,Looper::EVENT_INPUT,MessageQueue::cb_eventReceiver,this);}setEventThread()方法中
先調用了EventThread對象的createEventConnection()方法來創建一個連接
sp<BnDisplayEventConnection>EventThread::createEventConnection()const{//創建Connection對象,同時會調用它的onFirstRef方法returnnewConnection(const_cast<EventThread*>(this));}//Connection的構造方法,初始化BitTubemChannel對象,並設置mEventThreadEventThread::Connection::Connection(EventThread*eventThread):count(-1),mEventThread(eventThread),mChannel(gui::BitTube::DefaultSize){}//Connection對象的onFirstRef方法會將自己添加到EventThread中的mDisplayEventConnections中voidEventThread::Connection::onFirstRef(){//NOTE:mEventThreaddoesn'tholdastrongreferenceonusmEventThread->registerDisplayEventConnection(this);}//將connection對象添加到mDisplayEventConnections監聽集合中status_tEventThread::registerDisplayEventConnection(constsp<EventThread::Connection>&connection){std::lock_guard<std::mutex>lock(mMutex);//添加到mDisplayEventConnections集合中mDisplayEventConnections.add(connection);mCondition.notify_all();returnNO_ERROR;}createEventConnection()方法返回的是一個IDisplayEventConnection對象mEvents
EventThread是一個線程類,用於分發VSYNC消息,
EventThread內部會維護一個gui::BitTube mChannel用於通信,創建過程如下:
接着通過IDisplayEventConnection對象的stealReceiveChannel()方法
該方法主要是設置mEventTube對象的mReceiveFd,mEventTube的類型是BitTube
BitTube對象中包含一對Fd:mReceiveFd和mSendFd,初始化時會通過socketpair()創建全雙工通信
最後通過Looper類的addFd()方法將mReceiveFd添加到epoll監聽列表中,並且傳入了MessageQueue::cb_eventReceiver作為事件的回調方法
intMessageQueue::cb_eventReceiver(intfd,intevents,void*data){MessageQueue*queue=reinterpret_cast<MessageQueue*>(data);returnqueue->eventReceiver(fd,events);}intMessageQueue::eventReceiver(int/*fd*/,int/*events*/){ssize_tn;DisplayEventReceiver::Eventbuffer[8];while((n=DisplayEventReceiver::getEvents(&mEventTube,buffer,8))>0){for(inti=0;i<n;i++){if(buffer[i].header.type==DisplayEventReceiver::DISPLAY_EVENT_VSYNC){mHandler->dispatchInvalidate();break;}}}return1;}方法最後會調用mHandler->dispatchInvalidate();方法,這就會涉及到Handler的處理邏輯
回調方法如下:
我們看下Handler中的處理邏輯:
voidMessageQueue::Handler::handleMessage(constMessage&message){switch(message.what){caseINVALIDATE:android_atomic_and(~eventMaskInvalidate,&mEventMask);mQueue.mFlinger->onMessageReceived(message.what);break;caseREFRESH:android_atomic_and(~eventMaskRefresh,&mEventMask);mQueue.mFlinger->onMessageReceived(message.what);break;}}調用了SurfaceFlinger的onMessageReceived()方法,這裡才是真正處理消息的地方,後面細講這個方法哈
我們先看下EventThread類
消息和事件分發-`EventThread`EventThread的繼承關係如下:
classEventThread:publicandroid::EventThread,privateVSyncSource::Callback{}需要注意的是VSyncSource::Callback類,它提供了一個onVSyncEvent()的回調方法
EventThread的構造方法如下(精簡版):
EventThread::EventThread(...){...//創建線程並開始執行,核心業務通過threadMain()方法來完成mThread=std::thread(&EventThread::threadMain,this);//設置一些線程的名稱和優先級pthread_setname_np(mThread.native_handle(),threadName);...//設置調度策略為SP_FOREGROUNDset_sched_policy(tid,SP_FOREGROUND);}構造方法中啟動了一個線程,這個線程的執行邏輯在threadMain()方法中:
voidEventThread::threadMain()NO_THREAD_SAFETY_ANALYSIS{std::unique_lock<std::mutex>lock(mMutex);//mKeepRunning只會在析構函數中置為falsewhile(mKeepRunning){DisplayEventReceiver::Eventevent;Vector<sp<EventThread::Connection>>signalConnections;//通過waitForEventLocked()循環等待事件//方法中會通過mCondition對象的wait()方法進行等待signalConnections=waitForEventLocked(&lock,&event);constsize_tcount=signalConnections.size();for(size_ti=0;i<count;i++){constsp<Connection>&conn(signalConnections[i]);//通過postEvent()將事件通知到到MessageQueuestatus_terr=conn->postEvent(event);...}}}threadMain()方法中的重點是:
waitForEventLocked()方法會循環等待消息(也就是VSYNC信號),並獲取到註冊的Connection對象列表
當接收到信號後,通過Connection對象的postEvent()將數據發送到MessageQueue
此時MessageQueue中的Looper會檢測到數據輸入,然後通知回調MessageQueue的cb_eventReceiver()方法
信號分發過程前面講過VSYNC信號由HWC產生,為了方便接收,HWComposer提供了一個HW2::ComposerCallback用於監聽消息
定義如下:
classComposerCallback{public:virtualvoidonHotplugReceived(...)=0;virtualvoidonRefreshReceived(...)=0;virtualvoidonVsyncReceived(...)=0;virtual~ComposerCallback()=default;};從前面類關係圖中可以發現,SurfaceFlinger繼承該類,我們重點關注onVsyncReceived()方法
SurfaceFlinger::onVsyncReceived()方法如下:
voidSurfaceFlinger::onVsyncReceived(...){...boolneedsHwVsync=false;{//ScopeforthelockMutex::Autolock_l(mHWVsyncLock);if(type==DisplayDevice::DISPLAY_PRIMARY&&mPrimaryHWVsyncEnabled){//通過addResyncSample來進一步分發信號needsHwVsync=mPrimaryDispSync.addResyncSample(timestamp);}}...}onVsyncReceived()方法調用mPrimaryDispSync對象的addResyncSample()方法來進一步分發VSYNC信號
mPrimaryDispSync對象的類型是DispSync,這個類比較簡單,核心是它的成員變量mThread,類型是DispSyncThread
DispSyncThread是一個線程類,在DispSync對象初始化時進行創建,代碼如下:
DispSync::DispSync(constchar*name):mName(name),mRefreshSkipCount(0),mThread(newDispSyncThread(name)){}前面提到過,在SurfaceFlinger的構造方法中會調用DispSync對象的init()進行DispSyncThread線程的啟動
voidDispSync::init(boolhasSyncFramework,int64_tdispSyncPresentTimeOffset){...mThread->run("DispSync",PRIORITY_URGENT_DISPLAY+PRIORITY_MORE_FAVORABLE);...}addResyncSample()方法中最重要的是執行了DispSyncThread對象的updateModel()方法:
voidupdateModel(nsecs_tperiod,nsecs_tphase,nsecs_treferenceTime){...//省略和VSYNC信號相關的一些賦值操作//重點是此處通過Conditon.signal()來喚醒DispSyncThread線程mCond.signal();}DispSyncThread線程的執行函數如下:
virtualboolthreadLoop(){...while(true){Vector<CallbackInvocation>callbackInvocations;nsecs_ttargetTime=0;{//Scopeforlock...if(now<targetTime){if(targetTime==INT64_MAX){err=mCond.wait(mMutex);}else{err=mCond.waitRelative(mMutex,targetTime-now);}...}now=systemTime(SYSTEM_TIME_MONOTONIC);...//取得Callback列表callbackInvocations=gatherCallbackInvocationsLocked(now);}//通過fireCallbackInvocations()調用if(callbackInvocations.size()>0){fireCallbackInvocations(callbackInvocations);}}returnfalse;}threadLoop()中大部分是比較和計算時間,決定是否要發送信號
如果沒有信號發送,就會在mCond上等待
這也就是updateModel()中需要調用mCond的signal()來喚醒的原因
當確認需要發送信號時,先通過gatherCallbackInvocationsLocked()獲取本次VSYNC信號回調通知的監聽對象
這些監聽對象都是通過addEventListener()方法進行添加
最後,通過fireCallbackInvocations()方法一次調用列表中所有對象的onDispSyncEvent()方法
voidfireCallbackInvocations(constVector<CallbackInvocation>&callbacks){if(kTraceDetailedInfo)ATRACE_CALL();for(size_ti=0;i<callbacks.size();i++){callbacks[i].mCallback->onDispSyncEvent(callbacks[i].mEventTime);}}查看CallbackInvocation結構就會發現,回調接口的類型是DispSync::Callback
那麼SurfaceFlinger中哪幾個類實現了DispSync::Callback呢? 聰明的我們會發現,SurfaceFlinger中的DispSyncSource繼承了這個類,而且重點是下面部分的代碼:
classDispSyncSourcefinal:publicVSyncSource,privateDispSync::Callback{public:...voidsetVSyncEnabled(boolenable)override{Mutex::Autolocklock(mVsyncMutex);if(enable){status_terr=mDispSync->addEventListener(mName,mPhaseOffset,static_cast<DispSync::Callback*>(this));...}else{status_terr=mDispSync->removeEventListener(static_cast<DispSync::Callback*>(this));...}mEnabled=enable;}...private:virtualvoidonDispSyncEvent(nsecs_twhen){VSyncSource::Callback*callback;...//省略VSYNC信號處理的一些操作callback=mCallback;if(callback!=nullptr){callback->onVSyncEvent(when);}}...}可以發現:
在調用DispSyncSource對象的setVSyncEnabled()方法時會註冊DispSync的事件監聽
onDispSyncEvent()方法中最終調用了VSyncSource::Callback對象的onVSyncEvent()方法
VSyncSource::Callback對象又是和誰關聯呢? 還記得前面的EventThread麼!!!EventThread便是繼承了VSyncSource::Callback類,我們看下EventThread中關於onVSyncEvent()方法的實現:
voidEventThread::onVSyncEvent(nsecs_ttimestamp){std::lock_guard<std::mutex>lock(mMutex);mVSyncEvent[0].header.type=DisplayEventReceiver::DISPLAY_EVENT_VSYNC;mVSyncEvent[0].header.id=0;mVSyncEvent[0].header.timestamp=timestamp;mVSyncEvent[0].vsync.count++;mCondition.notify_all();}前面EventThread部分提到過
threadMain中的waitForEventLocked()會通過mCondition.wait()等待消息,
onVSyncEvent()會通過notify_all()喚醒threadMain處理消息
因此會執行到conn->postEvent(event);方法
postEvent()方法會通過BitTube對象將數據發送到MessageQueue中
接下來便會觸發執行MessageQueue的cb_eventReceiver()方法
前面MessageQueue章節提到過,cb_eventReceiver()方法最後會調用的是SurfaceFlinger的onMessageReceived()方法,而且消息類型是INVALIDATE。
我們看下方法內容:
voidSurfaceFlinger::onMessageReceived(int32_twhat){switch(what){caseMessageQueue::INVALIDATE:{...boolrefreshNeeded=handleMessageTransaction();...break;}caseMessageQueue::REFRESH:{handleMessageRefresh();break;}}}INVALIDATE消息的處理邏輯比較複雜,我們重點關注的是handleMessageTransaction()方法,它會創建DisplayDevice對象。我們先看下DisplayDevice對象
顯示設備的抽象-`DisplayDevice`DisplayDevice類是顯示設備的抽象,當前Android 9中定義了3種顯示設備類型:
DISPLAY_PRIMARY:主顯示設備
DISPLAY_EXTERNAL:擴展顯示設備,通過HDMI輸出的顯示信號
DISPLAY_VIRTUAL:虛擬顯示設備,通過WIFI輸出的顯示信號
這三種顯示設備,第一種是基本配置,另外兩種需要硬件支持。關於Display官網有個極其簡單的介紹:傳送門
在SurfaceFlinger中DisplayDevice負責與OpenGL ES交互,即使沒有任何物理顯示設備被檢測到,SurfaceFlinger都需要一個DisplayDevice對象才能正常工作
SurfaceFlinger將需要顯示的圖層Layer通過DisplayDevice對象傳遞到OpenGL ES中進行合成,合成後再通過HWComposer對象傳送到FrameBuffer中顯示
DisplayDevice對象中的成員變量Vector< sp<Layer> > mVisibleLayersSortedByZ;保存了所有需要在本設備中顯示的Layer對象
DisplayDevice比較複雜,先簡單了解下它的創建流程。前面提到了handleMessageTransaction()方法中會創建DisplayDevice對象,我們看下具體的創建流程:
初步調用流程:handleMessageTransaction()-->handleTransactionLocked()-->processDisplayChangesLocked()
voidSurfaceFlinger::processDisplayChangesLocked(){...if(!curr.isIdenticalTo(draw)){...for(size_ti=0;i<cc;i++){if(draw.indexOfKey(curr.keyAt(i))<0){constDisplayDeviceState&state(curr[i]);sp<DisplaySurface>dispSurface;sp<IGraphicBufferProducer>producer;sp<IGraphicBufferProducer>bqProducer;sp<IGraphicBufferConsumer>bqConsumer;//mCreateBufferQueue是一個函數指針,指向的是BufferQueue::createBufferQueue//這就很熟悉了,和我們前面分析Surface時創建的BufferQueue一樣mCreateBufferQueue(&bqProducer,&bqConsumer,false);int32_thwcId=-1;if(state.isVirtualDisplay()){...//省略虛擬屏幕創建的邏輯}else{...hwcId=state.type;//創建FramebufferSurface用於數據傳輸dispSurface=newFramebufferSurface(*getBE().mHwc,hwcId,bqConsumer);producer=bqProducer;}constwp<IBinder>&display(curr.keyAt(i));if(dispSurface!=nullptr){//通過setupNewDisplayDeviceInternal()創建DisplayDevice對象//並添加到mDisplays集合中mDisplays.add(display,setupNewDisplayDeviceInternal(display,hwcId,state,dispSurface,producer));if(!state.isVirtualDisplay()){mEventThread->onHotplugReceived(state.type,true);}}}}}mDrawingState.displays=mCurrentState.displays;}sp<DisplayDevice>SurfaceFlinger::setupNewDisplayDeviceInternal(constwp<IBinder>&display,inthwcId,constDisplayDeviceState&state,constsp<DisplaySurface>&dispSurface,constsp<IGraphicBufferProducer>&producer){...//mCreateNativeWindowSurface也是一個函數指針,執行的是NativeWindowSurface::create()方法//該方法利用IGraphicBufferProducer生成NativeWindowSurface和NativeWindow對象//其實也是EGL相關的接口調用autonativeWindowSurface=mCreateNativeWindowSurface(producer);autonativeWindow=nativeWindowSurface->getNativeWindow();//通過渲染引擎創建OpenGL渲染的目標EGLSurfacestd::unique_ptr<RE::Surface>renderSurface=getRenderEngine().createSurface();renderSurface->setCritical(state.type==DisplayDevice::DISPLAY_PRIMARY);renderSurface->setAsync(state.type>=DisplayDevice::DISPLAY_VIRTUAL);//執行eglCreateWindowSurface操作renderSurface->setNativeWindow(nativeWindow.get());...//創建DisplayDevice對象sp<DisplayDevice>hw=newDisplayDevice(this,state.type,hwcId,state.isSecure,display,nativeWindow,dispSurface,std::move(renderSurface),displayWidth,displayHeight,hasWideColorGamut,hdrCapabilities,supportedPerFrameMetadata,hwcColorModes,initialPowerMode);...returnhw;}上面的代碼中通過BufferQueue::createBufferQueue創建了consumer和producer對象(這部分和前面講的BufferQueue的邏輯是相同的)
並基於創建的consumer對象和一個HWComposer對象創建了一個FramebufferSurface對象
最後將上面的對象作為參數通過setupNewDisplayDeviceInternal()方法創建DisplayDevice對象,並添加到mDisplays集合中
DisplayDevice對象創建完成,意味着SurfaceFlinger就可以利用DisplayDevice對象寫入圖像數據,並通過
EGLSurface-->BufferQueue-->FrameBufferSurface-->HWCComposer-->Gralloc
這樣一條路徑到達顯示設備的FrameBuffer中
`SurfaceFlinger`的`init()`和`run()`有了前面的鋪墊知識,init()和run()就很好理解了
`SurfaceFlinger::init`voidSurfaceFlinger::init(){//創建app的DispSyncSource和EventThreadmEventThreadSource=std::make_unique<DispSyncSource>(&mPrimaryDispSync,SurfaceFlinger::vsyncPhaseOffsetNs,true,"app");mEventThread=std::make_unique<impl::EventThread>(mEventThreadSource.get(),...,"appEventThread");//創建sf的DispSyncSource和EventThreadmSfEventThreadSource=std::make_unique<DispSyncSource>(&mPrimaryDispSync,SurfaceFlinger::sfVsyncPhaseOffsetNs,true,"sf");mSFEventThread=std::make_unique<impl::EventThread>(mSfEventThreadSource.get(),...,"sfEventThread");//將mSFEventThread與MessageQueue進行關聯mEventQueue->setEventThread(mSFEventThread.get());//將mSFEventThread和mEventThread添加到VSYNC信號調製器中mVsyncModulator.setEventThreads(mSFEventThread.get(),mEventThread.get());//創建渲染引擎,主要是選擇EGL配置,選擇OpenGL版本,創建OpenGL上下文getBE().mRenderEngine=RE::impl::RenderEngine::create(HAL_PIXEL_FORMAT_RGBA_8888,...);...//初始化HWCgetBE().mHwc.reset(newHWComposer(std::make_unique<Hwc2::impl::Composer>(getBE().mHwcServiceName)));//註冊HWC的Callback監聽//VSYNC信號便會從這裡進行回調通知getBE().mHwc->registerCallback(this,getBE().mComposerSequenceId);...//創建VSYNC事件接收控制對象,enable=true表示允許HWC產生VSYNC信號//sufacefinlger通過這個對象來控制HWC是否產生VSYNC信號mEventControlThread=std::make_unique<impl::EventControlThread>([this](boolenabled){setVsyncEnabled(HWC_DISPLAY_PRIMARY,enabled);});...//該方法會通過MessageQueue發送一個異步消息//消息處理中會完成primaryDisplayDevice的創建,並進行VSYNC周期的設定initializeDisplays();...//根據PresentFenceIsNotReliable屬性創建StartPropertySetThread對象if(getHwComposer().hasCapability(HWC2::Capability::PresentFenceIsNotReliable)){mStartPropertySetThread=newStartPropertySetThread(false);}else{mStartPropertySetThread=newStartPropertySetThread(true);}//執行StartPropertySetThread,該線程會通過setProp觸發開機動畫,包括設置以下兩個Prop//property_set("service.bootanim.exit","0");復位動畫退出標記//property_set("ctl.start","bootanim");啟動開機動畫if(mStartPropertySetThread->Start()!=NO_ERROR){ALOGE("RunStartPropertySetThreadfailed!");}...ALOGV("Doneinitializing");}init()方法初始化了很多重要的對象:
初始化app和sf兩組DispSyncSource和EventThread對象
這兩個分別代表了`VSYNC`信號的兩個消費者:`App`和`SurfaceFlinger`
`sf`對應的信號分發邏輯與鋪墊知識中的一致,因為是通過`mEventQueue->setEventThread()`來進行的關聯
`app`的信號分發邏輯等下細看
初始化HWComposer,並通過registerCallback()註冊HWC2::ComposerCallback監聽
初始化EventControlThread對象,SurfaceFlinger用這個對象來控制HWC是否需要產生VSYNC信號
默認設置為不需要產生`VSYNC`信號
初始化StartPropertySetThread線程,該線程會通過setProp的方式觸發開機動畫
`SurfaceFlinger::run`run()方法比較簡單:
voidSurfaceFlinger::run(){do{waitForEvent();}while(true);}方法中執行了一個無限循環來調用waitForEvent(),具體代碼如下:
voidSurfaceFlinger::waitForEvent(){mEventQueue->waitMessage();}waitForEvent()方法又調用了MessageQueue對象的waitMessage()方法進入一個無限循環,這個方法在MessageQueue部分中已經介紹過就不細講啦
所以對於SurfaceFlinger進程來說,執行完run()當前線程就會進入一個無限循環,剩下的業務處理都變成了消息驅動來實現
`App`的繪製通知在SurfaceFlinger的init()方法中初始化了一個appEventThread,在接收到VSYNC信號後,它便會通知到App去進行繪製操作,我們看下這個通知流程
再看`onResume()`我們已經知道,onResume()方法後才會進行View的顯示,這部分體現在ActivityThread中的handleResumeActivity()方法中,代碼如下:
publicvoidhandleResumeActivity(...){...//TODOPushresumeArgsintotheactivityforconsiderationfinalActivityClientRecordr=performResumeActivity(token,finalStateRequest,reason);if(r==null){//Wedidn'tactuallyresumetheactivity,soskippinganyfollow-upactions.return;}finalActivitya=r.activity;...if(r.window==null&&!a.mFinished&&willBeVisible){r.window=r.activity.getWindow();Viewdecor=r.window.getDecorView();decor.setVisibility(View.INVISIBLE);ViewManagerwm=a.getWindowManager();WindowManager.LayoutParamsl=r.window.getAttributes();a.mDecor=decor;l.type=WindowManager.LayoutParams.TYPE_BASE_APPLICATION;l.softInputMode|=forwardBit;...if(a.mVisibleFromClient){if(!a.mWindowAdded){a.mWindowAdded=true;wm.addView(decor,l);}else{a.onWindowAttributesChanged(l);}}}...}上面performResumeActivity()會回調應用程序的onResume()函數。不過本次我們重點關注的是wm.addView()方法,最後調用到的是WindowManagerGlobal.java的addView(),代碼如下:
publicvoidaddView(...){...ViewRootImplroot;ViewpanelParentView=null;synchronized(mLock){...root=newViewRootImpl(view.getContext(),display);view.setLayoutParams(wparams);mViews.add(view);mRoots.add(root);mParams.add(wparams);//dothislastbecauseitfiresoffmessagestostartdoingthingstry{root.setView(view,wparams,panelParentView);}catch(RuntimeExceptione){//BadTokenExceptionorInvalidDisplayException,cleanup.if(index>=0){removeViewLocked(index,true);}throwe;}}}重點是初始化了ViewRootImpl對象,我們看下ViewRootImpl中的setView()方法的調用:
publicvoidsetView(Viewview,WindowManager.LayoutParamsattrs,ViewpanelParentView){synchronized(this){if(mView==null){mView=view;...requestLayout();...}}}publicvoidrequestLayout(){if(!mHandlingLayoutInLayoutRequest){checkThread();mLayoutRequested=true;scheduleTraversals();}}voidscheduleTraversals(){if(!mTraversalScheduled){mTraversalScheduled=true;mTraversalBarrier=mHandler.getLooper().getQueue().postSyncBarrier();mChoreographer.postCallback(Choreographer.CALLBACK_TRAVERSAL,mTraversalRunnable,null);if(!mUnbufferedInputDispatch){scheduleConsumeBatchedInput();}notifyRendererOfFramePending();pokeDrawLockIfNeeded();}}執行到scheduleTraversals()方法就引出來一個最重要的類Choreographer,整個應用布局的渲染依賴這個對象的發動。
在scheduleTraversals()方法中調用了mChoreographer對象的postCallback()方法添加了一個回調對象mTraversalRunnable
mChoreographer.postCallback(Choreographer.CALLBACK_TRAVERSAL,mTraversalRunnable,null);mTraversalRunnable回調對象的定義如下:
finalclassTraversalRunnableimplementsRunnable{@Overridepublicvoidrun(){doTraversal();}}doTraversal內部會調用大名鼎鼎的performTraversal()方法,到這裡App就可以進行measure/layout/draw三大流程
那麼 mTraversalRunnable對象是在什麼時候調用的呢? 我們帶着疑問,先看下應用是如何接收VSYNC信號的
`Choreographer`類App要求渲染動畫或者更新畫面布局時都會用到Choreographer,接收VSYNC信號也依賴於Choreographer
在上面的scheduleTraversals()方法中執行了Choreographer對象的postCallback()方法
mChoreographer.postCallback(Choreographer.CALLBACK_TRAVERSAL,mTraversalRunnable,null);這個方法的含義就是應用程序請求VSYNC信號,接收到VSYNC信號後執行mTraversalRunnable回調
那麼接下來我們看下Choreographer如何接收vsync信號
`DisplayEventReceiver`類應用層可以通過DisplayEventReceiver類用來接收vsync信號,當接收到vsync信號後,會執行DisplayEventReceiver對象的onVsync()方法
DisplayEventReceiver是在Android的View體系中定義的一個抽象類,對外隱藏的,核心定義如下
publicabstractclassDisplayEventReceiver{...//用來表示APP的VSYNC信號源publicstaticfinalintVSYNC_SOURCE_APP=0;publicDisplayEventReceiver(Looperlooper){this(looper,VSYNC_SOURCE_APP);}publicDisplayEventReceiver(Looperlooper,intvsyncSource){...mMessageQueue=looper.getQueue();mReceiverPtr=nativeInit(newWeakReference<DisplayEventReceiver>(this),mMessageQueue,vsyncSource);...}privatestaticnativelongnativeInit(WeakReference<DisplayEventReceiver>receiver,MessageQueuemessageQueue,intvsyncSource);privatestaticnativevoidnativeDispose(longreceiverPtr);privatestaticnativevoidnativeScheduleVsync(longreceiverPtr);...publicvoidonVsync(longtimestampNanos,intbuiltInDisplayId,intframe){}...}需要關注的是
構造方法中調用了native方法nativeInit()來進行初始化操作
定義了一個onVsync()方法的空實現,當接收到VSYNC信號後便會調用該方法
先看下nativeInit()的實現
staticjlongnativeInit(JNIEnv*env,jclassclazz,jobjectreceiverWeak,jobjectmessageQueueObj,jintvsyncSource){sp<MessageQueue>messageQueue=android_os_MessageQueue_getMessageQueue(env,messageQueueObj);...sp<NativeDisplayEventReceiver>receiver=newNativeDisplayEventReceiver(env,receiverWeak,messageQueue,vsyncSource);status_tstatus=receiver->initialize();...}nativeInit()方法創建了一個NativeDisplayEventReceiver對象,並調用了它的initialize()方法
NativeDisplayEventReceiver繼承了DisplayEventDispatcher類,那麼我們的重點便是DisplayEventDispatcher,頭文件定義如下:
classDisplayEventDispatcher:publicLooperCallback{public:DisplayEventDispatcher(constsp<Looper>&looper,ISurfaceComposer::VsyncSourcevsyncSource=ISurfaceComposer::eVsyncSourceApp);status_tinitialize();...private:sp<Looper>mLooper;DisplayEventReceivermReceiver;...};核心實現如下:
DisplayEventDispatcher::DisplayEventDispatcher(constsp<Looper>&looper,ISurfaceComposer::VsyncSourcevsyncSource):mLooper(looper),mReceiver(vsyncSource),mWaitingForVsync(false){ALOGV("dispatcher%p~Initializingdisplayeventdispatcher.",this);}status_tDisplayEventDispatcher::initialize(){status_tresult=mReceiver.initCheck();...intrc=mLooper->addFd(mReceiver.getFd(),0,Looper::EVENT_INPUT,this,NULL);if(rc<0){returnUNKNOWN_ERROR;}returnOK;}在鋪墊知識部分已經了解到,如果應用要接收VSYNC信號,需要將其添加到對應的EventThread中,SF中一共創建了兩個
mSFEventThread是SurfaceFlinger專用的
在`SurfaceFlinger`的`init()`中通過`mEventQueue->setEventThread()`進行關聯
`setEventThread()`在鋪墊部分也介紹過(鋪墊內容-消息和事件分發)
mEventThread用來通知App的
我們知道mEventQueue->setEventThread()關聯VSYNC信號的過程主要分為了兩步:
創建連接
註冊監聽
對比DisplayEventDispatcher中我們會發現
DisplayEventDispatcher的initialize()中做了一個mLooper->addFd()操作
前面介紹過:Looper類的addFd()方法是將mReceiveFd添加到epoll監聽列表
這樣,註冊監聽的部分我們找到了
DisplayEventDispatcher中包含一個native層的DisplayEventReceiver對象mReceiver
DisplayEventReceiver::DisplayEventReceiver(ISurfaceComposer::VsyncSourcevsyncSource){sp<ISurfaceComposer>sf(ComposerService::getComposerService());if(sf!=NULL){//createDisplayEventConnection方法便會調用mEventThread->createEventConnection()來創建連接//而mEventThread便是App的VSYNC分發線程mEventConnection=sf->createDisplayEventConnection(vsyncSource);if(mEventConnection!=NULL){mDataChannel=std::make_unique<gui::BitTube>();mEventConnection->stealReceiveChannel(mDataChannel.get());}}}native層的DisplayEventReceiver便封裝了創建連接的過程,我們需要關注的是構造方法部分
到這裡,DisplayEventReceiver便和SurfaceFlinger中的mEventThread建立了聯繫,當VSYNC信號產生後,SurfaceFlinger便會通過mEventThread通知到DisplayEventReceiver
VSYNC 分發過程已經介紹過了,可以看這裡
`FrameDisplayEventReceiver`類DisplayEventReceiver是一個抽象類,FrameDisplayEventReceiver便是這個類的具體實現,在Choreographer中定義,代碼如下:
privatefinalclassFrameDisplayEventReceiverextendsDisplayEventReceiverimplementsRunnable{privatebooleanmHavePendingVsync;privatelongmTimestampNanos;privateintmFrame;publicFrameDisplayEventReceiver(Looperlooper,intvsyncSource){super(looper,vsyncSource);}@OverridepublicvoidonVsync(longtimestampNanos,intbuiltInDisplayId,intframe){//vsync信號分發時便會回調到這裡...mTimestampNanos=timestampNanos;mFrame=frame;Messagemsg=Message.obtain(mHandler,this);msg.setAsynchronous(true);//這裡發了一個消息,此處並未主動設置msg.what,默認值應為0//0對應的數值為MSG_DO_FRAMEmHandler.sendMessageAtTime(msg,timestampNanos/TimeUtils.NANOS_PER_MS);}@Overridepublicvoidrun(){mHavePendingVsync=false;doFrame(mTimestampNanos,mFrame);}}上面onVsync會往消息隊列放一個消息,通過下面的FrameHandler進行處理:
privatefinalclassFrameHandlerextendsHandler{publicFrameHandler(Looperlooper){super(looper);}@OverridepublicvoidhandleMessage(Messagemsg){switch(msg.what){caseMSG_DO_FRAME:doFrame(System.nanoTime(),0);break;caseMSG_DO_SCHEDULE_VSYNC:doScheduleVsync();break;caseMSG_DO_SCHEDULE_CALLBACK:doScheduleCallback(msg.arg1);break;}}}對於MSG_DO_FRAME消息,會執行doFrame()方法,關鍵代碼如下:
voiddoFrame(longframeTimeNanos,intframe){...mFrameInfo.markInputHandlingStart();doCallbacks(Choreographer.CALLBACK_INPUT,frameTimeNanos);mFrameInfo.markAnimationsStart();doCallbacks(Choreographer.CALLBACK_ANIMATION,frameTimeNanos);mFrameInfo.markPerformTraversalsStart();doCallbacks(Choreographer.CALLBACK_TRAVERSAL,frameTimeNanos);doCallbacks(Choreographer.CALLBACK_COMMIT,frameTimeNanos);...}doFrame()方法通過doCallbacks()執行了各種類型的Callback,分為4類:
CALLBACK_INPUT : 處理輸入事件處理有關
CALLBACK_ANIMATION :處理Animation的處理有關
CALLBACK_TRAVERSAL : 處理和UI等控件繪製有關
CALLBACK_COMMIT :處理Commit相關回調
需要注意的是CALLBACK_TRAVERSAL類型的doCallbacks()
doCallbacks(Choreographer.CALLBACK_TRAVERSAL,frameTimeNanos);這個方法便會執行前面在scheduleTraversals()方法中添加的mTraversalRunnable回調。而由於CALLBACK_INPUT 、CALLBACK_ANIMATION會修改View的屬性,所以要先於CALLBACK_TRAVERSAL執行
結語狡辯ING:剛接手新平台比較忙,導致本來清明節計劃學習的章節一直拖到現在,好在磕磕絆絆的學習完了
SurfaceFlinger這部分涉及的知識很多,很遺憾深入Android系統(十二)Android圖形顯示系統系列也僅僅只是記錄一些基礎知識。
View的繪製部分也並未展開學習,考慮到後面的章節,等了解完整個Android系統知識後再來補充吧(挖坑ING…..)
原文鏈接: https://juejin.cn/post/6958064165458018317
推薦:
Android 圖形系統概述
Android 圖形顯示系統
全網最全的 Android 音視頻和 OpenGL ES 乾貨,都在這了