Android系统--视图绘制 View Render
发布日期:2021-09-29 04:02:18 浏览次数:25 分类:技术文章

本文共 20757 字,大约阅读时间需要 69 分钟。

分享一下我老师大神的人工智能教程!零基础,通俗易懂!

也欢迎大家转载本篇文章。分享知识,造福人民,实现我们中华民族伟大复兴!

               

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
mBitmaps = new ArrayList
(5);    final ArrayList
mChildDisplayLists = new ArrayList
();    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
{    // 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
sPool = Pools.synchronizedPool(            Pools.finitePool(new PoolableManager
() {                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!

这里写图片描述

转载地址:https://blog.csdn.net/hddghhfd/article/details/84024286 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:snd pcm open打开流程
下一篇:Linux Wireless基础知识

发表评论

最新留言

做的很好,不错不错
[***.243.131.199]2024年04月26日 00时36分11秒

关于作者

    喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!

推荐文章

spring boot 与 Ant Design of Vue 实现修改角色(二十一) 2019-04-27
spring boot 与 Ant Design of Vue 实现删除角色(补二十一) 2019-04-27
spring boot 与 Ant Design of Vue 实现组织管理布局的实现(二十二) 2019-04-27
spring boot 与 Ant Design of Vue 实现左侧组织树(二十三) 2019-04-27
spring boot 与 Ant Design of Vue 实现新增组织(二十四) 2019-04-27
spring boot 与 Ant Design of Vue 实现修改组织(二十五) 2019-04-27
spring boot 与 Ant Design of Vue 实现删除组织(二十六) 2019-04-27
spring boot 与 Ant Design of Vue 实现获取用户列表(二十七) 2019-04-27
Druid连接池实现自定义场景的多数据库的连接 2019-04-27
PL/SQL数据库管理工具的使用 2019-04-27
带你玩转属于自己的spring-boot-starter系列(一) 2019-04-27
带你玩转属于自己自己的spring-boot-starter系列(二) 2019-04-27
基于springboot的ShardingSphere5.X的分库分表的解决方案之关联查询解决方案(三) 2019-04-27
FTP文件管理项目(本地云)项目日报(二) 2019-04-27
FTP文件管理项目(本地云)项目日报(七) 2019-04-27
什么是服务熔断? 2019-04-27
服务器压力过大?CPU打满?我来帮你快速检查Linux服务器性能 2019-04-27
C++面经总结之《Effective C++》(一) 2019-04-27
C++面经总结之《Effective C++》(二) 2019-04-27
这是什么“虎狼之词”啊!!!程序员的健康问题,看一线老中医怎么说!!! 2019-04-27