<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                SurfaceFlinger駐留于system_server進程,這一點和Audio系統的幾個Service不太一樣。它創建的位置在SystemServer的init1函數中(第4章4.3.2節的第3點)。雖然位于SystemServer這個重要進程中,但是SF創建的代碼卻略顯波瀾不驚,沒有什么特別之處。SF的創建首先會調用instantiate函數,代碼如下所示: **SurfaceFlinger.cpp** ~~~ void SurfaceFlinger::instantiate() { defaultServiceManager()->addService( String16("SurfaceFlinger"), new SurfaceFlinger()); } ~~~ 前面在圖8-14中指出了SF,同時從BnSurfaceComposer和Thread類中派生,相關代碼如下所示: **class SurfaceFlinger : public BnSurfaceComposer,protected Thread** 從Thread派生這件事給了我們一個很明確的提示: - SurfaceFlinger會單獨啟動一個工作線程。 我們知道,Thread類的工作線程要通過調用它的run函數來創建,那這個run函數是在什么地方調用的呢?當然,最有可能的就是在構造函數中: **SurfaceFlinger.cpp** ~~~ SurfaceFlinger::SurfaceFlinger() : BnSurfaceComposer(), Thread(false), mTransactionFlags(0), mTransactionCount(0), mResizeTransationPending(false), mLayersRemoved(false), mBootTime(systemTime()), mHardwareTest("android.permission.HARDWARE_TEST"), mAccessSurfaceFlinger("android.permission.ACCESS_SURFACE_FLINGER"), mDump("android.permission.DUMP"), mVisibleRegionsDirty(false), mDeferReleaseConsole(false), mFreezeDisplay(false), mFreezeCount(0), mFreezeDisplayTime(0), mDebugRegion(0), mDebugBackground(0), mDebugInSwapBuffers(0), mLastSwapBufferTime(0), mDebugInTransaction(0), mLastTransactionTime(0), mBootFinished(false), mConsoleSignals(0), mSecureFrameBuffer(0) { init();//上面沒有調用run。必須到init去檢查一番。 } //init函數更簡單了。 void SurfaceFlinger::init() { charvalue[PROPERTY_VALUE_MAX]; property_get("debug.sf.showupdates", value, "0"); mDebugRegion = atoi(value); property_get("debug.sf.showbackground", value, "0"); mDebugBackground = atoi(value); } ~~~ 嗯?上面的代碼竟然沒有創建工作線程?難道在其他地方?讀者別急著在文件中搜索“run”,先猜測一下答案。 - 根據之前所學的知識,另外一個最有可能的地方就是onFirstRef函數了,這個函數在對象第一次被sp化后調用,很多初始化的工作也可以在這個函數中完成。 事實是這樣嗎?一起來看。 1. onFirstRef的分析 onFirstRef的代碼如下所示: **SurfaceFlinger.cpp** ~~~ void SurfaceFlinger::onFirstRef() { //真是夢里尋他千百度,果然是在onFirstRef中創建了工作線程 run("SurfaceFlinger",PRIORITY_URGENT_DISPLAY); /* mReadyToRunBarrier類型為Barrier,這個類就是封裝了一個Mutex對象和一個Condition 對象。如果讀者還記得第5章有關同步類的介紹,理解這個Barrier就非常簡單了。下面調用的 wait函數表示要等待一個同步條件的滿足。 */ mReadyToRunBarrier.wait(); } ~~~ onFirstRef創建工作線程后,將等待一個同步條件,那么這個同步條件在哪里被觸發呢?相信不用多說 大家也知道: 在工作線程中被觸發,而且極有可能是在readyToRun函數中。 不清楚Thread類的讀者可以復習一下與第5章有關的Thread類的知識。 2. readyToRun的分析 SF的readyToRun函數將完成一些初始化工作,代碼如下所示: **SurfaceFlinger.cpp** ~~~ status_t SurfaceFlinger::readyToRun() { intdpy = 0; { //①GraphicPlane是什么? GraphicPlane& plane(graphicPlane(dpy)); //②為這個GraphicPlane設置一個HAL對象——DisplayHardware DisplayHardware* const hw = new DisplayHardware(this, dpy); plane.setDisplayHardware(hw); } //創建Surface系統中的“CB”對象,按照老規矩,應該先創建一塊共享內存,然后使用placment new mServerHeap = new MemoryHeapBase(4096, MemoryHeapBase::READ_ONLY, "SurfaceFlingerread-only heap"); /* 注意這個“CB“對象的類型是surface_flinger_cblk_t。為什么在CB上打引號呢?因為這個對象 談不上什么控制,只不過被用來存儲一些信息罷了。其控制作用完全達不到audio_track_cblk_t 的程度。基于這樣的事實,我們把前面提到的SharedBuffer家族稱之為CB對象。 */ mServerCblk= static_cast<surface_flinger_cblk_t*>(mServerHeap->getBase()); //placementnew創建surface_flinger_cblk_t new(mServerCblk) surface_flinger_cblk_t; constGraphicPlane& plane(graphicPlane(dpy)); constDisplayHardware& hw = plane.displayHardware(); constuint32_t w = hw.getWidth(); constuint32_t h = hw.getHeight(); constuint32_t f = hw.getFormat(); hw.makeCurrent(); //當前只有一塊屏 mServerCblk->connected|= 1<<dpy; //屏幕在“CB”對象中的代表是display_cblk_t display_cblk_t* dcblk = mServerCblk->displays + dpy; memset(dcblk, 0, sizeof(display_cblk_t)); dcblk->w =plane.getWidth(); dcblk->h =plane.getHeight(); ......//獲取屏幕信息 //還用上了內聯匯編語句。 asmvolatile ("":::"memory"); /* 下面是一些和OpenGL相關的函數調用。讀者如感興趣,可以研究一下, 至少SurfaceFlinger.cpp中所涉及的相關代碼還不算難懂 */ glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, 0); ...... glOrthof(0, w, h, 0, 0, 1); //LayerDim是Dim類型的Layer LayerDim::initDimmer(this, w, h); //還記得在onFirstRef函數中的wait嗎?下面的open將觸發這個同步條件 mReadyToRunBarrier.open(); //資源準備好后,init將啟動bootanim程序,這樣就見到開機動畫了。 property_set("ctl.start", "bootanim"); returnNO_ERROR; } ~~~ 在上面的代碼中,列出了兩個關鍵點,下面一一進行分析。 (1)GraphicPlane的介紹 GraphicPlane是屏幕在SF代碼中的對應物,根據前面的介紹,目前Android只支持一塊屏幕,所以SF定義了一個一元數組: ~~~ GraphicPlane mGraphicPlanes[1]; ~~~ GraphicPlane雖無什么特別之處,但它有一個重要的函數,叫setDisplayHardware,這個函數把代表顯示設備的HAL對象和GraphicPlane關聯起來。這也是下面要介紹的第二個關鍵點DisplayHardware。 (2)DisplayHardware的介紹 從代碼上看,這個和顯示相關的HAL對象是在工作線程中new出來的,先看它的構造函數,代碼如下所示: **DisplayHardware.cpp** ~~~ DisplayHardware::DisplayHardware( const sp<SurfaceFlinger>& flinger, uint32_t dpy) :DisplayHardwareBase(flinger, dpy) { init(dpy); //最重要的是這個init函數。 } ~~~ init函數非常重要,應進去看看。下面先思考一個問題。 前面在介紹FrameBuffer時說過,顯示這一塊需要使用FrameBuffer,但在GraphicBuffer中用的卻是ashmem創建的共享內存。也就是說,之前在共享內存中繪制的圖像和FrameBuffer沒有什么關系。那么FrameBuffer是在哪里創建的呢? 答案就在init函數中,代碼如下所示: **DisplayHardware.cpp** ~~~ void DisplayHardware::init(uint32_t dpy) { //FrameBufferNativeWindow實現了對FrameBuffer的管理和操作,該類中創建了兩個 //FrameBuffer,分別起到FrontBuffer和BackBuffer的作用。 mNativeWindow = new FramebufferNativeWindow(); framebuffer_device_t const * fbDev = mNativeWindow->getDevice(); mOverlayEngine = NULL; hw_module_t const* module;//Overlay相關 if(hw_get_module(OVERLAY_HARDWARE_MODULE_ID, &module) == 0) { overlay_control_open(module, &mOverlayEngine); } ...... EGLint w, h, dummy; EGLintnumConfigs=0; EGLSurface surface; EGLContext context; mFlags= CACHED_BUFFERS; //EGLDisplay在EGL中代表屏幕 EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY); ...... /* surface是EGLSurface類型,下面這個函數會將EGL和Android中的Display系統綁定起來, 后續就可以利用OpenGL在這個Surface上繪畫,然后通過eglSwappBuffers輸出圖像了。 */ surface= eglCreateWindowSurface(display, config, mNativeWindow.get(),NULL); ...... mDisplay = display; mConfig = config; mSurface = surface; mContext = context; mFormat = fbDev->format; mPageFlipCount = 0; } ~~~ 根據上面的代碼,現在可以回答前面的問題了: - SF創建FrameBuffer,并將各個Surface傳輸的數據(通過GraphicBuffer)混合后,再由自己傳輸到FrameBuffer中進行顯示。 本節的內容,實際上涉及另外一個比Surface更復雜的Display系統,出于篇幅和精力的原因,本書目前不打算討論它。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看