android glsurfaceview renderer

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

分类: Android Framework 8208人阅读 评论(4) 收藏 举报

目录(?)[+]

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) 画装饰部分(如:滚动条)


  1. /** 
  2.  * Manually render this view (and all of its children) to the given Canvas. 
  3.  * The view must have already done a full layout before this function is 
  4.  * called.  When implementing a view, implement 
  5.  * {@link #onDraw(android.graphics.Canvas)} instead of overriding this method. 
  6.  * If you do need to override this method, call the superclass version. 
  7.  * 
  8.  * @param canvas The Canvas to which the View is rendered. 
  9.  */  
  10. public void draw(Canvas canvas) {  
  11.     final int privateFlags = mPrivateFlags;  
  12.     final boolean dirtyOpaque = (privateFlags & PFLAG_DIRTY_MASK) == PFLAG_DIRTY_OPAQUE &&  
  13.             (mAttachInfo == null || !mAttachInfo.mIgnoreDirtyState);  
  14.     mPrivateFlags = (privateFlags & ~PFLAG_DIRTY_MASK) | PFLAG_DRAWN;  
  15.   
  16.     /* 
  17.      * Draw traversal performs several drawing steps which must be executed 
  18.      * in the appropriate order: 
  19.      * 
  20.      *      1. Draw the background 
  21.      *      2. If necessary, save the canvas' layers to prepare for fading 
  22.      *      3. Draw view's content 
  23.      *      4. Draw children 
  24.      *      5. If necessary, draw the fading edges and restore layers 
  25.      *      6. Draw decorations (scrollbars for instance) 
  26.      */  
  27.   
  28.     // Step 1, draw the background, if needed  
  29.     int saveCount;  
  30.   
  31.     if (!dirtyOpaque) {  
  32.         final Drawable background = mBackground;  
  33.         if (background != null) {  
  34.             final int scrollX = mScrollX;  
  35.             final int scrollY = mScrollY;  
  36.   
  37.             if (mBackgroundSizeChanged) {  
  38.                 background.setBounds(00,  mRight - mLeft, mBottom - mTop);  
  39.                 mBackgroundSizeChanged = false;  
  40.             }  
  41.   
  42.             if ((scrollX | scrollY) == 0) {  
  43.                 background.draw(canvas);  
  44.             } else {  
  45.                 canvas.translate(scrollX, scrollY);  
  46.                 background.draw(canvas);  
  47.                 canvas.translate(-scrollX, -scrollY);  
  48.             }  
  49.         }  
  50.     }  
  51.   
  52.     // skip step 2 & 5 if possible (common case)  
  53.     final int viewFlags = mViewFlags;  
  54.     boolean horizontalEdges = (viewFlags & FADING_EDGE_HORIZONTAL) != 0;  
  55.     boolean verticalEdges = (viewFlags & FADING_EDGE_VERTICAL) != 0;  
  56.     if (!verticalEdges && !horizontalEdges) {  
  57.         // Step 3, draw the content  
  58.         if (!dirtyOpaque) onDraw(canvas);  
  59.   
  60.         // Step 4, draw the children  
  61.         dispatchDraw(canvas);  
  62.   
  63.         // Step 6, draw decorations (scrollbars)  
  64.         onDrawScrollBars(canvas);  
  65.   
  66.         // we're done...  
  67.         return;  
  68.     }  
  69. }  


2. 家族图谱

2.1 View家族图谱




2.2 Canvas和HardwareRenderer家族图谱




2.3 DisplayList和HardwareLayer家族图谱

2.4 Native OpenGLRenderer家族图谱



DisplayList.replay调用流程如下:

  1. //Java  
  2. GlRenderer.draw((View view, View.AttachInfo attachInfo,...)  
  3. GLES20Canvas.drawDisplayList(DisplayList displayList, Rect dirty, int flags)->  
  4. //JNI  
  5. nDrawDisplayList->  
  6. android_view_GLES20Canvas_drawDisplayList(...,OpenGLRenderer* renderer,   
  7.                                            DisplayList* displayList,...)->  
  8. //Native  
  9. OpenGLRenderer.drawDisplayList(DisplayList* displayList,...)->  
  10. 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,以供后面绘制视图使用。

  1. Activity.attach(Context context, ActivityThread aThread,  
  2.             Instrumentation instr, IBinder token, int ident,  
  3.             Application application, Intent intent, ActivityInfo info,  
  4.             CharSequence title, Activity parent, String id,  
  5.             NonConfigurationInstances lastNonConfigurationInstances,  
  6.             Configuration config)->  
  7.  1) PolicyManager.makeNewWindow(Context context)  
  8.    // 返回PhoneWindow实例并保存在mWindow中  
  9.    {  
  10.     Policy.makeNewWindow(Context context)->  
  11.        //new PhoneWindow(context)  
  12.     PhoneWindow(Context context)  
  13.        //获取LayoutInflater,它可以把Layout XML实例化为对应的View Objects  
  14.    }  
  15.  2) Window.setWindowManager(  
  16.                 (WindowManager)context.getSystemService(Context.WINDOW_SERVICE),  
  17.                 mToken, mComponent.flattenToString(),  
  18.                 (info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0)->  
  19.    {  
  20.     WindowManagerImpl.createLocalWindowManager(Window parentWindow)  
  21.     // 返回WindowManagerImpl实例,并保存在Window.mWindowManager  
  22.    }  
  23.  3)mWindow.setContainer(mParent.getWindow())  
  24.  4)mWindowManager = mWindow.getWindowManager()  
  25.    //返回Window.mWindowManager  
  26.    //即Activity与Window中的mWindowManager为同一个  
  27.    //WindowManagerImpl实例  

2.8 放置窗口内容setContentView

  setContentView的功能是:把Layout XML资源文件实例化为一棵视图树,然后把它加入PhoneWindow.mContentParent中,即成为PhoneWindow.mContentParent的子女。

  1. Activity.setContentView(int layoutResID)->  
  2.   //设置Activity内容  
  3. PhoneWindow.setContentView(int layoutResID)->  
  4. LayoutInflater.inflate(layoutResID, mContentParent)->  
  5.   //把XML资源文件实例化为一棵视图树,并返回视图树的树根(root)   
  6.   //树根为ViewGroup实例  
  7. LayoutInflater.inflate(layoutResID, root, root != null)->  
  8.   //根据资源生成XmlResourceParser  
  9. LayoutInflater.inflate(XmlPullParser parser, ViewGroup root, boolean attachToRoot)->  
  10. ViewGroup.addView(View child, LayoutParams params)->  
  11.   {  
  12.   //把资源文件中的视图树加入PhoneWindow中的mContentParent中  
  13.   View.requestLayout()  
  14.   View.invalidate(true)->  
  15.   addViewInner(child, index, params, false)  
  16.     //它将调用child.requestLayout(),依次递归下去  
  17.   }  
  18.   ViewGroup.invalidateChild(View child, final Rect dirty)->  
  19.   ViewGroup.invalidateChildInParent(final int[] location, final Rect dirty)  
  20.     //更新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()

  1. /** 
  2.  * Hardware renderer using OpenGL ES 2.0. 
  3.  */  
  4. static class Gl20Renderer extends GlRenderer {  
  5.     private GLES20Canvas mGlCanvas;  
  6.     final boolean mTranslucent;  
  7.     //...  
  8.     @Override  
  9.     HardwareCanvas createCanvas() {  
  10.         //创建直接绘制到屏幕上的画布,而不会录制到DisplayList中  
  11.         return mGlCanvas = new GLES20Canvas(mTranslucent);  
  12.     }  
  13.     //...  
  14. }  
  15.   
  16. /** 
  17.  * An implementation of Canvas on top of OpenGL ES 2.0. 
  18.  */  
  19. class GLES20Canvas extends HardwareCanvas {  
  20.   
  21.     private final boolean mOpaque;  
  22.     private int mRenderer;  
  23.   
  24.     //...  
  25.     /** 
  26.      * Creates a canvas to render directly on screen. 
  27.      * 创建直接绘制到屏幕上的画布,而不会录制到DisplayList中 
  28.      * 由Gl20Renderer.createCanvas调用 
  29.      */  
  30.     GLES20Canvas(boolean translucent) {  
  31.         // 直接调用OpenGL函数把图画到屏幕上  
  32.         this(false, translucent);  
  33.     }  
  34.   
  35.     /** 
  36.      * Creates a canvas to render into an FBO. 
  37.      * 创建离线绘制到FBO的画布 
  38.      */  
  39.     GLES20Canvas(int layer, boolean translucent) {  
  40.         mOpaque = !translucent;  
  41.         // mRenderer为Native中LayerRenderer类的实例  
  42.         mRenderer = nCreateLayerRenderer(layer);  
  43.         setupFinalizer();  
  44.     }  
  45.       
  46.     protected GLES20Canvas(boolean record, boolean translucent) {  
  47.         mOpaque = !translucent;  
  48.   
  49.         if (record) {  
  50.             // 把画图命令录制到DisplayListRenderer.mWriter中  
  51.             // mRender为Native中DisplayListRenderer类的实例  
  52.             mRenderer = nCreateDisplayListRenderer();  
  53.         } else {  
  54.             // 直接调用OpenGL函数把图画到屏幕上  
  55.             // mRenderer为Native中OpenGLRenderer类的实例  
  56.             mRenderer = nCreateRenderer();  
  57.         }  
  58.   
  59.         setupFinalizer();  
  60.     }  
  61.     //...  
  62. }    

4.2 GLES20RenderLayer使用的画布(离线绘制到FBO Layer)

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

  1. /** 
  2.  * An OpenGL ES 2.0 implementation of {@link HardwareLayer}. This 
  3.  * implementation can be used a rendering target. It generates a 
  4.  * {@link Canvas} that can be used to render into an FBO using OpenGL. 
  5.  */  
  6. class GLES20RenderLayer extends GLES20Layer {  
  7.     private int mLayerWidth;  
  8.     private int mLayerHeight;  
  9.   
  10.     private final GLES20Canvas mCanvas;  
  11.   
  12.     GLES20RenderLayer(int width, int height, boolean isOpaque) {  
  13.         super(width, height, isOpaque);  
  14.   
  15.         int[] layerInfo = new int[2];  
  16.         // 请求Native LayerRenderer创建一个FBO Layer,以用于离线Render  
  17.         mLayer = GLES20Canvas.nCreateLayer(width, height, isOpaque, layerInfo);  
  18.         if (mLayer != 0) {  
  19.             mLayerWidth = layerInfo[0];  
  20.             mLayerHeight = layerInfo[1];  
  21.   
  22.             // 使用FBO Layer创建一个Native LayerRenderer,然后实例化画布  
  23.             mCanvas = new GLES20Canvas(mLayer, !isOpaque);  
  24.             mFinalizer = new Finalizer(mLayer);  
  25.         } else {  
  26.             mCanvas = null;  
  27.             mFinalizer = null;  
  28.         }  
  29.     }  
  30.     //...  
  31. }  
  32.   
  33. /** 
  34.  * An implementation of Canvas on top of OpenGL ES 2.0. 
  35.  */  
  36. class GLES20Canvas extends HardwareCanvas {  
  37.   
  38.     private final boolean mOpaque;  
  39.     private int mRenderer;  
  40.   
  41.     //...  
  42.     /** 
  43.      * Creates a canvas to render directly on screen. 
  44.      * 创建直接绘制到屏幕上的画布,而不会录制到DisplayList中 
  45.      * 由Gl20Renderer.createCanvas调用 
  46.      */  
  47.     GLES20Canvas(boolean translucent) {  
  48.         // 直接调用OpenGL函数把图画到屏幕上  
  49.         this(false, translucent);  
  50.     }  
  51.   
  52.     /** 
  53.      * Creates a canvas to render into an FBO. 
  54.      * 创建离线绘制到FBO的画布 
  55.      */  
  56.     GLES20Canvas(int layer, boolean translucent) {  
  57.         mOpaque = !translucent;  
  58.         // mRenderer为Native中LayerRenderer类的实例  
  59.         mRenderer = nCreateLayerRenderer(layer);  
  60.         setupFinalizer();  
  61.     }  
  62.       
  63.     protected GLES20Canvas(boolean record, boolean translucent) {  
  64.         mOpaque = !translucent;  
  65.   
  66.         if (record) {  
  67.             // 把画图命令录制到DisplayListRenderer.mWriter中  
  68.             // mRender为Native中DisplayListRenderer类的实例  
  69.             mRenderer = nCreateDisplayListRenderer();  
  70.         } else {  
  71.             // 直接调用OpenGL函数把图画到屏幕上  
  72.             // mRenderer为Native中OpenGLRenderer类的实例  
  73.             mRenderer = nCreateRenderer();  
  74.         }  
  75.   
  76.         setupFinalizer();  
  77.     }  
  78.     //...  
  79. }    

4.3 GLES20RecordingCanvas使用的画布 (绘制到DisplayList)

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

  1. /** 
  2.  * An implementation of display list for OpenGL ES 2.0. 
  3.  */  
  4. class GLES20DisplayList extends DisplayList {  
  5.     // These lists ensure that any Bitmaps and DisplayLists recorded by a DisplayList are kept  
  6.     // alive as long as the DisplayList is alive.  The Bitmap and DisplayList lists  
  7.     // are populated by the GLES20RecordingCanvas during appropriate drawing calls and are  
  8.     // cleared at the start of a new drawing frame or when the view is detached from the window.  
  9.     final ArrayList<Bitmap> mBitmaps = new ArrayList<Bitmap>(5);  
  10.     final ArrayList<DisplayList> mChildDisplayLists = new ArrayList<DisplayList>();  
  11.   
  12.     private GLES20RecordingCanvas mCanvas;  
  13.   
  14.     // Used for debugging  
  15.     private final String mName;  
  16.   
  17.     // The native display list will be destroyed when this object dies.  
  18.     // DO NOT overwrite this reference once it is set.  
  19.     private DisplayListFinalizer mFinalizer;  
  20.   
  21.     GLES20DisplayList(String name) {  
  22.         mName = name;  
  23.     }  
  24.   
  25.     @Override  
  26.     public HardwareCanvas start() {  
  27.         if (mCanvas != null) {  
  28.             throw new IllegalStateException("Recording has already started");  
  29.         }  
  30.   
  31.         mValid = false;  
  32.         // 使用GLES20DisplayList创建GLES20RecordingCanvas  
  33.         mCanvas = GLES20RecordingCanvas.obtain(this);  
  34.         mCanvas.start();  
  35.         return mCanvas;  
  36.     }  
  37.     //...  
  38. }  
  39.   
  40.   
  41. /** 
  42.  * An implementation of a GL canvas that records drawing operations. 
  43.  * This is intended for use with a DisplayList. This class keeps a list of all the Paint and 
  44.  * Bitmap objects that it draws, preventing the backing memory of Bitmaps from being freed while 
  45.  * the DisplayList is still holding a native reference to the memory. 
  46.  */  
  47. class GLES20RecordingCanvas extends GLES20Canvas implements Poolable<GLES20RecordingCanvas> {  
  48.     // The recording canvas pool should be large enough to handle a deeply nested  
  49.     // view hierarchy because display lists are generated recursively.  
  50.     private static final int POOL_LIMIT = 25;  
  51.   
  52.     private static final Pool<GLES20RecordingCanvas> sPool = Pools.synchronizedPool(  
  53.             Pools.finitePool(new PoolableManager<GLES20RecordingCanvas>() {  
  54.                 public GLES20RecordingCanvas newInstance() {  
  55.                     return new GLES20RecordingCanvas();  
  56.                 }  
  57.                 @Override  
  58.                 public void onAcquired(GLES20RecordingCanvas element) {  
  59.                 }  
  60.                 @Override  
  61.                 public void onReleased(GLES20RecordingCanvas element) {  
  62.                 }  
  63.             }, POOL_LIMIT));  
  64.   
  65.     private GLES20DisplayList mDisplayList;  
  66.   
  67.     private GLES20RecordingCanvas() {  
  68.         //实例化DisplayListRender  
  69.         super(true /*record*/true /*translucent*/);  
  70.     }  
  71.   
  72.     static GLES20RecordingCanvas obtain(GLES20DisplayList displayList) {  
  73.         GLES20RecordingCanvas canvas = sPool.acquire();  
  74.         canvas.mDisplayList = displayList;  
  75.         return canvas;  
  76.     }  
  77.     // ...  
  78. }  
  79. /** 
  80.  * An implementation of Canvas on top of OpenGL ES 2.0. 
  81.  */  
  82. class GLES20Canvas extends HardwareCanvas {  
  83.   
  84.     private final boolean mOpaque;  
  85.     private int mRenderer;  
  86.   
  87.     //...  
  88.     /** 
  89.      * Creates a canvas to render directly on screen. 
  90.      * 创建直接绘制到屏幕上的画布,而不会录制到DisplayList中 
  91.      * 由Gl20Renderer.createCanvas调用 
  92.      */  
  93.     GLES20Canvas(boolean translucent) {  
  94.         // 直接调用OpenGL函数把图画到屏幕上  
  95.         this(false, translucent);  
  96.     }  
  97.   
  98.     /** 
  99.      * Creates a canvas to render into an FBO. 
  100.      * 创建离线绘制到FBO的画布 
  101.      */  
  102.     GLES20Canvas(int layer, boolean translucent) {  
  103.         mOpaque = !translucent;  
  104.         // mRenderer为Native中LayerRenderer类的实例  
  105.         mRenderer = nCreateLayerRenderer(layer);  
  106.         setupFinalizer();  
  107.     }  
  108.       
  109.     protected GLES20Canvas(boolean record, boolean translucent) {  
  110.         mOpaque = !translucent;  
  111.   
  112.         if (record) {  
  113.             // 把画图命令录制到DisplayListRenderer.mWriter中  
  114.             // mRender为Native中DisplayListRenderer类的实例  
  115.             mRenderer = nCreateDisplayListRenderer();  
  116.         } else {  
  117.             // 直接调用OpenGL函数把图画到屏幕上  
  118.             // mRenderer为Native中OpenGLRenderer类的实例  
  119.             mRenderer = nCreateRenderer();  
  120.         }  
  121.   
  122.         setupFinalizer();  
  123.     }  
  124.     //...  
  125. }    

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)流程

    其基本流程如下所示:

  1. ActivityThread.handleResumeActivity->  
  2. {  
  3.   ActivityClientRecord.window = ActivityClientRecord.activity.getWindow();  
  4.   View decor = ActivityClientRecord.window.getDecorView();  
  5.                //实际调用PhoneWindow.getDecorView();  
  6.   decor.setVisibility(View.INVISIBLE);  
  7.   
  8.   ViewManager wm = Activity.getWindowManager();  
  9.                //wm是WindowManagerImpl实例  
  10.   Activity.mDecor = decor;  
  11.   
  12.   WindowManager.LayoutParams l = r.window.getAttributes();  
  13.   l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;  
  14.   l.softInputMode |= forwardBit;  
  15.   if (a.mVisibleFromClient) {  
  16.       a.mWindowAdded = true;  
  17.       wm.addView(decor, l);--->  
  18.       //即调用WindowManagerImpl.addView,  
  19.       //把PhoneWindow.mDecor加入WindowManager中  
  20.   }  
  21. }  
  22.   
  23. WindowManagerImpl.addView(View view, ViewGroup.LayoutParams params)->    
  24. WindowManagerGlobal.addView(View view, ViewGroup.LayoutParams params,    
  25.             Display display, Window parentWindow)->    
  26.     (root = new ViewRootImpl(view.getContext(), display))    
  27. ViewRootImpl.setView(View view, WindowManager.LayoutParams attrs, View panelParentView)->    
  28.  requestLayout()    
  29.   
  30.  mWindowSession.addToDisplay(mWindow,...) --> //to Window Manager Server    
  31.   
  32.   Session.addToDisplay(IWindow window, int seq, WindowManager.LayoutParams attrs,    
  33.             int viewVisibility, int displayId, Rect outContentInsets,    
  34.             InputChannel outInputChannel)->    
  35.    WindowManagerService.addWindow(Session session, IWindow client, int seq,    
  36.             WindowManager.LayoutParams attrs, int viewVisibility, int displayId,    
  37.             Rect outContentInsets, InputChannel outInputChannel)->    
  38.      new WindowState(WindowManagerService service, Session s, IWindow c, WindowToken token,    
  39.            WindowState attachedWindow, int seq, WindowManager.LayoutParams a,    
  40.            int viewVisibility, final DisplayContent displayContent)     
  41.      // 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)窗口流程

  1. WMS.performLayoutAndPlaceSurfacesLocked->  
  2. WMS.performLayoutAndPlaceSurfacesLockedLoop->  
  3. WMS.performLayoutAndPlaceSurfacesLockedInner->  
  4. mRelayoutWhileAnimating.get(j).mClient.doneAnimating()->  
  5.   //即IWindow.doneAnimating()  
  6.   
  7. ViewRootImpl.W.doneAnimating()->  
  8. ViewRootImpl.dispatchDoneAnimating()->  
  9. ViewRootImpl.handleDispatchDoneAnimating()->  
  10. ViewRootImpl.scheduleTraversals()->  
  11. ViewRootImpl.mTraversalRunnable.run()->  
  12. ViewRootImpl.doTraversal()->  
  13. ViewRootImpl.performTraversals() ->  
  14. ViewRootImpl.performDraw()->  
  15. ViewRootImpl.draw()->  
  16.   // ViewRootImpl.drawSoftware(..),软件render,暂且不讲,以下为硬件Render  
  17. attachInfo.mHardwareRenderer.draw(mView,...)->  
  18.   // attachInfo.mHardwareRenderer实际为Gl20Renderer实例,  
  19.   // 在enableHardwareAcceleration中实例化  
  20.   // Gl20Renderer.createDisplayList: 实例化GLES20DisplayList  
  21.   // Gl20Renderer.createHardwareLayer(w,h):实例化GLES20RenderLayer  
  22.   // Gl20Renderer.create:实例化Gl20Renderer  
  23.   
  24. GlRenderer.draw(View view, View.AttachInfo attachInfo,...)->  
  25.   // 其mCanvas为GLES20Canvas,其对应的Native Render为OpenGLRenderer  
  26.   GLES20Canvas.onPreDraw(dirty)  
  27.   View.getDisplayList(mDisplayList, false)  
  28.       // 如果mDisplayList为null, 则调用  
  29.       mAttachInfo.mHardwareRenderer.createDisplayList  
  30.       // 返回的DisplayList为GLES20DisplayList实例  
  31.       GLES20DisplayList.start()  
  32.       // 返回GLES20RecordingCanvas实例  
  33.       //如果mLayerType为LAYER_TYPE_HARDWARE,则调用  
  34.       mAttachInfo.mHardwareRenderer.createHardwareLayer(w,h,..)  
  35.       //返回GLES20RenderLayer实例到mHardwareLayer中  
  36.       GLES20RecordingCanvas.drawHardwareLayer(mHardwareLayer,...)  
  37.     
  38.   GLES20Canvas.drawDisplayList(displayList,...)  
  39.   GLES20Canvas.onPostDraw()  
  40.   EGL10.eglSwapBuffers(sEglDisplay, mEglSurface)  







版权声明:本文为博主原创文章,未经博主允许不得转载。

1
0
主题推荐
android
猜你在找
查看评论
4楼 sinat_19635357 2014-10-28 10:34发表 [回复]
看了你画的2.1 View家族图谱,想问下博主有没有搞清楚基类和子类的关系,既然你说的很清楚了view是一个基类,那么箭头的方向是不是搞错了。
3楼 zhu85564043 2014-10-02 17:11发表 [回复]
写的非常好! 看了你的文章收获很多! 感谢博主的分享!
2楼 duanlove 2013-12-15 21:10发表 [回复]
写的挺细的。
1楼 talking 2013-11-23 17:12发表 [回复]
深入浅出,博主博客对我帮组挺大,感谢啊
发表评论
  • 用 户 名:
  • Caidifel
  • 评论内容:
  • 插入代码
  • 个人资料
    • 访问:1532616次
    • 积分:17356
    • 等级:
    • 排名:第246名
    • 原创:229篇
    • 转载:174篇
    • 译文:4篇
    • 评论:280条
  • 最新评论
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值