Android系统--视图绘制 (View Render)

本文详细解析了Android系统的视图绘制机制,包括Canvas、View、Gl20Renderer等核心组件的功能与工作流程,以及FBO、RBO在硬件加速渲染中的作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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调用流程如下:

//Java
GlRenderer.draw((View view, View.AttachInfo attachInfo,...)
GLES20Canvas.drawDisplayList(DisplayList displayList, Rect dirty, int flags)->
//JNI
nDrawDisplayList->
android_view_GLES20Canvas_drawDisplayList(...,OpenGLRenderer* renderer, 
                                           DisplayList* displayList,...)->
//Native
OpenGLRenderer.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)->
  //根据资源生成XmlResourceParser
LayoutInflater.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,暂且不讲,以下为硬件Render
attachInfo.mHardwareRenderer.draw(mView,...)->
  // attachInfo.mHardwareRenderer实际为Gl20Renderer实例,
  // 在enableHardwareAcceleration中实例化
  // Gl20Renderer.createDisplayList: 实例化GLES20DisplayList
  // Gl20Renderer.createHardwareLayer(w,h):实例化GLES20RenderLayer
  // Gl20Renderer.create:实例化Gl20Renderer

GlRenderer.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)







评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值