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)