1. 程式人生 > >Android系統--檢視繪製 View Render

Android系統--檢視繪製 View Render

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow

也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!

               

1. 簡介

     Android系統--檢視繪製主要由以下幾部分組成:

     1) Canvas(畫布)

         提供畫圖所需要的所有工具,即各種draw函式;當前可用的畫布物件有:具有硬體加速的GLES20Canvas和GLES20RecordingCanvas,不使用硬體加速的CompatibleCanvas)。

     2) View(檢視)

         在具體畫布物件上完成各種繪製圖形的操作,可根據需要選擇以上三種畫布中的一種。

     3)  Gl20Renderer(把圖直接繪製到螢幕上)

          它是硬體加速檢視繪製的引擎,負責整個與硬體加速相關的檢視繪製過程,具體功能如下:

           (1) 建立以下例項物件:

             • GLES20Canvas           (Canvas)
             • GLES20DisplayList      (DisplayList)
             • GLES20TextureLayer  (HardwareLayer)
             • GLES20RenderLayer  (HardwareLayer)
             • SurfaceTexture
             • Gl20Renderer              (HardwareRenderer)

           (2) 在GlRenderer.draw中呼叫View.getDisplayList()完成DisplayList命令的錄製,並返回DisplayList

                 注:只有View被attach到硬體加速,才能建立DisplayList;

                        真正的命令錄製工作在View.getDisplayList(DisplayList displayList, boolean isLayer)中完成。

           (3) GlRenderer.draw中呼叫GLES20Canvas.drawDisplayList把DisplayList中錄製的命令回放在畫布上。

           (4) Gl20Renderer物件對應的畫布為GLES20Canvas,Gl20Renderer物件在畫布上的繪製實際上是繪製在OPENGL繪製上下文對應的主緩衝區。

     4) GLES20DisplayList(把錄製命令錄製到Native的DiplayList中)

         GLES20DisplayList物件建立具體的DisplayList物件及繪製用的畫布(GLES20RecordingCanvas畫布),完成檢視繪製操作的DisplayList命令錄製等工作。

     5) GLES20RenderLayer(繪製到FOB Layer中,當作紋理)

         負責建立硬體Layer層(GLES20Canvas.nCreateLayer)和繪製用到的畫布(GLES20Canvas,使用Layer例項化GLES20Canvas(layer, trans))等工作。

         為了有效支援檢視的多層繪製,檢視物件可以建立一個HardwareLayer層完成檢視的圖形在硬體紋理上的繪製操作或者其它特效操作,這就是GLES20RenderLayer物件的作用,建立獨立的層並返回相應的畫布供檢視繪製使用。

1.1 View.draw(Canvas canvas)六步曲

      此函式將把View自身及其所有的子子孫孫繪製到給定的畫布上。其畫圖過程主要分為以下六步:

      1) 畫背景
      2) 如果需要,儲存畫布的層為未來的淡入淡出做好準備
      3) 畫View本身的內容
      4) 畫它的孩子
      5) 如果需要,畫淡入淡出的邊緣並恢復層
      6) 畫裝飾部分(如:滾動條)


    /**     * Manually render this view (and all of its children) to the given Canvas.     * The view must have already done a full layout before this function is     * called.  When implementing a view, implement     * {@link #onDraw(android.graphics.Canvas)} instead of overriding this method.     * If you do need to override this method, call the superclass version.     *     * @param canvas The Canvas to which the View is rendered.     */    public void draw(Canvas canvas) {        final int privateFlags = mPrivateFlags;        final boolean dirtyOpaque = (privateFlags & PFLAG_DIRTY_MASK) == PFLAG_DIRTY_OPAQUE &&                (mAttachInfo == null || !mAttachInfo.mIgnoreDirtyState);        mPrivateFlags = (privateFlags & ~PFLAG_DIRTY_MASK) | PFLAG_DRAWN;        /*         * Draw traversal performs several drawing steps which must be executed         * in the appropriate order:         *         *      1. Draw the background         *      2. If necessary, save the canvas' layers to prepare for fading         *      3. Draw view's content         *      4. Draw children         *      5. If necessary, draw the fading edges and restore layers         *      6. Draw decorations (scrollbars for instance)         */        // Step 1, draw the background, if needed        int saveCount;        if (!dirtyOpaque) {            final Drawable background = mBackground;            if (background != null) {                final int scrollX = mScrollX;                final int scrollY = mScrollY;                if (mBackgroundSizeChanged) {                    background.setBounds(0, 0,  mRight - mLeft, mBottom - mTop);                    mBackgroundSizeChanged = false;                }                if ((scrollX | scrollY) == 0) {                    background.draw(canvas);                } else {                    canvas.translate(scrollX, scrollY);                    background.draw(canvas);                    canvas.translate(-scrollX, -scrollY);                }            }        }        // skip step 2 & 5 if possible (common case)        final int viewFlags = mViewFlags;        boolean horizontalEdges = (viewFlags & FADING_EDGE_HORIZONTAL) != 0;        boolean verticalEdges = (viewFlags & FADING_EDGE_VERTICAL) != 0;        if (!verticalEdges && !horizontalEdges) {            // Step 3, draw the content            if (!dirtyOpaque) onDraw(canvas);            // Step 4, draw the children            dispatchDraw(canvas);            // Step 6, draw decorations (scrollbars)            onDrawScrollBars(canvas);            // we're done...            return;        }    }


2. 家族圖譜

2.1 View家族圖譜




2.2 Canvas和HardwareRenderer家族圖譜




2.3 DisplayList和HardwareLayer家族圖譜

2.4 Native OpenGLRenderer家族圖譜



DisplayList.replay呼叫流程如下:

//JavaGlRenderer.draw((View view, View.AttachInfo attachInfo,...)GLES20Canvas.drawDisplayList(DisplayList displayList, Rect dirty, int flags)->//JNInDrawDisplayList->android_view_GLES20Canvas_drawDisplayList(...,OpenGLRenderer* renderer,                                            DisplayList* displayList,...)->//NativeOpenGLRenderer.drawDisplayList(DisplayList* displayList,...)->DisplayList::replay(OpenGLRenderer& renderer,...)


2.5 Activity與Window家族圖譜

     

• WindowManagerImpl:

    允許把View子類增加到高階Window,應用不應該使用它,而是使用更高階的android.app.Activity或android.app.Dialog。

• PhoneWindow.mDecor(DecorView):視窗最高階的裝飾View,即視窗的View樹的樹根,它包含:標準的Window框架、裝飾、和放於視窗中的內容,可把它當作一個Window增加到Window Manager。

2.6 Activity與PhoneWindow的關係

    每一個Activity都有一個關聯的PhoneWindow物件,用來描述一個應用程式的視窗。每一個應用程式視窗(PhoneWindow)內部又包含有一個裝飾View物件(mDecor:DecorView,View樹的樹根)和一個內容View物件(mContentParent: ViewGroup),用來描述應用程式視窗的檢視。

   1) mContentParent(ViewGroup):是Layout 資源描述的檢視樹的樹根,它是mDecor的孩子

   2) mDecor(DecorView):是PhoneWindow視窗中的檢視樹的樹根

 

2.7 Activity例項化PhoneWindow流程

     Activity在attach函式中例項化了PhoneWindow和WindowManagerImpl,以供後面繪製檢視使用。

Activity.attach(Context context, ActivityThread aThread,            Instrumentation instr, IBinder token, int ident,            Application application, Intent intent, ActivityInfo info,            CharSequence title, Activity parent, String id,            NonConfigurationInstances lastNonConfigurationInstances,            Configuration config)-> 1) PolicyManager.makeNewWindow(Context context)   // 返回PhoneWindow例項並儲存在mWindow中   {    Policy.makeNewWindow(Context context)->       //new PhoneWindow(context)    PhoneWindow(Context context)       //獲取LayoutInflater,它可以把Layout XML例項化為對應的View Objects   } 2) Window.setWindowManager(                (WindowManager)context.getSystemService(Context.WINDOW_SERVICE),                mToken, mComponent.flattenToString(),                (info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0)->   {    WindowManagerImpl.createLocalWindowManager(Window parentWindow)    // 返回WindowManagerImpl例項,並儲存在Window.mWindowManager   } 3)mWindow.setContainer(mParent.getWindow()) 4)mWindowManager = mWindow.getWindowManager()   //返回Window.mWindowManager   //即Activity與Window中的mWindowManager為同一個   //WindowManagerImpl例項

2.8 放置視窗內容setContentView

  setContentView的功能是:把Layout XML資原始檔例項化為一棵檢視樹,然後把它加入PhoneWindow.mContentParent中,即成為PhoneWindow.mContentParent的子女。

Activity.setContentView(int layoutResID)->  //設定Activity內容PhoneWindow.setContentView(int layoutResID)->LayoutInflater.inflate(layoutResID, mContentParent)->  //把XML資原始檔例項化為一棵檢視樹,並返回檢視樹的樹根(root)   //樹根為ViewGroup例項LayoutInflater.inflate(layoutResID, root, root != null)->  //根據資源生成XmlResourceParserLayoutInflater.inflate(XmlPullParser parser, ViewGroup root, boolean attachToRoot)->ViewGroup.addView(View child, LayoutParams params)->  {  //把資原始檔中的檢視樹加入PhoneWindow中的mContentParent中  View.requestLayout()  View.invalidate(true)->  addViewInner(child, index, params, false)    //它將呼叫child.requestLayout(),依次遞迴下去  }  ViewGroup.invalidateChild(View child, final Rect dirty)->  ViewGroup.invalidateChildInParent(final int[] location, final Rect dirty)    //更新dirty區域




3. FBO (Frame Buffer Object)和RBO (Render Buffer Object)

    在瞭解下面的內容之前,需要了解一下FBO和RBO,除了使用視窗系統固有的Frame Buffer外,可以建立Frame Buffer Object,用於off-screen rendering(離線渲染:就是通過OpenGL將繪製結果渲染到視訊記憶體中的一張圖片上,通過gl介面函式可以從視訊記憶體讀取到記憶體中)。FBO是一種特殊的Buffer Object。

3.1 FBO

   1) glGenFramebuffers: 生成FBO物件的名字

   2) glBindFramebuffer: 繫結FBO並進行實始化

   3) glDeleteFramebuffers: 刪除FBO物件

   FBO建立後,還不能繪圖,必須為FBO提供繪圖的目標buffer,也即Render Buffer Object。

3.2 RBO

      Render Buffer Object包含具體的影象資料:

      1) glGenRenderbuffers:生成物件的名字

      2) glBindRenderbuffer: 繫結名字到RenderBuffer

      3) glRenderbufferStorage: 為render buffer分配儲存空間

3.3 把RBO連線到FBO上

      glFramebufferRenderbuffer(GLenum target, GLenum attachment,GLenum renderbuffertarget, GLuint renderbuffer);

      1) target:GL_DRAW_FRAMEBUFFER: 指定寫入用途FBO

                       GL_READ_FRAMEBUFFER:指定讀取用途FBO

                       GL_FRAMEBUFFER:指定兩者

      2) attachment:GL_COLOR_ATTACHMENT

                               GL_DEPTH_ATTACHMENT

                               GL_STENCIL_ATTACHMENT

                               GL_DEPTH_STENCIL_ATTACHMENT

      3)renderbuffertarget: GL_RENDERBUFFER

      4) renderbuffer: RBO名字


     使用FBO可以創建出動態的texture,glFramebufferTexture可以繫結texture到FBO。


4. 各種各樣的畫布

    從上面的家族圖譜中可以看到,可用的畫布有以下幾種:

    1) GLES20RecordingCanvas:  此GL畫布用於錄製畫圖操作

    2) GLES20Canvas:  在OpenGL ES 2.0之上實現的畫布

    3) HardwareCanvas: 硬體加速的畫布

    3) Canvas: 實現畫圖操作的畫布

4.1 Gl20Renderer使用的畫布(直接繪製在螢幕上)

     其相關程式碼如下:

Gl20Renderer.createCanvas()->

  GLES20Canvas.GLES20Canvas(false, boolean translucent)->

nCreateRenderer()

/** * Hardware renderer using OpenGL ES 2.0. */static class Gl20Renderer extends GlRenderer {    private GLES20Canvas mGlCanvas;    final boolean mTranslucent;    //...    @Override    HardwareCanvas createCanvas() {        //建立直接繪製到螢幕上的畫布,而不會錄製到DisplayList中        return mGlCanvas = new GLES20Canvas(mTranslucent);    }    //...}/** * An implementation of Canvas on top of OpenGL ES 2.0. */class GLES20Canvas extends HardwareCanvas {    private final boolean mOpaque;    private int mRenderer;    //...    /**     * Creates a canvas to render directly on screen.     * 建立直接繪製到螢幕上的畫布,而不會錄製到DisplayList中     * 由Gl20Renderer.createCanvas呼叫     */    GLES20Canvas(boolean translucent) {        // 直接呼叫OpenGL函式把圖畫到螢幕上        this(false, translucent);    }    /**     * Creates a canvas to render into an FBO.     * 建立離線繪製到FBO的畫布     */    GLES20Canvas(int layer, boolean translucent) {        mOpaque = !translucent;        // mRenderer為Native中LayerRenderer類的例項        mRenderer = nCreateLayerRenderer(layer);        setupFinalizer();    }        protected GLES20Canvas(boolean record, boolean translucent) {        mOpaque = !translucent;        if (record) {            // 把畫圖命令錄製到DisplayListRenderer.mWriter中            // mRender為Native中DisplayListRenderer類的例項            mRenderer = nCreateDisplayListRenderer();        } else {            // 直接呼叫OpenGL函式把圖畫到螢幕上            // mRenderer為Native中OpenGLRenderer類的例項            mRenderer = nCreateRenderer();        }        setupFinalizer();    }    //...

4.2 GLES20RenderLayer使用的畫布(離線繪製到FBO Layer)

GLES20RenderLayer.GLES20RenderLayer(w,h,trans)->
 GLES20Canvas.nCreateLayer(w,h,trans,layerInfo)
 GLES20Canvas.GLES20Canvas(int layer, boolean translucent)->
   nCreateLayerRenderer(layer)

/** * An OpenGL ES 2.0 implementation of {@link HardwareLayer}. This * implementation can be used a rendering target. It generates a * {@link Canvas} that can be used to render into an FBO using OpenGL. */class GLES20RenderLayer extends GLES20Layer {    private int mLayerWidth;    private int mLayerHeight;    private final GLES20Canvas mCanvas;    GLES20RenderLayer(int width, int height, boolean isOpaque) {        super(width, height, isOpaque);        int[] layerInfo = new int[2];        // 請求Native LayerRenderer建立一個FBO Layer,以用於離線Render        mLayer = GLES20Canvas.nCreateLayer(width, height, isOpaque, layerInfo);        if (mLayer != 0) {            mLayerWidth = layerInfo[0];            mLayerHeight = layerInfo[1];            // 使用FBO Layer建立一個Native LayerRenderer,然後例項化畫布            mCanvas = new GLES20Canvas(mLayer, !isOpaque);            mFinalizer = new Finalizer(mLayer);        } else {            mCanvas = null;            mFinalizer = null;        }    }    //...}/** * An implementation of Canvas on top of OpenGL ES 2.0. */class GLES20Canvas extends HardwareCanvas {    private final boolean mOpaque;    private int mRenderer;    //...    /**     * Creates a canvas to render directly on screen.     * 建立直接繪製到螢幕上的畫布,而不會錄製到DisplayList中     * 由Gl20Renderer.createCanvas呼叫     */    GLES20Canvas(boolean translucent) {        // 直接呼叫OpenGL函式把圖畫到螢幕上        this(false, translucent);    }    /**     * Creates a canvas to render into an FBO.     * 建立離線繪製到FBO的畫布     */    GLES20Canvas(int layer, boolean translucent) {        mOpaque = !translucent;        // mRenderer為Native中LayerRenderer類的例項        mRenderer = nCreateLayerRenderer(layer);        setupFinalizer();    }        protected GLES20Canvas(boolean record, boolean translucent) {        mOpaque = !translucent;        if (record) {            // 把畫圖命令錄製到DisplayListRenderer.mWriter中            // mRender為Native中DisplayListRenderer類的例項            mRenderer = nCreateDisplayListRenderer();        } else {            // 直接呼叫OpenGL函式把圖畫到螢幕上            // mRenderer為Native中OpenGLRenderer類的例項            mRenderer = nCreateRenderer();        }        setupFinalizer();    }    //...

4.3 GLES20RecordingCanvas使用的畫布 (繪製到DisplayList)

GLES20DisplayList.start->
  GLES20RecordingCanvas.obtain(GLES20DisplayList displayList)-> (static)
     GLES20RecordingCanvas.GLES20RecordingCanvas()->
       GLES20Canvas(true /*record*/, true /*translucent*/)-> 
         nCreateDisplayListRenderer()

/** * An implementation of display list for OpenGL ES 2.0. */class GLES20DisplayList extends DisplayList {    // These lists ensure that any Bitmaps and DisplayLists recorded by a DisplayList are kept    // alive as long as the DisplayList is alive.  The Bitmap and DisplayList lists    // are populated by the GLES20RecordingCanvas during appropriate drawing calls and are    // cleared at the start of a new drawing frame or when the view is detached from the window.    final ArrayList<Bitmap> mBitmaps = new ArrayList<Bitmap>(5);    final ArrayList<DisplayList> mChildDisplayLists = new ArrayList<DisplayList>();    private GLES20RecordingCanvas mCanvas;    // Used for debugging    private final String mName;    // The native display list will be destroyed when this object dies.    // DO NOT overwrite this reference once it is set.    private DisplayListFinalizer mFinalizer;    GLES20DisplayList(String name) {        mName = name;    }    @Override    public HardwareCanvas start() {        if (mCanvas != null) {            throw new IllegalStateException("Recording has already started");        }        mValid = false;        // 使用GLES20DisplayList建立GLES20RecordingCanvas        mCanvas = GLES20RecordingCanvas.obtain(this);        mCanvas.start();        return mCanvas;    }    //...}/** * An implementation of a GL canvas that records drawing operations. * This is intended for use with a DisplayList. This class keeps a list of all the Paint and * Bitmap objects that it draws, preventing the backing memory of Bitmaps from being freed while * the DisplayList is still holding a native reference to the memory. */class GLES20RecordingCanvas extends GLES20Canvas implements Poolable<GLES20RecordingCanvas> {    // The recording canvas pool should be large enough to handle a deeply nested    // view hierarchy because display lists are generated recursively.    private static final int POOL_LIMIT = 25;    private static final Pool<GLES20RecordingCanvas> sPool = Pools.synchronizedPool(            Pools.finitePool(new PoolableManager<GLES20RecordingCanvas>() {                public GLES20RecordingCanvas newInstance() {                    return new GLES20RecordingCanvas();                }                @Override                public void onAcquired(GLES20RecordingCanvas element) {                }                @Override                public void onReleased(GLES20RecordingCanvas element) {                }            }, POOL_LIMIT));    private GLES20DisplayList mDisplayList;    private GLES20RecordingCanvas() {        //例項化DisplayListRender        super(true /*record*/, true /*translucent*/);    }    static GLES20RecordingCanvas obtain(GLES20DisplayList displayList) {        GLES20RecordingCanvas canvas = sPool.acquire();        canvas.mDisplayList = displayList;        return canvas;    }    // ...}/** * An implementation of Canvas on top of OpenGL ES 2.0. */class GLES20Canvas extends HardwareCanvas {    private final boolean mOpaque;    private int mRenderer;    //...    /**     * Creates a canvas to render directly on screen.     * 建立直接繪製到螢幕上的畫布,而不會錄製到DisplayList中     * 由Gl20Renderer.createCanvas呼叫     */    GLES20Canvas(boolean translucent) {        // 直接呼叫OpenGL函式把圖畫到螢幕上        this(false, translucent);    }    /**     * Creates a canvas to render into an FBO.     * 建立離線繪製到FBO的畫布     */    GLES20Canvas(int layer, boolean translucent) {        mOpaque = !translucent;        // mRenderer為Native中LayerRenderer類的例項        mRenderer = nCreateLayerRenderer(layer);        setupFinalizer();    }        protected GLES20Canvas(boolean record, boolean translucent) {        mOpaque = !translucent;        if (record) {            // 把畫圖命令錄製到DisplayListRenderer.mWriter中            // mRender為Native中DisplayListRenderer類的例項            mRenderer = nCreateDisplayListRenderer();        } else {            // 直接呼叫OpenGL函式把圖畫到螢幕上            // mRenderer為Native中OpenGLRenderer類的例項            mRenderer = nCreateRenderer();        }        setupFinalizer();    }    //...

5. 繪製(Render)元素小結

    為了把圖形繪製到螢幕上,必須使用Native Render,其最本質的東東是OpenGL,為了方便管理,其Native Render分為三類,其相關資訊如下表所示:

Native Render類名
OpenGLRenderer
DisplayListRenderer
LayerRenderer
繪製到哪兒?
直接繪製到螢幕上
錄製到SkWriter32
離線繪製到FBO Layer
JNI建立函式
nCreateRenderer
nCreateDisplayListRenderer
nCreateLayerRenderer
由誰管理?
GLES20Canvas
GLES20Canvas
GLES20Canvas
由誰使用?
Gl20Renderer
GLES20DisplayList
GLES20RenderLayer
使用者類別 HardwareRenderer
DisplayList
HardwareLayer

     畫圖五元素間的曖昧關係如下圖所示:



6. 建立視窗(Window)流程

    其基本流程如下所示:

ActivityThread.handleResumeActivity->{  ActivityClientRecord.window = ActivityClientRecord.activity.getWindow();  View decor = ActivityClientRecord.window.getDecorView();               //實際呼叫PhoneWindow.getDecorView();  decor.setVisibility(View.INVISIBLE);  ViewManager wm = Activity.getWindowManager();               //wm是WindowManagerImpl例項  Activity.mDecor = decor;  WindowManager.LayoutParams l = r.window.getAttributes();  l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;  l.softInputMode |= forwardBit;  if (a.mVisibleFromClient) {      a.mWindowAdded = true;      wm.addView(decor, l);--->      //即呼叫WindowManagerImpl.addView,      //把PhoneWindow.mDecor加入WindowManager中  }}WindowManagerImpl.addView(View view, ViewGroup.LayoutParams params)->  WindowManagerGlobal.addView(View view, ViewGroup.LayoutParams params,              Display display, Window parentWindow)->      (root = new ViewRootImpl(view.getContext(), display))  ViewRootImpl.setView(View view, WindowManager.LayoutParams attrs, View panelParentView)->   requestLayout()   mWindowSession.addToDisplay(mWindow,...) --> //to Window Manager Server    Session.addToDisplay(IWindow window, int seq, WindowManager.LayoutParams attrs,              int viewVisibility, int displayId, Rect outContentInsets,              InputChannel outInputChannel)->     WindowManagerService.addWindow(Session session, IWindow client, int seq,              WindowManager.LayoutParams attrs, int viewVisibility, int displayId,              Rect outContentInsets, InputChannel outInputChannel)->       new WindowState(WindowManagerService service, Session s, IWindow c, WindowToken token,             WindowState attachedWindow, int seq, WindowManager.LayoutParams a,             int viewVisibility, final DisplayContent displayContent)        // WindowState例項即為Window Manager中剛建立的視窗  

     在以上過程中,ViewRootImpl為客戶端,通過IWindowSession介面把建立視窗的請求傳送給Server端(Session),然後呼叫WindowManagerService中對應的功能函式。同時把IWindow.Stub (W extends IWindow.Stub)的實現例項傳送給伺服器端,以便WindowMangerService通過IWindow介面向ViewRootImpl傳送命令。其相互關係如下圖所示:



    Activity<-->PhoneWindow<-->ViewRootImpl<-->WindowManagerService

   在以上關係中,WindowManagerService系統中僅一個例項,其它三個例項一一對應,即一個Activity例項有一個唯一的PhoneWindow和ViewRootImpl例項與之一一對應。


7. 硬體繪製(Hardware Render)視窗流程

WMS.performLayoutAndPlaceSurfacesLocked->WMS.performLayoutAndPlaceSurfacesLockedLoop->WMS.performLayoutAndPlaceSurfacesLockedInner->mRelayoutWhileAnimating.get(j).mClient.doneAnimating()->  //即IWindow.doneAnimating()ViewRootImpl.W.doneAnimating()->ViewRootImpl.dispatchDoneAnimating()->ViewRootImpl.handleDispatchDoneAnimating()->ViewRootImpl.scheduleTraversals()->ViewRootImpl.mTraversalRunnable.run()->ViewRootImpl.doTraversal()->ViewRootImpl.performTraversals() ->ViewRootImpl.performDraw()->ViewRootImpl.draw()->  // ViewRootImpl.drawSoftware(..),軟體render,暫且不講,以下為硬體RenderattachInfo.mHardwareRenderer.draw(mView,...)->  // attachInfo.mHardwareRenderer實際為Gl20Renderer例項,  // 在enableHardwareAcceleration中例項化  // Gl20Renderer.createDisplayList: 例項化GLES20DisplayList  // Gl20Renderer.createHardwareLayer(w,h):例項化GLES20RenderLayer  // Gl20Renderer.create:例項化Gl20RendererGlRenderer.draw(View view, View.AttachInfo attachInfo,...)->  // 其mCanvas為GLES20Canvas,其對應的Native Render為OpenGLRenderer  GLES20Canvas.onPreDraw(dirty)  View.getDisplayList(mDisplayList, false)      // 如果mDisplayList為null, 則呼叫      mAttachInfo.mHardwareRenderer.createDisplayList      // 返回的DisplayList為GLES20DisplayList例項      GLES20DisplayList.start()      // 返回GLES20RecordingCanvas例項      //如果mLayerType為LAYER_TYPE_HARDWARE,則呼叫      mAttachInfo.mHardwareRenderer.createHardwareLayer(w,h,..)      //返回GLES20RenderLayer例項到mHardwareLayer中      GLES20RecordingCanvas.drawHardwareLayer(mHardwareLayer,...)    GLES20Canvas.drawDisplayList(displayList,...)  GLES20Canvas.onPostDraw()  EGL10.eglSwapBuffers(sEglDisplay, mEglSurface)







           

給我老師的人工智慧教程打call!http://blog.csdn.net/jiangjunshow

這裡寫圖片描述