Android 4.4 Graphic系統詳解(1) SurfaceFlinger的啓動過程

init啓動SurfaceFlinger

SurfaceFlinger目前的啓動方式是做爲init進程中的一個Service來啓動。
在init中添加如下配置代碼:

  1. # Set this property so surfaceflinger is not started by system_init  
  2. setprop system_init.startsurfaceflinger 0  
  3.   
  4. service surfaceflinger /system/bin/surfaceflinger  
  5. class main  
  6. user system  
  7. group graphics drmrpc  
  8. onrestart restart zygote  

系統將啓動/system/bin/目錄下的surfaceflinger bin文件來運行SurfaceFlinger。

關於init.rc的語法問題,我們將有專門的文章展開討論(TODO)。

SurfaceFlinger啓動過程

我們繼續來看下對應的bin文件中的代碼,位置在Android\frameworks\native\services\surfaceflinger下。

  1. int main(int argc, char** argv) {  
  2.     // 1.創建surfaceflinger對象  
  3.     sp<SurfaceFlinger> flinger = new SurfaceFlinger();  
  4.     // initialize before clients can connect  
  5.     // 2.初始化  
  6.     flinger->init();  
  7.     // 3.註冊SF服務  
  8.     sp<IServiceManager> sm(defaultServiceManager());  
  9.     sm->addService(String16(SurfaceFlinger::getServiceName()), flinger, false);  
  10.     // 4.運行程序  
  11.     flinger->run();  
  12.     return 0;  
  13. }  

從上面代碼中我們看到SF的創建過程主要有四個步驟,我們來逐一分析一下。

1. 創建SF對象

  1. SurfaceFlinger::SurfaceFlinger()  
  2.     :   BnSurfaceComposer(),  
  3.         mTransactionFlags(0),  
  4.         mTransactionPending(false),  
  5.         mAnimTransactionPending(false),  
  6.         mLayersRemoved(false),  
  7.         mRepaintEverything(0),  
  8.         mRenderEngine(NULL),  
  9.         mBootTime(systemTime()),  
  10.         mVisibleRegionsDirty(false),  
  11.         mHwWorkListDirty(false),  
  12.         mAnimCompositionPending(false),  
  13.         mDebugRegion(0),  
  14.         mDebugFps(0),  
  15.         mDebugDDMS(0),  
  16.         mDebugDisableHWC(0),  
  17.         mDebugDisableTransformHint(0),  
  18.         mDebugInSwapBuffers(0),  
  19.         mLastSwapBufferTime(0),  
  20.         mDebugInTransaction(0),  
  21.         mLastTransactionTime(0),  
  22.         mBootFinished(false),  
  23.         mPrimaryHWVsyncEnabled(false),  
  24.         mHWVsyncAvailable(false),  
  25.         mDaltonize(false),  
  26.         /* Activity-Activity: */  
  27.         mProjectionType(ORTHOGRAPHIC_PROJECTION)  
  28.         /* Activity-Activity: Change End*/  
  29. // End  
  30. {  
  31.     ALOGI("SurfaceFlinger is starting");  
  32.   
  33.     // debugging stuff...  
  34.     char value[PROPERTY_VALUE_MAX];  
  35.   
  36.     property_get("ro.bq.gpu_to_cpu_unsupported", value, "0");  
  37.     mGpuToCpuSupported = !atoi(value);  
  38.   
  39.     property_get("debug.sf.showupdates", value, "0");  
  40.     mDebugRegion = atoi(value);  
  41.     property_get("debug.sf.showfps", value, "0");  
  42.     mDebugFps = atoi(value);  
  43.   
  44.     property_get("debug.sf.ddms", value, "0");  
  45.     mDebugDDMS = atoi(value);  
  46.     if (mDebugDDMS) {  
  47.         if (!startDdmConnection()) {  
  48.             // start failed, and DDMS debugging not enabled  
  49.             mDebugDDMS = 0;  
  50.         }  
  51.     }  
  52.     ALOGI_IF(mDebugRegion, "showupdates enabled");  
  53. //    ALOGI_IF(mDebugFps,          "showfps enabled");  
  54.     ALOGI_IF(mDebugDDMS, "DDMS debugging enabled");  
  55. }  

其實這個創建過程很簡單,無非就是初始化了一些值。從配置中讀取了一些值。
需要注意的一點是,SurfaceFlinger實現了三個接口:

  1. class SurfaceFlinger : public BnSurfaceComposer,  
  2.                        private IBinder::DeathRecipient,  
  3.                        private HWComposer::EventHandler  

BnSurfaceComposer意思是指這個Surface混合的native端,這顯然也符合我們對SF功能的認識—-用於Layer的混合處理。
另外,我們會在後面消息的處理一節中單獨講解HWComposer::EventHandler接口的作用。

2.初始化

其實相比SurfaceFlinger的創建,初始化做了更多的工作。
這一過程比較複雜,我們分爲幾部分來分析:

2.1 EGL初始化
  1. void SurfaceFlinger::init() {  
  2.     ALOGI(  "SurfaceFlinger's main thread ready to run. "  
  3.             "Initializing graphics H/W...");  
  4.     status_t err;  
  5.     Mutex::Autolock _l(mStateLock);  
  6.     // initialize EGL for the default display  
  7.     mEGLDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);  
  8.     eglInitialize(mEGLDisplay, NULL, NULL);  
  9.    ...  
  10.    }  

首先SF初始化時,會進行一些EGL的初始化工作。
我們知道EGL是用來管理繪圖表面(Drawing surfaces),並且提供瞭如下的機制
1) 與本地窗口系統進行通信(本地窗口在X-Window下是XDisplay ID,在MS Windows下是Window DC,而在Android平臺上EGL是NativeDisplayType)
2) 查找繪圖表面可用的類型和配置信息
3) 創建繪圖表面
4) 同步OpenGL ES 2.0和其他的渲染API(Open VG、本地窗口系統的繪圖命令等)
5) 管理渲染資源,比如材質

eglGetDisplay調用egl_display_t::get_display(dpy)獲取(連接)顯示設備的句柄。
egl_display_t結構用來存儲get_display函數獲取的物理顯示設備。
這裏的EGL_DEFAULT_DISPLAY類型是NativeDisplayType,是一個關聯繫統物理屏幕的通用數據類型。

每個 EGLDisplay 在使用前都需要通過eglInitialize函數來初始化。初始化 EGLDisplay 的同時,你可以得到系統中 EGL 的實現版本號。

這個整個過程是由平臺實現的,我們看不到具體實現代碼(libagl裏面有一套谷歌的實現,但是非常簡單)。

2.2 創建HWComposer
  1. {  
  2. ...  
  3. // Initialize the H/W composer object.  There may or may not be an  
  4.     // actual hardware composer underneath.  
  5.     mHwc = new HWComposer(this,  
  6.             *static_cast<HWComposer::EventHandler *>(this));  
  7. ...  
  8. }  

接下來是創建了一個HWComposer,也就是一個負責硬件合成的模塊。但是我們也看到上面的註釋明確寫着,下面可能並沒有一個真正的硬件支持。我們來研究下這個HWComposer的創建過程:

  1. HWComposer::HWComposer(  
  2.         const sp<SurfaceFlinger>& flinger,  
  3.         EventHandler& handler)  
  4.     : mFlinger(flinger),  
  5.       mFbDev(0), mHwc(0), mNumDisplays(1),  
  6.       mCBContext(new cb_context),  
  7.       mEventHandler(handler),  
  8.       mDebugForceFakeVSync(false)  
  9. {  
  10.     for (size_t i =0 ; i<MAX_HWC_DISPLAYS ; i++) {  
  11.         mLists[i] = 0;  
  12.     }  
  13.     //首先是一些和VSYNC有關的信息的初始化  
  14.     //因爲在硬件支持的情況下,VSYNC的功能就是由HWC提供的  
  15.     for (size_t i=0 ; i<HWC_NUM_PHYSICAL_DISPLAY_TYPES ; i++) {  
  16.         mLastHwVSync[i] = 0;  
  17.         mVSyncCounts[i] = 0;  
  18.     }  
  19.     //根據配置來看是否需要模擬VSYNC消息  
  20.     char value[PROPERTY_VALUE_MAX];  
  21.     property_get("debug.sf.no_hw_vsync", value, "0");  
  22.     mDebugForceFakeVSync = atoi(value);  
  23.   
  24.     bool needVSyncThread = true;  
  25.     //加載Gralloc中的GRALLOC_HARDWARE_FB0設備,和HWC設備  
  26.     // Note: some devices may insist that the FB HAL be opened before HWC.  
  27.     int fberr = loadFbHalModule();  
  28.     loadHwcModule();  
  29.   
  30.     if (mFbDev && mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {  
  31.         // close FB HAL if we don't needed it.  
  32.         // FIXME: this is temporary until we're not forced to open FB HAL  
  33.         // before HWC.  
  34.         framebuffer_close(mFbDev);  
  35.         mFbDev = NULL;  
  36.     }  
  37.   
  38.     // If we have no HWC, or a pre-1.1 HWC, an FB dev is mandatory.  
  39.     if ((!mHwc || !hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1))  
  40.             && !mFbDev) {  
  41.         ALOGE("ERROR: failed to open framebuffer (%s), aborting",  
  42.                 strerror(-fberr));  
  43.         abort();  
  44.     }  
  45.   
  46.     // these display IDs are always reserved  
  47.     for (size_t i=0 ; i<NUM_BUILTIN_DISPLAYS ; i++) {  
  48.         mAllocatedDisplayIDs.markBit(i);  
  49.     }  
  50.     //如果我們有HWC這個硬件設備,那麼我們就註冊一些HWC的函數  
  51.     //另外,就不需要使用vsync的進程,因爲我們有了硬件支持的VSYNC中斷  
  52.     if (mHwc) {  
  53.         ALOGI("Using %s version %u.%u", HWC_HARDWARE_COMPOSER,  
  54.               (hwcApiVersion(mHwc) >> 24) & 0xff,  
  55.               (hwcApiVersion(mHwc) >> 16) & 0xff);  
  56.         if (mHwc->registerProcs) {  
  57.             mCBContext->hwc = this;  
  58.             mCBContext->procs.invalidate = &hook_invalidate;  
  59.             mCBContext->procs.vsync = &hook_vsync;  
  60.             if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1))  
  61.                 mCBContext->procs.hotplug = &hook_hotplug;  
  62.             else  
  63.                 mCBContext->procs.hotplug = NULL;  
  64.             memset(mCBContext->procs.zero, 0, sizeof(mCBContext->procs.zero));  
  65.             mHwc->registerProcs(mHwc, &mCBContext->procs);  
  66.         }  
  67.   
  68.         // don't need a vsync thread if we have a hardware composer  
  69.         needVSyncThread = false;  
  70.         // always turn vsync off when we start  
  71.         eventControl(HWC_DISPLAY_PRIMARY, HWC_EVENT_VSYNC, 0);  
  72.   
  73.         // the number of displays we actually have depends on the  
  74.         // hw composer version  
  75.         //根據HWC硬件的支持情況,來設置顯示屏幕的數量  
  76.         if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_3)) {  
  77.             // 1.3 adds support for virtual displays  
  78.             mNumDisplays = MAX_HWC_DISPLAYS;  
  79.         } else if (hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)) {  
  80.             // 1.1 adds support for multiple displays  
  81.             mNumDisplays = NUM_BUILTIN_DISPLAYS;  
  82.         } else {  
  83.             mNumDisplays = 1;  
  84.         }  
  85.     }  
  86.     //如果我們能獲取到FB設置,那麼我們就從FB設備裏面讀取一些屏幕相關的I型難洗  
  87.     if (mFbDev) {  
  88.         ALOG_ASSERT(!(mHwc && hwcHasApiVersion(mHwc, HWC_DEVICE_API_VERSION_1_1)),  
  89.                 "should only have fbdev if no hwc or hwc is 1.0");  
  90.   
  91.         DisplayData& disp(mDisplayData[HWC_DISPLAY_PRIMARY]);  
  92.         disp.connected = true;  
  93.         disp.width = mFbDev->width;  
  94.         disp.height = mFbDev->height;  
  95.         disp.format = mFbDev->format;  
  96.         disp.xdpi = mFbDev->xdpi;  
  97.         disp.ydpi = mFbDev->ydpi;  
  98.         if (disp.refresh == 0) {  
  99.             disp.refresh = nsecs_t(1e9 / mFbDev->fps);  
  100.             ALOGW("getting VSYNC period from fb HAL: %lld", disp.refresh);  
  101.         }  
  102.         if (disp.refresh == 0) {  
  103.             disp.refresh = nsecs_t(1e9 / 60.0);  
  104.             ALOGW("getting VSYNC period from thin air: %lld",  
  105.                     mDisplayData[HWC_DISPLAY_PRIMARY].refresh);  
  106.         }  
  107.     } else if (mHwc) {//否則我們將會從HWC中讀取相關配置,打log確認下走哪個分支  
  108.         // here we're guaranteed to have at least HWC 1.1  
  109.         for (size_t i =0 ; i<NUM_BUILTIN_DISPLAYS ; i++) {  
  110.             queryDisplayProperties(i);  
  111.         }  
  112.     }  
  113.   
  114. // End  
  115.     //顯然,如果需要模擬VSync信號的話,我們需要線程來做這個工作  
  116.     if (needVSyncThread) {  
  117.         // we don't have VSYNC support, we need to fake it  
  118.         //VSyncThread類的實現很簡單,無非就是一個計時器而已,定時發送消息而已  
  119.         //TODO VSYNC專題  
  120.         mVSyncThread = new VSyncThread(*this);  
  121.     }  
  122. }  
2.3 EGL配置

HWC模塊創建完成之後,我們繼續回到SurfaceFlinger的初始化過程,後面將繼續是一些EGL相關的配置:

  1. {  
  2. ...  
  3.     //首先獲取OpenGL ES2.0的配置,在另外一篇文檔中,我們提到過從KK之後,SF開始使用ES 2.0  
  4.     // First try to get an ES2 config  
  5.     err = selectEGLConfig(mEGLDisplay, mHwc->getVisualID(), EGL_OPENGL_ES2_BIT,  
  6.             &mEGLConfig);  
  7.     //當然如果獲取失敗,還是會繼續使用1.0,TODO 我們會新開一個專題講OpengGL  
  8.     if (err != NO_ERROR) {  
  9.         // If ES2 fails, try ES1  
  10.         err = selectEGLConfig(mEGLDisplay, mHwc->getVisualID(),  
  11.                 EGL_OPENGL_ES_BIT, &mEGLConfig);  
  12.     }  
  13.   
  14.     if (err != NO_ERROR) {  
  15.         // still didn't work, probably because we're on the emulator...  
  16.         // try a simplified query  
  17.         ALOGW("no suitable EGLConfig found, trying a simpler query");  
  18.         err = selectEGLConfig(mEGLDisplay, mHwc->getVisualID(), 0, &mEGLConfig);  
  19.     }  
  20.   
  21.     if (err != NO_ERROR) {  
  22.         // this EGL is too lame for android  
  23.         LOG_ALWAYS_FATAL("no suitable EGLConfig found, giving up");  
  24.     }  
  25.   
  26.     // 打印一些配置信息  
  27.     EGLint r,g,b,a;  
  28.     eglGetConfigAttrib(mEGLDisplay, mEGLConfig, EGL_RED_SIZE,   &r);  
  29.     eglGetConfigAttrib(mEGLDisplay, mEGLConfig, EGL_GREEN_SIZE, &g);  
  30.     eglGetConfigAttrib(mEGLDisplay, mEGLConfig, EGL_BLUE_SIZE,  &b);  
  31.     eglGetConfigAttrib(mEGLDisplay, mEGLConfig, EGL_ALPHA_SIZE, &a);  
  32.     ALOGI("EGL informations:");  
  33.     ALOGI("vendor    : %s", eglQueryString(mEGLDisplay, EGL_VENDOR));  
  34.     ALOGI("version   : %s", eglQueryString(mEGLDisplay, EGL_VERSION));  
  35.     ALOGI("extensions: %s", eglQueryString(mEGLDisplay, EGL_EXTENSIONS));  
  36.     ALOGI("Client API: %s", eglQueryString(mEGLDisplay, EGL_CLIENT_APIS)?:"Not Supported");  
  37.     ALOGI("EGLSurface: %d-%d-%d-%d, config=%p", r, g, b, a, mEGLConfig);  
  38.   
  39.     // get a RenderEngine for the given display / config (can't fail)  
  40.     // KK升級一章中我們講過SF通過RenderEngine來實現了使用不同版本的OpenGL  
  41.     mRenderEngine = RenderEngine::create(mEGLDisplay, mEGLConfig);  
  42.   
  43.     // retrieve the EGL context that was selected/created  
  44.     //獲取ES的上下文,這個是用於SF的上下文  
  45.     mEGLContext = mRenderEngine->getEGLContext();  
  46.   
  47.     // figure out which format we got  
  48.     eglGetConfigAttrib(mEGLDisplay, mEGLConfig,  
  49.             EGL_NATIVE_VISUAL_ID, &mEGLNativeVisualId);  
  50.   
  51.     LOG_ALWAYS_FATAL_IF(mEGLContext == EGL_NO_CONTEXT,  
  52.             "couldn't create EGLContext");  
  53. ...  
  54. }  
2.4 display設置

EGL和OpenGL ES的配置設置完畢之後,我們將對display進行設置。

  1. {  
  2. ...  
  3.   // initialize our non-virtual displays  
  4.     for (size_t i=0 ; i<DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES ; i++) {  
  5.         DisplayDevice::DisplayType type((DisplayDevice::DisplayType)i);  
  6.         // set-up the displays that are already connected  
  7.         if (mHwc->isConnected(i) || type==DisplayDevice::DISPLAY_PRIMARY) {  
  8.             // All non-virtual displays are currently considered secure.  
  9.             bool isSecure = true;  
  10.             createBuiltinDisplayLocked(type);  
  11.             wp<IBinder> token = mBuiltinDisplays[i];  
  12.   
  13.             //對於每個display,SF都會創建一個新的BufferQueue  
  14.             sp<BufferQueue> bq = new BufferQueue(new GraphicBufferAlloc());  
  15.             sp<FramebufferSurface> fbs = new FramebufferSurface(*mHwc, i, bq);  
  16.             //最後,用我們創建的這些內容,來創建一個DisplayDevice  
  17.             //它有兩個重要的變量,一個是mFrameBufferSurface和mNativeWindow。  
  18.             //mFrameBufferSurace是FrameBufferSurface類型,  
  19.             //當顯示設備不屬於VIRTUAL類型的話,則該變量不爲空  
  20.             sp<DisplayDevice> hw = new DisplayDevice(this,  
  21.                     type, allocateHwcDisplayId(type), isSecure, token,  
  22.                     fbs, bq,  
  23.                     mEGLConfig);  
  24.             if (i > DisplayDevice::DISPLAY_PRIMARY) {  
  25.                 // FIXME: currently we don't get blank/unblank requests  
  26.                 // for displays other than the main display, so we always  
  27.                 // assume a connected display is unblanked.  
  28.                 ALOGD("marking display %d as acquired/unblanked", i);  
  29.                 //這裏應該是指非主屏幕的屏幕一旦註冊,就長期處於開啓狀態  
  30.                 hw->acquireScreen();  
  31.             }  
  32.             mDisplays.add(token, hw);  
  33.         }  
  34.     }  
  35.     ...  
  36.     }  

上面這段代碼其實涉及到了三個重要的概念,BufferQueue、FrameBufferSurface以及DisplayDevice。
BufferQueue做爲Graphic的核心組件,我們在講解Graphic總體結構時已經有說明,後面會另開專題說明。我們先來看下FrameBufferSurface的實現:

  1. FramebufferSurface::FramebufferSurface(HWComposer& hwc, int disp,  
  2.         const sp<IGraphicBufferConsumer>& consumer) :  
  3.     ConsumerBase(consumer),  
  4.     mDisplayType(disp),  
  5.     mCurrentBufferSlot(-1),  
  6.     mCurrentBuffer(0),  
  7.     mHwc(hwc)  
  8. {  
  9.     mName = "FramebufferSurface";  
  10.     mConsumer->setConsumerName(mName);  
  11.     mConsumer->setConsumerUsageBits(GRALLOC_USAGE_HW_FB |  
  12.                                        GRALLOC_USAGE_HW_RENDER |  
  13.                                        GRALLOC_USAGE_HW_COMPOSER);  
  14.     mConsumer->setDefaultBufferFormat(mHwc.getFormat(disp));  
  15.     mConsumer->setDefaultBufferSize(mHwc.getWidth(disp),  mHwc.getHeight(disp));  
  16.     mConsumer->setDefaultMaxBufferCount(NUM_FRAMEBUFFER_SURFACE_BUFFERS);  
  17.     mConsumer->setMaxAcquiredBufferCount(NUM_FRAMEBUFFER_SURFACE_BUFFERS - 1);  
  18. }  

我們使用了BufferQueue來創建了一個FramebufferSurface,顯然這個FramebufferSurface是一個消費者。在創建過程我們使用了屏幕的編號和HWC,我們可以猜測這個FBS是和一個屏幕綁定的,而且最終應該也是要通過HWC進行渲染。我們可以理解爲這是SF在這個屏幕上使用的幀緩衝區,那麼也就是一旦使用SF合成,最後數據應該是合成在了這裏面(待驗證),然後這裏面的數據通過HWC顯示在了屏幕上。猜測一下,這個是不是就是抓dump時抓到的那個HWC_FRAMEBUFFER_TARGET?

FBS的創建並沒有特別之處,需要留意的是這裏設置了MaxBufferCount和MaxAcquiredBufferCount,我們在Graphic總體架構一文中已經提到了設置這兩個屬性的作用。

DisplayDevice其實是抽象了顯示設備,封裝了用於渲染的Surface和HWComposer模塊等,從而儘可能使得SurfaceFlinger只要和它打交道。來看下他的創建過程:

  1. DisplayDevice::DisplayDevice(  
  2.         const sp<SurfaceFlinger>& flinger,  
  3.         DisplayType type,  
  4.         int32_t hwcId,  
  5.         bool isSecure,  
  6.         const wp<IBinder>& displayToken,  
  7.         const sp<DisplaySurface>& displaySurface,  
  8.         const sp<IGraphicBufferProducer>& producer,  
  9.         EGLConfig config)  
  10.     : mFlinger(flinger),  
  11.       mType(type), mHwcDisplayId(hwcId),  
  12.       mDisplayToken(displayToken),  
  13.       mDisplaySurface(displaySurface),  
  14.       mDisplay(EGL_NO_DISPLAY),  
  15.       mSurface(EGL_NO_SURFACE),  
  16.       mDisplayWidth(), mDisplayHeight(), mFormat(),  
  17.       mFlags(),  
  18.       mPageFlipCount(),  
  19.       mIsSecure(isSecure),  
  20.       mSecureLayerVisible(false),  
  21.       mScreenAcquired(false),  
  22.       mLayerStack(NO_LAYER_STACK),  
  23.       mOrientation()  
  24. {  
  25.     mNativeWindow = new Surface(producer, false);  
  26.     ANativeWindow* const window = mNativeWindow.get();  
  27.   
  28.     int format;  
  29.     window->query(window, NATIVE_WINDOW_FORMAT, &format);  
  30.   
  31.     /* 
  32.      * Create our display's surface 
  33.      */  
  34.     EGLSurface surface;  
  35.     EGLint w, h;  
  36.     EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);  
  37.     surface = eglCreateWindowSurface(display, config, window, NULL);  
  38.     eglQuerySurface(display, surface, EGL_WIDTH,  &mDisplayWidth);  
  39.     eglQuerySurface(display, surface, EGL_HEIGHT, &mDisplayHeight);  
  40.   
  41.     mDisplay = display;  
  42.     mSurface = surface;  
  43.     mFormat  = format;  
  44.     mPageFlipCount = 0;  
  45.     mViewport.makeInvalid();  
  46.     mFrame.makeInvalid();  
  47.     float mFOV = 30.0f;  
  48.     float tangent = tan(PI / 180.0f * mFOV / 2.0f);  
  49.     mDefaultX = -((float) mDisplayWidth / 2.0f);  
  50.     mDefaultY = -((float) mDisplayHeight / 2.0f);  
  51.     mDefaultZ = -(((float) mDisplayHeight / 2.0f) / tangent);  
  52.     /* Activity-Activity: Change End*/  
  53.   
  54.     // virtual displays are always considered enabled  
  55.     mScreenAcquired = (mType >= DisplayDevice::DISPLAY_VIRTUAL);  
  56.   
  57.     // Name the display.  The name will be replaced shortly if the display  
  58.     // was created with createDisplay().  
  59.     switch (mType) {  
  60.         case DISPLAY_PRIMARY:  
  61.             mDisplayName = "Built-in Screen";  
  62.             break;  
  63.         case DISPLAY_EXTERNAL:  
  64.             mDisplayName = "HDMI Screen";  
  65.             break;  
  66.         default:  
  67.             mDisplayName = "Virtual Screen";    // e.g. Overlay #n  
  68.             break;  
  69.     }  
  70.     char property[PROPERTY_VALUE_MAX];  
  71.     int panelOrientation = DisplayState::eOrientationDefault;  
  72.     // Set the panel orientation from the property.  
  73.     property_get("persist.panel.orientation", property, "0");  
  74.     panelOrientation = atoi(property) / 90;  
  75.   
  76.     // initialize the display orientation transform.  
  77.     setProjection(panelOrientation, mViewport, mFrame);  
  78. }  

這段創建同樣相當之長,我們目前只關注這裏面創建了一個EGLSurface。我們在前面的文章中曾經提到過這個類,這個實際上就是一個供GLES使用的窗口緩衝區,爲GLES提供了一個繪製的地方。
在這個EGLSurface裏面是一個Surface,本質上下面還是一個BufferQueue。
渲染這個EGLSurface將導致一個buffer出隊渲染入隊的過程,lock和unlock過程是通過eglSwapBuffers函數來提供的。

2.5 makeCurrent

看完了上面幾個重要概念的講解,我們繼續回到SF的init過程中來。
下面是對主屏幕對應的display進行makeCurrent操作:

  1. {  
  2. ...  
  3.     //  initialize OpenGL ES  
  4.     /* Activity-Activity: */  
  5.     setProjectionType(ORTHOGRAPHIC_PROJECTION);  
  6.     /* Activity-Activity: Change End*/  
  7.   
  8.     // make the GLContext current so that we can create textures when creating Layers  
  9.     // (which may happens before we render something)  
  10.     getDefaultDisplayDevice()->makeCurrent(mEGLDisplay, mEGLContext);  
  11. ...  
  12. }  

注意到這裏調用的實際上是DisplayDevice類提供的函數,這也某種程度上說明了我們前面提到的DisplayDevice的作用是:封裝了用於渲染的Surface和HWComposer模塊等,從而儘可能使得SurfaceFlinger只要和它打交道。看下這個makeCurrent函數:

  1. EGLBoolean DisplayDevice::makeCurrent(EGLDisplay dpy, EGLContext ctx) const {  
  2.     EGLBoolean result = EGL_TRUE;  
  3.     EGLSurface sur = eglGetCurrentSurface(EGL_DRAW);  
  4.     if (sur != mSurface) {  
  5.         result = eglMakeCurrent(dpy, mSurface, mSurface, ctx);  
  6.         if (result == EGL_TRUE) {  
  7.             if (mType >= DisplayDevice::DISPLAY_VIRTUAL)  
  8.                 eglSwapInterval(dpy, 0);  
  9.         }  
  10.     }  
  11.     setViewportAndProjection();  
  12.     return result;  
  13. }  

這裏獲取了當前使用的EGLSurface,一旦發現這個Surface發生了改變,就要重新調用eglMakeCurrent函數來設置,這是因爲一個線程同時只能有一個EGLSurface作爲current。而關於eglMakeCurrent函數的更詳盡的說明,我們將在EGL和GLES的章節中給予說明。

2.6 EventThread的創建

再次回到SF的init過程中來:

  1. {  
  2. ...  
  3.     // start the EventThread  
  4.     sp<VSyncSource> vsyncSrc = new DispSyncSource(&mPrimaryDispSync,  
  5.             vsyncPhaseOffsetNs, true);  
  6.     mEventThread = new EventThread(vsyncSrc);  
  7.     sp<VSyncSource> sfVsyncSrc = new DispSyncSource(&mPrimaryDispSync,  
  8.             sfVsyncPhaseOffsetNs, true);  
  9.     mSFEventThread = new EventThread(sfVsyncSrc);  
  10.     mEventQueue.setEventThread(mSFEventThread);  
  11.   
  12.     mEventControlThread = new EventControlThread(this);  
  13.     mEventControlThread->run("EventControl", PRIORITY_URGENT_DISPLAY);  
  14.   
  15.     // set a fake vsync period if there is no HWComposer  
  16.     if (mHwc->initCheck() != NO_ERROR) {  
  17.         mPrimaryDispSync.setPeriod(16666667);  
  18.     }  
  19. ...  
  20. }  

這段講了EventThread的創建和使用。EventThread主要用於VSYNC消息的處理,我們同樣會單開一個章節來講解VSYNC的邏輯。
EventControlThread是用來向真實的VSync硬件發命令的,我們這裏暫時不展開。
而一旦硬件不能正常發送VSYNC命令時,我們則通過軟件方式模擬,我們可以看到這裏把模擬的間隔時間設置爲16.6ms左右。

2.7 初始化顯示設備

終於到了init函數的最後幾句話,首先是初始化顯示設備。

  1. {  
  2. ...  
  3.     // initialize our drawing state  
  4.     mDrawingState = mCurrentState;  
  5.   
  6.     // set initial conditions (e.g. unblank default device)  
  7.     initializeDisplays();  
  8.   
  9. ...  
  10. }  

我們來看初始化顯示設備的邏輯:

  1. void SurfaceFlinger::onInitializeDisplays() {  
  2.     // reset screen orientation and use primary layer stack  
  3.     Vector<ComposerState> state;  
  4.     Vector<DisplayState> displays;  
  5.     DisplayState d;  
  6.     d.what = DisplayState::eDisplayProjectionChanged |  
  7.              DisplayState::eLayerStackChanged;  
  8.     d.token = mBuiltinDisplays[DisplayDevice::DISPLAY_PRIMARY];  
  9.     d.layerStack = 0;  
  10.     d.orientation = DisplayState::eOrientationDefault;  
  11.     d.frame.makeInvalid();  
  12.     d.viewport.makeInvalid();  
  13.     displays.add(d);  
  14.     setTransactionState(state, displays, 0);  
  15.     onScreenAcquired(getDefaultDisplayDevice());  
  16.   
  17.     const nsecs_t period =  
  18.             getHwComposer().getRefreshPeriod(HWC_DISPLAY_PRIMARY);  
  19.     mAnimFrameTracker.setDisplayRefreshPeriod(period);  
  20.     property_set("debug.sf.layerdump""0");  
  21. }  

其中setTransactionState函數在很多地方都會有調用,作用主要是處理上層的各個命令,並根據flag設置event通知Threadloop進行處理,TODO
而onScreenAcquired同樣是一個重要的函數,不僅在這裏,在屏幕會喚醒時同樣會調用。

  1. void SurfaceFlinger::onScreenAcquired(const sp<const DisplayDevice>& hw) {  
  2.     ALOGD("Screen acquired, type=%d flinger=%p", hw->getDisplayType(), this);  
  3.     if (hw->isScreenAcquired()) {  
  4.         // this is expected, e.g. when power manager wakes up during boot  
  5.         ALOGD(" screen was previously acquired");  
  6.         return;  
  7.     }  
  8.   
  9.     hw->acquireScreen();  
  10.     int32_t type = hw->getDisplayType();  
  11.     if (type < DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES) {  
  12.         // built-in display, tell the HWC  
  13.         getHwComposer().acquire(type);  
  14.   
  15.         if (type == DisplayDevice::DISPLAY_PRIMARY) {  
  16.             // FIXME: eventthread only knows about the main display right now  
  17.             mEventThread->onScreenAcquired();  
  18.   
  19.             resyncToHardwareVsync(true);  
  20.         }  
  21.     }  
  22.     mVisibleRegionsDirty = true;  
  23.     repaintEverything();  
  24. }  

這裏有幾個點比較重要,首先是通知HWC,調用了HWC的acquire函數:

  1. status_t HWComposer::acquire(int disp) {  
  2.     LOG_FATAL_IF(disp >= VIRTUAL_DISPLAY_ID_BASE);  
  3.     if (mHwc) {  
  4.         return (status_t)mHwc->blank(mHwc, disp, 0);  
  5.     }  
  6.     return NO_ERROR;  
  7. }  

接下來,調用了EventThread的onScreenAcquired函數。

  1. void EventThread::onScreenAcquired() {  
  2.     if (mUseSoftwareVSync) {  
  3.         // resume use of h/w vsync  
  4.         mUseSoftwareVSync = false;  
  5.         mCondition.broadcast();  
  6.     }  
  7. }  

這個函數首先判斷如果在之前mUseSoftwareVSync被設置爲了true,這裏需要改回來。而mUseSoftwareVSync這個值其實是在onScreenReleased被設置爲true的(也就是說,在屏幕被滅掉之後,就變爲軟件的VSync,TODO,在屏幕黑掉之後,還有沒有繪製或者顯示方面的工作?)。

後面這個廣播發送的主要作用是喚醒EventThread線程,並打開VSync事件發送器(可以看下waitForEvent函數)。

接下來的resyncToHardwareVsync函數邏輯比較簡單,應該就是開啓硬件的VSYNC。

  1. void SurfaceFlinger::resyncToHardwareVsync(bool makeAvailable) {  
  2.     Mutex::Autolock _l(mHWVsyncLock);  
  3.   
  4.     if (makeAvailable) {  
  5.         mHWVsyncAvailable = true;  
  6.     } else if (!mHWVsyncAvailable) {  
  7.         ALOGE("resyncToHardwareVsync called when HW vsync unavailable");  
  8.         return;  
  9.     }  
  10.   
  11.     const nsecs_t period =  
  12.             getHwComposer().getRefreshPeriod(HWC_DISPLAY_PRIMARY);  
  13.   
  14.     mPrimaryDispSync.reset();  
  15.     mPrimaryDispSync.setPeriod(period);  
  16.   
  17.     if (!mPrimaryHWVsyncEnabled) {  
  18.         mPrimaryDispSync.beginResync();  
  19.         //eventControl(HWC_DISPLAY_PRIMARY, SurfaceFlinger::EVENT_VSYNC, true);  
  20.         mEventControlThread->setVsyncEnabled(true);  
  21.         mPrimaryHWVsyncEnabled = true;  
  22.     }  
  23. }  

最後是調用了repaintEverything函數,這個函數就是發送invalidate消息,請求屏幕刷新。

2.8 開機動畫

回到init的過程上來。

  1. {  
  2. ...  
  3.     // start boot animation  
  4.     startBootAnim();  
  5.   
  6. }  

播放開機動畫我們會專門講解,這裏不再展開。

3.註冊SF服務

向Android的ServiceManager進程註冊服務是系統的通用邏輯,不再展開,這裏就是註冊了一個名叫的SurfaceFlinger的服務而已。

4.運行程序

在一系列的準備工作之後,終於到了啓動SurfaceFlinger的時候。

  1. void SurfaceFlinger::run() {  
  2.     do {  
  3.         waitForEvent();  
  4.     } while (true);  
  5. }  
  6. void SurfaceFlinger::waitForEvent() {  
  7.     mEventQueue.waitMessage();  
  8. }  

而這個過程其實異常簡單,SF進入死循環中,一直在等待消息的傳來。

總結

這樣,我們就完整的分析了SF的啓動過程,我們將在下一節繼續分析SF對消息的處理過程。

發佈了8 篇原創文章 · 獲贊 5 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章