init啓動SurfaceFlinger
SurfaceFlinger目前的啓動方式是做爲init進程中的一個Service來啓動。
在init中添加如下配置代碼:
- # Set this property so surfaceflinger is not started by system_init
- setprop system_init.startsurfaceflinger 0
- service surfaceflinger /system/bin/surfaceflinger
- class main
- user system
- group graphics drmrpc
- onrestart restart zygote
系統將啓動/system/bin/目錄下的surfaceflinger bin文件來運行SurfaceFlinger。
關於init.rc的語法問題,我們將有專門的文章展開討論(TODO)。
SurfaceFlinger啓動過程
我們繼續來看下對應的bin文件中的代碼,位置在Android\frameworks\native\services\surfaceflinger下。
- int main(int argc, char** argv) {
- // 1.創建surfaceflinger對象
- sp<SurfaceFlinger> flinger = new SurfaceFlinger();
- // initialize before clients can connect
- // 2.初始化
- flinger->init();
- // 3.註冊SF服務
- sp<IServiceManager> sm(defaultServiceManager());
- sm->addService(String16(SurfaceFlinger::getServiceName()), flinger, false);
- // 4.運行程序
- flinger->run();
- return 0;
- }
從上面代碼中我們看到SF的創建過程主要有四個步驟,我們來逐一分析一下。
1. 創建SF對象
- SurfaceFlinger::SurfaceFlinger()
- : BnSurfaceComposer(),
- mTransactionFlags(0),
- mTransactionPending(false),
- mAnimTransactionPending(false),
- mLayersRemoved(false),
- mRepaintEverything(0),
- mRenderEngine(NULL),
- mBootTime(systemTime()),
- mVisibleRegionsDirty(false),
- mHwWorkListDirty(false),
- mAnimCompositionPending(false),
- mDebugRegion(0),
- mDebugFps(0),
- mDebugDDMS(0),
- mDebugDisableHWC(0),
- mDebugDisableTransformHint(0),
- mDebugInSwapBuffers(0),
- mLastSwapBufferTime(0),
- mDebugInTransaction(0),
- mLastTransactionTime(0),
- mBootFinished(false),
- mPrimaryHWVsyncEnabled(false),
- mHWVsyncAvailable(false),
- mDaltonize(false),
- /* Activity-Activity: */
- mProjectionType(ORTHOGRAPHIC_PROJECTION)
- /* Activity-Activity: Change End*/
- // End
- {
- ALOGI("SurfaceFlinger is starting");
- // debugging stuff...
- char value[PROPERTY_VALUE_MAX];
- property_get("ro.bq.gpu_to_cpu_unsupported", value, "0");
- mGpuToCpuSupported = !atoi(value);
- property_get("debug.sf.showupdates", value, "0");
- mDebugRegion = atoi(value);
- property_get("debug.sf.showfps", value, "0");
- mDebugFps = atoi(value);
- property_get("debug.sf.ddms", value, "0");
- mDebugDDMS = atoi(value);
- if (mDebugDDMS) {
- if (!startDdmConnection()) {
- // start failed, and DDMS debugging not enabled
- mDebugDDMS = 0;
- }
- }
- ALOGI_IF(mDebugRegion, "showupdates enabled");
- // ALOGI_IF(mDebugFps, "showfps enabled");
- ALOGI_IF(mDebugDDMS, "DDMS debugging enabled");
- }
其實這個創建過程很簡單,無非就是初始化了一些值。從配置中讀取了一些值。
需要注意的一點是,SurfaceFlinger實現了三個接口:
- class SurfaceFlinger : public BnSurfaceComposer,
- private IBinder::DeathRecipient,
- private HWComposer::EventHandler
BnSurfaceComposer意思是指這個Surface混合的native端,這顯然也符合我們對SF功能的認識—-用於Layer的混合處理。
另外,我們會在後面消息的處理一節中單獨講解HWComposer::EventHandler接口的作用。
2.初始化
其實相比SurfaceFlinger的創建,初始化做了更多的工作。
這一過程比較複雜,我們分爲幾部分來分析:
2.1 EGL初始化
- void SurfaceFlinger::init() {
- ALOGI( "SurfaceFlinger's main thread ready to run. "
- "Initializing graphics H/W...");
- status_t err;
- Mutex::Autolock _l(mStateLock);
- // initialize EGL for the default display
- mEGLDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
- eglInitialize(mEGLDisplay, NULL, NULL);
- ...
- }
首先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
- {
- ...
- // Initialize the H/W composer object. There may or may not be an
- // actual hardware composer underneath.
- mHwc = new HWComposer(this,
- *static_cast<HWComposer::EventHandler *>(this));
- ...
- }
接下來是創建了一個HWComposer,也就是一個負責硬件合成的模塊。但是我們也看到上面的註釋明確寫着,下面可能並沒有一個真正的硬件支持。我們來研究下這個HWComposer的創建過程:
- 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;
- }
- //首先是一些和VSYNC有關的信息的初始化
- //因爲在硬件支持的情況下,VSYNC的功能就是由HWC提供的
- for (size_t i=0 ; i<HWC_NUM_PHYSICAL_DISPLAY_TYPES ; i++) {
- mLastHwVSync[i] = 0;
- mVSyncCounts[i] = 0;
- }
- //根據配置來看是否需要模擬VSYNC消息
- char value[PROPERTY_VALUE_MAX];
- property_get("debug.sf.no_hw_vsync", value, "0");
- mDebugForceFakeVSync = atoi(value);
- bool needVSyncThread = true;
- //加載Gralloc中的GRALLOC_HARDWARE_FB0設備,和HWC設備
- // 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);
- }
- //如果我們有HWC這個硬件設備,那麼我們就註冊一些HWC的函數
- //另外,就不需要使用vsync的進程,因爲我們有了硬件支持的VSYNC中斷
- 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
- //根據HWC硬件的支持情況,來設置顯示屏幕的數量
- 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;
- }
- }
- //如果我們能獲取到FB設置,那麼我們就從FB設備裏面讀取一些屏幕相關的I型難洗
- 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.width = mFbDev->width;
- disp.height = mFbDev->height;
- disp.format = mFbDev->format;
- disp.xdpi = mFbDev->xdpi;
- disp.ydpi = mFbDev->ydpi;
- if (disp.refresh == 0) {
- disp.refresh = nsecs_t(1e9 / mFbDev->fps);
- ALOGW("getting VSYNC period from fb HAL: %lld", disp.refresh);
- }
- if (disp.refresh == 0) {
- disp.refresh = nsecs_t(1e9 / 60.0);
- ALOGW("getting VSYNC period from thin air: %lld",
- mDisplayData[HWC_DISPLAY_PRIMARY].refresh);
- }
- } else if (mHwc) {//否則我們將會從HWC中讀取相關配置,打log確認下走哪個分支
- // here we're guaranteed to have at least HWC 1.1
- for (size_t i =0 ; i<NUM_BUILTIN_DISPLAYS ; i++) {
- queryDisplayProperties(i);
- }
- }
- // End
- //顯然,如果需要模擬VSync信號的話,我們需要線程來做這個工作
- if (needVSyncThread) {
- // we don't have VSYNC support, we need to fake it
- //VSyncThread類的實現很簡單,無非就是一個計時器而已,定時發送消息而已
- //TODO VSYNC專題
- mVSyncThread = new VSyncThread(*this);
- }
- }
2.3 EGL配置
HWC模塊創建完成之後,我們繼續回到SurfaceFlinger的初始化過程,後面將繼續是一些EGL相關的配置:
- {
- ...
- //首先獲取OpenGL ES2.0的配置,在另外一篇文檔中,我們提到過從KK之後,SF開始使用ES 2.0
- // First try to get an ES2 config
- err = selectEGLConfig(mEGLDisplay, mHwc->getVisualID(), EGL_OPENGL_ES2_BIT,
- &mEGLConfig);
- //當然如果獲取失敗,還是會繼續使用1.0,TODO 我們會新開一個專題講OpengGL
- if (err != NO_ERROR) {
- // If ES2 fails, try ES1
- err = selectEGLConfig(mEGLDisplay, mHwc->getVisualID(),
- EGL_OPENGL_ES_BIT, &mEGLConfig);
- }
- if (err != NO_ERROR) {
- // still didn't work, probably because we're on the emulator...
- // try a simplified query
- ALOGW("no suitable EGLConfig found, trying a simpler query");
- err = selectEGLConfig(mEGLDisplay, mHwc->getVisualID(), 0, &mEGLConfig);
- }
- if (err != NO_ERROR) {
- // this EGL is too lame for android
- LOG_ALWAYS_FATAL("no suitable EGLConfig found, giving up");
- }
- // 打印一些配置信息
- EGLint r,g,b,a;
- eglGetConfigAttrib(mEGLDisplay, mEGLConfig, EGL_RED_SIZE, &r);
- eglGetConfigAttrib(mEGLDisplay, mEGLConfig, EGL_GREEN_SIZE, &g);
- eglGetConfigAttrib(mEGLDisplay, mEGLConfig, EGL_BLUE_SIZE, &b);
- eglGetConfigAttrib(mEGLDisplay, mEGLConfig, EGL_ALPHA_SIZE, &a);
- ALOGI("EGL informations:");
- ALOGI("vendor : %s", eglQueryString(mEGLDisplay, EGL_VENDOR));
- ALOGI("version : %s", eglQueryString(mEGLDisplay, EGL_VERSION));
- ALOGI("extensions: %s", eglQueryString(mEGLDisplay, EGL_EXTENSIONS));
- ALOGI("Client API: %s", eglQueryString(mEGLDisplay, EGL_CLIENT_APIS)?:"Not Supported");
- ALOGI("EGLSurface: %d-%d-%d-%d, config=%p", r, g, b, a, mEGLConfig);
- // get a RenderEngine for the given display / config (can't fail)
- // KK升級一章中我們講過SF通過RenderEngine來實現了使用不同版本的OpenGL
- mRenderEngine = RenderEngine::create(mEGLDisplay, mEGLConfig);
- // retrieve the EGL context that was selected/created
- //獲取ES的上下文,這個是用於SF的上下文
- mEGLContext = mRenderEngine->getEGLContext();
- // figure out which format we got
- eglGetConfigAttrib(mEGLDisplay, mEGLConfig,
- EGL_NATIVE_VISUAL_ID, &mEGLNativeVisualId);
- LOG_ALWAYS_FATAL_IF(mEGLContext == EGL_NO_CONTEXT,
- "couldn't create EGLContext");
- ...
- }
2.4 display設置
EGL和OpenGL ES的配置設置完畢之後,我們將對display進行設置。
- {
- ...
- // initialize our non-virtual displays
- for (size_t i=0 ; i<DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES ; i++) {
- DisplayDevice::DisplayType type((DisplayDevice::DisplayType)i);
- // set-up the displays that are already connected
- if (mHwc->isConnected(i) || type==DisplayDevice::DISPLAY_PRIMARY) {
- // All non-virtual displays are currently considered secure.
- bool isSecure = true;
- createBuiltinDisplayLocked(type);
- wp<IBinder> token = mBuiltinDisplays[i];
- //對於每個display,SF都會創建一個新的BufferQueue
- sp<BufferQueue> bq = new BufferQueue(new GraphicBufferAlloc());
- sp<FramebufferSurface> fbs = new FramebufferSurface(*mHwc, i, bq);
- //最後,用我們創建的這些內容,來創建一個DisplayDevice
- //它有兩個重要的變量,一個是mFrameBufferSurface和mNativeWindow。
- //mFrameBufferSurace是FrameBufferSurface類型,
- //當顯示設備不屬於VIRTUAL類型的話,則該變量不爲空
- sp<DisplayDevice> hw = new DisplayDevice(this,
- type, allocateHwcDisplayId(type), isSecure, token,
- fbs, bq,
- mEGLConfig);
- if (i > DisplayDevice::DISPLAY_PRIMARY) {
- // FIXME: currently we don't get blank/unblank requests
- // for displays other than the main display, so we always
- // assume a connected display is unblanked.
- ALOGD("marking display %d as acquired/unblanked", i);
- //這裏應該是指非主屏幕的屏幕一旦註冊,就長期處於開啓狀態
- hw->acquireScreen();
- }
- mDisplays.add(token, hw);
- }
- }
- ...
- }
上面這段代碼其實涉及到了三個重要的概念,BufferQueue、FrameBufferSurface以及DisplayDevice。
BufferQueue做爲Graphic的核心組件,我們在講解Graphic總體結構時已經有說明,後面會另開專題說明。我們先來看下FrameBufferSurface的實現:
- FramebufferSurface::FramebufferSurface(HWComposer& hwc, int disp,
- const sp<IGraphicBufferConsumer>& consumer) :
- ConsumerBase(consumer),
- mDisplayType(disp),
- mCurrentBufferSlot(-1),
- mCurrentBuffer(0),
- mHwc(hwc)
- {
- mName = "FramebufferSurface";
- mConsumer->setConsumerName(mName);
- mConsumer->setConsumerUsageBits(GRALLOC_USAGE_HW_FB |
- GRALLOC_USAGE_HW_RENDER |
- GRALLOC_USAGE_HW_COMPOSER);
- mConsumer->setDefaultBufferFormat(mHwc.getFormat(disp));
- mConsumer->setDefaultBufferSize(mHwc.getWidth(disp), mHwc.getHeight(disp));
- mConsumer->setDefaultMaxBufferCount(NUM_FRAMEBUFFER_SURFACE_BUFFERS);
- mConsumer->setMaxAcquiredBufferCount(NUM_FRAMEBUFFER_SURFACE_BUFFERS - 1);
- }
我們使用了BufferQueue來創建了一個FramebufferSurface,顯然這個FramebufferSurface是一個消費者。在創建過程我們使用了屏幕的編號和HWC,我們可以猜測這個FBS是和一個屏幕綁定的,而且最終應該也是要通過HWC進行渲染。我們可以理解爲這是SF在這個屏幕上使用的幀緩衝區,那麼也就是一旦使用SF合成,最後數據應該是合成在了這裏面(待驗證),然後這裏面的數據通過HWC顯示在了屏幕上。猜測一下,這個是不是就是抓dump時抓到的那個HWC_FRAMEBUFFER_TARGET?
FBS的創建並沒有特別之處,需要留意的是這裏設置了MaxBufferCount和MaxAcquiredBufferCount,我們在Graphic總體架構一文中已經提到了設置這兩個屬性的作用。
DisplayDevice其實是抽象了顯示設備,封裝了用於渲染的Surface和HWComposer模塊等,從而儘可能使得SurfaceFlinger只要和它打交道。來看下他的創建過程:
- DisplayDevice::DisplayDevice(
- const sp<SurfaceFlinger>& flinger,
- DisplayType type,
- int32_t hwcId,
- bool isSecure,
- const wp<IBinder>& displayToken,
- const sp<DisplaySurface>& displaySurface,
- const sp<IGraphicBufferProducer>& producer,
- EGLConfig config)
- : mFlinger(flinger),
- mType(type), mHwcDisplayId(hwcId),
- mDisplayToken(displayToken),
- mDisplaySurface(displaySurface),
- mDisplay(EGL_NO_DISPLAY),
- mSurface(EGL_NO_SURFACE),
- mDisplayWidth(), mDisplayHeight(), mFormat(),
- mFlags(),
- mPageFlipCount(),
- mIsSecure(isSecure),
- mSecureLayerVisible(false),
- mScreenAcquired(false),
- mLayerStack(NO_LAYER_STACK),
- mOrientation()
- {
- mNativeWindow = new Surface(producer, false);
- ANativeWindow* const window = mNativeWindow.get();
- int format;
- window->query(window, NATIVE_WINDOW_FORMAT, &format);
- /*
- * Create our display's surface
- */
- EGLSurface surface;
- EGLint w, h;
- EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
- surface = eglCreateWindowSurface(display, config, window, NULL);
- eglQuerySurface(display, surface, EGL_WIDTH, &mDisplayWidth);
- eglQuerySurface(display, surface, EGL_HEIGHT, &mDisplayHeight);
- mDisplay = display;
- mSurface = surface;
- mFormat = format;
- mPageFlipCount = 0;
- mViewport.makeInvalid();
- mFrame.makeInvalid();
- float mFOV = 30.0f;
- float tangent = tan(PI / 180.0f * mFOV / 2.0f);
- mDefaultX = -((float) mDisplayWidth / 2.0f);
- mDefaultY = -((float) mDisplayHeight / 2.0f);
- mDefaultZ = -(((float) mDisplayHeight / 2.0f) / tangent);
- /* Activity-Activity: Change End*/
- // virtual displays are always considered enabled
- mScreenAcquired = (mType >= DisplayDevice::DISPLAY_VIRTUAL);
- // Name the display. The name will be replaced shortly if the display
- // was created with createDisplay().
- switch (mType) {
- case DISPLAY_PRIMARY:
- mDisplayName = "Built-in Screen";
- break;
- case DISPLAY_EXTERNAL:
- mDisplayName = "HDMI Screen";
- break;
- default:
- mDisplayName = "Virtual Screen"; // e.g. Overlay #n
- break;
- }
- char property[PROPERTY_VALUE_MAX];
- int panelOrientation = DisplayState::eOrientationDefault;
- // Set the panel orientation from the property.
- property_get("persist.panel.orientation", property, "0");
- panelOrientation = atoi(property) / 90;
- // initialize the display orientation transform.
- setProjection(panelOrientation, mViewport, mFrame);
- }
這段創建同樣相當之長,我們目前只關注這裏面創建了一個EGLSurface。我們在前面的文章中曾經提到過這個類,這個實際上就是一個供GLES使用的窗口緩衝區,爲GLES提供了一個繪製的地方。
在這個EGLSurface裏面是一個Surface,本質上下面還是一個BufferQueue。
渲染這個EGLSurface將導致一個buffer出隊渲染入隊的過程,lock和unlock過程是通過eglSwapBuffers函數來提供的。
2.5 makeCurrent
看完了上面幾個重要概念的講解,我們繼續回到SF的init過程中來。
下面是對主屏幕對應的display進行makeCurrent操作:
- {
- ...
- // initialize OpenGL ES
- /* Activity-Activity: */
- setProjectionType(ORTHOGRAPHIC_PROJECTION);
- /* Activity-Activity: Change End*/
- // make the GLContext current so that we can create textures when creating Layers
- // (which may happens before we render something)
- getDefaultDisplayDevice()->makeCurrent(mEGLDisplay, mEGLContext);
- ...
- }
注意到這裏調用的實際上是DisplayDevice類提供的函數,這也某種程度上說明了我們前面提到的DisplayDevice的作用是:封裝了用於渲染的Surface和HWComposer模塊等,從而儘可能使得SurfaceFlinger只要和它打交道。看下這個makeCurrent函數:
- EGLBoolean DisplayDevice::makeCurrent(EGLDisplay dpy, EGLContext ctx) const {
- EGLBoolean result = EGL_TRUE;
- EGLSurface sur = eglGetCurrentSurface(EGL_DRAW);
- if (sur != mSurface) {
- result = eglMakeCurrent(dpy, mSurface, mSurface, ctx);
- if (result == EGL_TRUE) {
- if (mType >= DisplayDevice::DISPLAY_VIRTUAL)
- eglSwapInterval(dpy, 0);
- }
- }
- setViewportAndProjection();
- return result;
- }
這裏獲取了當前使用的EGLSurface,一旦發現這個Surface發生了改變,就要重新調用eglMakeCurrent函數來設置,這是因爲一個線程同時只能有一個EGLSurface作爲current。而關於eglMakeCurrent函數的更詳盡的說明,我們將在EGL和GLES的章節中給予說明。
2.6 EventThread的創建
再次回到SF的init過程中來:
- {
- ...
- // start the EventThread
- sp<VSyncSource> vsyncSrc = new DispSyncSource(&mPrimaryDispSync,
- vsyncPhaseOffsetNs, true);
- mEventThread = new EventThread(vsyncSrc);
- sp<VSyncSource> sfVsyncSrc = new DispSyncSource(&mPrimaryDispSync,
- sfVsyncPhaseOffsetNs, true);
- mSFEventThread = new EventThread(sfVsyncSrc);
- mEventQueue.setEventThread(mSFEventThread);
- mEventControlThread = new EventControlThread(this);
- mEventControlThread->run("EventControl", PRIORITY_URGENT_DISPLAY);
- // set a fake vsync period if there is no HWComposer
- if (mHwc->initCheck() != NO_ERROR) {
- mPrimaryDispSync.setPeriod(16666667);
- }
- ...
- }
這段講了EventThread的創建和使用。EventThread主要用於VSYNC消息的處理,我們同樣會單開一個章節來講解VSYNC的邏輯。
EventControlThread是用來向真實的VSync硬件發命令的,我們這裏暫時不展開。
而一旦硬件不能正常發送VSYNC命令時,我們則通過軟件方式模擬,我們可以看到這裏把模擬的間隔時間設置爲16.6ms左右。
2.7 初始化顯示設備
終於到了init函數的最後幾句話,首先是初始化顯示設備。
- {
- ...
- // initialize our drawing state
- mDrawingState = mCurrentState;
- // set initial conditions (e.g. unblank default device)
- initializeDisplays();
- ...
- }
我們來看初始化顯示設備的邏輯:
- void SurfaceFlinger::onInitializeDisplays() {
- // reset screen orientation and use primary layer stack
- Vector<ComposerState> state;
- Vector<DisplayState> displays;
- DisplayState d;
- d.what = DisplayState::eDisplayProjectionChanged |
- DisplayState::eLayerStackChanged;
- d.token = mBuiltinDisplays[DisplayDevice::DISPLAY_PRIMARY];
- d.layerStack = 0;
- d.orientation = DisplayState::eOrientationDefault;
- d.frame.makeInvalid();
- d.viewport.makeInvalid();
- displays.add(d);
- setTransactionState(state, displays, 0);
- onScreenAcquired(getDefaultDisplayDevice());
- const nsecs_t period =
- getHwComposer().getRefreshPeriod(HWC_DISPLAY_PRIMARY);
- mAnimFrameTracker.setDisplayRefreshPeriod(period);
- property_set("debug.sf.layerdump", "0");
- }
其中setTransactionState函數在很多地方都會有調用,作用主要是處理上層的各個命令,並根據flag設置event通知Threadloop進行處理,TODO
而onScreenAcquired同樣是一個重要的函數,不僅在這裏,在屏幕會喚醒時同樣會調用。
- void SurfaceFlinger::onScreenAcquired(const sp<const DisplayDevice>& hw) {
- ALOGD("Screen acquired, type=%d flinger=%p", hw->getDisplayType(), this);
- if (hw->isScreenAcquired()) {
- // this is expected, e.g. when power manager wakes up during boot
- ALOGD(" screen was previously acquired");
- return;
- }
- hw->acquireScreen();
- int32_t type = hw->getDisplayType();
- if (type < DisplayDevice::NUM_BUILTIN_DISPLAY_TYPES) {
- // built-in display, tell the HWC
- getHwComposer().acquire(type);
- if (type == DisplayDevice::DISPLAY_PRIMARY) {
- // FIXME: eventthread only knows about the main display right now
- mEventThread->onScreenAcquired();
- resyncToHardwareVsync(true);
- }
- }
- mVisibleRegionsDirty = true;
- repaintEverything();
- }
這裏有幾個點比較重要,首先是通知HWC,調用了HWC的acquire函數:
- status_t HWComposer::acquire(int disp) {
- LOG_FATAL_IF(disp >= VIRTUAL_DISPLAY_ID_BASE);
- if (mHwc) {
- return (status_t)mHwc->blank(mHwc, disp, 0);
- }
- return NO_ERROR;
- }
接下來,調用了EventThread的onScreenAcquired函數。
- void EventThread::onScreenAcquired() {
- if (mUseSoftwareVSync) {
- // resume use of h/w vsync
- mUseSoftwareVSync = false;
- mCondition.broadcast();
- }
- }
這個函數首先判斷如果在之前mUseSoftwareVSync被設置爲了true,這裏需要改回來。而mUseSoftwareVSync這個值其實是在onScreenReleased被設置爲true的(也就是說,在屏幕被滅掉之後,就變爲軟件的VSync,TODO,在屏幕黑掉之後,還有沒有繪製或者顯示方面的工作?)。
後面這個廣播發送的主要作用是喚醒EventThread線程,並打開VSync事件發送器(可以看下waitForEvent函數)。
接下來的resyncToHardwareVsync函數邏輯比較簡單,應該就是開啓硬件的VSYNC。
- void SurfaceFlinger::resyncToHardwareVsync(bool makeAvailable) {
- Mutex::Autolock _l(mHWVsyncLock);
- if (makeAvailable) {
- mHWVsyncAvailable = true;
- } else if (!mHWVsyncAvailable) {
- ALOGE("resyncToHardwareVsync called when HW vsync unavailable");
- return;
- }
- const nsecs_t period =
- getHwComposer().getRefreshPeriod(HWC_DISPLAY_PRIMARY);
- mPrimaryDispSync.reset();
- mPrimaryDispSync.setPeriod(period);
- if (!mPrimaryHWVsyncEnabled) {
- mPrimaryDispSync.beginResync();
- //eventControl(HWC_DISPLAY_PRIMARY, SurfaceFlinger::EVENT_VSYNC, true);
- mEventControlThread->setVsyncEnabled(true);
- mPrimaryHWVsyncEnabled = true;
- }
- }
最後是調用了repaintEverything函數,這個函數就是發送invalidate消息,請求屏幕刷新。
2.8 開機動畫
回到init的過程上來。
- {
- ...
- // start boot animation
- startBootAnim();
- }
播放開機動畫我們會專門講解,這裏不再展開。
3.註冊SF服務
向Android的ServiceManager進程註冊服務是系統的通用邏輯,不再展開,這裏就是註冊了一個名叫的SurfaceFlinger的服務而已。
4.運行程序
在一系列的準備工作之後,終於到了啓動SurfaceFlinger的時候。
- void SurfaceFlinger::run() {
- do {
- waitForEvent();
- } while (true);
- }
- void SurfaceFlinger::waitForEvent() {
- mEventQueue.waitMessage();
- }
而這個過程其實異常簡單,SF進入死循環中,一直在等待消息的傳來。
總結
這樣,我們就完整的分析了SF的啓動過程,我們將在下一節繼續分析SF對消息的處理過程。