Surface 总结:绘制流程

2016-8-5 chenhui Surface

Surface 非常复杂,这里就写一个大致流程,详细见图。

简单的说,绘制流程可以简单分为:

  1. 创建 SharedClient( 31 个 SharedBufferStack )
  2. 创建 Layout( 两个 GriphicBuffer )
  3. 创建 SharedBufferServer
  4. 创建 SharedBufferClient
  5. 调用 DecorView 的 measure、layout、draw, 绘制 View 树
  6. 开始绘制(这一步绘制, 是指混合各显示层图像, 最终显示到 FrameBuffer )

SharedClient、Layout、SharedBufferServer、SharedBufferClient 这三个数据结构是绘制的基础。他们的作用是:

  • SharedClient 中的 31 个 SharedBufferStack 用来控制 31 个显示层的读写
  • Layout 描述显示层, 最多 31 个, 其中有两个 GriphicBuffer, 用来保存显示层的图像数据
  • SharedBufferServer 是 SF 内的, 用来读显示层的图像数据
  • SharedBufferClient 是应用程序内的, 用来写显示层的图像数据

更详细的功能介绍,可阅读:Native 层数据结构之间的关系


下面是稍详细版步骤(文尾有更详细的图解)


    应用程序开始

    1. 构造根 View, 并把默认的标题背景添加进去, 注意, 此时没有绘制

    2. 构造 ViewRoot, ViewRoot 的作用是和 WMS 通信

    3. ViewRoot 和 WMS 建立发出请求的连接。WMS 创建 Session, ViewRoot 创建 Surface

    4. ViewRoot 和 WMS 建立接受请求的第二条连接。

        WMS 开始(目的是创建 SharedClient

        4.1. WMS 为这条连接建立 WindowState、SurfaceSession、SurfaceComposerClient

        4.2. WMS 使用 SCC 得到 SurfaceFlinger 的代理对象

        4.3. WMS 使用 SF 的代理对象和 SF 建立用来发送请求的连接

            SF 开始(创建 SharedClient 完成 

            4.3.1. SF 为这条连接创建 Client, Client 又创建一块共享内存

            4.3.2. SF 从共享内存中分配 SharedClient 对象, 他包含了 31 个 SharedBufferStack。

    5. ViewRoot 给自己发送一个 DO_TRAVERSAL 命令, 并开始处理

    6. ViewRoot 请求 WMS 创建一个 Native 层的 Surface 对象。

        WMS 开始(开始创建 Surface 对象和 Layout 对象)

        6.1. WMS 构造 Surface

        构造 Surface 时, 进入 Native 层。

        6.2. WMS 通知 SF 为 Surface 创建显示层。一个 Surface 对应一个显示层。

            SF 开始(创建 Layout 完成)

            6.2.1. SF 创建 Layout、SharedBufferServer, SBS 控制其中一个 SharedBufferStack

            6.2.2. SF 为 Layout 创建 GriphicBuffer, 用作显示层数据的存放

            6.2.3. SF 把 Layout 加入显示层叠层

        6.3. 构造 SurfaceControl

        返回 java 层

        6.4. 把 SurfaceControl 通过 Binder 传递给应用程序。

            应用程序开始(创建 SharedBufferClient 

            6.4.1. 读出 WMS 发过来的 SurfaceControl, 并使用他创建 Surface 对象

            6.4.2. 构造 SharedBufferClient


    此时,客户端的 SharedBufferClient 和 SF 端的 SharedBufferStack、Layout 都已经创建,基础已经打好。

    下面延续 DO_TRVARSAL 命令的处理,开始绘图

    

    7.0. 调用根 View (DecorView) 的 measure 来测量他的大小, 这会导致所有 View 的 measure 被调用

    7.1. 调用根 View 的 layout 来决定他的位置, 这会导致所有 View 的 layout 被调用

    7.2. 根据根 View 的大小创建一个 Canvas 对象

    7.3. 为 GriphicBuffer[2] 两个 GB 对象分配内存, 并把 SBC 和 SBS 的 GriphicBuffer 指向他 

    7.4. 调用根 View 的 draw 来绘制 View 树, 这里通过 SBC 把图像绘制到两个 GB 对象中的一个

    7.5. 通知 SF 开始绘图( 图像数据都已经绘制到显示层, 这里的绘制是混合他们写到 FrameBuffer 上。

        SF 开始(绘图)

        7.5.1. 遍历显示层叠层, 为每一个脏显示层写数据

        7.5.2. 取出两个 GB 对象中存放新图像数据的, 进行图像混合。

        7.5.3. 混合后的数据写到 FrameBuffer。


关于 DecorView 的 measure、layout、draw 这三个方法, 想必大家做自定义 View 的时候都接触过, 这里就不多说了。关于 View 树的绘制,可见 View 系列:View


下为图解大图:




评论:


2018-06-14 22:54
加我QQ,有事找你。627945721

2017-07-21 17:47
想找你合作,我的联系方式186586

28657
chenhui
2017-07-22 01:56
@林:你是?

发表评论:

Copyright ©2015-2016 freehui All rights reserved