Beyond Android Views - Window, Surface, Special Views and More Roger [email protected] [email protected] www.twitter.com/roger2yi +易易易 in Google+
May 10, 2015
Beyond Android Views -Window Surface Special Views and
MoreRogeryixxucwebcomroger2yigmailcomwwwtwittercomroger2yi+易旭昕 in Google+
bull 介绍隐藏在用户界面后面的系统底层模块 - Window Surface Canvas 和它们之间的关系与交互
bull 介绍一些特殊 View 的运作原理 - SurfaceView GLSurfaceView TextureView
bull 介绍硬件加速绘图与非硬件加速绘图的差异
Major Contents
Activity and Views
Viewbull This class represents the basic building block f
or user interface componentsbull A View occupies a rectangular area on the scre
en and is responsible for drawing and event handling
bull View is the base class for widgets which are used to create interactive UI components (buttons text fields etc)
Activity
bull 提供了一个与用户进行交互的 GUI 上下文环境(场景)和这个上下文环境的生命周期管理
bull 应用在 ActivityonCreate 中构建用户界面调用 ActivitysetContentView 方法设置界面
Those things behind Activity and Views
System Services
bull Activity Management Servicebull Window Management Servicebull Suface Flingerbull etc
The Startup of an Activity in New Process
bull AMS 接收到请求要在新的进程启动一个 Activitybull AMS 转发请求给 zygote 进程 zygote fork 一个新的进程然后调
用 ActivityThreadmain 方法 ActivityThread 创建 MessageQueue attach 到 AMS 然后进入消息循环这个线程就是主线程也是所谓的 UI 线程
bull 当 ActivityThread attch 到 AMS 后 AMS 发送请求给 ActivityThread 要求启动 Activity ( LAUNCH_ACTIVITY )
bull ActivityThread 在消息循环中启动 Activity ( handleLaunchActivity )
ndash 创建 Activity 后调用 onCreate ( performLaunchActivity )ndash 应用则在 onCreate 中设置 Content View 然后开始跟用户的交互
Window
bull Android 中的 Window 是一个十分容易混淆的概念
bull 它存在应用层面窗口和系统层面窗口的区别
bull 在系统窗口这个层面中存在客户端窗口和服务端窗口的区别
androidviewWindow
bull Abstract base class for a top-level window look and behavior policy
bull It provides standard UI policies such as a background title area default key processing etc
bull 它是通常意义上我们理解的应用层面窗口TopLevelWindow or WindowPolicy 可能是一个更合适的名字
PhoneWindowbull PhoneWindow 是抽象类 Window 的唯一实现bull ActivityThread 在启动一个 Activity 的时候 Activity 会
创建一个 PhoneWindowndash ActivityThreadhandleLaunchActivityndash -gt ActivityThreadperformLaunchActivity ndash -gt Activityattach
bull ActivitysetContentView 实际上是调用 PhoneWindowsetContentView 在该方法的第一次调用时 PhoneWindow 会创建一个 DecorView 作为 Top-Level-Window 的View Hierachy 的根节点
View Hierachy
WindowManagerbull androidviewWindowManager
ndash The interface that apps use to talk to the window managerndash 真正的实现是 WindowManagerImpl 由 PhoneWindow 在 Act
ivity 启动时创建bull ActivityThreadhandleLaunchActivitybull -gt ActivityThreadperformLaunchActivitybull -gt Activityattachbull -gt PhoneWindowsetWindowManager
ndash 当 Activity 启动后 ActivityThread 将 DocorView 添加到 WindowManagerImpl 中
bull ActivityThreadhandleLaunchActivitybull -gt ActivityThreadhandleResumeActivity bull -gt WindowManageraddView
Contbull WindowManagerImpl 负责跟 WMS 通讯
ndash 但实际上每一个 Window 跟 WMS 之间的通讯是由 ViewRootImpl 负责 ViewRootImpl 在 addView 时被创建
ndash 这里的 Window 是指系统层面的 Window 除了之前的 PhoneWindow 外其它如 Dialog Menu 都拥有一个独立的 Window
ndash ViewRootImpl 的每一个实例都跟通过 addView 传进来一个 View Hierachy 的根节点形成一一对应的关系它是真正意义上的 View Hierachy 的根节点
ndash ViewRootImpl 可以看作是系统层面的 Window 在客户端的代理者
ViewRootImpl
bull The top of a view hierarchy implementing the needed protocol between View and the WindowManager
bull This is for the most part an internal implementation detail WindowManagerImpl
Contbull ViewRootImpl 会打开一个 IWindowSession 用于跟 WM
S 对话bull 并通过 IWindowSession 向 WMS 注册一个窗口(实际上
是让 WMS 在服务端创建一个窗口( WindowState )并且把该服务端的窗口跟 ViewRootImpl 传过来的 IWindow 回调接口绑定在一起)
ndash ActivityThreadhandleLaunchActivityndash -gt ActivityThreadhandleResumeActivity ndash -gt WindowManagerImpladdViewndash -gt ViewRootImplsetView
Contbull IWindow
ndash API back to a client window that the Window Manager uses to inform it of interesting things happening
ndash 回调接口用于接收 WMS 关于窗口的消息 mdashmdash 显示 隐藏大小改变焦点变化等等
bull 除了注册窗口外 ViewRootImpl还向 WMS (通过 InputQueue )注册了一个 InputHandler 用于接收输入事件
bull 接收到的输入事件会先放在 UI 线程的消息循环中然后通过 ViewRootImpl 进行分派在它对应的 View Hierachy 上路由
class Window
Activ ityThread
+ handleLaunchActivity() void+ handleResumeActivity() void+ performLaunchActivity() void
Activ ity
+ attach() void+ onCreate() void+ setContentView() void
Window
+ setContentView() void
PhoneWindow PhoneWindowDecorView
ViewRootImpl
+ setView() void+ scheduleTraversals() void+ performTraversals() void+ relayoutWindow() void
ViewGroup
laquointerfaceraquoWindowManager
laquointerfaceraquoViewManager
WindowLocalWindowManager
WindowManagerImpl
+ addView() void
WindowManagerImplCompatModeWrapper
laquointerfaceraquoViewParent
laquointerfaceraquoIWindowSession
+ add() void+ relayout() void
laquointerfaceraquoIWindow
ViewRootImplW IWindowStub
create +mWindow
+mDecor
+mContentParent
+mWindowManager
+mWindowManager
+mRoots
parent
+mView
+sWindowSession
addView
+mWindow
Overall Flowbull ActivityThead 创建 Activitybull Activity 创建 PhoneWindowbull PhoneWindow 创建 DecorView 作为 View Hierachy 的根节点 Client 端设
置的 Content View 会 attach 到 DecorView 下面(间接)bull PhoneWindow 创建 WindowManagerImplbull ActivityThead 把 DecorView 加到 WindowManagerImpl 里面bull WindowManagerImpl 创建 ViewRootImpl 并把 DecorView 传给它bull ViewRootImpl 打开一个 Window Session 跟 WMS 通讯通过 Session 注册
一个窗口最后客户端拥有一个 IWindow 回调接口服务端拥有一个 WindowState 跟该回调接口绑定
View Hierachy Rendering
bull 当 ViewRootImpl 建立跟 WMS 的联系注册了窗口后会发出第一次渲染 View Hierachy 的请求
ndash ViewRootImplsetViewndash ViewRootImplrequestLayoutndash ViewRootImplscheduleTraversals
bull 在第一次的 View Hierachy 的渲染中( ViewRootImplperformTraversals ) ViewRootImpl需要创建 Surface
Contbull 当 Surface 创建后后续的渲染就可以通过获得
Surface 的 Canvas ( SurfacelockCanvas )bull 然后遍历 View Hierachy 把需要绘制的 Views
通过 Canvas 绘制到 Surface 上面( ViewonDraw )
bull 绘制完后需要解锁( SurfaceunlockCanvasPost )让 SurfaceFlinger 可以将 Surface 绘制到屏幕上( Screen Composite )
Surfacebull Handle onto a raw buffer that is being managed by the
screen compositor
bull 每个 Window 都有一个 Surface 由窗口在客户端的代理者 ViewRootImpl 所拥有
bull Surface 在 ViewRootImpl 第一次渲染 View Hierachy 时创建
ndash ViewRootImplperformTraversalsndash ViewRootImplrelayoutWindowndash IWindowSessionrelayout
Contbull ViewRootImpl预先创建一个空的 Surface 对象( Java )在需要
创建真正的 Surface 的时候它调用 IWindowSessionrelayout 这是一个 RPC 最终是 WMS 的 relayoutWindow 被调用
bull WMS 调用 WindowStatecreateSurfaceLocked 创建了一个 Surface对象( Java )并把这个对象的数据传回给客户端而客户端则负责用这些数据填充预先创建的空 Surface 对象( Java )
ndash 实际上 WMS 是请求 SurfaceFlinger 创建真正的 Surface 然后把 Surface相关的信息再传回给客户端
ndash 客户端利用这些信息来创建一个 native Surface 对象然后把它跟 Java Surface 对象绑定在一起
ndash 客户端的 Java Surface 对象以后就可以通过这个 native Surface 对象来操作图像缓存( GraphicsBuffer )图像缓存可以看作是一块共享内存在客户端和 SurfaceFlinger 之间共享
Surface amp Canvasbull Surface ( Java )包含一个 Canvas ( Java )而 Can
vas ( Java )包含一个 native 的 SkCanvas 对象bull 当调用 SurfacelockCanvas 时
ndash 从图像缓存队列中取出一个可用的缓存ndash 把当前的 Posted Buffer 的内容拷贝到新缓存中(除了 Dirty Regi
on 之外的区域)然后将这块缓存加锁并设置为 Locked Buffer
ndash 获得新缓存的内存地址根据内存地址构建一个 SkBitmapndash 把该 SkBitmap 设置到 SkCanvas 里面ndash 返回跟 SkCanvas 对应的 Canvas ( Java )透过 Canvas ( Ja
va )绘制的内容实际上就是绘制到当前的缓存
Cont
bull 当调用 SurfaceunlockCanvasAndPost 的时候ndash 置空 SkCanvas 设置一个空的 SkBitmapndash 将 Locked Buffer 解锁并返回到图像缓存队列里面ndash 将 Posted Buffer 设置为 Locked Buffer 旧的 Poste
d Buffer 就可以被下次取出来使用设置 Locked Buffer 为空
ndash 当 SurfaceFlinger 下次进行 Screen Composite 的时候就会把当前的 Posted Buffer 绘制到屏幕上
SurfaceFlingerbull 应用跟 SF 之间的关系是就像是生产者与消费者的关系bull 应用从 Surface 的 GraphicsBuffer队列的前端取出一个缓存然后进行绘制
bull 绘制完毕后把该缓存放置回队列的后端(生产)bull 而 SF 则不断地将 Surface 的 GraphicsBuffer队列的最后
一个缓存绘制到屏幕上(消费)bull 两者在不同的进程是异步进行的对队列的访问需要进
行同步
class Surface
ViewRootImpl
+ setView() void+ scheduleTraversals() void+ performTraversals() void+ relayoutWindow() void
Surface
+ lockCanvas () Canvas+ unlockCanvasAndPost (Canvas) void
laquointerfaceraquoIWindowSession
+ add() void+ relayout() void
Canvas
+ isHardwareAccelerated() void
laquonativeraquoSurface
laquonativeraquoSurfaceController
SurfaceCompatibleCanvas
laquonativeraquoSkCanvas
WindowManagerServ ice
+ relayoutWindow() void
SurfaceSession
Session
+ relayout() void
WindowState
+ createSurfaceLocked() void
laquonativeraquoSurfaceFlinger
IWindowSessionStub
laquonativeraquoSurfaceComposerCilent
laquonativeraquoBnSurfaceComposer
laquonativeraquoISurfaceComposerClient
laquonativeraquoSurfaceTextureClient
+mSurface
+sWindowSession
+mCanvas
+mSurfaceControl
+mNativeSurface
+mNativeCanvas
+mSurfaceSession
+mService
+mSessions
+mWindowMap
setBitmapDevice
communication+mClient
+mClient
Overall Flowbull ViewRootImpl 第一次渲染 View Hierachy 的时候会创建一个 Surfac
ebull 客户端请求 WMS 创建 Surface 并返回 Surface相关的数据用于构
建一个 native 的 Surface 对象并把它跟 ViewRootImpl 的 Surface( Java )绑定在一起
bull ViewRootImpl 在渲染时先从 Surface获得 Canvasbull 然后把需要绘制的 Views 通过 Canvas 绘制到 Surface 上面bull 绘制完毕后解锁该 Surfacebull SurfaceFlinger 在做 Screen Composite 的时候把解锁后的 Surface
绘制到屏幕上
Those special Views
SurfaceViewbull Provides a dedicated drawing surface embedded
inside of a view hierarchy You can control the format of this surface and if you like its size the SurfaceView takes care of placing the surface at the correct location on the screen
bull The surface is Z ordered so that it is behind the window holding its SurfaceView the SurfaceView punches a hole in its window to allow its surface to be displayed
Contbull Pros
ndash 可以跟 View Hierachy较好地结合在一起可以移动改变大小在上方叠加其它的 View
ndash 在单独的渲染线程进行渲染渲染效率高
ndash SV 的 Surface 和 Window Surface 之间的混合是由系统( SurfaceFlinger )使用硬件加速完成效率高并且不占用应用本身的 UI 线程时间
bull Consndash SurfaceView 的渲染毕竟跟
真正的 View不一样它不是由 ViewRootImpl渲染到当前的 Window Surface 上面
ndash 不能改变 Alpha 不支持跟下方的 View 进行 Alpha 混合
ndash 不能做 Rotation Skew等变换
GLSurfaceViewbull An implementation of SurfaceView that uses the dedicated surfac
e for displaying OpenGL renderingbull A GLSurfaceView provides the following features
ndash Manages a surface which is a special piece of memory that can be composited into the Android view system
ndash Manages an EGL display which enables OpenGL to render into a surfacendash Accepts a user-provided Renderer object that does the actual renderingndash Renders on a dedicated thread to decouple rendering performance from
the UI threadndash Supports both on-demand and continuous renderingndash Optionally wraps traces andor error-checks the renderers OpenGL call
s
Contbull GLSurfaceView 创建一个内部的线程 GLThreadbull 在该线程运行环境下创建一个 EglContextbull 创建一个 EglSurface ( Window Surface )bull 设置之前创建的 EglContext 为当前的 GL Contex
t 并绑定到创建的 EglSurface 上bull 在该线程内就可以通过 EGL 指令在当前的 GL Co
ntext 上绘图
Contbull GLSurfaceView支持两种不同的绘图模式
ndash 连续模式下 GLThread 会不断调用 RendereronDrawFrame 进行绘图
ndash Dirty 模式下 GLThread处于等待状态直到程序发送绘图请求( GLSurfaceViewrequestRender )才调用 RendereronDrawFrame 进行绘图绘制完一帧后重新进入等待状态
bull 在 RendereronDrawFrame 的回调中应用可以通过 SDK提供的 EGL API 绘图也可以转到 native 端使用 NDK提供的 EGL API 绘图
class SurfaceView
SurfaceView
GLSurfaceView GLSurfaceViewRenderer
+ onDrawFrame() void
GLSurfaceViewGLThread
GLSurfaceViewEglHelper
laquointerfaceraquoSurfaceHolder
laquointerfaceraquoSurfaceHolder
Callback
Surface
+ lockCanvas () Canvas+ unlockCanvasAndPost (Canvas) void
laquointerfaceraquoIWindowSession
+ add() void+ relayout() void
SurfaceViewMyWindow
BaseIWindow IWindowStublaquointerfaceraquo
IWindow
+mSurface
+mSession
+mWindow
+mCallbacks
+mSurfaceHolder
+mRenderer
+mGLThread
call
+mRenderer
+mEglHelper
TextureView
bull Since Android 40只在硬件加速环境下起作用bull 具备 SurfaceView 的特性
ndash 但是可以跟其它普通的 View 一样实现 Rotation Screw等变换
ndash 支持 Alpha 可以跟它下方的 View 进行 Alpha 混合
bull 可以基于 TextureView 创建一个 GL Surface 在上面进行 OpenGL渲染
Things become more complicated after Android 30
HW Accelerated 2D Renderingbull Android 30后开始支持硬件加速的 2D 绘图原
有的绘图流程变得更加复杂bull 所谓硬件加速的 2D 绘图就是将 2D Graphics A
PI 的实现改成使用 OpenGL API 来进行绘图bull OpenGL 的绘图模式跟一般的 2D 绘图有很大区
别它需要先将绘图所需的各种素材如贴图多边形顶点阵列 Shader等先加载到当前的 GLContext 然后流水线式的顺序执行绘图指令通过这种方式来充分利用硬件的能力
ViewRootImplbull 当 Actitity 的 View Hierachy 的根节点被添加到 WindowM
anager 的时候( WindowManageraddView ) WindowManager 的实现类 WindowManagerImpl 会创建一个 ViewRootImpl 并把它跟传进来的 View 绑定在一起( ViewRootImplsetView )并且 ViewRootImpl 会根据是否开启硬件加速来决定是否创建一个 HardwareRenderer
bull 在 ViewRootImpl 第一次渲染 View Hierachy 时会创建 Surface 如果开启硬件加速则通过 HardwareRenderer在当前的 UI 线程初始化EGL 绘图环境(类似 GLSurfaceView )
Contbull 在 ViewRootImpl 真正渲染 View Hierachy
时如果开启硬件加速则从 HardwareRenderer获得一个 HardwareCanvas 然后 View Hierachy 的渲染通过 HardwareCanvas 来进行
bull HardwareCanvas 跟一个 native 的 OpenGLRenderer 绑定通过它调用 EGL API 来完成真正的绘制
DisplayList and Hardware Layerbull 为了充分利用硬件加速的能力 Android 30 还引入了 Di
splayList 和 Hardware Layerbull DisplayList 用于记录一系列OpenGL 绘图指令和缓存所需的各种绘图素材( Bitmap Paint Shape Shader )当 View 的内容不发生变化时可以直接使用 DisplayList 进行绘制而不需要重新调用 onDraw
bull Hardware Layer 用于缓存绘制的内存到 Frame Buffer Object 当内容不发生变化时可以直接使用 Layer 进行Layer Composite获得更快的绘图速度
class Hardward2D
DisplayListHardwareCanv as
+ drawDisplayList() void+ drawHardwareLayer() void
Canv as
+ isHardwareAccelerated() voidHardwareLayer
HardwareRenderer
+ initialize() void
HardwareRendererGlRenderer
HardwareRendererGl20Renderer
GLES20Canv as
GLES20RecordingCanv as
GLES20DisplayList
laquonativeraquoDisplayList
laquonativeraquoOpenGLRenderer
laquonativeraquoDisplayListRenderer
ViewAttachInfo
ViewRootImpl
+ setView() void+ scheduleTraversals() void+ performTraversals() void+ relayoutWindow() void
GLES20Layer
GLES20TextureLayer
+mCanvas
+mNativeDisplayList
draw
+mRenderer
+mAttachInfo
+mHardwareRenderer
+mHardwareCanvas
+mResizeBuffer
Reference
bull Android 圖形系統 -- 設計與實做分析
bull How to replace GLSurfaceView with TextureView in Android Ice Cream Sandwich
The End
Thank you for your listeningYours Sincerely Roger
bull 介绍隐藏在用户界面后面的系统底层模块 - Window Surface Canvas 和它们之间的关系与交互
bull 介绍一些特殊 View 的运作原理 - SurfaceView GLSurfaceView TextureView
bull 介绍硬件加速绘图与非硬件加速绘图的差异
Major Contents
Activity and Views
Viewbull This class represents the basic building block f
or user interface componentsbull A View occupies a rectangular area on the scre
en and is responsible for drawing and event handling
bull View is the base class for widgets which are used to create interactive UI components (buttons text fields etc)
Activity
bull 提供了一个与用户进行交互的 GUI 上下文环境(场景)和这个上下文环境的生命周期管理
bull 应用在 ActivityonCreate 中构建用户界面调用 ActivitysetContentView 方法设置界面
Those things behind Activity and Views
System Services
bull Activity Management Servicebull Window Management Servicebull Suface Flingerbull etc
The Startup of an Activity in New Process
bull AMS 接收到请求要在新的进程启动一个 Activitybull AMS 转发请求给 zygote 进程 zygote fork 一个新的进程然后调
用 ActivityThreadmain 方法 ActivityThread 创建 MessageQueue attach 到 AMS 然后进入消息循环这个线程就是主线程也是所谓的 UI 线程
bull 当 ActivityThread attch 到 AMS 后 AMS 发送请求给 ActivityThread 要求启动 Activity ( LAUNCH_ACTIVITY )
bull ActivityThread 在消息循环中启动 Activity ( handleLaunchActivity )
ndash 创建 Activity 后调用 onCreate ( performLaunchActivity )ndash 应用则在 onCreate 中设置 Content View 然后开始跟用户的交互
Window
bull Android 中的 Window 是一个十分容易混淆的概念
bull 它存在应用层面窗口和系统层面窗口的区别
bull 在系统窗口这个层面中存在客户端窗口和服务端窗口的区别
androidviewWindow
bull Abstract base class for a top-level window look and behavior policy
bull It provides standard UI policies such as a background title area default key processing etc
bull 它是通常意义上我们理解的应用层面窗口TopLevelWindow or WindowPolicy 可能是一个更合适的名字
PhoneWindowbull PhoneWindow 是抽象类 Window 的唯一实现bull ActivityThread 在启动一个 Activity 的时候 Activity 会
创建一个 PhoneWindowndash ActivityThreadhandleLaunchActivityndash -gt ActivityThreadperformLaunchActivity ndash -gt Activityattach
bull ActivitysetContentView 实际上是调用 PhoneWindowsetContentView 在该方法的第一次调用时 PhoneWindow 会创建一个 DecorView 作为 Top-Level-Window 的View Hierachy 的根节点
View Hierachy
WindowManagerbull androidviewWindowManager
ndash The interface that apps use to talk to the window managerndash 真正的实现是 WindowManagerImpl 由 PhoneWindow 在 Act
ivity 启动时创建bull ActivityThreadhandleLaunchActivitybull -gt ActivityThreadperformLaunchActivitybull -gt Activityattachbull -gt PhoneWindowsetWindowManager
ndash 当 Activity 启动后 ActivityThread 将 DocorView 添加到 WindowManagerImpl 中
bull ActivityThreadhandleLaunchActivitybull -gt ActivityThreadhandleResumeActivity bull -gt WindowManageraddView
Contbull WindowManagerImpl 负责跟 WMS 通讯
ndash 但实际上每一个 Window 跟 WMS 之间的通讯是由 ViewRootImpl 负责 ViewRootImpl 在 addView 时被创建
ndash 这里的 Window 是指系统层面的 Window 除了之前的 PhoneWindow 外其它如 Dialog Menu 都拥有一个独立的 Window
ndash ViewRootImpl 的每一个实例都跟通过 addView 传进来一个 View Hierachy 的根节点形成一一对应的关系它是真正意义上的 View Hierachy 的根节点
ndash ViewRootImpl 可以看作是系统层面的 Window 在客户端的代理者
ViewRootImpl
bull The top of a view hierarchy implementing the needed protocol between View and the WindowManager
bull This is for the most part an internal implementation detail WindowManagerImpl
Contbull ViewRootImpl 会打开一个 IWindowSession 用于跟 WM
S 对话bull 并通过 IWindowSession 向 WMS 注册一个窗口(实际上
是让 WMS 在服务端创建一个窗口( WindowState )并且把该服务端的窗口跟 ViewRootImpl 传过来的 IWindow 回调接口绑定在一起)
ndash ActivityThreadhandleLaunchActivityndash -gt ActivityThreadhandleResumeActivity ndash -gt WindowManagerImpladdViewndash -gt ViewRootImplsetView
Contbull IWindow
ndash API back to a client window that the Window Manager uses to inform it of interesting things happening
ndash 回调接口用于接收 WMS 关于窗口的消息 mdashmdash 显示 隐藏大小改变焦点变化等等
bull 除了注册窗口外 ViewRootImpl还向 WMS (通过 InputQueue )注册了一个 InputHandler 用于接收输入事件
bull 接收到的输入事件会先放在 UI 线程的消息循环中然后通过 ViewRootImpl 进行分派在它对应的 View Hierachy 上路由
class Window
Activ ityThread
+ handleLaunchActivity() void+ handleResumeActivity() void+ performLaunchActivity() void
Activ ity
+ attach() void+ onCreate() void+ setContentView() void
Window
+ setContentView() void
PhoneWindow PhoneWindowDecorView
ViewRootImpl
+ setView() void+ scheduleTraversals() void+ performTraversals() void+ relayoutWindow() void
ViewGroup
laquointerfaceraquoWindowManager
laquointerfaceraquoViewManager
WindowLocalWindowManager
WindowManagerImpl
+ addView() void
WindowManagerImplCompatModeWrapper
laquointerfaceraquoViewParent
laquointerfaceraquoIWindowSession
+ add() void+ relayout() void
laquointerfaceraquoIWindow
ViewRootImplW IWindowStub
create +mWindow
+mDecor
+mContentParent
+mWindowManager
+mWindowManager
+mRoots
parent
+mView
+sWindowSession
addView
+mWindow
Overall Flowbull ActivityThead 创建 Activitybull Activity 创建 PhoneWindowbull PhoneWindow 创建 DecorView 作为 View Hierachy 的根节点 Client 端设
置的 Content View 会 attach 到 DecorView 下面(间接)bull PhoneWindow 创建 WindowManagerImplbull ActivityThead 把 DecorView 加到 WindowManagerImpl 里面bull WindowManagerImpl 创建 ViewRootImpl 并把 DecorView 传给它bull ViewRootImpl 打开一个 Window Session 跟 WMS 通讯通过 Session 注册
一个窗口最后客户端拥有一个 IWindow 回调接口服务端拥有一个 WindowState 跟该回调接口绑定
View Hierachy Rendering
bull 当 ViewRootImpl 建立跟 WMS 的联系注册了窗口后会发出第一次渲染 View Hierachy 的请求
ndash ViewRootImplsetViewndash ViewRootImplrequestLayoutndash ViewRootImplscheduleTraversals
bull 在第一次的 View Hierachy 的渲染中( ViewRootImplperformTraversals ) ViewRootImpl需要创建 Surface
Contbull 当 Surface 创建后后续的渲染就可以通过获得
Surface 的 Canvas ( SurfacelockCanvas )bull 然后遍历 View Hierachy 把需要绘制的 Views
通过 Canvas 绘制到 Surface 上面( ViewonDraw )
bull 绘制完后需要解锁( SurfaceunlockCanvasPost )让 SurfaceFlinger 可以将 Surface 绘制到屏幕上( Screen Composite )
Surfacebull Handle onto a raw buffer that is being managed by the
screen compositor
bull 每个 Window 都有一个 Surface 由窗口在客户端的代理者 ViewRootImpl 所拥有
bull Surface 在 ViewRootImpl 第一次渲染 View Hierachy 时创建
ndash ViewRootImplperformTraversalsndash ViewRootImplrelayoutWindowndash IWindowSessionrelayout
Contbull ViewRootImpl预先创建一个空的 Surface 对象( Java )在需要
创建真正的 Surface 的时候它调用 IWindowSessionrelayout 这是一个 RPC 最终是 WMS 的 relayoutWindow 被调用
bull WMS 调用 WindowStatecreateSurfaceLocked 创建了一个 Surface对象( Java )并把这个对象的数据传回给客户端而客户端则负责用这些数据填充预先创建的空 Surface 对象( Java )
ndash 实际上 WMS 是请求 SurfaceFlinger 创建真正的 Surface 然后把 Surface相关的信息再传回给客户端
ndash 客户端利用这些信息来创建一个 native Surface 对象然后把它跟 Java Surface 对象绑定在一起
ndash 客户端的 Java Surface 对象以后就可以通过这个 native Surface 对象来操作图像缓存( GraphicsBuffer )图像缓存可以看作是一块共享内存在客户端和 SurfaceFlinger 之间共享
Surface amp Canvasbull Surface ( Java )包含一个 Canvas ( Java )而 Can
vas ( Java )包含一个 native 的 SkCanvas 对象bull 当调用 SurfacelockCanvas 时
ndash 从图像缓存队列中取出一个可用的缓存ndash 把当前的 Posted Buffer 的内容拷贝到新缓存中(除了 Dirty Regi
on 之外的区域)然后将这块缓存加锁并设置为 Locked Buffer
ndash 获得新缓存的内存地址根据内存地址构建一个 SkBitmapndash 把该 SkBitmap 设置到 SkCanvas 里面ndash 返回跟 SkCanvas 对应的 Canvas ( Java )透过 Canvas ( Ja
va )绘制的内容实际上就是绘制到当前的缓存
Cont
bull 当调用 SurfaceunlockCanvasAndPost 的时候ndash 置空 SkCanvas 设置一个空的 SkBitmapndash 将 Locked Buffer 解锁并返回到图像缓存队列里面ndash 将 Posted Buffer 设置为 Locked Buffer 旧的 Poste
d Buffer 就可以被下次取出来使用设置 Locked Buffer 为空
ndash 当 SurfaceFlinger 下次进行 Screen Composite 的时候就会把当前的 Posted Buffer 绘制到屏幕上
SurfaceFlingerbull 应用跟 SF 之间的关系是就像是生产者与消费者的关系bull 应用从 Surface 的 GraphicsBuffer队列的前端取出一个缓存然后进行绘制
bull 绘制完毕后把该缓存放置回队列的后端(生产)bull 而 SF 则不断地将 Surface 的 GraphicsBuffer队列的最后
一个缓存绘制到屏幕上(消费)bull 两者在不同的进程是异步进行的对队列的访问需要进
行同步
class Surface
ViewRootImpl
+ setView() void+ scheduleTraversals() void+ performTraversals() void+ relayoutWindow() void
Surface
+ lockCanvas () Canvas+ unlockCanvasAndPost (Canvas) void
laquointerfaceraquoIWindowSession
+ add() void+ relayout() void
Canvas
+ isHardwareAccelerated() void
laquonativeraquoSurface
laquonativeraquoSurfaceController
SurfaceCompatibleCanvas
laquonativeraquoSkCanvas
WindowManagerServ ice
+ relayoutWindow() void
SurfaceSession
Session
+ relayout() void
WindowState
+ createSurfaceLocked() void
laquonativeraquoSurfaceFlinger
IWindowSessionStub
laquonativeraquoSurfaceComposerCilent
laquonativeraquoBnSurfaceComposer
laquonativeraquoISurfaceComposerClient
laquonativeraquoSurfaceTextureClient
+mSurface
+sWindowSession
+mCanvas
+mSurfaceControl
+mNativeSurface
+mNativeCanvas
+mSurfaceSession
+mService
+mSessions
+mWindowMap
setBitmapDevice
communication+mClient
+mClient
Overall Flowbull ViewRootImpl 第一次渲染 View Hierachy 的时候会创建一个 Surfac
ebull 客户端请求 WMS 创建 Surface 并返回 Surface相关的数据用于构
建一个 native 的 Surface 对象并把它跟 ViewRootImpl 的 Surface( Java )绑定在一起
bull ViewRootImpl 在渲染时先从 Surface获得 Canvasbull 然后把需要绘制的 Views 通过 Canvas 绘制到 Surface 上面bull 绘制完毕后解锁该 Surfacebull SurfaceFlinger 在做 Screen Composite 的时候把解锁后的 Surface
绘制到屏幕上
Those special Views
SurfaceViewbull Provides a dedicated drawing surface embedded
inside of a view hierarchy You can control the format of this surface and if you like its size the SurfaceView takes care of placing the surface at the correct location on the screen
bull The surface is Z ordered so that it is behind the window holding its SurfaceView the SurfaceView punches a hole in its window to allow its surface to be displayed
Contbull Pros
ndash 可以跟 View Hierachy较好地结合在一起可以移动改变大小在上方叠加其它的 View
ndash 在单独的渲染线程进行渲染渲染效率高
ndash SV 的 Surface 和 Window Surface 之间的混合是由系统( SurfaceFlinger )使用硬件加速完成效率高并且不占用应用本身的 UI 线程时间
bull Consndash SurfaceView 的渲染毕竟跟
真正的 View不一样它不是由 ViewRootImpl渲染到当前的 Window Surface 上面
ndash 不能改变 Alpha 不支持跟下方的 View 进行 Alpha 混合
ndash 不能做 Rotation Skew等变换
GLSurfaceViewbull An implementation of SurfaceView that uses the dedicated surfac
e for displaying OpenGL renderingbull A GLSurfaceView provides the following features
ndash Manages a surface which is a special piece of memory that can be composited into the Android view system
ndash Manages an EGL display which enables OpenGL to render into a surfacendash Accepts a user-provided Renderer object that does the actual renderingndash Renders on a dedicated thread to decouple rendering performance from
the UI threadndash Supports both on-demand and continuous renderingndash Optionally wraps traces andor error-checks the renderers OpenGL call
s
Contbull GLSurfaceView 创建一个内部的线程 GLThreadbull 在该线程运行环境下创建一个 EglContextbull 创建一个 EglSurface ( Window Surface )bull 设置之前创建的 EglContext 为当前的 GL Contex
t 并绑定到创建的 EglSurface 上bull 在该线程内就可以通过 EGL 指令在当前的 GL Co
ntext 上绘图
Contbull GLSurfaceView支持两种不同的绘图模式
ndash 连续模式下 GLThread 会不断调用 RendereronDrawFrame 进行绘图
ndash Dirty 模式下 GLThread处于等待状态直到程序发送绘图请求( GLSurfaceViewrequestRender )才调用 RendereronDrawFrame 进行绘图绘制完一帧后重新进入等待状态
bull 在 RendereronDrawFrame 的回调中应用可以通过 SDK提供的 EGL API 绘图也可以转到 native 端使用 NDK提供的 EGL API 绘图
class SurfaceView
SurfaceView
GLSurfaceView GLSurfaceViewRenderer
+ onDrawFrame() void
GLSurfaceViewGLThread
GLSurfaceViewEglHelper
laquointerfaceraquoSurfaceHolder
laquointerfaceraquoSurfaceHolder
Callback
Surface
+ lockCanvas () Canvas+ unlockCanvasAndPost (Canvas) void
laquointerfaceraquoIWindowSession
+ add() void+ relayout() void
SurfaceViewMyWindow
BaseIWindow IWindowStublaquointerfaceraquo
IWindow
+mSurface
+mSession
+mWindow
+mCallbacks
+mSurfaceHolder
+mRenderer
+mGLThread
call
+mRenderer
+mEglHelper
TextureView
bull Since Android 40只在硬件加速环境下起作用bull 具备 SurfaceView 的特性
ndash 但是可以跟其它普通的 View 一样实现 Rotation Screw等变换
ndash 支持 Alpha 可以跟它下方的 View 进行 Alpha 混合
bull 可以基于 TextureView 创建一个 GL Surface 在上面进行 OpenGL渲染
Things become more complicated after Android 30
HW Accelerated 2D Renderingbull Android 30后开始支持硬件加速的 2D 绘图原
有的绘图流程变得更加复杂bull 所谓硬件加速的 2D 绘图就是将 2D Graphics A
PI 的实现改成使用 OpenGL API 来进行绘图bull OpenGL 的绘图模式跟一般的 2D 绘图有很大区
别它需要先将绘图所需的各种素材如贴图多边形顶点阵列 Shader等先加载到当前的 GLContext 然后流水线式的顺序执行绘图指令通过这种方式来充分利用硬件的能力
ViewRootImplbull 当 Actitity 的 View Hierachy 的根节点被添加到 WindowM
anager 的时候( WindowManageraddView ) WindowManager 的实现类 WindowManagerImpl 会创建一个 ViewRootImpl 并把它跟传进来的 View 绑定在一起( ViewRootImplsetView )并且 ViewRootImpl 会根据是否开启硬件加速来决定是否创建一个 HardwareRenderer
bull 在 ViewRootImpl 第一次渲染 View Hierachy 时会创建 Surface 如果开启硬件加速则通过 HardwareRenderer在当前的 UI 线程初始化EGL 绘图环境(类似 GLSurfaceView )
Contbull 在 ViewRootImpl 真正渲染 View Hierachy
时如果开启硬件加速则从 HardwareRenderer获得一个 HardwareCanvas 然后 View Hierachy 的渲染通过 HardwareCanvas 来进行
bull HardwareCanvas 跟一个 native 的 OpenGLRenderer 绑定通过它调用 EGL API 来完成真正的绘制
DisplayList and Hardware Layerbull 为了充分利用硬件加速的能力 Android 30 还引入了 Di
splayList 和 Hardware Layerbull DisplayList 用于记录一系列OpenGL 绘图指令和缓存所需的各种绘图素材( Bitmap Paint Shape Shader )当 View 的内容不发生变化时可以直接使用 DisplayList 进行绘制而不需要重新调用 onDraw
bull Hardware Layer 用于缓存绘制的内存到 Frame Buffer Object 当内容不发生变化时可以直接使用 Layer 进行Layer Composite获得更快的绘图速度
class Hardward2D
DisplayListHardwareCanv as
+ drawDisplayList() void+ drawHardwareLayer() void
Canv as
+ isHardwareAccelerated() voidHardwareLayer
HardwareRenderer
+ initialize() void
HardwareRendererGlRenderer
HardwareRendererGl20Renderer
GLES20Canv as
GLES20RecordingCanv as
GLES20DisplayList
laquonativeraquoDisplayList
laquonativeraquoOpenGLRenderer
laquonativeraquoDisplayListRenderer
ViewAttachInfo
ViewRootImpl
+ setView() void+ scheduleTraversals() void+ performTraversals() void+ relayoutWindow() void
GLES20Layer
GLES20TextureLayer
+mCanvas
+mNativeDisplayList
draw
+mRenderer
+mAttachInfo
+mHardwareRenderer
+mHardwareCanvas
+mResizeBuffer
Reference
bull Android 圖形系統 -- 設計與實做分析
bull How to replace GLSurfaceView with TextureView in Android Ice Cream Sandwich
The End
Thank you for your listeningYours Sincerely Roger
Activity and Views
Viewbull This class represents the basic building block f
or user interface componentsbull A View occupies a rectangular area on the scre
en and is responsible for drawing and event handling
bull View is the base class for widgets which are used to create interactive UI components (buttons text fields etc)
Activity
bull 提供了一个与用户进行交互的 GUI 上下文环境(场景)和这个上下文环境的生命周期管理
bull 应用在 ActivityonCreate 中构建用户界面调用 ActivitysetContentView 方法设置界面
Those things behind Activity and Views
System Services
bull Activity Management Servicebull Window Management Servicebull Suface Flingerbull etc
The Startup of an Activity in New Process
bull AMS 接收到请求要在新的进程启动一个 Activitybull AMS 转发请求给 zygote 进程 zygote fork 一个新的进程然后调
用 ActivityThreadmain 方法 ActivityThread 创建 MessageQueue attach 到 AMS 然后进入消息循环这个线程就是主线程也是所谓的 UI 线程
bull 当 ActivityThread attch 到 AMS 后 AMS 发送请求给 ActivityThread 要求启动 Activity ( LAUNCH_ACTIVITY )
bull ActivityThread 在消息循环中启动 Activity ( handleLaunchActivity )
ndash 创建 Activity 后调用 onCreate ( performLaunchActivity )ndash 应用则在 onCreate 中设置 Content View 然后开始跟用户的交互
Window
bull Android 中的 Window 是一个十分容易混淆的概念
bull 它存在应用层面窗口和系统层面窗口的区别
bull 在系统窗口这个层面中存在客户端窗口和服务端窗口的区别
androidviewWindow
bull Abstract base class for a top-level window look and behavior policy
bull It provides standard UI policies such as a background title area default key processing etc
bull 它是通常意义上我们理解的应用层面窗口TopLevelWindow or WindowPolicy 可能是一个更合适的名字
PhoneWindowbull PhoneWindow 是抽象类 Window 的唯一实现bull ActivityThread 在启动一个 Activity 的时候 Activity 会
创建一个 PhoneWindowndash ActivityThreadhandleLaunchActivityndash -gt ActivityThreadperformLaunchActivity ndash -gt Activityattach
bull ActivitysetContentView 实际上是调用 PhoneWindowsetContentView 在该方法的第一次调用时 PhoneWindow 会创建一个 DecorView 作为 Top-Level-Window 的View Hierachy 的根节点
View Hierachy
WindowManagerbull androidviewWindowManager
ndash The interface that apps use to talk to the window managerndash 真正的实现是 WindowManagerImpl 由 PhoneWindow 在 Act
ivity 启动时创建bull ActivityThreadhandleLaunchActivitybull -gt ActivityThreadperformLaunchActivitybull -gt Activityattachbull -gt PhoneWindowsetWindowManager
ndash 当 Activity 启动后 ActivityThread 将 DocorView 添加到 WindowManagerImpl 中
bull ActivityThreadhandleLaunchActivitybull -gt ActivityThreadhandleResumeActivity bull -gt WindowManageraddView
Contbull WindowManagerImpl 负责跟 WMS 通讯
ndash 但实际上每一个 Window 跟 WMS 之间的通讯是由 ViewRootImpl 负责 ViewRootImpl 在 addView 时被创建
ndash 这里的 Window 是指系统层面的 Window 除了之前的 PhoneWindow 外其它如 Dialog Menu 都拥有一个独立的 Window
ndash ViewRootImpl 的每一个实例都跟通过 addView 传进来一个 View Hierachy 的根节点形成一一对应的关系它是真正意义上的 View Hierachy 的根节点
ndash ViewRootImpl 可以看作是系统层面的 Window 在客户端的代理者
ViewRootImpl
bull The top of a view hierarchy implementing the needed protocol between View and the WindowManager
bull This is for the most part an internal implementation detail WindowManagerImpl
Contbull ViewRootImpl 会打开一个 IWindowSession 用于跟 WM
S 对话bull 并通过 IWindowSession 向 WMS 注册一个窗口(实际上
是让 WMS 在服务端创建一个窗口( WindowState )并且把该服务端的窗口跟 ViewRootImpl 传过来的 IWindow 回调接口绑定在一起)
ndash ActivityThreadhandleLaunchActivityndash -gt ActivityThreadhandleResumeActivity ndash -gt WindowManagerImpladdViewndash -gt ViewRootImplsetView
Contbull IWindow
ndash API back to a client window that the Window Manager uses to inform it of interesting things happening
ndash 回调接口用于接收 WMS 关于窗口的消息 mdashmdash 显示 隐藏大小改变焦点变化等等
bull 除了注册窗口外 ViewRootImpl还向 WMS (通过 InputQueue )注册了一个 InputHandler 用于接收输入事件
bull 接收到的输入事件会先放在 UI 线程的消息循环中然后通过 ViewRootImpl 进行分派在它对应的 View Hierachy 上路由
class Window
Activ ityThread
+ handleLaunchActivity() void+ handleResumeActivity() void+ performLaunchActivity() void
Activ ity
+ attach() void+ onCreate() void+ setContentView() void
Window
+ setContentView() void
PhoneWindow PhoneWindowDecorView
ViewRootImpl
+ setView() void+ scheduleTraversals() void+ performTraversals() void+ relayoutWindow() void
ViewGroup
laquointerfaceraquoWindowManager
laquointerfaceraquoViewManager
WindowLocalWindowManager
WindowManagerImpl
+ addView() void
WindowManagerImplCompatModeWrapper
laquointerfaceraquoViewParent
laquointerfaceraquoIWindowSession
+ add() void+ relayout() void
laquointerfaceraquoIWindow
ViewRootImplW IWindowStub
create +mWindow
+mDecor
+mContentParent
+mWindowManager
+mWindowManager
+mRoots
parent
+mView
+sWindowSession
addView
+mWindow
Overall Flowbull ActivityThead 创建 Activitybull Activity 创建 PhoneWindowbull PhoneWindow 创建 DecorView 作为 View Hierachy 的根节点 Client 端设
置的 Content View 会 attach 到 DecorView 下面(间接)bull PhoneWindow 创建 WindowManagerImplbull ActivityThead 把 DecorView 加到 WindowManagerImpl 里面bull WindowManagerImpl 创建 ViewRootImpl 并把 DecorView 传给它bull ViewRootImpl 打开一个 Window Session 跟 WMS 通讯通过 Session 注册
一个窗口最后客户端拥有一个 IWindow 回调接口服务端拥有一个 WindowState 跟该回调接口绑定
View Hierachy Rendering
bull 当 ViewRootImpl 建立跟 WMS 的联系注册了窗口后会发出第一次渲染 View Hierachy 的请求
ndash ViewRootImplsetViewndash ViewRootImplrequestLayoutndash ViewRootImplscheduleTraversals
bull 在第一次的 View Hierachy 的渲染中( ViewRootImplperformTraversals ) ViewRootImpl需要创建 Surface
Contbull 当 Surface 创建后后续的渲染就可以通过获得
Surface 的 Canvas ( SurfacelockCanvas )bull 然后遍历 View Hierachy 把需要绘制的 Views
通过 Canvas 绘制到 Surface 上面( ViewonDraw )
bull 绘制完后需要解锁( SurfaceunlockCanvasPost )让 SurfaceFlinger 可以将 Surface 绘制到屏幕上( Screen Composite )
Surfacebull Handle onto a raw buffer that is being managed by the
screen compositor
bull 每个 Window 都有一个 Surface 由窗口在客户端的代理者 ViewRootImpl 所拥有
bull Surface 在 ViewRootImpl 第一次渲染 View Hierachy 时创建
ndash ViewRootImplperformTraversalsndash ViewRootImplrelayoutWindowndash IWindowSessionrelayout
Contbull ViewRootImpl预先创建一个空的 Surface 对象( Java )在需要
创建真正的 Surface 的时候它调用 IWindowSessionrelayout 这是一个 RPC 最终是 WMS 的 relayoutWindow 被调用
bull WMS 调用 WindowStatecreateSurfaceLocked 创建了一个 Surface对象( Java )并把这个对象的数据传回给客户端而客户端则负责用这些数据填充预先创建的空 Surface 对象( Java )
ndash 实际上 WMS 是请求 SurfaceFlinger 创建真正的 Surface 然后把 Surface相关的信息再传回给客户端
ndash 客户端利用这些信息来创建一个 native Surface 对象然后把它跟 Java Surface 对象绑定在一起
ndash 客户端的 Java Surface 对象以后就可以通过这个 native Surface 对象来操作图像缓存( GraphicsBuffer )图像缓存可以看作是一块共享内存在客户端和 SurfaceFlinger 之间共享
Surface amp Canvasbull Surface ( Java )包含一个 Canvas ( Java )而 Can
vas ( Java )包含一个 native 的 SkCanvas 对象bull 当调用 SurfacelockCanvas 时
ndash 从图像缓存队列中取出一个可用的缓存ndash 把当前的 Posted Buffer 的内容拷贝到新缓存中(除了 Dirty Regi
on 之外的区域)然后将这块缓存加锁并设置为 Locked Buffer
ndash 获得新缓存的内存地址根据内存地址构建一个 SkBitmapndash 把该 SkBitmap 设置到 SkCanvas 里面ndash 返回跟 SkCanvas 对应的 Canvas ( Java )透过 Canvas ( Ja
va )绘制的内容实际上就是绘制到当前的缓存
Cont
bull 当调用 SurfaceunlockCanvasAndPost 的时候ndash 置空 SkCanvas 设置一个空的 SkBitmapndash 将 Locked Buffer 解锁并返回到图像缓存队列里面ndash 将 Posted Buffer 设置为 Locked Buffer 旧的 Poste
d Buffer 就可以被下次取出来使用设置 Locked Buffer 为空
ndash 当 SurfaceFlinger 下次进行 Screen Composite 的时候就会把当前的 Posted Buffer 绘制到屏幕上
SurfaceFlingerbull 应用跟 SF 之间的关系是就像是生产者与消费者的关系bull 应用从 Surface 的 GraphicsBuffer队列的前端取出一个缓存然后进行绘制
bull 绘制完毕后把该缓存放置回队列的后端(生产)bull 而 SF 则不断地将 Surface 的 GraphicsBuffer队列的最后
一个缓存绘制到屏幕上(消费)bull 两者在不同的进程是异步进行的对队列的访问需要进
行同步
class Surface
ViewRootImpl
+ setView() void+ scheduleTraversals() void+ performTraversals() void+ relayoutWindow() void
Surface
+ lockCanvas () Canvas+ unlockCanvasAndPost (Canvas) void
laquointerfaceraquoIWindowSession
+ add() void+ relayout() void
Canvas
+ isHardwareAccelerated() void
laquonativeraquoSurface
laquonativeraquoSurfaceController
SurfaceCompatibleCanvas
laquonativeraquoSkCanvas
WindowManagerServ ice
+ relayoutWindow() void
SurfaceSession
Session
+ relayout() void
WindowState
+ createSurfaceLocked() void
laquonativeraquoSurfaceFlinger
IWindowSessionStub
laquonativeraquoSurfaceComposerCilent
laquonativeraquoBnSurfaceComposer
laquonativeraquoISurfaceComposerClient
laquonativeraquoSurfaceTextureClient
+mSurface
+sWindowSession
+mCanvas
+mSurfaceControl
+mNativeSurface
+mNativeCanvas
+mSurfaceSession
+mService
+mSessions
+mWindowMap
setBitmapDevice
communication+mClient
+mClient
Overall Flowbull ViewRootImpl 第一次渲染 View Hierachy 的时候会创建一个 Surfac
ebull 客户端请求 WMS 创建 Surface 并返回 Surface相关的数据用于构
建一个 native 的 Surface 对象并把它跟 ViewRootImpl 的 Surface( Java )绑定在一起
bull ViewRootImpl 在渲染时先从 Surface获得 Canvasbull 然后把需要绘制的 Views 通过 Canvas 绘制到 Surface 上面bull 绘制完毕后解锁该 Surfacebull SurfaceFlinger 在做 Screen Composite 的时候把解锁后的 Surface
绘制到屏幕上
Those special Views
SurfaceViewbull Provides a dedicated drawing surface embedded
inside of a view hierarchy You can control the format of this surface and if you like its size the SurfaceView takes care of placing the surface at the correct location on the screen
bull The surface is Z ordered so that it is behind the window holding its SurfaceView the SurfaceView punches a hole in its window to allow its surface to be displayed
Contbull Pros
ndash 可以跟 View Hierachy较好地结合在一起可以移动改变大小在上方叠加其它的 View
ndash 在单独的渲染线程进行渲染渲染效率高
ndash SV 的 Surface 和 Window Surface 之间的混合是由系统( SurfaceFlinger )使用硬件加速完成效率高并且不占用应用本身的 UI 线程时间
bull Consndash SurfaceView 的渲染毕竟跟
真正的 View不一样它不是由 ViewRootImpl渲染到当前的 Window Surface 上面
ndash 不能改变 Alpha 不支持跟下方的 View 进行 Alpha 混合
ndash 不能做 Rotation Skew等变换
GLSurfaceViewbull An implementation of SurfaceView that uses the dedicated surfac
e for displaying OpenGL renderingbull A GLSurfaceView provides the following features
ndash Manages a surface which is a special piece of memory that can be composited into the Android view system
ndash Manages an EGL display which enables OpenGL to render into a surfacendash Accepts a user-provided Renderer object that does the actual renderingndash Renders on a dedicated thread to decouple rendering performance from
the UI threadndash Supports both on-demand and continuous renderingndash Optionally wraps traces andor error-checks the renderers OpenGL call
s
Contbull GLSurfaceView 创建一个内部的线程 GLThreadbull 在该线程运行环境下创建一个 EglContextbull 创建一个 EglSurface ( Window Surface )bull 设置之前创建的 EglContext 为当前的 GL Contex
t 并绑定到创建的 EglSurface 上bull 在该线程内就可以通过 EGL 指令在当前的 GL Co
ntext 上绘图
Contbull GLSurfaceView支持两种不同的绘图模式
ndash 连续模式下 GLThread 会不断调用 RendereronDrawFrame 进行绘图
ndash Dirty 模式下 GLThread处于等待状态直到程序发送绘图请求( GLSurfaceViewrequestRender )才调用 RendereronDrawFrame 进行绘图绘制完一帧后重新进入等待状态
bull 在 RendereronDrawFrame 的回调中应用可以通过 SDK提供的 EGL API 绘图也可以转到 native 端使用 NDK提供的 EGL API 绘图
class SurfaceView
SurfaceView
GLSurfaceView GLSurfaceViewRenderer
+ onDrawFrame() void
GLSurfaceViewGLThread
GLSurfaceViewEglHelper
laquointerfaceraquoSurfaceHolder
laquointerfaceraquoSurfaceHolder
Callback
Surface
+ lockCanvas () Canvas+ unlockCanvasAndPost (Canvas) void
laquointerfaceraquoIWindowSession
+ add() void+ relayout() void
SurfaceViewMyWindow
BaseIWindow IWindowStublaquointerfaceraquo
IWindow
+mSurface
+mSession
+mWindow
+mCallbacks
+mSurfaceHolder
+mRenderer
+mGLThread
call
+mRenderer
+mEglHelper
TextureView
bull Since Android 40只在硬件加速环境下起作用bull 具备 SurfaceView 的特性
ndash 但是可以跟其它普通的 View 一样实现 Rotation Screw等变换
ndash 支持 Alpha 可以跟它下方的 View 进行 Alpha 混合
bull 可以基于 TextureView 创建一个 GL Surface 在上面进行 OpenGL渲染
Things become more complicated after Android 30
HW Accelerated 2D Renderingbull Android 30后开始支持硬件加速的 2D 绘图原
有的绘图流程变得更加复杂bull 所谓硬件加速的 2D 绘图就是将 2D Graphics A
PI 的实现改成使用 OpenGL API 来进行绘图bull OpenGL 的绘图模式跟一般的 2D 绘图有很大区
别它需要先将绘图所需的各种素材如贴图多边形顶点阵列 Shader等先加载到当前的 GLContext 然后流水线式的顺序执行绘图指令通过这种方式来充分利用硬件的能力
ViewRootImplbull 当 Actitity 的 View Hierachy 的根节点被添加到 WindowM
anager 的时候( WindowManageraddView ) WindowManager 的实现类 WindowManagerImpl 会创建一个 ViewRootImpl 并把它跟传进来的 View 绑定在一起( ViewRootImplsetView )并且 ViewRootImpl 会根据是否开启硬件加速来决定是否创建一个 HardwareRenderer
bull 在 ViewRootImpl 第一次渲染 View Hierachy 时会创建 Surface 如果开启硬件加速则通过 HardwareRenderer在当前的 UI 线程初始化EGL 绘图环境(类似 GLSurfaceView )
Contbull 在 ViewRootImpl 真正渲染 View Hierachy
时如果开启硬件加速则从 HardwareRenderer获得一个 HardwareCanvas 然后 View Hierachy 的渲染通过 HardwareCanvas 来进行
bull HardwareCanvas 跟一个 native 的 OpenGLRenderer 绑定通过它调用 EGL API 来完成真正的绘制
DisplayList and Hardware Layerbull 为了充分利用硬件加速的能力 Android 30 还引入了 Di
splayList 和 Hardware Layerbull DisplayList 用于记录一系列OpenGL 绘图指令和缓存所需的各种绘图素材( Bitmap Paint Shape Shader )当 View 的内容不发生变化时可以直接使用 DisplayList 进行绘制而不需要重新调用 onDraw
bull Hardware Layer 用于缓存绘制的内存到 Frame Buffer Object 当内容不发生变化时可以直接使用 Layer 进行Layer Composite获得更快的绘图速度
class Hardward2D
DisplayListHardwareCanv as
+ drawDisplayList() void+ drawHardwareLayer() void
Canv as
+ isHardwareAccelerated() voidHardwareLayer
HardwareRenderer
+ initialize() void
HardwareRendererGlRenderer
HardwareRendererGl20Renderer
GLES20Canv as
GLES20RecordingCanv as
GLES20DisplayList
laquonativeraquoDisplayList
laquonativeraquoOpenGLRenderer
laquonativeraquoDisplayListRenderer
ViewAttachInfo
ViewRootImpl
+ setView() void+ scheduleTraversals() void+ performTraversals() void+ relayoutWindow() void
GLES20Layer
GLES20TextureLayer
+mCanvas
+mNativeDisplayList
draw
+mRenderer
+mAttachInfo
+mHardwareRenderer
+mHardwareCanvas
+mResizeBuffer
Reference
bull Android 圖形系統 -- 設計與實做分析
bull How to replace GLSurfaceView with TextureView in Android Ice Cream Sandwich
The End
Thank you for your listeningYours Sincerely Roger
Viewbull This class represents the basic building block f
or user interface componentsbull A View occupies a rectangular area on the scre
en and is responsible for drawing and event handling
bull View is the base class for widgets which are used to create interactive UI components (buttons text fields etc)
Activity
bull 提供了一个与用户进行交互的 GUI 上下文环境(场景)和这个上下文环境的生命周期管理
bull 应用在 ActivityonCreate 中构建用户界面调用 ActivitysetContentView 方法设置界面
Those things behind Activity and Views
System Services
bull Activity Management Servicebull Window Management Servicebull Suface Flingerbull etc
The Startup of an Activity in New Process
bull AMS 接收到请求要在新的进程启动一个 Activitybull AMS 转发请求给 zygote 进程 zygote fork 一个新的进程然后调
用 ActivityThreadmain 方法 ActivityThread 创建 MessageQueue attach 到 AMS 然后进入消息循环这个线程就是主线程也是所谓的 UI 线程
bull 当 ActivityThread attch 到 AMS 后 AMS 发送请求给 ActivityThread 要求启动 Activity ( LAUNCH_ACTIVITY )
bull ActivityThread 在消息循环中启动 Activity ( handleLaunchActivity )
ndash 创建 Activity 后调用 onCreate ( performLaunchActivity )ndash 应用则在 onCreate 中设置 Content View 然后开始跟用户的交互
Window
bull Android 中的 Window 是一个十分容易混淆的概念
bull 它存在应用层面窗口和系统层面窗口的区别
bull 在系统窗口这个层面中存在客户端窗口和服务端窗口的区别
androidviewWindow
bull Abstract base class for a top-level window look and behavior policy
bull It provides standard UI policies such as a background title area default key processing etc
bull 它是通常意义上我们理解的应用层面窗口TopLevelWindow or WindowPolicy 可能是一个更合适的名字
PhoneWindowbull PhoneWindow 是抽象类 Window 的唯一实现bull ActivityThread 在启动一个 Activity 的时候 Activity 会
创建一个 PhoneWindowndash ActivityThreadhandleLaunchActivityndash -gt ActivityThreadperformLaunchActivity ndash -gt Activityattach
bull ActivitysetContentView 实际上是调用 PhoneWindowsetContentView 在该方法的第一次调用时 PhoneWindow 会创建一个 DecorView 作为 Top-Level-Window 的View Hierachy 的根节点
View Hierachy
WindowManagerbull androidviewWindowManager
ndash The interface that apps use to talk to the window managerndash 真正的实现是 WindowManagerImpl 由 PhoneWindow 在 Act
ivity 启动时创建bull ActivityThreadhandleLaunchActivitybull -gt ActivityThreadperformLaunchActivitybull -gt Activityattachbull -gt PhoneWindowsetWindowManager
ndash 当 Activity 启动后 ActivityThread 将 DocorView 添加到 WindowManagerImpl 中
bull ActivityThreadhandleLaunchActivitybull -gt ActivityThreadhandleResumeActivity bull -gt WindowManageraddView
Contbull WindowManagerImpl 负责跟 WMS 通讯
ndash 但实际上每一个 Window 跟 WMS 之间的通讯是由 ViewRootImpl 负责 ViewRootImpl 在 addView 时被创建
ndash 这里的 Window 是指系统层面的 Window 除了之前的 PhoneWindow 外其它如 Dialog Menu 都拥有一个独立的 Window
ndash ViewRootImpl 的每一个实例都跟通过 addView 传进来一个 View Hierachy 的根节点形成一一对应的关系它是真正意义上的 View Hierachy 的根节点
ndash ViewRootImpl 可以看作是系统层面的 Window 在客户端的代理者
ViewRootImpl
bull The top of a view hierarchy implementing the needed protocol between View and the WindowManager
bull This is for the most part an internal implementation detail WindowManagerImpl
Contbull ViewRootImpl 会打开一个 IWindowSession 用于跟 WM
S 对话bull 并通过 IWindowSession 向 WMS 注册一个窗口(实际上
是让 WMS 在服务端创建一个窗口( WindowState )并且把该服务端的窗口跟 ViewRootImpl 传过来的 IWindow 回调接口绑定在一起)
ndash ActivityThreadhandleLaunchActivityndash -gt ActivityThreadhandleResumeActivity ndash -gt WindowManagerImpladdViewndash -gt ViewRootImplsetView
Contbull IWindow
ndash API back to a client window that the Window Manager uses to inform it of interesting things happening
ndash 回调接口用于接收 WMS 关于窗口的消息 mdashmdash 显示 隐藏大小改变焦点变化等等
bull 除了注册窗口外 ViewRootImpl还向 WMS (通过 InputQueue )注册了一个 InputHandler 用于接收输入事件
bull 接收到的输入事件会先放在 UI 线程的消息循环中然后通过 ViewRootImpl 进行分派在它对应的 View Hierachy 上路由
class Window
Activ ityThread
+ handleLaunchActivity() void+ handleResumeActivity() void+ performLaunchActivity() void
Activ ity
+ attach() void+ onCreate() void+ setContentView() void
Window
+ setContentView() void
PhoneWindow PhoneWindowDecorView
ViewRootImpl
+ setView() void+ scheduleTraversals() void+ performTraversals() void+ relayoutWindow() void
ViewGroup
laquointerfaceraquoWindowManager
laquointerfaceraquoViewManager
WindowLocalWindowManager
WindowManagerImpl
+ addView() void
WindowManagerImplCompatModeWrapper
laquointerfaceraquoViewParent
laquointerfaceraquoIWindowSession
+ add() void+ relayout() void
laquointerfaceraquoIWindow
ViewRootImplW IWindowStub
create +mWindow
+mDecor
+mContentParent
+mWindowManager
+mWindowManager
+mRoots
parent
+mView
+sWindowSession
addView
+mWindow
Overall Flowbull ActivityThead 创建 Activitybull Activity 创建 PhoneWindowbull PhoneWindow 创建 DecorView 作为 View Hierachy 的根节点 Client 端设
置的 Content View 会 attach 到 DecorView 下面(间接)bull PhoneWindow 创建 WindowManagerImplbull ActivityThead 把 DecorView 加到 WindowManagerImpl 里面bull WindowManagerImpl 创建 ViewRootImpl 并把 DecorView 传给它bull ViewRootImpl 打开一个 Window Session 跟 WMS 通讯通过 Session 注册
一个窗口最后客户端拥有一个 IWindow 回调接口服务端拥有一个 WindowState 跟该回调接口绑定
View Hierachy Rendering
bull 当 ViewRootImpl 建立跟 WMS 的联系注册了窗口后会发出第一次渲染 View Hierachy 的请求
ndash ViewRootImplsetViewndash ViewRootImplrequestLayoutndash ViewRootImplscheduleTraversals
bull 在第一次的 View Hierachy 的渲染中( ViewRootImplperformTraversals ) ViewRootImpl需要创建 Surface
Contbull 当 Surface 创建后后续的渲染就可以通过获得
Surface 的 Canvas ( SurfacelockCanvas )bull 然后遍历 View Hierachy 把需要绘制的 Views
通过 Canvas 绘制到 Surface 上面( ViewonDraw )
bull 绘制完后需要解锁( SurfaceunlockCanvasPost )让 SurfaceFlinger 可以将 Surface 绘制到屏幕上( Screen Composite )
Surfacebull Handle onto a raw buffer that is being managed by the
screen compositor
bull 每个 Window 都有一个 Surface 由窗口在客户端的代理者 ViewRootImpl 所拥有
bull Surface 在 ViewRootImpl 第一次渲染 View Hierachy 时创建
ndash ViewRootImplperformTraversalsndash ViewRootImplrelayoutWindowndash IWindowSessionrelayout
Contbull ViewRootImpl预先创建一个空的 Surface 对象( Java )在需要
创建真正的 Surface 的时候它调用 IWindowSessionrelayout 这是一个 RPC 最终是 WMS 的 relayoutWindow 被调用
bull WMS 调用 WindowStatecreateSurfaceLocked 创建了一个 Surface对象( Java )并把这个对象的数据传回给客户端而客户端则负责用这些数据填充预先创建的空 Surface 对象( Java )
ndash 实际上 WMS 是请求 SurfaceFlinger 创建真正的 Surface 然后把 Surface相关的信息再传回给客户端
ndash 客户端利用这些信息来创建一个 native Surface 对象然后把它跟 Java Surface 对象绑定在一起
ndash 客户端的 Java Surface 对象以后就可以通过这个 native Surface 对象来操作图像缓存( GraphicsBuffer )图像缓存可以看作是一块共享内存在客户端和 SurfaceFlinger 之间共享
Surface amp Canvasbull Surface ( Java )包含一个 Canvas ( Java )而 Can
vas ( Java )包含一个 native 的 SkCanvas 对象bull 当调用 SurfacelockCanvas 时
ndash 从图像缓存队列中取出一个可用的缓存ndash 把当前的 Posted Buffer 的内容拷贝到新缓存中(除了 Dirty Regi
on 之外的区域)然后将这块缓存加锁并设置为 Locked Buffer
ndash 获得新缓存的内存地址根据内存地址构建一个 SkBitmapndash 把该 SkBitmap 设置到 SkCanvas 里面ndash 返回跟 SkCanvas 对应的 Canvas ( Java )透过 Canvas ( Ja
va )绘制的内容实际上就是绘制到当前的缓存
Cont
bull 当调用 SurfaceunlockCanvasAndPost 的时候ndash 置空 SkCanvas 设置一个空的 SkBitmapndash 将 Locked Buffer 解锁并返回到图像缓存队列里面ndash 将 Posted Buffer 设置为 Locked Buffer 旧的 Poste
d Buffer 就可以被下次取出来使用设置 Locked Buffer 为空
ndash 当 SurfaceFlinger 下次进行 Screen Composite 的时候就会把当前的 Posted Buffer 绘制到屏幕上
SurfaceFlingerbull 应用跟 SF 之间的关系是就像是生产者与消费者的关系bull 应用从 Surface 的 GraphicsBuffer队列的前端取出一个缓存然后进行绘制
bull 绘制完毕后把该缓存放置回队列的后端(生产)bull 而 SF 则不断地将 Surface 的 GraphicsBuffer队列的最后
一个缓存绘制到屏幕上(消费)bull 两者在不同的进程是异步进行的对队列的访问需要进
行同步
class Surface
ViewRootImpl
+ setView() void+ scheduleTraversals() void+ performTraversals() void+ relayoutWindow() void
Surface
+ lockCanvas () Canvas+ unlockCanvasAndPost (Canvas) void
laquointerfaceraquoIWindowSession
+ add() void+ relayout() void
Canvas
+ isHardwareAccelerated() void
laquonativeraquoSurface
laquonativeraquoSurfaceController
SurfaceCompatibleCanvas
laquonativeraquoSkCanvas
WindowManagerServ ice
+ relayoutWindow() void
SurfaceSession
Session
+ relayout() void
WindowState
+ createSurfaceLocked() void
laquonativeraquoSurfaceFlinger
IWindowSessionStub
laquonativeraquoSurfaceComposerCilent
laquonativeraquoBnSurfaceComposer
laquonativeraquoISurfaceComposerClient
laquonativeraquoSurfaceTextureClient
+mSurface
+sWindowSession
+mCanvas
+mSurfaceControl
+mNativeSurface
+mNativeCanvas
+mSurfaceSession
+mService
+mSessions
+mWindowMap
setBitmapDevice
communication+mClient
+mClient
Overall Flowbull ViewRootImpl 第一次渲染 View Hierachy 的时候会创建一个 Surfac
ebull 客户端请求 WMS 创建 Surface 并返回 Surface相关的数据用于构
建一个 native 的 Surface 对象并把它跟 ViewRootImpl 的 Surface( Java )绑定在一起
bull ViewRootImpl 在渲染时先从 Surface获得 Canvasbull 然后把需要绘制的 Views 通过 Canvas 绘制到 Surface 上面bull 绘制完毕后解锁该 Surfacebull SurfaceFlinger 在做 Screen Composite 的时候把解锁后的 Surface
绘制到屏幕上
Those special Views
SurfaceViewbull Provides a dedicated drawing surface embedded
inside of a view hierarchy You can control the format of this surface and if you like its size the SurfaceView takes care of placing the surface at the correct location on the screen
bull The surface is Z ordered so that it is behind the window holding its SurfaceView the SurfaceView punches a hole in its window to allow its surface to be displayed
Contbull Pros
ndash 可以跟 View Hierachy较好地结合在一起可以移动改变大小在上方叠加其它的 View
ndash 在单独的渲染线程进行渲染渲染效率高
ndash SV 的 Surface 和 Window Surface 之间的混合是由系统( SurfaceFlinger )使用硬件加速完成效率高并且不占用应用本身的 UI 线程时间
bull Consndash SurfaceView 的渲染毕竟跟
真正的 View不一样它不是由 ViewRootImpl渲染到当前的 Window Surface 上面
ndash 不能改变 Alpha 不支持跟下方的 View 进行 Alpha 混合
ndash 不能做 Rotation Skew等变换
GLSurfaceViewbull An implementation of SurfaceView that uses the dedicated surfac
e for displaying OpenGL renderingbull A GLSurfaceView provides the following features
ndash Manages a surface which is a special piece of memory that can be composited into the Android view system
ndash Manages an EGL display which enables OpenGL to render into a surfacendash Accepts a user-provided Renderer object that does the actual renderingndash Renders on a dedicated thread to decouple rendering performance from
the UI threadndash Supports both on-demand and continuous renderingndash Optionally wraps traces andor error-checks the renderers OpenGL call
s
Contbull GLSurfaceView 创建一个内部的线程 GLThreadbull 在该线程运行环境下创建一个 EglContextbull 创建一个 EglSurface ( Window Surface )bull 设置之前创建的 EglContext 为当前的 GL Contex
t 并绑定到创建的 EglSurface 上bull 在该线程内就可以通过 EGL 指令在当前的 GL Co
ntext 上绘图
Contbull GLSurfaceView支持两种不同的绘图模式
ndash 连续模式下 GLThread 会不断调用 RendereronDrawFrame 进行绘图
ndash Dirty 模式下 GLThread处于等待状态直到程序发送绘图请求( GLSurfaceViewrequestRender )才调用 RendereronDrawFrame 进行绘图绘制完一帧后重新进入等待状态
bull 在 RendereronDrawFrame 的回调中应用可以通过 SDK提供的 EGL API 绘图也可以转到 native 端使用 NDK提供的 EGL API 绘图
class SurfaceView
SurfaceView
GLSurfaceView GLSurfaceViewRenderer
+ onDrawFrame() void
GLSurfaceViewGLThread
GLSurfaceViewEglHelper
laquointerfaceraquoSurfaceHolder
laquointerfaceraquoSurfaceHolder
Callback
Surface
+ lockCanvas () Canvas+ unlockCanvasAndPost (Canvas) void
laquointerfaceraquoIWindowSession
+ add() void+ relayout() void
SurfaceViewMyWindow
BaseIWindow IWindowStublaquointerfaceraquo
IWindow
+mSurface
+mSession
+mWindow
+mCallbacks
+mSurfaceHolder
+mRenderer
+mGLThread
call
+mRenderer
+mEglHelper
TextureView
bull Since Android 40只在硬件加速环境下起作用bull 具备 SurfaceView 的特性
ndash 但是可以跟其它普通的 View 一样实现 Rotation Screw等变换
ndash 支持 Alpha 可以跟它下方的 View 进行 Alpha 混合
bull 可以基于 TextureView 创建一个 GL Surface 在上面进行 OpenGL渲染
Things become more complicated after Android 30
HW Accelerated 2D Renderingbull Android 30后开始支持硬件加速的 2D 绘图原
有的绘图流程变得更加复杂bull 所谓硬件加速的 2D 绘图就是将 2D Graphics A
PI 的实现改成使用 OpenGL API 来进行绘图bull OpenGL 的绘图模式跟一般的 2D 绘图有很大区
别它需要先将绘图所需的各种素材如贴图多边形顶点阵列 Shader等先加载到当前的 GLContext 然后流水线式的顺序执行绘图指令通过这种方式来充分利用硬件的能力
ViewRootImplbull 当 Actitity 的 View Hierachy 的根节点被添加到 WindowM
anager 的时候( WindowManageraddView ) WindowManager 的实现类 WindowManagerImpl 会创建一个 ViewRootImpl 并把它跟传进来的 View 绑定在一起( ViewRootImplsetView )并且 ViewRootImpl 会根据是否开启硬件加速来决定是否创建一个 HardwareRenderer
bull 在 ViewRootImpl 第一次渲染 View Hierachy 时会创建 Surface 如果开启硬件加速则通过 HardwareRenderer在当前的 UI 线程初始化EGL 绘图环境(类似 GLSurfaceView )
Contbull 在 ViewRootImpl 真正渲染 View Hierachy
时如果开启硬件加速则从 HardwareRenderer获得一个 HardwareCanvas 然后 View Hierachy 的渲染通过 HardwareCanvas 来进行
bull HardwareCanvas 跟一个 native 的 OpenGLRenderer 绑定通过它调用 EGL API 来完成真正的绘制
DisplayList and Hardware Layerbull 为了充分利用硬件加速的能力 Android 30 还引入了 Di
splayList 和 Hardware Layerbull DisplayList 用于记录一系列OpenGL 绘图指令和缓存所需的各种绘图素材( Bitmap Paint Shape Shader )当 View 的内容不发生变化时可以直接使用 DisplayList 进行绘制而不需要重新调用 onDraw
bull Hardware Layer 用于缓存绘制的内存到 Frame Buffer Object 当内容不发生变化时可以直接使用 Layer 进行Layer Composite获得更快的绘图速度
class Hardward2D
DisplayListHardwareCanv as
+ drawDisplayList() void+ drawHardwareLayer() void
Canv as
+ isHardwareAccelerated() voidHardwareLayer
HardwareRenderer
+ initialize() void
HardwareRendererGlRenderer
HardwareRendererGl20Renderer
GLES20Canv as
GLES20RecordingCanv as
GLES20DisplayList
laquonativeraquoDisplayList
laquonativeraquoOpenGLRenderer
laquonativeraquoDisplayListRenderer
ViewAttachInfo
ViewRootImpl
+ setView() void+ scheduleTraversals() void+ performTraversals() void+ relayoutWindow() void
GLES20Layer
GLES20TextureLayer
+mCanvas
+mNativeDisplayList
draw
+mRenderer
+mAttachInfo
+mHardwareRenderer
+mHardwareCanvas
+mResizeBuffer
Reference
bull Android 圖形系統 -- 設計與實做分析
bull How to replace GLSurfaceView with TextureView in Android Ice Cream Sandwich
The End
Thank you for your listeningYours Sincerely Roger
Activity
bull 提供了一个与用户进行交互的 GUI 上下文环境(场景)和这个上下文环境的生命周期管理
bull 应用在 ActivityonCreate 中构建用户界面调用 ActivitysetContentView 方法设置界面
Those things behind Activity and Views
System Services
bull Activity Management Servicebull Window Management Servicebull Suface Flingerbull etc
The Startup of an Activity in New Process
bull AMS 接收到请求要在新的进程启动一个 Activitybull AMS 转发请求给 zygote 进程 zygote fork 一个新的进程然后调
用 ActivityThreadmain 方法 ActivityThread 创建 MessageQueue attach 到 AMS 然后进入消息循环这个线程就是主线程也是所谓的 UI 线程
bull 当 ActivityThread attch 到 AMS 后 AMS 发送请求给 ActivityThread 要求启动 Activity ( LAUNCH_ACTIVITY )
bull ActivityThread 在消息循环中启动 Activity ( handleLaunchActivity )
ndash 创建 Activity 后调用 onCreate ( performLaunchActivity )ndash 应用则在 onCreate 中设置 Content View 然后开始跟用户的交互
Window
bull Android 中的 Window 是一个十分容易混淆的概念
bull 它存在应用层面窗口和系统层面窗口的区别
bull 在系统窗口这个层面中存在客户端窗口和服务端窗口的区别
androidviewWindow
bull Abstract base class for a top-level window look and behavior policy
bull It provides standard UI policies such as a background title area default key processing etc
bull 它是通常意义上我们理解的应用层面窗口TopLevelWindow or WindowPolicy 可能是一个更合适的名字
PhoneWindowbull PhoneWindow 是抽象类 Window 的唯一实现bull ActivityThread 在启动一个 Activity 的时候 Activity 会
创建一个 PhoneWindowndash ActivityThreadhandleLaunchActivityndash -gt ActivityThreadperformLaunchActivity ndash -gt Activityattach
bull ActivitysetContentView 实际上是调用 PhoneWindowsetContentView 在该方法的第一次调用时 PhoneWindow 会创建一个 DecorView 作为 Top-Level-Window 的View Hierachy 的根节点
View Hierachy
WindowManagerbull androidviewWindowManager
ndash The interface that apps use to talk to the window managerndash 真正的实现是 WindowManagerImpl 由 PhoneWindow 在 Act
ivity 启动时创建bull ActivityThreadhandleLaunchActivitybull -gt ActivityThreadperformLaunchActivitybull -gt Activityattachbull -gt PhoneWindowsetWindowManager
ndash 当 Activity 启动后 ActivityThread 将 DocorView 添加到 WindowManagerImpl 中
bull ActivityThreadhandleLaunchActivitybull -gt ActivityThreadhandleResumeActivity bull -gt WindowManageraddView
Contbull WindowManagerImpl 负责跟 WMS 通讯
ndash 但实际上每一个 Window 跟 WMS 之间的通讯是由 ViewRootImpl 负责 ViewRootImpl 在 addView 时被创建
ndash 这里的 Window 是指系统层面的 Window 除了之前的 PhoneWindow 外其它如 Dialog Menu 都拥有一个独立的 Window
ndash ViewRootImpl 的每一个实例都跟通过 addView 传进来一个 View Hierachy 的根节点形成一一对应的关系它是真正意义上的 View Hierachy 的根节点
ndash ViewRootImpl 可以看作是系统层面的 Window 在客户端的代理者
ViewRootImpl
bull The top of a view hierarchy implementing the needed protocol between View and the WindowManager
bull This is for the most part an internal implementation detail WindowManagerImpl
Contbull ViewRootImpl 会打开一个 IWindowSession 用于跟 WM
S 对话bull 并通过 IWindowSession 向 WMS 注册一个窗口(实际上
是让 WMS 在服务端创建一个窗口( WindowState )并且把该服务端的窗口跟 ViewRootImpl 传过来的 IWindow 回调接口绑定在一起)
ndash ActivityThreadhandleLaunchActivityndash -gt ActivityThreadhandleResumeActivity ndash -gt WindowManagerImpladdViewndash -gt ViewRootImplsetView
Contbull IWindow
ndash API back to a client window that the Window Manager uses to inform it of interesting things happening
ndash 回调接口用于接收 WMS 关于窗口的消息 mdashmdash 显示 隐藏大小改变焦点变化等等
bull 除了注册窗口外 ViewRootImpl还向 WMS (通过 InputQueue )注册了一个 InputHandler 用于接收输入事件
bull 接收到的输入事件会先放在 UI 线程的消息循环中然后通过 ViewRootImpl 进行分派在它对应的 View Hierachy 上路由
class Window
Activ ityThread
+ handleLaunchActivity() void+ handleResumeActivity() void+ performLaunchActivity() void
Activ ity
+ attach() void+ onCreate() void+ setContentView() void
Window
+ setContentView() void
PhoneWindow PhoneWindowDecorView
ViewRootImpl
+ setView() void+ scheduleTraversals() void+ performTraversals() void+ relayoutWindow() void
ViewGroup
laquointerfaceraquoWindowManager
laquointerfaceraquoViewManager
WindowLocalWindowManager
WindowManagerImpl
+ addView() void
WindowManagerImplCompatModeWrapper
laquointerfaceraquoViewParent
laquointerfaceraquoIWindowSession
+ add() void+ relayout() void
laquointerfaceraquoIWindow
ViewRootImplW IWindowStub
create +mWindow
+mDecor
+mContentParent
+mWindowManager
+mWindowManager
+mRoots
parent
+mView
+sWindowSession
addView
+mWindow
Overall Flowbull ActivityThead 创建 Activitybull Activity 创建 PhoneWindowbull PhoneWindow 创建 DecorView 作为 View Hierachy 的根节点 Client 端设
置的 Content View 会 attach 到 DecorView 下面(间接)bull PhoneWindow 创建 WindowManagerImplbull ActivityThead 把 DecorView 加到 WindowManagerImpl 里面bull WindowManagerImpl 创建 ViewRootImpl 并把 DecorView 传给它bull ViewRootImpl 打开一个 Window Session 跟 WMS 通讯通过 Session 注册
一个窗口最后客户端拥有一个 IWindow 回调接口服务端拥有一个 WindowState 跟该回调接口绑定
View Hierachy Rendering
bull 当 ViewRootImpl 建立跟 WMS 的联系注册了窗口后会发出第一次渲染 View Hierachy 的请求
ndash ViewRootImplsetViewndash ViewRootImplrequestLayoutndash ViewRootImplscheduleTraversals
bull 在第一次的 View Hierachy 的渲染中( ViewRootImplperformTraversals ) ViewRootImpl需要创建 Surface
Contbull 当 Surface 创建后后续的渲染就可以通过获得
Surface 的 Canvas ( SurfacelockCanvas )bull 然后遍历 View Hierachy 把需要绘制的 Views
通过 Canvas 绘制到 Surface 上面( ViewonDraw )
bull 绘制完后需要解锁( SurfaceunlockCanvasPost )让 SurfaceFlinger 可以将 Surface 绘制到屏幕上( Screen Composite )
Surfacebull Handle onto a raw buffer that is being managed by the
screen compositor
bull 每个 Window 都有一个 Surface 由窗口在客户端的代理者 ViewRootImpl 所拥有
bull Surface 在 ViewRootImpl 第一次渲染 View Hierachy 时创建
ndash ViewRootImplperformTraversalsndash ViewRootImplrelayoutWindowndash IWindowSessionrelayout
Contbull ViewRootImpl预先创建一个空的 Surface 对象( Java )在需要
创建真正的 Surface 的时候它调用 IWindowSessionrelayout 这是一个 RPC 最终是 WMS 的 relayoutWindow 被调用
bull WMS 调用 WindowStatecreateSurfaceLocked 创建了一个 Surface对象( Java )并把这个对象的数据传回给客户端而客户端则负责用这些数据填充预先创建的空 Surface 对象( Java )
ndash 实际上 WMS 是请求 SurfaceFlinger 创建真正的 Surface 然后把 Surface相关的信息再传回给客户端
ndash 客户端利用这些信息来创建一个 native Surface 对象然后把它跟 Java Surface 对象绑定在一起
ndash 客户端的 Java Surface 对象以后就可以通过这个 native Surface 对象来操作图像缓存( GraphicsBuffer )图像缓存可以看作是一块共享内存在客户端和 SurfaceFlinger 之间共享
Surface amp Canvasbull Surface ( Java )包含一个 Canvas ( Java )而 Can
vas ( Java )包含一个 native 的 SkCanvas 对象bull 当调用 SurfacelockCanvas 时
ndash 从图像缓存队列中取出一个可用的缓存ndash 把当前的 Posted Buffer 的内容拷贝到新缓存中(除了 Dirty Regi
on 之外的区域)然后将这块缓存加锁并设置为 Locked Buffer
ndash 获得新缓存的内存地址根据内存地址构建一个 SkBitmapndash 把该 SkBitmap 设置到 SkCanvas 里面ndash 返回跟 SkCanvas 对应的 Canvas ( Java )透过 Canvas ( Ja
va )绘制的内容实际上就是绘制到当前的缓存
Cont
bull 当调用 SurfaceunlockCanvasAndPost 的时候ndash 置空 SkCanvas 设置一个空的 SkBitmapndash 将 Locked Buffer 解锁并返回到图像缓存队列里面ndash 将 Posted Buffer 设置为 Locked Buffer 旧的 Poste
d Buffer 就可以被下次取出来使用设置 Locked Buffer 为空
ndash 当 SurfaceFlinger 下次进行 Screen Composite 的时候就会把当前的 Posted Buffer 绘制到屏幕上
SurfaceFlingerbull 应用跟 SF 之间的关系是就像是生产者与消费者的关系bull 应用从 Surface 的 GraphicsBuffer队列的前端取出一个缓存然后进行绘制
bull 绘制完毕后把该缓存放置回队列的后端(生产)bull 而 SF 则不断地将 Surface 的 GraphicsBuffer队列的最后
一个缓存绘制到屏幕上(消费)bull 两者在不同的进程是异步进行的对队列的访问需要进
行同步
class Surface
ViewRootImpl
+ setView() void+ scheduleTraversals() void+ performTraversals() void+ relayoutWindow() void
Surface
+ lockCanvas () Canvas+ unlockCanvasAndPost (Canvas) void
laquointerfaceraquoIWindowSession
+ add() void+ relayout() void
Canvas
+ isHardwareAccelerated() void
laquonativeraquoSurface
laquonativeraquoSurfaceController
SurfaceCompatibleCanvas
laquonativeraquoSkCanvas
WindowManagerServ ice
+ relayoutWindow() void
SurfaceSession
Session
+ relayout() void
WindowState
+ createSurfaceLocked() void
laquonativeraquoSurfaceFlinger
IWindowSessionStub
laquonativeraquoSurfaceComposerCilent
laquonativeraquoBnSurfaceComposer
laquonativeraquoISurfaceComposerClient
laquonativeraquoSurfaceTextureClient
+mSurface
+sWindowSession
+mCanvas
+mSurfaceControl
+mNativeSurface
+mNativeCanvas
+mSurfaceSession
+mService
+mSessions
+mWindowMap
setBitmapDevice
communication+mClient
+mClient
Overall Flowbull ViewRootImpl 第一次渲染 View Hierachy 的时候会创建一个 Surfac
ebull 客户端请求 WMS 创建 Surface 并返回 Surface相关的数据用于构
建一个 native 的 Surface 对象并把它跟 ViewRootImpl 的 Surface( Java )绑定在一起
bull ViewRootImpl 在渲染时先从 Surface获得 Canvasbull 然后把需要绘制的 Views 通过 Canvas 绘制到 Surface 上面bull 绘制完毕后解锁该 Surfacebull SurfaceFlinger 在做 Screen Composite 的时候把解锁后的 Surface
绘制到屏幕上
Those special Views
SurfaceViewbull Provides a dedicated drawing surface embedded
inside of a view hierarchy You can control the format of this surface and if you like its size the SurfaceView takes care of placing the surface at the correct location on the screen
bull The surface is Z ordered so that it is behind the window holding its SurfaceView the SurfaceView punches a hole in its window to allow its surface to be displayed
Contbull Pros
ndash 可以跟 View Hierachy较好地结合在一起可以移动改变大小在上方叠加其它的 View
ndash 在单独的渲染线程进行渲染渲染效率高
ndash SV 的 Surface 和 Window Surface 之间的混合是由系统( SurfaceFlinger )使用硬件加速完成效率高并且不占用应用本身的 UI 线程时间
bull Consndash SurfaceView 的渲染毕竟跟
真正的 View不一样它不是由 ViewRootImpl渲染到当前的 Window Surface 上面
ndash 不能改变 Alpha 不支持跟下方的 View 进行 Alpha 混合
ndash 不能做 Rotation Skew等变换
GLSurfaceViewbull An implementation of SurfaceView that uses the dedicated surfac
e for displaying OpenGL renderingbull A GLSurfaceView provides the following features
ndash Manages a surface which is a special piece of memory that can be composited into the Android view system
ndash Manages an EGL display which enables OpenGL to render into a surfacendash Accepts a user-provided Renderer object that does the actual renderingndash Renders on a dedicated thread to decouple rendering performance from
the UI threadndash Supports both on-demand and continuous renderingndash Optionally wraps traces andor error-checks the renderers OpenGL call
s
Contbull GLSurfaceView 创建一个内部的线程 GLThreadbull 在该线程运行环境下创建一个 EglContextbull 创建一个 EglSurface ( Window Surface )bull 设置之前创建的 EglContext 为当前的 GL Contex
t 并绑定到创建的 EglSurface 上bull 在该线程内就可以通过 EGL 指令在当前的 GL Co
ntext 上绘图
Contbull GLSurfaceView支持两种不同的绘图模式
ndash 连续模式下 GLThread 会不断调用 RendereronDrawFrame 进行绘图
ndash Dirty 模式下 GLThread处于等待状态直到程序发送绘图请求( GLSurfaceViewrequestRender )才调用 RendereronDrawFrame 进行绘图绘制完一帧后重新进入等待状态
bull 在 RendereronDrawFrame 的回调中应用可以通过 SDK提供的 EGL API 绘图也可以转到 native 端使用 NDK提供的 EGL API 绘图
class SurfaceView
SurfaceView
GLSurfaceView GLSurfaceViewRenderer
+ onDrawFrame() void
GLSurfaceViewGLThread
GLSurfaceViewEglHelper
laquointerfaceraquoSurfaceHolder
laquointerfaceraquoSurfaceHolder
Callback
Surface
+ lockCanvas () Canvas+ unlockCanvasAndPost (Canvas) void
laquointerfaceraquoIWindowSession
+ add() void+ relayout() void
SurfaceViewMyWindow
BaseIWindow IWindowStublaquointerfaceraquo
IWindow
+mSurface
+mSession
+mWindow
+mCallbacks
+mSurfaceHolder
+mRenderer
+mGLThread
call
+mRenderer
+mEglHelper
TextureView
bull Since Android 40只在硬件加速环境下起作用bull 具备 SurfaceView 的特性
ndash 但是可以跟其它普通的 View 一样实现 Rotation Screw等变换
ndash 支持 Alpha 可以跟它下方的 View 进行 Alpha 混合
bull 可以基于 TextureView 创建一个 GL Surface 在上面进行 OpenGL渲染
Things become more complicated after Android 30
HW Accelerated 2D Renderingbull Android 30后开始支持硬件加速的 2D 绘图原
有的绘图流程变得更加复杂bull 所谓硬件加速的 2D 绘图就是将 2D Graphics A
PI 的实现改成使用 OpenGL API 来进行绘图bull OpenGL 的绘图模式跟一般的 2D 绘图有很大区
别它需要先将绘图所需的各种素材如贴图多边形顶点阵列 Shader等先加载到当前的 GLContext 然后流水线式的顺序执行绘图指令通过这种方式来充分利用硬件的能力
ViewRootImplbull 当 Actitity 的 View Hierachy 的根节点被添加到 WindowM
anager 的时候( WindowManageraddView ) WindowManager 的实现类 WindowManagerImpl 会创建一个 ViewRootImpl 并把它跟传进来的 View 绑定在一起( ViewRootImplsetView )并且 ViewRootImpl 会根据是否开启硬件加速来决定是否创建一个 HardwareRenderer
bull 在 ViewRootImpl 第一次渲染 View Hierachy 时会创建 Surface 如果开启硬件加速则通过 HardwareRenderer在当前的 UI 线程初始化EGL 绘图环境(类似 GLSurfaceView )
Contbull 在 ViewRootImpl 真正渲染 View Hierachy
时如果开启硬件加速则从 HardwareRenderer获得一个 HardwareCanvas 然后 View Hierachy 的渲染通过 HardwareCanvas 来进行
bull HardwareCanvas 跟一个 native 的 OpenGLRenderer 绑定通过它调用 EGL API 来完成真正的绘制
DisplayList and Hardware Layerbull 为了充分利用硬件加速的能力 Android 30 还引入了 Di
splayList 和 Hardware Layerbull DisplayList 用于记录一系列OpenGL 绘图指令和缓存所需的各种绘图素材( Bitmap Paint Shape Shader )当 View 的内容不发生变化时可以直接使用 DisplayList 进行绘制而不需要重新调用 onDraw
bull Hardware Layer 用于缓存绘制的内存到 Frame Buffer Object 当内容不发生变化时可以直接使用 Layer 进行Layer Composite获得更快的绘图速度
class Hardward2D
DisplayListHardwareCanv as
+ drawDisplayList() void+ drawHardwareLayer() void
Canv as
+ isHardwareAccelerated() voidHardwareLayer
HardwareRenderer
+ initialize() void
HardwareRendererGlRenderer
HardwareRendererGl20Renderer
GLES20Canv as
GLES20RecordingCanv as
GLES20DisplayList
laquonativeraquoDisplayList
laquonativeraquoOpenGLRenderer
laquonativeraquoDisplayListRenderer
ViewAttachInfo
ViewRootImpl
+ setView() void+ scheduleTraversals() void+ performTraversals() void+ relayoutWindow() void
GLES20Layer
GLES20TextureLayer
+mCanvas
+mNativeDisplayList
draw
+mRenderer
+mAttachInfo
+mHardwareRenderer
+mHardwareCanvas
+mResizeBuffer
Reference
bull Android 圖形系統 -- 設計與實做分析
bull How to replace GLSurfaceView with TextureView in Android Ice Cream Sandwich
The End
Thank you for your listeningYours Sincerely Roger
Those things behind Activity and Views
System Services
bull Activity Management Servicebull Window Management Servicebull Suface Flingerbull etc
The Startup of an Activity in New Process
bull AMS 接收到请求要在新的进程启动一个 Activitybull AMS 转发请求给 zygote 进程 zygote fork 一个新的进程然后调
用 ActivityThreadmain 方法 ActivityThread 创建 MessageQueue attach 到 AMS 然后进入消息循环这个线程就是主线程也是所谓的 UI 线程
bull 当 ActivityThread attch 到 AMS 后 AMS 发送请求给 ActivityThread 要求启动 Activity ( LAUNCH_ACTIVITY )
bull ActivityThread 在消息循环中启动 Activity ( handleLaunchActivity )
ndash 创建 Activity 后调用 onCreate ( performLaunchActivity )ndash 应用则在 onCreate 中设置 Content View 然后开始跟用户的交互
Window
bull Android 中的 Window 是一个十分容易混淆的概念
bull 它存在应用层面窗口和系统层面窗口的区别
bull 在系统窗口这个层面中存在客户端窗口和服务端窗口的区别
androidviewWindow
bull Abstract base class for a top-level window look and behavior policy
bull It provides standard UI policies such as a background title area default key processing etc
bull 它是通常意义上我们理解的应用层面窗口TopLevelWindow or WindowPolicy 可能是一个更合适的名字
PhoneWindowbull PhoneWindow 是抽象类 Window 的唯一实现bull ActivityThread 在启动一个 Activity 的时候 Activity 会
创建一个 PhoneWindowndash ActivityThreadhandleLaunchActivityndash -gt ActivityThreadperformLaunchActivity ndash -gt Activityattach
bull ActivitysetContentView 实际上是调用 PhoneWindowsetContentView 在该方法的第一次调用时 PhoneWindow 会创建一个 DecorView 作为 Top-Level-Window 的View Hierachy 的根节点
View Hierachy
WindowManagerbull androidviewWindowManager
ndash The interface that apps use to talk to the window managerndash 真正的实现是 WindowManagerImpl 由 PhoneWindow 在 Act
ivity 启动时创建bull ActivityThreadhandleLaunchActivitybull -gt ActivityThreadperformLaunchActivitybull -gt Activityattachbull -gt PhoneWindowsetWindowManager
ndash 当 Activity 启动后 ActivityThread 将 DocorView 添加到 WindowManagerImpl 中
bull ActivityThreadhandleLaunchActivitybull -gt ActivityThreadhandleResumeActivity bull -gt WindowManageraddView
Contbull WindowManagerImpl 负责跟 WMS 通讯
ndash 但实际上每一个 Window 跟 WMS 之间的通讯是由 ViewRootImpl 负责 ViewRootImpl 在 addView 时被创建
ndash 这里的 Window 是指系统层面的 Window 除了之前的 PhoneWindow 外其它如 Dialog Menu 都拥有一个独立的 Window
ndash ViewRootImpl 的每一个实例都跟通过 addView 传进来一个 View Hierachy 的根节点形成一一对应的关系它是真正意义上的 View Hierachy 的根节点
ndash ViewRootImpl 可以看作是系统层面的 Window 在客户端的代理者
ViewRootImpl
bull The top of a view hierarchy implementing the needed protocol between View and the WindowManager
bull This is for the most part an internal implementation detail WindowManagerImpl
Contbull ViewRootImpl 会打开一个 IWindowSession 用于跟 WM
S 对话bull 并通过 IWindowSession 向 WMS 注册一个窗口(实际上
是让 WMS 在服务端创建一个窗口( WindowState )并且把该服务端的窗口跟 ViewRootImpl 传过来的 IWindow 回调接口绑定在一起)
ndash ActivityThreadhandleLaunchActivityndash -gt ActivityThreadhandleResumeActivity ndash -gt WindowManagerImpladdViewndash -gt ViewRootImplsetView
Contbull IWindow
ndash API back to a client window that the Window Manager uses to inform it of interesting things happening
ndash 回调接口用于接收 WMS 关于窗口的消息 mdashmdash 显示 隐藏大小改变焦点变化等等
bull 除了注册窗口外 ViewRootImpl还向 WMS (通过 InputQueue )注册了一个 InputHandler 用于接收输入事件
bull 接收到的输入事件会先放在 UI 线程的消息循环中然后通过 ViewRootImpl 进行分派在它对应的 View Hierachy 上路由
class Window
Activ ityThread
+ handleLaunchActivity() void+ handleResumeActivity() void+ performLaunchActivity() void
Activ ity
+ attach() void+ onCreate() void+ setContentView() void
Window
+ setContentView() void
PhoneWindow PhoneWindowDecorView
ViewRootImpl
+ setView() void+ scheduleTraversals() void+ performTraversals() void+ relayoutWindow() void
ViewGroup
laquointerfaceraquoWindowManager
laquointerfaceraquoViewManager
WindowLocalWindowManager
WindowManagerImpl
+ addView() void
WindowManagerImplCompatModeWrapper
laquointerfaceraquoViewParent
laquointerfaceraquoIWindowSession
+ add() void+ relayout() void
laquointerfaceraquoIWindow
ViewRootImplW IWindowStub
create +mWindow
+mDecor
+mContentParent
+mWindowManager
+mWindowManager
+mRoots
parent
+mView
+sWindowSession
addView
+mWindow
Overall Flowbull ActivityThead 创建 Activitybull Activity 创建 PhoneWindowbull PhoneWindow 创建 DecorView 作为 View Hierachy 的根节点 Client 端设
置的 Content View 会 attach 到 DecorView 下面(间接)bull PhoneWindow 创建 WindowManagerImplbull ActivityThead 把 DecorView 加到 WindowManagerImpl 里面bull WindowManagerImpl 创建 ViewRootImpl 并把 DecorView 传给它bull ViewRootImpl 打开一个 Window Session 跟 WMS 通讯通过 Session 注册
一个窗口最后客户端拥有一个 IWindow 回调接口服务端拥有一个 WindowState 跟该回调接口绑定
View Hierachy Rendering
bull 当 ViewRootImpl 建立跟 WMS 的联系注册了窗口后会发出第一次渲染 View Hierachy 的请求
ndash ViewRootImplsetViewndash ViewRootImplrequestLayoutndash ViewRootImplscheduleTraversals
bull 在第一次的 View Hierachy 的渲染中( ViewRootImplperformTraversals ) ViewRootImpl需要创建 Surface
Contbull 当 Surface 创建后后续的渲染就可以通过获得
Surface 的 Canvas ( SurfacelockCanvas )bull 然后遍历 View Hierachy 把需要绘制的 Views
通过 Canvas 绘制到 Surface 上面( ViewonDraw )
bull 绘制完后需要解锁( SurfaceunlockCanvasPost )让 SurfaceFlinger 可以将 Surface 绘制到屏幕上( Screen Composite )
Surfacebull Handle onto a raw buffer that is being managed by the
screen compositor
bull 每个 Window 都有一个 Surface 由窗口在客户端的代理者 ViewRootImpl 所拥有
bull Surface 在 ViewRootImpl 第一次渲染 View Hierachy 时创建
ndash ViewRootImplperformTraversalsndash ViewRootImplrelayoutWindowndash IWindowSessionrelayout
Contbull ViewRootImpl预先创建一个空的 Surface 对象( Java )在需要
创建真正的 Surface 的时候它调用 IWindowSessionrelayout 这是一个 RPC 最终是 WMS 的 relayoutWindow 被调用
bull WMS 调用 WindowStatecreateSurfaceLocked 创建了一个 Surface对象( Java )并把这个对象的数据传回给客户端而客户端则负责用这些数据填充预先创建的空 Surface 对象( Java )
ndash 实际上 WMS 是请求 SurfaceFlinger 创建真正的 Surface 然后把 Surface相关的信息再传回给客户端
ndash 客户端利用这些信息来创建一个 native Surface 对象然后把它跟 Java Surface 对象绑定在一起
ndash 客户端的 Java Surface 对象以后就可以通过这个 native Surface 对象来操作图像缓存( GraphicsBuffer )图像缓存可以看作是一块共享内存在客户端和 SurfaceFlinger 之间共享
Surface amp Canvasbull Surface ( Java )包含一个 Canvas ( Java )而 Can
vas ( Java )包含一个 native 的 SkCanvas 对象bull 当调用 SurfacelockCanvas 时
ndash 从图像缓存队列中取出一个可用的缓存ndash 把当前的 Posted Buffer 的内容拷贝到新缓存中(除了 Dirty Regi
on 之外的区域)然后将这块缓存加锁并设置为 Locked Buffer
ndash 获得新缓存的内存地址根据内存地址构建一个 SkBitmapndash 把该 SkBitmap 设置到 SkCanvas 里面ndash 返回跟 SkCanvas 对应的 Canvas ( Java )透过 Canvas ( Ja
va )绘制的内容实际上就是绘制到当前的缓存
Cont
bull 当调用 SurfaceunlockCanvasAndPost 的时候ndash 置空 SkCanvas 设置一个空的 SkBitmapndash 将 Locked Buffer 解锁并返回到图像缓存队列里面ndash 将 Posted Buffer 设置为 Locked Buffer 旧的 Poste
d Buffer 就可以被下次取出来使用设置 Locked Buffer 为空
ndash 当 SurfaceFlinger 下次进行 Screen Composite 的时候就会把当前的 Posted Buffer 绘制到屏幕上
SurfaceFlingerbull 应用跟 SF 之间的关系是就像是生产者与消费者的关系bull 应用从 Surface 的 GraphicsBuffer队列的前端取出一个缓存然后进行绘制
bull 绘制完毕后把该缓存放置回队列的后端(生产)bull 而 SF 则不断地将 Surface 的 GraphicsBuffer队列的最后
一个缓存绘制到屏幕上(消费)bull 两者在不同的进程是异步进行的对队列的访问需要进
行同步
class Surface
ViewRootImpl
+ setView() void+ scheduleTraversals() void+ performTraversals() void+ relayoutWindow() void
Surface
+ lockCanvas () Canvas+ unlockCanvasAndPost (Canvas) void
laquointerfaceraquoIWindowSession
+ add() void+ relayout() void
Canvas
+ isHardwareAccelerated() void
laquonativeraquoSurface
laquonativeraquoSurfaceController
SurfaceCompatibleCanvas
laquonativeraquoSkCanvas
WindowManagerServ ice
+ relayoutWindow() void
SurfaceSession
Session
+ relayout() void
WindowState
+ createSurfaceLocked() void
laquonativeraquoSurfaceFlinger
IWindowSessionStub
laquonativeraquoSurfaceComposerCilent
laquonativeraquoBnSurfaceComposer
laquonativeraquoISurfaceComposerClient
laquonativeraquoSurfaceTextureClient
+mSurface
+sWindowSession
+mCanvas
+mSurfaceControl
+mNativeSurface
+mNativeCanvas
+mSurfaceSession
+mService
+mSessions
+mWindowMap
setBitmapDevice
communication+mClient
+mClient
Overall Flowbull ViewRootImpl 第一次渲染 View Hierachy 的时候会创建一个 Surfac
ebull 客户端请求 WMS 创建 Surface 并返回 Surface相关的数据用于构
建一个 native 的 Surface 对象并把它跟 ViewRootImpl 的 Surface( Java )绑定在一起
bull ViewRootImpl 在渲染时先从 Surface获得 Canvasbull 然后把需要绘制的 Views 通过 Canvas 绘制到 Surface 上面bull 绘制完毕后解锁该 Surfacebull SurfaceFlinger 在做 Screen Composite 的时候把解锁后的 Surface
绘制到屏幕上
Those special Views
SurfaceViewbull Provides a dedicated drawing surface embedded
inside of a view hierarchy You can control the format of this surface and if you like its size the SurfaceView takes care of placing the surface at the correct location on the screen
bull The surface is Z ordered so that it is behind the window holding its SurfaceView the SurfaceView punches a hole in its window to allow its surface to be displayed
Contbull Pros
ndash 可以跟 View Hierachy较好地结合在一起可以移动改变大小在上方叠加其它的 View
ndash 在单独的渲染线程进行渲染渲染效率高
ndash SV 的 Surface 和 Window Surface 之间的混合是由系统( SurfaceFlinger )使用硬件加速完成效率高并且不占用应用本身的 UI 线程时间
bull Consndash SurfaceView 的渲染毕竟跟
真正的 View不一样它不是由 ViewRootImpl渲染到当前的 Window Surface 上面
ndash 不能改变 Alpha 不支持跟下方的 View 进行 Alpha 混合
ndash 不能做 Rotation Skew等变换
GLSurfaceViewbull An implementation of SurfaceView that uses the dedicated surfac
e for displaying OpenGL renderingbull A GLSurfaceView provides the following features
ndash Manages a surface which is a special piece of memory that can be composited into the Android view system
ndash Manages an EGL display which enables OpenGL to render into a surfacendash Accepts a user-provided Renderer object that does the actual renderingndash Renders on a dedicated thread to decouple rendering performance from
the UI threadndash Supports both on-demand and continuous renderingndash Optionally wraps traces andor error-checks the renderers OpenGL call
s
Contbull GLSurfaceView 创建一个内部的线程 GLThreadbull 在该线程运行环境下创建一个 EglContextbull 创建一个 EglSurface ( Window Surface )bull 设置之前创建的 EglContext 为当前的 GL Contex
t 并绑定到创建的 EglSurface 上bull 在该线程内就可以通过 EGL 指令在当前的 GL Co
ntext 上绘图
Contbull GLSurfaceView支持两种不同的绘图模式
ndash 连续模式下 GLThread 会不断调用 RendereronDrawFrame 进行绘图
ndash Dirty 模式下 GLThread处于等待状态直到程序发送绘图请求( GLSurfaceViewrequestRender )才调用 RendereronDrawFrame 进行绘图绘制完一帧后重新进入等待状态
bull 在 RendereronDrawFrame 的回调中应用可以通过 SDK提供的 EGL API 绘图也可以转到 native 端使用 NDK提供的 EGL API 绘图
class SurfaceView
SurfaceView
GLSurfaceView GLSurfaceViewRenderer
+ onDrawFrame() void
GLSurfaceViewGLThread
GLSurfaceViewEglHelper
laquointerfaceraquoSurfaceHolder
laquointerfaceraquoSurfaceHolder
Callback
Surface
+ lockCanvas () Canvas+ unlockCanvasAndPost (Canvas) void
laquointerfaceraquoIWindowSession
+ add() void+ relayout() void
SurfaceViewMyWindow
BaseIWindow IWindowStublaquointerfaceraquo
IWindow
+mSurface
+mSession
+mWindow
+mCallbacks
+mSurfaceHolder
+mRenderer
+mGLThread
call
+mRenderer
+mEglHelper
TextureView
bull Since Android 40只在硬件加速环境下起作用bull 具备 SurfaceView 的特性
ndash 但是可以跟其它普通的 View 一样实现 Rotation Screw等变换
ndash 支持 Alpha 可以跟它下方的 View 进行 Alpha 混合
bull 可以基于 TextureView 创建一个 GL Surface 在上面进行 OpenGL渲染
Things become more complicated after Android 30
HW Accelerated 2D Renderingbull Android 30后开始支持硬件加速的 2D 绘图原
有的绘图流程变得更加复杂bull 所谓硬件加速的 2D 绘图就是将 2D Graphics A
PI 的实现改成使用 OpenGL API 来进行绘图bull OpenGL 的绘图模式跟一般的 2D 绘图有很大区
别它需要先将绘图所需的各种素材如贴图多边形顶点阵列 Shader等先加载到当前的 GLContext 然后流水线式的顺序执行绘图指令通过这种方式来充分利用硬件的能力
ViewRootImplbull 当 Actitity 的 View Hierachy 的根节点被添加到 WindowM
anager 的时候( WindowManageraddView ) WindowManager 的实现类 WindowManagerImpl 会创建一个 ViewRootImpl 并把它跟传进来的 View 绑定在一起( ViewRootImplsetView )并且 ViewRootImpl 会根据是否开启硬件加速来决定是否创建一个 HardwareRenderer
bull 在 ViewRootImpl 第一次渲染 View Hierachy 时会创建 Surface 如果开启硬件加速则通过 HardwareRenderer在当前的 UI 线程初始化EGL 绘图环境(类似 GLSurfaceView )
Contbull 在 ViewRootImpl 真正渲染 View Hierachy
时如果开启硬件加速则从 HardwareRenderer获得一个 HardwareCanvas 然后 View Hierachy 的渲染通过 HardwareCanvas 来进行
bull HardwareCanvas 跟一个 native 的 OpenGLRenderer 绑定通过它调用 EGL API 来完成真正的绘制
DisplayList and Hardware Layerbull 为了充分利用硬件加速的能力 Android 30 还引入了 Di
splayList 和 Hardware Layerbull DisplayList 用于记录一系列OpenGL 绘图指令和缓存所需的各种绘图素材( Bitmap Paint Shape Shader )当 View 的内容不发生变化时可以直接使用 DisplayList 进行绘制而不需要重新调用 onDraw
bull Hardware Layer 用于缓存绘制的内存到 Frame Buffer Object 当内容不发生变化时可以直接使用 Layer 进行Layer Composite获得更快的绘图速度
class Hardward2D
DisplayListHardwareCanv as
+ drawDisplayList() void+ drawHardwareLayer() void
Canv as
+ isHardwareAccelerated() voidHardwareLayer
HardwareRenderer
+ initialize() void
HardwareRendererGlRenderer
HardwareRendererGl20Renderer
GLES20Canv as
GLES20RecordingCanv as
GLES20DisplayList
laquonativeraquoDisplayList
laquonativeraquoOpenGLRenderer
laquonativeraquoDisplayListRenderer
ViewAttachInfo
ViewRootImpl
+ setView() void+ scheduleTraversals() void+ performTraversals() void+ relayoutWindow() void
GLES20Layer
GLES20TextureLayer
+mCanvas
+mNativeDisplayList
draw
+mRenderer
+mAttachInfo
+mHardwareRenderer
+mHardwareCanvas
+mResizeBuffer
Reference
bull Android 圖形系統 -- 設計與實做分析
bull How to replace GLSurfaceView with TextureView in Android Ice Cream Sandwich
The End
Thank you for your listeningYours Sincerely Roger
System Services
bull Activity Management Servicebull Window Management Servicebull Suface Flingerbull etc
The Startup of an Activity in New Process
bull AMS 接收到请求要在新的进程启动一个 Activitybull AMS 转发请求给 zygote 进程 zygote fork 一个新的进程然后调
用 ActivityThreadmain 方法 ActivityThread 创建 MessageQueue attach 到 AMS 然后进入消息循环这个线程就是主线程也是所谓的 UI 线程
bull 当 ActivityThread attch 到 AMS 后 AMS 发送请求给 ActivityThread 要求启动 Activity ( LAUNCH_ACTIVITY )
bull ActivityThread 在消息循环中启动 Activity ( handleLaunchActivity )
ndash 创建 Activity 后调用 onCreate ( performLaunchActivity )ndash 应用则在 onCreate 中设置 Content View 然后开始跟用户的交互
Window
bull Android 中的 Window 是一个十分容易混淆的概念
bull 它存在应用层面窗口和系统层面窗口的区别
bull 在系统窗口这个层面中存在客户端窗口和服务端窗口的区别
androidviewWindow
bull Abstract base class for a top-level window look and behavior policy
bull It provides standard UI policies such as a background title area default key processing etc
bull 它是通常意义上我们理解的应用层面窗口TopLevelWindow or WindowPolicy 可能是一个更合适的名字
PhoneWindowbull PhoneWindow 是抽象类 Window 的唯一实现bull ActivityThread 在启动一个 Activity 的时候 Activity 会
创建一个 PhoneWindowndash ActivityThreadhandleLaunchActivityndash -gt ActivityThreadperformLaunchActivity ndash -gt Activityattach
bull ActivitysetContentView 实际上是调用 PhoneWindowsetContentView 在该方法的第一次调用时 PhoneWindow 会创建一个 DecorView 作为 Top-Level-Window 的View Hierachy 的根节点
View Hierachy
WindowManagerbull androidviewWindowManager
ndash The interface that apps use to talk to the window managerndash 真正的实现是 WindowManagerImpl 由 PhoneWindow 在 Act
ivity 启动时创建bull ActivityThreadhandleLaunchActivitybull -gt ActivityThreadperformLaunchActivitybull -gt Activityattachbull -gt PhoneWindowsetWindowManager
ndash 当 Activity 启动后 ActivityThread 将 DocorView 添加到 WindowManagerImpl 中
bull ActivityThreadhandleLaunchActivitybull -gt ActivityThreadhandleResumeActivity bull -gt WindowManageraddView
Contbull WindowManagerImpl 负责跟 WMS 通讯
ndash 但实际上每一个 Window 跟 WMS 之间的通讯是由 ViewRootImpl 负责 ViewRootImpl 在 addView 时被创建
ndash 这里的 Window 是指系统层面的 Window 除了之前的 PhoneWindow 外其它如 Dialog Menu 都拥有一个独立的 Window
ndash ViewRootImpl 的每一个实例都跟通过 addView 传进来一个 View Hierachy 的根节点形成一一对应的关系它是真正意义上的 View Hierachy 的根节点
ndash ViewRootImpl 可以看作是系统层面的 Window 在客户端的代理者
ViewRootImpl
bull The top of a view hierarchy implementing the needed protocol between View and the WindowManager
bull This is for the most part an internal implementation detail WindowManagerImpl
Contbull ViewRootImpl 会打开一个 IWindowSession 用于跟 WM
S 对话bull 并通过 IWindowSession 向 WMS 注册一个窗口(实际上
是让 WMS 在服务端创建一个窗口( WindowState )并且把该服务端的窗口跟 ViewRootImpl 传过来的 IWindow 回调接口绑定在一起)
ndash ActivityThreadhandleLaunchActivityndash -gt ActivityThreadhandleResumeActivity ndash -gt WindowManagerImpladdViewndash -gt ViewRootImplsetView
Contbull IWindow
ndash API back to a client window that the Window Manager uses to inform it of interesting things happening
ndash 回调接口用于接收 WMS 关于窗口的消息 mdashmdash 显示 隐藏大小改变焦点变化等等
bull 除了注册窗口外 ViewRootImpl还向 WMS (通过 InputQueue )注册了一个 InputHandler 用于接收输入事件
bull 接收到的输入事件会先放在 UI 线程的消息循环中然后通过 ViewRootImpl 进行分派在它对应的 View Hierachy 上路由
class Window
Activ ityThread
+ handleLaunchActivity() void+ handleResumeActivity() void+ performLaunchActivity() void
Activ ity
+ attach() void+ onCreate() void+ setContentView() void
Window
+ setContentView() void
PhoneWindow PhoneWindowDecorView
ViewRootImpl
+ setView() void+ scheduleTraversals() void+ performTraversals() void+ relayoutWindow() void
ViewGroup
laquointerfaceraquoWindowManager
laquointerfaceraquoViewManager
WindowLocalWindowManager
WindowManagerImpl
+ addView() void
WindowManagerImplCompatModeWrapper
laquointerfaceraquoViewParent
laquointerfaceraquoIWindowSession
+ add() void+ relayout() void
laquointerfaceraquoIWindow
ViewRootImplW IWindowStub
create +mWindow
+mDecor
+mContentParent
+mWindowManager
+mWindowManager
+mRoots
parent
+mView
+sWindowSession
addView
+mWindow
Overall Flowbull ActivityThead 创建 Activitybull Activity 创建 PhoneWindowbull PhoneWindow 创建 DecorView 作为 View Hierachy 的根节点 Client 端设
置的 Content View 会 attach 到 DecorView 下面(间接)bull PhoneWindow 创建 WindowManagerImplbull ActivityThead 把 DecorView 加到 WindowManagerImpl 里面bull WindowManagerImpl 创建 ViewRootImpl 并把 DecorView 传给它bull ViewRootImpl 打开一个 Window Session 跟 WMS 通讯通过 Session 注册
一个窗口最后客户端拥有一个 IWindow 回调接口服务端拥有一个 WindowState 跟该回调接口绑定
View Hierachy Rendering
bull 当 ViewRootImpl 建立跟 WMS 的联系注册了窗口后会发出第一次渲染 View Hierachy 的请求
ndash ViewRootImplsetViewndash ViewRootImplrequestLayoutndash ViewRootImplscheduleTraversals
bull 在第一次的 View Hierachy 的渲染中( ViewRootImplperformTraversals ) ViewRootImpl需要创建 Surface
Contbull 当 Surface 创建后后续的渲染就可以通过获得
Surface 的 Canvas ( SurfacelockCanvas )bull 然后遍历 View Hierachy 把需要绘制的 Views
通过 Canvas 绘制到 Surface 上面( ViewonDraw )
bull 绘制完后需要解锁( SurfaceunlockCanvasPost )让 SurfaceFlinger 可以将 Surface 绘制到屏幕上( Screen Composite )
Surfacebull Handle onto a raw buffer that is being managed by the
screen compositor
bull 每个 Window 都有一个 Surface 由窗口在客户端的代理者 ViewRootImpl 所拥有
bull Surface 在 ViewRootImpl 第一次渲染 View Hierachy 时创建
ndash ViewRootImplperformTraversalsndash ViewRootImplrelayoutWindowndash IWindowSessionrelayout
Contbull ViewRootImpl预先创建一个空的 Surface 对象( Java )在需要
创建真正的 Surface 的时候它调用 IWindowSessionrelayout 这是一个 RPC 最终是 WMS 的 relayoutWindow 被调用
bull WMS 调用 WindowStatecreateSurfaceLocked 创建了一个 Surface对象( Java )并把这个对象的数据传回给客户端而客户端则负责用这些数据填充预先创建的空 Surface 对象( Java )
ndash 实际上 WMS 是请求 SurfaceFlinger 创建真正的 Surface 然后把 Surface相关的信息再传回给客户端
ndash 客户端利用这些信息来创建一个 native Surface 对象然后把它跟 Java Surface 对象绑定在一起
ndash 客户端的 Java Surface 对象以后就可以通过这个 native Surface 对象来操作图像缓存( GraphicsBuffer )图像缓存可以看作是一块共享内存在客户端和 SurfaceFlinger 之间共享
Surface amp Canvasbull Surface ( Java )包含一个 Canvas ( Java )而 Can
vas ( Java )包含一个 native 的 SkCanvas 对象bull 当调用 SurfacelockCanvas 时
ndash 从图像缓存队列中取出一个可用的缓存ndash 把当前的 Posted Buffer 的内容拷贝到新缓存中(除了 Dirty Regi
on 之外的区域)然后将这块缓存加锁并设置为 Locked Buffer
ndash 获得新缓存的内存地址根据内存地址构建一个 SkBitmapndash 把该 SkBitmap 设置到 SkCanvas 里面ndash 返回跟 SkCanvas 对应的 Canvas ( Java )透过 Canvas ( Ja
va )绘制的内容实际上就是绘制到当前的缓存
Cont
bull 当调用 SurfaceunlockCanvasAndPost 的时候ndash 置空 SkCanvas 设置一个空的 SkBitmapndash 将 Locked Buffer 解锁并返回到图像缓存队列里面ndash 将 Posted Buffer 设置为 Locked Buffer 旧的 Poste
d Buffer 就可以被下次取出来使用设置 Locked Buffer 为空
ndash 当 SurfaceFlinger 下次进行 Screen Composite 的时候就会把当前的 Posted Buffer 绘制到屏幕上
SurfaceFlingerbull 应用跟 SF 之间的关系是就像是生产者与消费者的关系bull 应用从 Surface 的 GraphicsBuffer队列的前端取出一个缓存然后进行绘制
bull 绘制完毕后把该缓存放置回队列的后端(生产)bull 而 SF 则不断地将 Surface 的 GraphicsBuffer队列的最后
一个缓存绘制到屏幕上(消费)bull 两者在不同的进程是异步进行的对队列的访问需要进
行同步
class Surface
ViewRootImpl
+ setView() void+ scheduleTraversals() void+ performTraversals() void+ relayoutWindow() void
Surface
+ lockCanvas () Canvas+ unlockCanvasAndPost (Canvas) void
laquointerfaceraquoIWindowSession
+ add() void+ relayout() void
Canvas
+ isHardwareAccelerated() void
laquonativeraquoSurface
laquonativeraquoSurfaceController
SurfaceCompatibleCanvas
laquonativeraquoSkCanvas
WindowManagerServ ice
+ relayoutWindow() void
SurfaceSession
Session
+ relayout() void
WindowState
+ createSurfaceLocked() void
laquonativeraquoSurfaceFlinger
IWindowSessionStub
laquonativeraquoSurfaceComposerCilent
laquonativeraquoBnSurfaceComposer
laquonativeraquoISurfaceComposerClient
laquonativeraquoSurfaceTextureClient
+mSurface
+sWindowSession
+mCanvas
+mSurfaceControl
+mNativeSurface
+mNativeCanvas
+mSurfaceSession
+mService
+mSessions
+mWindowMap
setBitmapDevice
communication+mClient
+mClient
Overall Flowbull ViewRootImpl 第一次渲染 View Hierachy 的时候会创建一个 Surfac
ebull 客户端请求 WMS 创建 Surface 并返回 Surface相关的数据用于构
建一个 native 的 Surface 对象并把它跟 ViewRootImpl 的 Surface( Java )绑定在一起
bull ViewRootImpl 在渲染时先从 Surface获得 Canvasbull 然后把需要绘制的 Views 通过 Canvas 绘制到 Surface 上面bull 绘制完毕后解锁该 Surfacebull SurfaceFlinger 在做 Screen Composite 的时候把解锁后的 Surface
绘制到屏幕上
Those special Views
SurfaceViewbull Provides a dedicated drawing surface embedded
inside of a view hierarchy You can control the format of this surface and if you like its size the SurfaceView takes care of placing the surface at the correct location on the screen
bull The surface is Z ordered so that it is behind the window holding its SurfaceView the SurfaceView punches a hole in its window to allow its surface to be displayed
Contbull Pros
ndash 可以跟 View Hierachy较好地结合在一起可以移动改变大小在上方叠加其它的 View
ndash 在单独的渲染线程进行渲染渲染效率高
ndash SV 的 Surface 和 Window Surface 之间的混合是由系统( SurfaceFlinger )使用硬件加速完成效率高并且不占用应用本身的 UI 线程时间
bull Consndash SurfaceView 的渲染毕竟跟
真正的 View不一样它不是由 ViewRootImpl渲染到当前的 Window Surface 上面
ndash 不能改变 Alpha 不支持跟下方的 View 进行 Alpha 混合
ndash 不能做 Rotation Skew等变换
GLSurfaceViewbull An implementation of SurfaceView that uses the dedicated surfac
e for displaying OpenGL renderingbull A GLSurfaceView provides the following features
ndash Manages a surface which is a special piece of memory that can be composited into the Android view system
ndash Manages an EGL display which enables OpenGL to render into a surfacendash Accepts a user-provided Renderer object that does the actual renderingndash Renders on a dedicated thread to decouple rendering performance from
the UI threadndash Supports both on-demand and continuous renderingndash Optionally wraps traces andor error-checks the renderers OpenGL call
s
Contbull GLSurfaceView 创建一个内部的线程 GLThreadbull 在该线程运行环境下创建一个 EglContextbull 创建一个 EglSurface ( Window Surface )bull 设置之前创建的 EglContext 为当前的 GL Contex
t 并绑定到创建的 EglSurface 上bull 在该线程内就可以通过 EGL 指令在当前的 GL Co
ntext 上绘图
Contbull GLSurfaceView支持两种不同的绘图模式
ndash 连续模式下 GLThread 会不断调用 RendereronDrawFrame 进行绘图
ndash Dirty 模式下 GLThread处于等待状态直到程序发送绘图请求( GLSurfaceViewrequestRender )才调用 RendereronDrawFrame 进行绘图绘制完一帧后重新进入等待状态
bull 在 RendereronDrawFrame 的回调中应用可以通过 SDK提供的 EGL API 绘图也可以转到 native 端使用 NDK提供的 EGL API 绘图
class SurfaceView
SurfaceView
GLSurfaceView GLSurfaceViewRenderer
+ onDrawFrame() void
GLSurfaceViewGLThread
GLSurfaceViewEglHelper
laquointerfaceraquoSurfaceHolder
laquointerfaceraquoSurfaceHolder
Callback
Surface
+ lockCanvas () Canvas+ unlockCanvasAndPost (Canvas) void
laquointerfaceraquoIWindowSession
+ add() void+ relayout() void
SurfaceViewMyWindow
BaseIWindow IWindowStublaquointerfaceraquo
IWindow
+mSurface
+mSession
+mWindow
+mCallbacks
+mSurfaceHolder
+mRenderer
+mGLThread
call
+mRenderer
+mEglHelper
TextureView
bull Since Android 40只在硬件加速环境下起作用bull 具备 SurfaceView 的特性
ndash 但是可以跟其它普通的 View 一样实现 Rotation Screw等变换
ndash 支持 Alpha 可以跟它下方的 View 进行 Alpha 混合
bull 可以基于 TextureView 创建一个 GL Surface 在上面进行 OpenGL渲染
Things become more complicated after Android 30
HW Accelerated 2D Renderingbull Android 30后开始支持硬件加速的 2D 绘图原
有的绘图流程变得更加复杂bull 所谓硬件加速的 2D 绘图就是将 2D Graphics A
PI 的实现改成使用 OpenGL API 来进行绘图bull OpenGL 的绘图模式跟一般的 2D 绘图有很大区
别它需要先将绘图所需的各种素材如贴图多边形顶点阵列 Shader等先加载到当前的 GLContext 然后流水线式的顺序执行绘图指令通过这种方式来充分利用硬件的能力
ViewRootImplbull 当 Actitity 的 View Hierachy 的根节点被添加到 WindowM
anager 的时候( WindowManageraddView ) WindowManager 的实现类 WindowManagerImpl 会创建一个 ViewRootImpl 并把它跟传进来的 View 绑定在一起( ViewRootImplsetView )并且 ViewRootImpl 会根据是否开启硬件加速来决定是否创建一个 HardwareRenderer
bull 在 ViewRootImpl 第一次渲染 View Hierachy 时会创建 Surface 如果开启硬件加速则通过 HardwareRenderer在当前的 UI 线程初始化EGL 绘图环境(类似 GLSurfaceView )
Contbull 在 ViewRootImpl 真正渲染 View Hierachy
时如果开启硬件加速则从 HardwareRenderer获得一个 HardwareCanvas 然后 View Hierachy 的渲染通过 HardwareCanvas 来进行
bull HardwareCanvas 跟一个 native 的 OpenGLRenderer 绑定通过它调用 EGL API 来完成真正的绘制
DisplayList and Hardware Layerbull 为了充分利用硬件加速的能力 Android 30 还引入了 Di
splayList 和 Hardware Layerbull DisplayList 用于记录一系列OpenGL 绘图指令和缓存所需的各种绘图素材( Bitmap Paint Shape Shader )当 View 的内容不发生变化时可以直接使用 DisplayList 进行绘制而不需要重新调用 onDraw
bull Hardware Layer 用于缓存绘制的内存到 Frame Buffer Object 当内容不发生变化时可以直接使用 Layer 进行Layer Composite获得更快的绘图速度
class Hardward2D
DisplayListHardwareCanv as
+ drawDisplayList() void+ drawHardwareLayer() void
Canv as
+ isHardwareAccelerated() voidHardwareLayer
HardwareRenderer
+ initialize() void
HardwareRendererGlRenderer
HardwareRendererGl20Renderer
GLES20Canv as
GLES20RecordingCanv as
GLES20DisplayList
laquonativeraquoDisplayList
laquonativeraquoOpenGLRenderer
laquonativeraquoDisplayListRenderer
ViewAttachInfo
ViewRootImpl
+ setView() void+ scheduleTraversals() void+ performTraversals() void+ relayoutWindow() void
GLES20Layer
GLES20TextureLayer
+mCanvas
+mNativeDisplayList
draw
+mRenderer
+mAttachInfo
+mHardwareRenderer
+mHardwareCanvas
+mResizeBuffer
Reference
bull Android 圖形系統 -- 設計與實做分析
bull How to replace GLSurfaceView with TextureView in Android Ice Cream Sandwich
The End
Thank you for your listeningYours Sincerely Roger
The Startup of an Activity in New Process
bull AMS 接收到请求要在新的进程启动一个 Activitybull AMS 转发请求给 zygote 进程 zygote fork 一个新的进程然后调
用 ActivityThreadmain 方法 ActivityThread 创建 MessageQueue attach 到 AMS 然后进入消息循环这个线程就是主线程也是所谓的 UI 线程
bull 当 ActivityThread attch 到 AMS 后 AMS 发送请求给 ActivityThread 要求启动 Activity ( LAUNCH_ACTIVITY )
bull ActivityThread 在消息循环中启动 Activity ( handleLaunchActivity )
ndash 创建 Activity 后调用 onCreate ( performLaunchActivity )ndash 应用则在 onCreate 中设置 Content View 然后开始跟用户的交互
Window
bull Android 中的 Window 是一个十分容易混淆的概念
bull 它存在应用层面窗口和系统层面窗口的区别
bull 在系统窗口这个层面中存在客户端窗口和服务端窗口的区别
androidviewWindow
bull Abstract base class for a top-level window look and behavior policy
bull It provides standard UI policies such as a background title area default key processing etc
bull 它是通常意义上我们理解的应用层面窗口TopLevelWindow or WindowPolicy 可能是一个更合适的名字
PhoneWindowbull PhoneWindow 是抽象类 Window 的唯一实现bull ActivityThread 在启动一个 Activity 的时候 Activity 会
创建一个 PhoneWindowndash ActivityThreadhandleLaunchActivityndash -gt ActivityThreadperformLaunchActivity ndash -gt Activityattach
bull ActivitysetContentView 实际上是调用 PhoneWindowsetContentView 在该方法的第一次调用时 PhoneWindow 会创建一个 DecorView 作为 Top-Level-Window 的View Hierachy 的根节点
View Hierachy
WindowManagerbull androidviewWindowManager
ndash The interface that apps use to talk to the window managerndash 真正的实现是 WindowManagerImpl 由 PhoneWindow 在 Act
ivity 启动时创建bull ActivityThreadhandleLaunchActivitybull -gt ActivityThreadperformLaunchActivitybull -gt Activityattachbull -gt PhoneWindowsetWindowManager
ndash 当 Activity 启动后 ActivityThread 将 DocorView 添加到 WindowManagerImpl 中
bull ActivityThreadhandleLaunchActivitybull -gt ActivityThreadhandleResumeActivity bull -gt WindowManageraddView
Contbull WindowManagerImpl 负责跟 WMS 通讯
ndash 但实际上每一个 Window 跟 WMS 之间的通讯是由 ViewRootImpl 负责 ViewRootImpl 在 addView 时被创建
ndash 这里的 Window 是指系统层面的 Window 除了之前的 PhoneWindow 外其它如 Dialog Menu 都拥有一个独立的 Window
ndash ViewRootImpl 的每一个实例都跟通过 addView 传进来一个 View Hierachy 的根节点形成一一对应的关系它是真正意义上的 View Hierachy 的根节点
ndash ViewRootImpl 可以看作是系统层面的 Window 在客户端的代理者
ViewRootImpl
bull The top of a view hierarchy implementing the needed protocol between View and the WindowManager
bull This is for the most part an internal implementation detail WindowManagerImpl
Contbull ViewRootImpl 会打开一个 IWindowSession 用于跟 WM
S 对话bull 并通过 IWindowSession 向 WMS 注册一个窗口(实际上
是让 WMS 在服务端创建一个窗口( WindowState )并且把该服务端的窗口跟 ViewRootImpl 传过来的 IWindow 回调接口绑定在一起)
ndash ActivityThreadhandleLaunchActivityndash -gt ActivityThreadhandleResumeActivity ndash -gt WindowManagerImpladdViewndash -gt ViewRootImplsetView
Contbull IWindow
ndash API back to a client window that the Window Manager uses to inform it of interesting things happening
ndash 回调接口用于接收 WMS 关于窗口的消息 mdashmdash 显示 隐藏大小改变焦点变化等等
bull 除了注册窗口外 ViewRootImpl还向 WMS (通过 InputQueue )注册了一个 InputHandler 用于接收输入事件
bull 接收到的输入事件会先放在 UI 线程的消息循环中然后通过 ViewRootImpl 进行分派在它对应的 View Hierachy 上路由
class Window
Activ ityThread
+ handleLaunchActivity() void+ handleResumeActivity() void+ performLaunchActivity() void
Activ ity
+ attach() void+ onCreate() void+ setContentView() void
Window
+ setContentView() void
PhoneWindow PhoneWindowDecorView
ViewRootImpl
+ setView() void+ scheduleTraversals() void+ performTraversals() void+ relayoutWindow() void
ViewGroup
laquointerfaceraquoWindowManager
laquointerfaceraquoViewManager
WindowLocalWindowManager
WindowManagerImpl
+ addView() void
WindowManagerImplCompatModeWrapper
laquointerfaceraquoViewParent
laquointerfaceraquoIWindowSession
+ add() void+ relayout() void
laquointerfaceraquoIWindow
ViewRootImplW IWindowStub
create +mWindow
+mDecor
+mContentParent
+mWindowManager
+mWindowManager
+mRoots
parent
+mView
+sWindowSession
addView
+mWindow
Overall Flowbull ActivityThead 创建 Activitybull Activity 创建 PhoneWindowbull PhoneWindow 创建 DecorView 作为 View Hierachy 的根节点 Client 端设
置的 Content View 会 attach 到 DecorView 下面(间接)bull PhoneWindow 创建 WindowManagerImplbull ActivityThead 把 DecorView 加到 WindowManagerImpl 里面bull WindowManagerImpl 创建 ViewRootImpl 并把 DecorView 传给它bull ViewRootImpl 打开一个 Window Session 跟 WMS 通讯通过 Session 注册
一个窗口最后客户端拥有一个 IWindow 回调接口服务端拥有一个 WindowState 跟该回调接口绑定
View Hierachy Rendering
bull 当 ViewRootImpl 建立跟 WMS 的联系注册了窗口后会发出第一次渲染 View Hierachy 的请求
ndash ViewRootImplsetViewndash ViewRootImplrequestLayoutndash ViewRootImplscheduleTraversals
bull 在第一次的 View Hierachy 的渲染中( ViewRootImplperformTraversals ) ViewRootImpl需要创建 Surface
Contbull 当 Surface 创建后后续的渲染就可以通过获得
Surface 的 Canvas ( SurfacelockCanvas )bull 然后遍历 View Hierachy 把需要绘制的 Views
通过 Canvas 绘制到 Surface 上面( ViewonDraw )
bull 绘制完后需要解锁( SurfaceunlockCanvasPost )让 SurfaceFlinger 可以将 Surface 绘制到屏幕上( Screen Composite )
Surfacebull Handle onto a raw buffer that is being managed by the
screen compositor
bull 每个 Window 都有一个 Surface 由窗口在客户端的代理者 ViewRootImpl 所拥有
bull Surface 在 ViewRootImpl 第一次渲染 View Hierachy 时创建
ndash ViewRootImplperformTraversalsndash ViewRootImplrelayoutWindowndash IWindowSessionrelayout
Contbull ViewRootImpl预先创建一个空的 Surface 对象( Java )在需要
创建真正的 Surface 的时候它调用 IWindowSessionrelayout 这是一个 RPC 最终是 WMS 的 relayoutWindow 被调用
bull WMS 调用 WindowStatecreateSurfaceLocked 创建了一个 Surface对象( Java )并把这个对象的数据传回给客户端而客户端则负责用这些数据填充预先创建的空 Surface 对象( Java )
ndash 实际上 WMS 是请求 SurfaceFlinger 创建真正的 Surface 然后把 Surface相关的信息再传回给客户端
ndash 客户端利用这些信息来创建一个 native Surface 对象然后把它跟 Java Surface 对象绑定在一起
ndash 客户端的 Java Surface 对象以后就可以通过这个 native Surface 对象来操作图像缓存( GraphicsBuffer )图像缓存可以看作是一块共享内存在客户端和 SurfaceFlinger 之间共享
Surface amp Canvasbull Surface ( Java )包含一个 Canvas ( Java )而 Can
vas ( Java )包含一个 native 的 SkCanvas 对象bull 当调用 SurfacelockCanvas 时
ndash 从图像缓存队列中取出一个可用的缓存ndash 把当前的 Posted Buffer 的内容拷贝到新缓存中(除了 Dirty Regi
on 之外的区域)然后将这块缓存加锁并设置为 Locked Buffer
ndash 获得新缓存的内存地址根据内存地址构建一个 SkBitmapndash 把该 SkBitmap 设置到 SkCanvas 里面ndash 返回跟 SkCanvas 对应的 Canvas ( Java )透过 Canvas ( Ja
va )绘制的内容实际上就是绘制到当前的缓存
Cont
bull 当调用 SurfaceunlockCanvasAndPost 的时候ndash 置空 SkCanvas 设置一个空的 SkBitmapndash 将 Locked Buffer 解锁并返回到图像缓存队列里面ndash 将 Posted Buffer 设置为 Locked Buffer 旧的 Poste
d Buffer 就可以被下次取出来使用设置 Locked Buffer 为空
ndash 当 SurfaceFlinger 下次进行 Screen Composite 的时候就会把当前的 Posted Buffer 绘制到屏幕上
SurfaceFlingerbull 应用跟 SF 之间的关系是就像是生产者与消费者的关系bull 应用从 Surface 的 GraphicsBuffer队列的前端取出一个缓存然后进行绘制
bull 绘制完毕后把该缓存放置回队列的后端(生产)bull 而 SF 则不断地将 Surface 的 GraphicsBuffer队列的最后
一个缓存绘制到屏幕上(消费)bull 两者在不同的进程是异步进行的对队列的访问需要进
行同步
class Surface
ViewRootImpl
+ setView() void+ scheduleTraversals() void+ performTraversals() void+ relayoutWindow() void
Surface
+ lockCanvas () Canvas+ unlockCanvasAndPost (Canvas) void
laquointerfaceraquoIWindowSession
+ add() void+ relayout() void
Canvas
+ isHardwareAccelerated() void
laquonativeraquoSurface
laquonativeraquoSurfaceController
SurfaceCompatibleCanvas
laquonativeraquoSkCanvas
WindowManagerServ ice
+ relayoutWindow() void
SurfaceSession
Session
+ relayout() void
WindowState
+ createSurfaceLocked() void
laquonativeraquoSurfaceFlinger
IWindowSessionStub
laquonativeraquoSurfaceComposerCilent
laquonativeraquoBnSurfaceComposer
laquonativeraquoISurfaceComposerClient
laquonativeraquoSurfaceTextureClient
+mSurface
+sWindowSession
+mCanvas
+mSurfaceControl
+mNativeSurface
+mNativeCanvas
+mSurfaceSession
+mService
+mSessions
+mWindowMap
setBitmapDevice
communication+mClient
+mClient
Overall Flowbull ViewRootImpl 第一次渲染 View Hierachy 的时候会创建一个 Surfac
ebull 客户端请求 WMS 创建 Surface 并返回 Surface相关的数据用于构
建一个 native 的 Surface 对象并把它跟 ViewRootImpl 的 Surface( Java )绑定在一起
bull ViewRootImpl 在渲染时先从 Surface获得 Canvasbull 然后把需要绘制的 Views 通过 Canvas 绘制到 Surface 上面bull 绘制完毕后解锁该 Surfacebull SurfaceFlinger 在做 Screen Composite 的时候把解锁后的 Surface
绘制到屏幕上
Those special Views
SurfaceViewbull Provides a dedicated drawing surface embedded
inside of a view hierarchy You can control the format of this surface and if you like its size the SurfaceView takes care of placing the surface at the correct location on the screen
bull The surface is Z ordered so that it is behind the window holding its SurfaceView the SurfaceView punches a hole in its window to allow its surface to be displayed
Contbull Pros
ndash 可以跟 View Hierachy较好地结合在一起可以移动改变大小在上方叠加其它的 View
ndash 在单独的渲染线程进行渲染渲染效率高
ndash SV 的 Surface 和 Window Surface 之间的混合是由系统( SurfaceFlinger )使用硬件加速完成效率高并且不占用应用本身的 UI 线程时间
bull Consndash SurfaceView 的渲染毕竟跟
真正的 View不一样它不是由 ViewRootImpl渲染到当前的 Window Surface 上面
ndash 不能改变 Alpha 不支持跟下方的 View 进行 Alpha 混合
ndash 不能做 Rotation Skew等变换
GLSurfaceViewbull An implementation of SurfaceView that uses the dedicated surfac
e for displaying OpenGL renderingbull A GLSurfaceView provides the following features
ndash Manages a surface which is a special piece of memory that can be composited into the Android view system
ndash Manages an EGL display which enables OpenGL to render into a surfacendash Accepts a user-provided Renderer object that does the actual renderingndash Renders on a dedicated thread to decouple rendering performance from
the UI threadndash Supports both on-demand and continuous renderingndash Optionally wraps traces andor error-checks the renderers OpenGL call
s
Contbull GLSurfaceView 创建一个内部的线程 GLThreadbull 在该线程运行环境下创建一个 EglContextbull 创建一个 EglSurface ( Window Surface )bull 设置之前创建的 EglContext 为当前的 GL Contex
t 并绑定到创建的 EglSurface 上bull 在该线程内就可以通过 EGL 指令在当前的 GL Co
ntext 上绘图
Contbull GLSurfaceView支持两种不同的绘图模式
ndash 连续模式下 GLThread 会不断调用 RendereronDrawFrame 进行绘图
ndash Dirty 模式下 GLThread处于等待状态直到程序发送绘图请求( GLSurfaceViewrequestRender )才调用 RendereronDrawFrame 进行绘图绘制完一帧后重新进入等待状态
bull 在 RendereronDrawFrame 的回调中应用可以通过 SDK提供的 EGL API 绘图也可以转到 native 端使用 NDK提供的 EGL API 绘图
class SurfaceView
SurfaceView
GLSurfaceView GLSurfaceViewRenderer
+ onDrawFrame() void
GLSurfaceViewGLThread
GLSurfaceViewEglHelper
laquointerfaceraquoSurfaceHolder
laquointerfaceraquoSurfaceHolder
Callback
Surface
+ lockCanvas () Canvas+ unlockCanvasAndPost (Canvas) void
laquointerfaceraquoIWindowSession
+ add() void+ relayout() void
SurfaceViewMyWindow
BaseIWindow IWindowStublaquointerfaceraquo
IWindow
+mSurface
+mSession
+mWindow
+mCallbacks
+mSurfaceHolder
+mRenderer
+mGLThread
call
+mRenderer
+mEglHelper
TextureView
bull Since Android 40只在硬件加速环境下起作用bull 具备 SurfaceView 的特性
ndash 但是可以跟其它普通的 View 一样实现 Rotation Screw等变换
ndash 支持 Alpha 可以跟它下方的 View 进行 Alpha 混合
bull 可以基于 TextureView 创建一个 GL Surface 在上面进行 OpenGL渲染
Things become more complicated after Android 30
HW Accelerated 2D Renderingbull Android 30后开始支持硬件加速的 2D 绘图原
有的绘图流程变得更加复杂bull 所谓硬件加速的 2D 绘图就是将 2D Graphics A
PI 的实现改成使用 OpenGL API 来进行绘图bull OpenGL 的绘图模式跟一般的 2D 绘图有很大区
别它需要先将绘图所需的各种素材如贴图多边形顶点阵列 Shader等先加载到当前的 GLContext 然后流水线式的顺序执行绘图指令通过这种方式来充分利用硬件的能力
ViewRootImplbull 当 Actitity 的 View Hierachy 的根节点被添加到 WindowM
anager 的时候( WindowManageraddView ) WindowManager 的实现类 WindowManagerImpl 会创建一个 ViewRootImpl 并把它跟传进来的 View 绑定在一起( ViewRootImplsetView )并且 ViewRootImpl 会根据是否开启硬件加速来决定是否创建一个 HardwareRenderer
bull 在 ViewRootImpl 第一次渲染 View Hierachy 时会创建 Surface 如果开启硬件加速则通过 HardwareRenderer在当前的 UI 线程初始化EGL 绘图环境(类似 GLSurfaceView )
Contbull 在 ViewRootImpl 真正渲染 View Hierachy
时如果开启硬件加速则从 HardwareRenderer获得一个 HardwareCanvas 然后 View Hierachy 的渲染通过 HardwareCanvas 来进行
bull HardwareCanvas 跟一个 native 的 OpenGLRenderer 绑定通过它调用 EGL API 来完成真正的绘制
DisplayList and Hardware Layerbull 为了充分利用硬件加速的能力 Android 30 还引入了 Di
splayList 和 Hardware Layerbull DisplayList 用于记录一系列OpenGL 绘图指令和缓存所需的各种绘图素材( Bitmap Paint Shape Shader )当 View 的内容不发生变化时可以直接使用 DisplayList 进行绘制而不需要重新调用 onDraw
bull Hardware Layer 用于缓存绘制的内存到 Frame Buffer Object 当内容不发生变化时可以直接使用 Layer 进行Layer Composite获得更快的绘图速度
class Hardward2D
DisplayListHardwareCanv as
+ drawDisplayList() void+ drawHardwareLayer() void
Canv as
+ isHardwareAccelerated() voidHardwareLayer
HardwareRenderer
+ initialize() void
HardwareRendererGlRenderer
HardwareRendererGl20Renderer
GLES20Canv as
GLES20RecordingCanv as
GLES20DisplayList
laquonativeraquoDisplayList
laquonativeraquoOpenGLRenderer
laquonativeraquoDisplayListRenderer
ViewAttachInfo
ViewRootImpl
+ setView() void+ scheduleTraversals() void+ performTraversals() void+ relayoutWindow() void
GLES20Layer
GLES20TextureLayer
+mCanvas
+mNativeDisplayList
draw
+mRenderer
+mAttachInfo
+mHardwareRenderer
+mHardwareCanvas
+mResizeBuffer
Reference
bull Android 圖形系統 -- 設計與實做分析
bull How to replace GLSurfaceView with TextureView in Android Ice Cream Sandwich
The End
Thank you for your listeningYours Sincerely Roger
Window
bull Android 中的 Window 是一个十分容易混淆的概念
bull 它存在应用层面窗口和系统层面窗口的区别
bull 在系统窗口这个层面中存在客户端窗口和服务端窗口的区别
androidviewWindow
bull Abstract base class for a top-level window look and behavior policy
bull It provides standard UI policies such as a background title area default key processing etc
bull 它是通常意义上我们理解的应用层面窗口TopLevelWindow or WindowPolicy 可能是一个更合适的名字
PhoneWindowbull PhoneWindow 是抽象类 Window 的唯一实现bull ActivityThread 在启动一个 Activity 的时候 Activity 会
创建一个 PhoneWindowndash ActivityThreadhandleLaunchActivityndash -gt ActivityThreadperformLaunchActivity ndash -gt Activityattach
bull ActivitysetContentView 实际上是调用 PhoneWindowsetContentView 在该方法的第一次调用时 PhoneWindow 会创建一个 DecorView 作为 Top-Level-Window 的View Hierachy 的根节点
View Hierachy
WindowManagerbull androidviewWindowManager
ndash The interface that apps use to talk to the window managerndash 真正的实现是 WindowManagerImpl 由 PhoneWindow 在 Act
ivity 启动时创建bull ActivityThreadhandleLaunchActivitybull -gt ActivityThreadperformLaunchActivitybull -gt Activityattachbull -gt PhoneWindowsetWindowManager
ndash 当 Activity 启动后 ActivityThread 将 DocorView 添加到 WindowManagerImpl 中
bull ActivityThreadhandleLaunchActivitybull -gt ActivityThreadhandleResumeActivity bull -gt WindowManageraddView
Contbull WindowManagerImpl 负责跟 WMS 通讯
ndash 但实际上每一个 Window 跟 WMS 之间的通讯是由 ViewRootImpl 负责 ViewRootImpl 在 addView 时被创建
ndash 这里的 Window 是指系统层面的 Window 除了之前的 PhoneWindow 外其它如 Dialog Menu 都拥有一个独立的 Window
ndash ViewRootImpl 的每一个实例都跟通过 addView 传进来一个 View Hierachy 的根节点形成一一对应的关系它是真正意义上的 View Hierachy 的根节点
ndash ViewRootImpl 可以看作是系统层面的 Window 在客户端的代理者
ViewRootImpl
bull The top of a view hierarchy implementing the needed protocol between View and the WindowManager
bull This is for the most part an internal implementation detail WindowManagerImpl
Contbull ViewRootImpl 会打开一个 IWindowSession 用于跟 WM
S 对话bull 并通过 IWindowSession 向 WMS 注册一个窗口(实际上
是让 WMS 在服务端创建一个窗口( WindowState )并且把该服务端的窗口跟 ViewRootImpl 传过来的 IWindow 回调接口绑定在一起)
ndash ActivityThreadhandleLaunchActivityndash -gt ActivityThreadhandleResumeActivity ndash -gt WindowManagerImpladdViewndash -gt ViewRootImplsetView
Contbull IWindow
ndash API back to a client window that the Window Manager uses to inform it of interesting things happening
ndash 回调接口用于接收 WMS 关于窗口的消息 mdashmdash 显示 隐藏大小改变焦点变化等等
bull 除了注册窗口外 ViewRootImpl还向 WMS (通过 InputQueue )注册了一个 InputHandler 用于接收输入事件
bull 接收到的输入事件会先放在 UI 线程的消息循环中然后通过 ViewRootImpl 进行分派在它对应的 View Hierachy 上路由
class Window
Activ ityThread
+ handleLaunchActivity() void+ handleResumeActivity() void+ performLaunchActivity() void
Activ ity
+ attach() void+ onCreate() void+ setContentView() void
Window
+ setContentView() void
PhoneWindow PhoneWindowDecorView
ViewRootImpl
+ setView() void+ scheduleTraversals() void+ performTraversals() void+ relayoutWindow() void
ViewGroup
laquointerfaceraquoWindowManager
laquointerfaceraquoViewManager
WindowLocalWindowManager
WindowManagerImpl
+ addView() void
WindowManagerImplCompatModeWrapper
laquointerfaceraquoViewParent
laquointerfaceraquoIWindowSession
+ add() void+ relayout() void
laquointerfaceraquoIWindow
ViewRootImplW IWindowStub
create +mWindow
+mDecor
+mContentParent
+mWindowManager
+mWindowManager
+mRoots
parent
+mView
+sWindowSession
addView
+mWindow
Overall Flowbull ActivityThead 创建 Activitybull Activity 创建 PhoneWindowbull PhoneWindow 创建 DecorView 作为 View Hierachy 的根节点 Client 端设
置的 Content View 会 attach 到 DecorView 下面(间接)bull PhoneWindow 创建 WindowManagerImplbull ActivityThead 把 DecorView 加到 WindowManagerImpl 里面bull WindowManagerImpl 创建 ViewRootImpl 并把 DecorView 传给它bull ViewRootImpl 打开一个 Window Session 跟 WMS 通讯通过 Session 注册
一个窗口最后客户端拥有一个 IWindow 回调接口服务端拥有一个 WindowState 跟该回调接口绑定
View Hierachy Rendering
bull 当 ViewRootImpl 建立跟 WMS 的联系注册了窗口后会发出第一次渲染 View Hierachy 的请求
ndash ViewRootImplsetViewndash ViewRootImplrequestLayoutndash ViewRootImplscheduleTraversals
bull 在第一次的 View Hierachy 的渲染中( ViewRootImplperformTraversals ) ViewRootImpl需要创建 Surface
Contbull 当 Surface 创建后后续的渲染就可以通过获得
Surface 的 Canvas ( SurfacelockCanvas )bull 然后遍历 View Hierachy 把需要绘制的 Views
通过 Canvas 绘制到 Surface 上面( ViewonDraw )
bull 绘制完后需要解锁( SurfaceunlockCanvasPost )让 SurfaceFlinger 可以将 Surface 绘制到屏幕上( Screen Composite )
Surfacebull Handle onto a raw buffer that is being managed by the
screen compositor
bull 每个 Window 都有一个 Surface 由窗口在客户端的代理者 ViewRootImpl 所拥有
bull Surface 在 ViewRootImpl 第一次渲染 View Hierachy 时创建
ndash ViewRootImplperformTraversalsndash ViewRootImplrelayoutWindowndash IWindowSessionrelayout
Contbull ViewRootImpl预先创建一个空的 Surface 对象( Java )在需要
创建真正的 Surface 的时候它调用 IWindowSessionrelayout 这是一个 RPC 最终是 WMS 的 relayoutWindow 被调用
bull WMS 调用 WindowStatecreateSurfaceLocked 创建了一个 Surface对象( Java )并把这个对象的数据传回给客户端而客户端则负责用这些数据填充预先创建的空 Surface 对象( Java )
ndash 实际上 WMS 是请求 SurfaceFlinger 创建真正的 Surface 然后把 Surface相关的信息再传回给客户端
ndash 客户端利用这些信息来创建一个 native Surface 对象然后把它跟 Java Surface 对象绑定在一起
ndash 客户端的 Java Surface 对象以后就可以通过这个 native Surface 对象来操作图像缓存( GraphicsBuffer )图像缓存可以看作是一块共享内存在客户端和 SurfaceFlinger 之间共享
Surface amp Canvasbull Surface ( Java )包含一个 Canvas ( Java )而 Can
vas ( Java )包含一个 native 的 SkCanvas 对象bull 当调用 SurfacelockCanvas 时
ndash 从图像缓存队列中取出一个可用的缓存ndash 把当前的 Posted Buffer 的内容拷贝到新缓存中(除了 Dirty Regi
on 之外的区域)然后将这块缓存加锁并设置为 Locked Buffer
ndash 获得新缓存的内存地址根据内存地址构建一个 SkBitmapndash 把该 SkBitmap 设置到 SkCanvas 里面ndash 返回跟 SkCanvas 对应的 Canvas ( Java )透过 Canvas ( Ja
va )绘制的内容实际上就是绘制到当前的缓存
Cont
bull 当调用 SurfaceunlockCanvasAndPost 的时候ndash 置空 SkCanvas 设置一个空的 SkBitmapndash 将 Locked Buffer 解锁并返回到图像缓存队列里面ndash 将 Posted Buffer 设置为 Locked Buffer 旧的 Poste
d Buffer 就可以被下次取出来使用设置 Locked Buffer 为空
ndash 当 SurfaceFlinger 下次进行 Screen Composite 的时候就会把当前的 Posted Buffer 绘制到屏幕上
SurfaceFlingerbull 应用跟 SF 之间的关系是就像是生产者与消费者的关系bull 应用从 Surface 的 GraphicsBuffer队列的前端取出一个缓存然后进行绘制
bull 绘制完毕后把该缓存放置回队列的后端(生产)bull 而 SF 则不断地将 Surface 的 GraphicsBuffer队列的最后
一个缓存绘制到屏幕上(消费)bull 两者在不同的进程是异步进行的对队列的访问需要进
行同步
class Surface
ViewRootImpl
+ setView() void+ scheduleTraversals() void+ performTraversals() void+ relayoutWindow() void
Surface
+ lockCanvas () Canvas+ unlockCanvasAndPost (Canvas) void
laquointerfaceraquoIWindowSession
+ add() void+ relayout() void
Canvas
+ isHardwareAccelerated() void
laquonativeraquoSurface
laquonativeraquoSurfaceController
SurfaceCompatibleCanvas
laquonativeraquoSkCanvas
WindowManagerServ ice
+ relayoutWindow() void
SurfaceSession
Session
+ relayout() void
WindowState
+ createSurfaceLocked() void
laquonativeraquoSurfaceFlinger
IWindowSessionStub
laquonativeraquoSurfaceComposerCilent
laquonativeraquoBnSurfaceComposer
laquonativeraquoISurfaceComposerClient
laquonativeraquoSurfaceTextureClient
+mSurface
+sWindowSession
+mCanvas
+mSurfaceControl
+mNativeSurface
+mNativeCanvas
+mSurfaceSession
+mService
+mSessions
+mWindowMap
setBitmapDevice
communication+mClient
+mClient
Overall Flowbull ViewRootImpl 第一次渲染 View Hierachy 的时候会创建一个 Surfac
ebull 客户端请求 WMS 创建 Surface 并返回 Surface相关的数据用于构
建一个 native 的 Surface 对象并把它跟 ViewRootImpl 的 Surface( Java )绑定在一起
bull ViewRootImpl 在渲染时先从 Surface获得 Canvasbull 然后把需要绘制的 Views 通过 Canvas 绘制到 Surface 上面bull 绘制完毕后解锁该 Surfacebull SurfaceFlinger 在做 Screen Composite 的时候把解锁后的 Surface
绘制到屏幕上
Those special Views
SurfaceViewbull Provides a dedicated drawing surface embedded
inside of a view hierarchy You can control the format of this surface and if you like its size the SurfaceView takes care of placing the surface at the correct location on the screen
bull The surface is Z ordered so that it is behind the window holding its SurfaceView the SurfaceView punches a hole in its window to allow its surface to be displayed
Contbull Pros
ndash 可以跟 View Hierachy较好地结合在一起可以移动改变大小在上方叠加其它的 View
ndash 在单独的渲染线程进行渲染渲染效率高
ndash SV 的 Surface 和 Window Surface 之间的混合是由系统( SurfaceFlinger )使用硬件加速完成效率高并且不占用应用本身的 UI 线程时间
bull Consndash SurfaceView 的渲染毕竟跟
真正的 View不一样它不是由 ViewRootImpl渲染到当前的 Window Surface 上面
ndash 不能改变 Alpha 不支持跟下方的 View 进行 Alpha 混合
ndash 不能做 Rotation Skew等变换
GLSurfaceViewbull An implementation of SurfaceView that uses the dedicated surfac
e for displaying OpenGL renderingbull A GLSurfaceView provides the following features
ndash Manages a surface which is a special piece of memory that can be composited into the Android view system
ndash Manages an EGL display which enables OpenGL to render into a surfacendash Accepts a user-provided Renderer object that does the actual renderingndash Renders on a dedicated thread to decouple rendering performance from
the UI threadndash Supports both on-demand and continuous renderingndash Optionally wraps traces andor error-checks the renderers OpenGL call
s
Contbull GLSurfaceView 创建一个内部的线程 GLThreadbull 在该线程运行环境下创建一个 EglContextbull 创建一个 EglSurface ( Window Surface )bull 设置之前创建的 EglContext 为当前的 GL Contex
t 并绑定到创建的 EglSurface 上bull 在该线程内就可以通过 EGL 指令在当前的 GL Co
ntext 上绘图
Contbull GLSurfaceView支持两种不同的绘图模式
ndash 连续模式下 GLThread 会不断调用 RendereronDrawFrame 进行绘图
ndash Dirty 模式下 GLThread处于等待状态直到程序发送绘图请求( GLSurfaceViewrequestRender )才调用 RendereronDrawFrame 进行绘图绘制完一帧后重新进入等待状态
bull 在 RendereronDrawFrame 的回调中应用可以通过 SDK提供的 EGL API 绘图也可以转到 native 端使用 NDK提供的 EGL API 绘图
class SurfaceView
SurfaceView
GLSurfaceView GLSurfaceViewRenderer
+ onDrawFrame() void
GLSurfaceViewGLThread
GLSurfaceViewEglHelper
laquointerfaceraquoSurfaceHolder
laquointerfaceraquoSurfaceHolder
Callback
Surface
+ lockCanvas () Canvas+ unlockCanvasAndPost (Canvas) void
laquointerfaceraquoIWindowSession
+ add() void+ relayout() void
SurfaceViewMyWindow
BaseIWindow IWindowStublaquointerfaceraquo
IWindow
+mSurface
+mSession
+mWindow
+mCallbacks
+mSurfaceHolder
+mRenderer
+mGLThread
call
+mRenderer
+mEglHelper
TextureView
bull Since Android 40只在硬件加速环境下起作用bull 具备 SurfaceView 的特性
ndash 但是可以跟其它普通的 View 一样实现 Rotation Screw等变换
ndash 支持 Alpha 可以跟它下方的 View 进行 Alpha 混合
bull 可以基于 TextureView 创建一个 GL Surface 在上面进行 OpenGL渲染
Things become more complicated after Android 30
HW Accelerated 2D Renderingbull Android 30后开始支持硬件加速的 2D 绘图原
有的绘图流程变得更加复杂bull 所谓硬件加速的 2D 绘图就是将 2D Graphics A
PI 的实现改成使用 OpenGL API 来进行绘图bull OpenGL 的绘图模式跟一般的 2D 绘图有很大区
别它需要先将绘图所需的各种素材如贴图多边形顶点阵列 Shader等先加载到当前的 GLContext 然后流水线式的顺序执行绘图指令通过这种方式来充分利用硬件的能力
ViewRootImplbull 当 Actitity 的 View Hierachy 的根节点被添加到 WindowM
anager 的时候( WindowManageraddView ) WindowManager 的实现类 WindowManagerImpl 会创建一个 ViewRootImpl 并把它跟传进来的 View 绑定在一起( ViewRootImplsetView )并且 ViewRootImpl 会根据是否开启硬件加速来决定是否创建一个 HardwareRenderer
bull 在 ViewRootImpl 第一次渲染 View Hierachy 时会创建 Surface 如果开启硬件加速则通过 HardwareRenderer在当前的 UI 线程初始化EGL 绘图环境(类似 GLSurfaceView )
Contbull 在 ViewRootImpl 真正渲染 View Hierachy
时如果开启硬件加速则从 HardwareRenderer获得一个 HardwareCanvas 然后 View Hierachy 的渲染通过 HardwareCanvas 来进行
bull HardwareCanvas 跟一个 native 的 OpenGLRenderer 绑定通过它调用 EGL API 来完成真正的绘制
DisplayList and Hardware Layerbull 为了充分利用硬件加速的能力 Android 30 还引入了 Di
splayList 和 Hardware Layerbull DisplayList 用于记录一系列OpenGL 绘图指令和缓存所需的各种绘图素材( Bitmap Paint Shape Shader )当 View 的内容不发生变化时可以直接使用 DisplayList 进行绘制而不需要重新调用 onDraw
bull Hardware Layer 用于缓存绘制的内存到 Frame Buffer Object 当内容不发生变化时可以直接使用 Layer 进行Layer Composite获得更快的绘图速度
class Hardward2D
DisplayListHardwareCanv as
+ drawDisplayList() void+ drawHardwareLayer() void
Canv as
+ isHardwareAccelerated() voidHardwareLayer
HardwareRenderer
+ initialize() void
HardwareRendererGlRenderer
HardwareRendererGl20Renderer
GLES20Canv as
GLES20RecordingCanv as
GLES20DisplayList
laquonativeraquoDisplayList
laquonativeraquoOpenGLRenderer
laquonativeraquoDisplayListRenderer
ViewAttachInfo
ViewRootImpl
+ setView() void+ scheduleTraversals() void+ performTraversals() void+ relayoutWindow() void
GLES20Layer
GLES20TextureLayer
+mCanvas
+mNativeDisplayList
draw
+mRenderer
+mAttachInfo
+mHardwareRenderer
+mHardwareCanvas
+mResizeBuffer
Reference
bull Android 圖形系統 -- 設計與實做分析
bull How to replace GLSurfaceView with TextureView in Android Ice Cream Sandwich
The End
Thank you for your listeningYours Sincerely Roger
androidviewWindow
bull Abstract base class for a top-level window look and behavior policy
bull It provides standard UI policies such as a background title area default key processing etc
bull 它是通常意义上我们理解的应用层面窗口TopLevelWindow or WindowPolicy 可能是一个更合适的名字
PhoneWindowbull PhoneWindow 是抽象类 Window 的唯一实现bull ActivityThread 在启动一个 Activity 的时候 Activity 会
创建一个 PhoneWindowndash ActivityThreadhandleLaunchActivityndash -gt ActivityThreadperformLaunchActivity ndash -gt Activityattach
bull ActivitysetContentView 实际上是调用 PhoneWindowsetContentView 在该方法的第一次调用时 PhoneWindow 会创建一个 DecorView 作为 Top-Level-Window 的View Hierachy 的根节点
View Hierachy
WindowManagerbull androidviewWindowManager
ndash The interface that apps use to talk to the window managerndash 真正的实现是 WindowManagerImpl 由 PhoneWindow 在 Act
ivity 启动时创建bull ActivityThreadhandleLaunchActivitybull -gt ActivityThreadperformLaunchActivitybull -gt Activityattachbull -gt PhoneWindowsetWindowManager
ndash 当 Activity 启动后 ActivityThread 将 DocorView 添加到 WindowManagerImpl 中
bull ActivityThreadhandleLaunchActivitybull -gt ActivityThreadhandleResumeActivity bull -gt WindowManageraddView
Contbull WindowManagerImpl 负责跟 WMS 通讯
ndash 但实际上每一个 Window 跟 WMS 之间的通讯是由 ViewRootImpl 负责 ViewRootImpl 在 addView 时被创建
ndash 这里的 Window 是指系统层面的 Window 除了之前的 PhoneWindow 外其它如 Dialog Menu 都拥有一个独立的 Window
ndash ViewRootImpl 的每一个实例都跟通过 addView 传进来一个 View Hierachy 的根节点形成一一对应的关系它是真正意义上的 View Hierachy 的根节点
ndash ViewRootImpl 可以看作是系统层面的 Window 在客户端的代理者
ViewRootImpl
bull The top of a view hierarchy implementing the needed protocol between View and the WindowManager
bull This is for the most part an internal implementation detail WindowManagerImpl
Contbull ViewRootImpl 会打开一个 IWindowSession 用于跟 WM
S 对话bull 并通过 IWindowSession 向 WMS 注册一个窗口(实际上
是让 WMS 在服务端创建一个窗口( WindowState )并且把该服务端的窗口跟 ViewRootImpl 传过来的 IWindow 回调接口绑定在一起)
ndash ActivityThreadhandleLaunchActivityndash -gt ActivityThreadhandleResumeActivity ndash -gt WindowManagerImpladdViewndash -gt ViewRootImplsetView
Contbull IWindow
ndash API back to a client window that the Window Manager uses to inform it of interesting things happening
ndash 回调接口用于接收 WMS 关于窗口的消息 mdashmdash 显示 隐藏大小改变焦点变化等等
bull 除了注册窗口外 ViewRootImpl还向 WMS (通过 InputQueue )注册了一个 InputHandler 用于接收输入事件
bull 接收到的输入事件会先放在 UI 线程的消息循环中然后通过 ViewRootImpl 进行分派在它对应的 View Hierachy 上路由
class Window
Activ ityThread
+ handleLaunchActivity() void+ handleResumeActivity() void+ performLaunchActivity() void
Activ ity
+ attach() void+ onCreate() void+ setContentView() void
Window
+ setContentView() void
PhoneWindow PhoneWindowDecorView
ViewRootImpl
+ setView() void+ scheduleTraversals() void+ performTraversals() void+ relayoutWindow() void
ViewGroup
laquointerfaceraquoWindowManager
laquointerfaceraquoViewManager
WindowLocalWindowManager
WindowManagerImpl
+ addView() void
WindowManagerImplCompatModeWrapper
laquointerfaceraquoViewParent
laquointerfaceraquoIWindowSession
+ add() void+ relayout() void
laquointerfaceraquoIWindow
ViewRootImplW IWindowStub
create +mWindow
+mDecor
+mContentParent
+mWindowManager
+mWindowManager
+mRoots
parent
+mView
+sWindowSession
addView
+mWindow
Overall Flowbull ActivityThead 创建 Activitybull Activity 创建 PhoneWindowbull PhoneWindow 创建 DecorView 作为 View Hierachy 的根节点 Client 端设
置的 Content View 会 attach 到 DecorView 下面(间接)bull PhoneWindow 创建 WindowManagerImplbull ActivityThead 把 DecorView 加到 WindowManagerImpl 里面bull WindowManagerImpl 创建 ViewRootImpl 并把 DecorView 传给它bull ViewRootImpl 打开一个 Window Session 跟 WMS 通讯通过 Session 注册
一个窗口最后客户端拥有一个 IWindow 回调接口服务端拥有一个 WindowState 跟该回调接口绑定
View Hierachy Rendering
bull 当 ViewRootImpl 建立跟 WMS 的联系注册了窗口后会发出第一次渲染 View Hierachy 的请求
ndash ViewRootImplsetViewndash ViewRootImplrequestLayoutndash ViewRootImplscheduleTraversals
bull 在第一次的 View Hierachy 的渲染中( ViewRootImplperformTraversals ) ViewRootImpl需要创建 Surface
Contbull 当 Surface 创建后后续的渲染就可以通过获得
Surface 的 Canvas ( SurfacelockCanvas )bull 然后遍历 View Hierachy 把需要绘制的 Views
通过 Canvas 绘制到 Surface 上面( ViewonDraw )
bull 绘制完后需要解锁( SurfaceunlockCanvasPost )让 SurfaceFlinger 可以将 Surface 绘制到屏幕上( Screen Composite )
Surfacebull Handle onto a raw buffer that is being managed by the
screen compositor
bull 每个 Window 都有一个 Surface 由窗口在客户端的代理者 ViewRootImpl 所拥有
bull Surface 在 ViewRootImpl 第一次渲染 View Hierachy 时创建
ndash ViewRootImplperformTraversalsndash ViewRootImplrelayoutWindowndash IWindowSessionrelayout
Contbull ViewRootImpl预先创建一个空的 Surface 对象( Java )在需要
创建真正的 Surface 的时候它调用 IWindowSessionrelayout 这是一个 RPC 最终是 WMS 的 relayoutWindow 被调用
bull WMS 调用 WindowStatecreateSurfaceLocked 创建了一个 Surface对象( Java )并把这个对象的数据传回给客户端而客户端则负责用这些数据填充预先创建的空 Surface 对象( Java )
ndash 实际上 WMS 是请求 SurfaceFlinger 创建真正的 Surface 然后把 Surface相关的信息再传回给客户端
ndash 客户端利用这些信息来创建一个 native Surface 对象然后把它跟 Java Surface 对象绑定在一起
ndash 客户端的 Java Surface 对象以后就可以通过这个 native Surface 对象来操作图像缓存( GraphicsBuffer )图像缓存可以看作是一块共享内存在客户端和 SurfaceFlinger 之间共享
Surface amp Canvasbull Surface ( Java )包含一个 Canvas ( Java )而 Can
vas ( Java )包含一个 native 的 SkCanvas 对象bull 当调用 SurfacelockCanvas 时
ndash 从图像缓存队列中取出一个可用的缓存ndash 把当前的 Posted Buffer 的内容拷贝到新缓存中(除了 Dirty Regi
on 之外的区域)然后将这块缓存加锁并设置为 Locked Buffer
ndash 获得新缓存的内存地址根据内存地址构建一个 SkBitmapndash 把该 SkBitmap 设置到 SkCanvas 里面ndash 返回跟 SkCanvas 对应的 Canvas ( Java )透过 Canvas ( Ja
va )绘制的内容实际上就是绘制到当前的缓存
Cont
bull 当调用 SurfaceunlockCanvasAndPost 的时候ndash 置空 SkCanvas 设置一个空的 SkBitmapndash 将 Locked Buffer 解锁并返回到图像缓存队列里面ndash 将 Posted Buffer 设置为 Locked Buffer 旧的 Poste
d Buffer 就可以被下次取出来使用设置 Locked Buffer 为空
ndash 当 SurfaceFlinger 下次进行 Screen Composite 的时候就会把当前的 Posted Buffer 绘制到屏幕上
SurfaceFlingerbull 应用跟 SF 之间的关系是就像是生产者与消费者的关系bull 应用从 Surface 的 GraphicsBuffer队列的前端取出一个缓存然后进行绘制
bull 绘制完毕后把该缓存放置回队列的后端(生产)bull 而 SF 则不断地将 Surface 的 GraphicsBuffer队列的最后
一个缓存绘制到屏幕上(消费)bull 两者在不同的进程是异步进行的对队列的访问需要进
行同步
class Surface
ViewRootImpl
+ setView() void+ scheduleTraversals() void+ performTraversals() void+ relayoutWindow() void
Surface
+ lockCanvas () Canvas+ unlockCanvasAndPost (Canvas) void
laquointerfaceraquoIWindowSession
+ add() void+ relayout() void
Canvas
+ isHardwareAccelerated() void
laquonativeraquoSurface
laquonativeraquoSurfaceController
SurfaceCompatibleCanvas
laquonativeraquoSkCanvas
WindowManagerServ ice
+ relayoutWindow() void
SurfaceSession
Session
+ relayout() void
WindowState
+ createSurfaceLocked() void
laquonativeraquoSurfaceFlinger
IWindowSessionStub
laquonativeraquoSurfaceComposerCilent
laquonativeraquoBnSurfaceComposer
laquonativeraquoISurfaceComposerClient
laquonativeraquoSurfaceTextureClient
+mSurface
+sWindowSession
+mCanvas
+mSurfaceControl
+mNativeSurface
+mNativeCanvas
+mSurfaceSession
+mService
+mSessions
+mWindowMap
setBitmapDevice
communication+mClient
+mClient
Overall Flowbull ViewRootImpl 第一次渲染 View Hierachy 的时候会创建一个 Surfac
ebull 客户端请求 WMS 创建 Surface 并返回 Surface相关的数据用于构
建一个 native 的 Surface 对象并把它跟 ViewRootImpl 的 Surface( Java )绑定在一起
bull ViewRootImpl 在渲染时先从 Surface获得 Canvasbull 然后把需要绘制的 Views 通过 Canvas 绘制到 Surface 上面bull 绘制完毕后解锁该 Surfacebull SurfaceFlinger 在做 Screen Composite 的时候把解锁后的 Surface
绘制到屏幕上
Those special Views
SurfaceViewbull Provides a dedicated drawing surface embedded
inside of a view hierarchy You can control the format of this surface and if you like its size the SurfaceView takes care of placing the surface at the correct location on the screen
bull The surface is Z ordered so that it is behind the window holding its SurfaceView the SurfaceView punches a hole in its window to allow its surface to be displayed
Contbull Pros
ndash 可以跟 View Hierachy较好地结合在一起可以移动改变大小在上方叠加其它的 View
ndash 在单独的渲染线程进行渲染渲染效率高
ndash SV 的 Surface 和 Window Surface 之间的混合是由系统( SurfaceFlinger )使用硬件加速完成效率高并且不占用应用本身的 UI 线程时间
bull Consndash SurfaceView 的渲染毕竟跟
真正的 View不一样它不是由 ViewRootImpl渲染到当前的 Window Surface 上面
ndash 不能改变 Alpha 不支持跟下方的 View 进行 Alpha 混合
ndash 不能做 Rotation Skew等变换
GLSurfaceViewbull An implementation of SurfaceView that uses the dedicated surfac
e for displaying OpenGL renderingbull A GLSurfaceView provides the following features
ndash Manages a surface which is a special piece of memory that can be composited into the Android view system
ndash Manages an EGL display which enables OpenGL to render into a surfacendash Accepts a user-provided Renderer object that does the actual renderingndash Renders on a dedicated thread to decouple rendering performance from
the UI threadndash Supports both on-demand and continuous renderingndash Optionally wraps traces andor error-checks the renderers OpenGL call
s
Contbull GLSurfaceView 创建一个内部的线程 GLThreadbull 在该线程运行环境下创建一个 EglContextbull 创建一个 EglSurface ( Window Surface )bull 设置之前创建的 EglContext 为当前的 GL Contex
t 并绑定到创建的 EglSurface 上bull 在该线程内就可以通过 EGL 指令在当前的 GL Co
ntext 上绘图
Contbull GLSurfaceView支持两种不同的绘图模式
ndash 连续模式下 GLThread 会不断调用 RendereronDrawFrame 进行绘图
ndash Dirty 模式下 GLThread处于等待状态直到程序发送绘图请求( GLSurfaceViewrequestRender )才调用 RendereronDrawFrame 进行绘图绘制完一帧后重新进入等待状态
bull 在 RendereronDrawFrame 的回调中应用可以通过 SDK提供的 EGL API 绘图也可以转到 native 端使用 NDK提供的 EGL API 绘图
class SurfaceView
SurfaceView
GLSurfaceView GLSurfaceViewRenderer
+ onDrawFrame() void
GLSurfaceViewGLThread
GLSurfaceViewEglHelper
laquointerfaceraquoSurfaceHolder
laquointerfaceraquoSurfaceHolder
Callback
Surface
+ lockCanvas () Canvas+ unlockCanvasAndPost (Canvas) void
laquointerfaceraquoIWindowSession
+ add() void+ relayout() void
SurfaceViewMyWindow
BaseIWindow IWindowStublaquointerfaceraquo
IWindow
+mSurface
+mSession
+mWindow
+mCallbacks
+mSurfaceHolder
+mRenderer
+mGLThread
call
+mRenderer
+mEglHelper
TextureView
bull Since Android 40只在硬件加速环境下起作用bull 具备 SurfaceView 的特性
ndash 但是可以跟其它普通的 View 一样实现 Rotation Screw等变换
ndash 支持 Alpha 可以跟它下方的 View 进行 Alpha 混合
bull 可以基于 TextureView 创建一个 GL Surface 在上面进行 OpenGL渲染
Things become more complicated after Android 30
HW Accelerated 2D Renderingbull Android 30后开始支持硬件加速的 2D 绘图原
有的绘图流程变得更加复杂bull 所谓硬件加速的 2D 绘图就是将 2D Graphics A
PI 的实现改成使用 OpenGL API 来进行绘图bull OpenGL 的绘图模式跟一般的 2D 绘图有很大区
别它需要先将绘图所需的各种素材如贴图多边形顶点阵列 Shader等先加载到当前的 GLContext 然后流水线式的顺序执行绘图指令通过这种方式来充分利用硬件的能力
ViewRootImplbull 当 Actitity 的 View Hierachy 的根节点被添加到 WindowM
anager 的时候( WindowManageraddView ) WindowManager 的实现类 WindowManagerImpl 会创建一个 ViewRootImpl 并把它跟传进来的 View 绑定在一起( ViewRootImplsetView )并且 ViewRootImpl 会根据是否开启硬件加速来决定是否创建一个 HardwareRenderer
bull 在 ViewRootImpl 第一次渲染 View Hierachy 时会创建 Surface 如果开启硬件加速则通过 HardwareRenderer在当前的 UI 线程初始化EGL 绘图环境(类似 GLSurfaceView )
Contbull 在 ViewRootImpl 真正渲染 View Hierachy
时如果开启硬件加速则从 HardwareRenderer获得一个 HardwareCanvas 然后 View Hierachy 的渲染通过 HardwareCanvas 来进行
bull HardwareCanvas 跟一个 native 的 OpenGLRenderer 绑定通过它调用 EGL API 来完成真正的绘制
DisplayList and Hardware Layerbull 为了充分利用硬件加速的能力 Android 30 还引入了 Di
splayList 和 Hardware Layerbull DisplayList 用于记录一系列OpenGL 绘图指令和缓存所需的各种绘图素材( Bitmap Paint Shape Shader )当 View 的内容不发生变化时可以直接使用 DisplayList 进行绘制而不需要重新调用 onDraw
bull Hardware Layer 用于缓存绘制的内存到 Frame Buffer Object 当内容不发生变化时可以直接使用 Layer 进行Layer Composite获得更快的绘图速度
class Hardward2D
DisplayListHardwareCanv as
+ drawDisplayList() void+ drawHardwareLayer() void
Canv as
+ isHardwareAccelerated() voidHardwareLayer
HardwareRenderer
+ initialize() void
HardwareRendererGlRenderer
HardwareRendererGl20Renderer
GLES20Canv as
GLES20RecordingCanv as
GLES20DisplayList
laquonativeraquoDisplayList
laquonativeraquoOpenGLRenderer
laquonativeraquoDisplayListRenderer
ViewAttachInfo
ViewRootImpl
+ setView() void+ scheduleTraversals() void+ performTraversals() void+ relayoutWindow() void
GLES20Layer
GLES20TextureLayer
+mCanvas
+mNativeDisplayList
draw
+mRenderer
+mAttachInfo
+mHardwareRenderer
+mHardwareCanvas
+mResizeBuffer
Reference
bull Android 圖形系統 -- 設計與實做分析
bull How to replace GLSurfaceView with TextureView in Android Ice Cream Sandwich
The End
Thank you for your listeningYours Sincerely Roger
PhoneWindowbull PhoneWindow 是抽象类 Window 的唯一实现bull ActivityThread 在启动一个 Activity 的时候 Activity 会
创建一个 PhoneWindowndash ActivityThreadhandleLaunchActivityndash -gt ActivityThreadperformLaunchActivity ndash -gt Activityattach
bull ActivitysetContentView 实际上是调用 PhoneWindowsetContentView 在该方法的第一次调用时 PhoneWindow 会创建一个 DecorView 作为 Top-Level-Window 的View Hierachy 的根节点
View Hierachy
WindowManagerbull androidviewWindowManager
ndash The interface that apps use to talk to the window managerndash 真正的实现是 WindowManagerImpl 由 PhoneWindow 在 Act
ivity 启动时创建bull ActivityThreadhandleLaunchActivitybull -gt ActivityThreadperformLaunchActivitybull -gt Activityattachbull -gt PhoneWindowsetWindowManager
ndash 当 Activity 启动后 ActivityThread 将 DocorView 添加到 WindowManagerImpl 中
bull ActivityThreadhandleLaunchActivitybull -gt ActivityThreadhandleResumeActivity bull -gt WindowManageraddView
Contbull WindowManagerImpl 负责跟 WMS 通讯
ndash 但实际上每一个 Window 跟 WMS 之间的通讯是由 ViewRootImpl 负责 ViewRootImpl 在 addView 时被创建
ndash 这里的 Window 是指系统层面的 Window 除了之前的 PhoneWindow 外其它如 Dialog Menu 都拥有一个独立的 Window
ndash ViewRootImpl 的每一个实例都跟通过 addView 传进来一个 View Hierachy 的根节点形成一一对应的关系它是真正意义上的 View Hierachy 的根节点
ndash ViewRootImpl 可以看作是系统层面的 Window 在客户端的代理者
ViewRootImpl
bull The top of a view hierarchy implementing the needed protocol between View and the WindowManager
bull This is for the most part an internal implementation detail WindowManagerImpl
Contbull ViewRootImpl 会打开一个 IWindowSession 用于跟 WM
S 对话bull 并通过 IWindowSession 向 WMS 注册一个窗口(实际上
是让 WMS 在服务端创建一个窗口( WindowState )并且把该服务端的窗口跟 ViewRootImpl 传过来的 IWindow 回调接口绑定在一起)
ndash ActivityThreadhandleLaunchActivityndash -gt ActivityThreadhandleResumeActivity ndash -gt WindowManagerImpladdViewndash -gt ViewRootImplsetView
Contbull IWindow
ndash API back to a client window that the Window Manager uses to inform it of interesting things happening
ndash 回调接口用于接收 WMS 关于窗口的消息 mdashmdash 显示 隐藏大小改变焦点变化等等
bull 除了注册窗口外 ViewRootImpl还向 WMS (通过 InputQueue )注册了一个 InputHandler 用于接收输入事件
bull 接收到的输入事件会先放在 UI 线程的消息循环中然后通过 ViewRootImpl 进行分派在它对应的 View Hierachy 上路由
class Window
Activ ityThread
+ handleLaunchActivity() void+ handleResumeActivity() void+ performLaunchActivity() void
Activ ity
+ attach() void+ onCreate() void+ setContentView() void
Window
+ setContentView() void
PhoneWindow PhoneWindowDecorView
ViewRootImpl
+ setView() void+ scheduleTraversals() void+ performTraversals() void+ relayoutWindow() void
ViewGroup
laquointerfaceraquoWindowManager
laquointerfaceraquoViewManager
WindowLocalWindowManager
WindowManagerImpl
+ addView() void
WindowManagerImplCompatModeWrapper
laquointerfaceraquoViewParent
laquointerfaceraquoIWindowSession
+ add() void+ relayout() void
laquointerfaceraquoIWindow
ViewRootImplW IWindowStub
create +mWindow
+mDecor
+mContentParent
+mWindowManager
+mWindowManager
+mRoots
parent
+mView
+sWindowSession
addView
+mWindow
Overall Flowbull ActivityThead 创建 Activitybull Activity 创建 PhoneWindowbull PhoneWindow 创建 DecorView 作为 View Hierachy 的根节点 Client 端设
置的 Content View 会 attach 到 DecorView 下面(间接)bull PhoneWindow 创建 WindowManagerImplbull ActivityThead 把 DecorView 加到 WindowManagerImpl 里面bull WindowManagerImpl 创建 ViewRootImpl 并把 DecorView 传给它bull ViewRootImpl 打开一个 Window Session 跟 WMS 通讯通过 Session 注册
一个窗口最后客户端拥有一个 IWindow 回调接口服务端拥有一个 WindowState 跟该回调接口绑定
View Hierachy Rendering
bull 当 ViewRootImpl 建立跟 WMS 的联系注册了窗口后会发出第一次渲染 View Hierachy 的请求
ndash ViewRootImplsetViewndash ViewRootImplrequestLayoutndash ViewRootImplscheduleTraversals
bull 在第一次的 View Hierachy 的渲染中( ViewRootImplperformTraversals ) ViewRootImpl需要创建 Surface
Contbull 当 Surface 创建后后续的渲染就可以通过获得
Surface 的 Canvas ( SurfacelockCanvas )bull 然后遍历 View Hierachy 把需要绘制的 Views
通过 Canvas 绘制到 Surface 上面( ViewonDraw )
bull 绘制完后需要解锁( SurfaceunlockCanvasPost )让 SurfaceFlinger 可以将 Surface 绘制到屏幕上( Screen Composite )
Surfacebull Handle onto a raw buffer that is being managed by the
screen compositor
bull 每个 Window 都有一个 Surface 由窗口在客户端的代理者 ViewRootImpl 所拥有
bull Surface 在 ViewRootImpl 第一次渲染 View Hierachy 时创建
ndash ViewRootImplperformTraversalsndash ViewRootImplrelayoutWindowndash IWindowSessionrelayout
Contbull ViewRootImpl预先创建一个空的 Surface 对象( Java )在需要
创建真正的 Surface 的时候它调用 IWindowSessionrelayout 这是一个 RPC 最终是 WMS 的 relayoutWindow 被调用
bull WMS 调用 WindowStatecreateSurfaceLocked 创建了一个 Surface对象( Java )并把这个对象的数据传回给客户端而客户端则负责用这些数据填充预先创建的空 Surface 对象( Java )
ndash 实际上 WMS 是请求 SurfaceFlinger 创建真正的 Surface 然后把 Surface相关的信息再传回给客户端
ndash 客户端利用这些信息来创建一个 native Surface 对象然后把它跟 Java Surface 对象绑定在一起
ndash 客户端的 Java Surface 对象以后就可以通过这个 native Surface 对象来操作图像缓存( GraphicsBuffer )图像缓存可以看作是一块共享内存在客户端和 SurfaceFlinger 之间共享
Surface amp Canvasbull Surface ( Java )包含一个 Canvas ( Java )而 Can
vas ( Java )包含一个 native 的 SkCanvas 对象bull 当调用 SurfacelockCanvas 时
ndash 从图像缓存队列中取出一个可用的缓存ndash 把当前的 Posted Buffer 的内容拷贝到新缓存中(除了 Dirty Regi
on 之外的区域)然后将这块缓存加锁并设置为 Locked Buffer
ndash 获得新缓存的内存地址根据内存地址构建一个 SkBitmapndash 把该 SkBitmap 设置到 SkCanvas 里面ndash 返回跟 SkCanvas 对应的 Canvas ( Java )透过 Canvas ( Ja
va )绘制的内容实际上就是绘制到当前的缓存
Cont
bull 当调用 SurfaceunlockCanvasAndPost 的时候ndash 置空 SkCanvas 设置一个空的 SkBitmapndash 将 Locked Buffer 解锁并返回到图像缓存队列里面ndash 将 Posted Buffer 设置为 Locked Buffer 旧的 Poste
d Buffer 就可以被下次取出来使用设置 Locked Buffer 为空
ndash 当 SurfaceFlinger 下次进行 Screen Composite 的时候就会把当前的 Posted Buffer 绘制到屏幕上
SurfaceFlingerbull 应用跟 SF 之间的关系是就像是生产者与消费者的关系bull 应用从 Surface 的 GraphicsBuffer队列的前端取出一个缓存然后进行绘制
bull 绘制完毕后把该缓存放置回队列的后端(生产)bull 而 SF 则不断地将 Surface 的 GraphicsBuffer队列的最后
一个缓存绘制到屏幕上(消费)bull 两者在不同的进程是异步进行的对队列的访问需要进
行同步
class Surface
ViewRootImpl
+ setView() void+ scheduleTraversals() void+ performTraversals() void+ relayoutWindow() void
Surface
+ lockCanvas () Canvas+ unlockCanvasAndPost (Canvas) void
laquointerfaceraquoIWindowSession
+ add() void+ relayout() void
Canvas
+ isHardwareAccelerated() void
laquonativeraquoSurface
laquonativeraquoSurfaceController
SurfaceCompatibleCanvas
laquonativeraquoSkCanvas
WindowManagerServ ice
+ relayoutWindow() void
SurfaceSession
Session
+ relayout() void
WindowState
+ createSurfaceLocked() void
laquonativeraquoSurfaceFlinger
IWindowSessionStub
laquonativeraquoSurfaceComposerCilent
laquonativeraquoBnSurfaceComposer
laquonativeraquoISurfaceComposerClient
laquonativeraquoSurfaceTextureClient
+mSurface
+sWindowSession
+mCanvas
+mSurfaceControl
+mNativeSurface
+mNativeCanvas
+mSurfaceSession
+mService
+mSessions
+mWindowMap
setBitmapDevice
communication+mClient
+mClient
Overall Flowbull ViewRootImpl 第一次渲染 View Hierachy 的时候会创建一个 Surfac
ebull 客户端请求 WMS 创建 Surface 并返回 Surface相关的数据用于构
建一个 native 的 Surface 对象并把它跟 ViewRootImpl 的 Surface( Java )绑定在一起
bull ViewRootImpl 在渲染时先从 Surface获得 Canvasbull 然后把需要绘制的 Views 通过 Canvas 绘制到 Surface 上面bull 绘制完毕后解锁该 Surfacebull SurfaceFlinger 在做 Screen Composite 的时候把解锁后的 Surface
绘制到屏幕上
Those special Views
SurfaceViewbull Provides a dedicated drawing surface embedded
inside of a view hierarchy You can control the format of this surface and if you like its size the SurfaceView takes care of placing the surface at the correct location on the screen
bull The surface is Z ordered so that it is behind the window holding its SurfaceView the SurfaceView punches a hole in its window to allow its surface to be displayed
Contbull Pros
ndash 可以跟 View Hierachy较好地结合在一起可以移动改变大小在上方叠加其它的 View
ndash 在单独的渲染线程进行渲染渲染效率高
ndash SV 的 Surface 和 Window Surface 之间的混合是由系统( SurfaceFlinger )使用硬件加速完成效率高并且不占用应用本身的 UI 线程时间
bull Consndash SurfaceView 的渲染毕竟跟
真正的 View不一样它不是由 ViewRootImpl渲染到当前的 Window Surface 上面
ndash 不能改变 Alpha 不支持跟下方的 View 进行 Alpha 混合
ndash 不能做 Rotation Skew等变换
GLSurfaceViewbull An implementation of SurfaceView that uses the dedicated surfac
e for displaying OpenGL renderingbull A GLSurfaceView provides the following features
ndash Manages a surface which is a special piece of memory that can be composited into the Android view system
ndash Manages an EGL display which enables OpenGL to render into a surfacendash Accepts a user-provided Renderer object that does the actual renderingndash Renders on a dedicated thread to decouple rendering performance from
the UI threadndash Supports both on-demand and continuous renderingndash Optionally wraps traces andor error-checks the renderers OpenGL call
s
Contbull GLSurfaceView 创建一个内部的线程 GLThreadbull 在该线程运行环境下创建一个 EglContextbull 创建一个 EglSurface ( Window Surface )bull 设置之前创建的 EglContext 为当前的 GL Contex
t 并绑定到创建的 EglSurface 上bull 在该线程内就可以通过 EGL 指令在当前的 GL Co
ntext 上绘图
Contbull GLSurfaceView支持两种不同的绘图模式
ndash 连续模式下 GLThread 会不断调用 RendereronDrawFrame 进行绘图
ndash Dirty 模式下 GLThread处于等待状态直到程序发送绘图请求( GLSurfaceViewrequestRender )才调用 RendereronDrawFrame 进行绘图绘制完一帧后重新进入等待状态
bull 在 RendereronDrawFrame 的回调中应用可以通过 SDK提供的 EGL API 绘图也可以转到 native 端使用 NDK提供的 EGL API 绘图
class SurfaceView
SurfaceView
GLSurfaceView GLSurfaceViewRenderer
+ onDrawFrame() void
GLSurfaceViewGLThread
GLSurfaceViewEglHelper
laquointerfaceraquoSurfaceHolder
laquointerfaceraquoSurfaceHolder
Callback
Surface
+ lockCanvas () Canvas+ unlockCanvasAndPost (Canvas) void
laquointerfaceraquoIWindowSession
+ add() void+ relayout() void
SurfaceViewMyWindow
BaseIWindow IWindowStublaquointerfaceraquo
IWindow
+mSurface
+mSession
+mWindow
+mCallbacks
+mSurfaceHolder
+mRenderer
+mGLThread
call
+mRenderer
+mEglHelper
TextureView
bull Since Android 40只在硬件加速环境下起作用bull 具备 SurfaceView 的特性
ndash 但是可以跟其它普通的 View 一样实现 Rotation Screw等变换
ndash 支持 Alpha 可以跟它下方的 View 进行 Alpha 混合
bull 可以基于 TextureView 创建一个 GL Surface 在上面进行 OpenGL渲染
Things become more complicated after Android 30
HW Accelerated 2D Renderingbull Android 30后开始支持硬件加速的 2D 绘图原
有的绘图流程变得更加复杂bull 所谓硬件加速的 2D 绘图就是将 2D Graphics A
PI 的实现改成使用 OpenGL API 来进行绘图bull OpenGL 的绘图模式跟一般的 2D 绘图有很大区
别它需要先将绘图所需的各种素材如贴图多边形顶点阵列 Shader等先加载到当前的 GLContext 然后流水线式的顺序执行绘图指令通过这种方式来充分利用硬件的能力
ViewRootImplbull 当 Actitity 的 View Hierachy 的根节点被添加到 WindowM
anager 的时候( WindowManageraddView ) WindowManager 的实现类 WindowManagerImpl 会创建一个 ViewRootImpl 并把它跟传进来的 View 绑定在一起( ViewRootImplsetView )并且 ViewRootImpl 会根据是否开启硬件加速来决定是否创建一个 HardwareRenderer
bull 在 ViewRootImpl 第一次渲染 View Hierachy 时会创建 Surface 如果开启硬件加速则通过 HardwareRenderer在当前的 UI 线程初始化EGL 绘图环境(类似 GLSurfaceView )
Contbull 在 ViewRootImpl 真正渲染 View Hierachy
时如果开启硬件加速则从 HardwareRenderer获得一个 HardwareCanvas 然后 View Hierachy 的渲染通过 HardwareCanvas 来进行
bull HardwareCanvas 跟一个 native 的 OpenGLRenderer 绑定通过它调用 EGL API 来完成真正的绘制
DisplayList and Hardware Layerbull 为了充分利用硬件加速的能力 Android 30 还引入了 Di
splayList 和 Hardware Layerbull DisplayList 用于记录一系列OpenGL 绘图指令和缓存所需的各种绘图素材( Bitmap Paint Shape Shader )当 View 的内容不发生变化时可以直接使用 DisplayList 进行绘制而不需要重新调用 onDraw
bull Hardware Layer 用于缓存绘制的内存到 Frame Buffer Object 当内容不发生变化时可以直接使用 Layer 进行Layer Composite获得更快的绘图速度
class Hardward2D
DisplayListHardwareCanv as
+ drawDisplayList() void+ drawHardwareLayer() void
Canv as
+ isHardwareAccelerated() voidHardwareLayer
HardwareRenderer
+ initialize() void
HardwareRendererGlRenderer
HardwareRendererGl20Renderer
GLES20Canv as
GLES20RecordingCanv as
GLES20DisplayList
laquonativeraquoDisplayList
laquonativeraquoOpenGLRenderer
laquonativeraquoDisplayListRenderer
ViewAttachInfo
ViewRootImpl
+ setView() void+ scheduleTraversals() void+ performTraversals() void+ relayoutWindow() void
GLES20Layer
GLES20TextureLayer
+mCanvas
+mNativeDisplayList
draw
+mRenderer
+mAttachInfo
+mHardwareRenderer
+mHardwareCanvas
+mResizeBuffer
Reference
bull Android 圖形系統 -- 設計與實做分析
bull How to replace GLSurfaceView with TextureView in Android Ice Cream Sandwich
The End
Thank you for your listeningYours Sincerely Roger
View Hierachy
WindowManagerbull androidviewWindowManager
ndash The interface that apps use to talk to the window managerndash 真正的实现是 WindowManagerImpl 由 PhoneWindow 在 Act
ivity 启动时创建bull ActivityThreadhandleLaunchActivitybull -gt ActivityThreadperformLaunchActivitybull -gt Activityattachbull -gt PhoneWindowsetWindowManager
ndash 当 Activity 启动后 ActivityThread 将 DocorView 添加到 WindowManagerImpl 中
bull ActivityThreadhandleLaunchActivitybull -gt ActivityThreadhandleResumeActivity bull -gt WindowManageraddView
Contbull WindowManagerImpl 负责跟 WMS 通讯
ndash 但实际上每一个 Window 跟 WMS 之间的通讯是由 ViewRootImpl 负责 ViewRootImpl 在 addView 时被创建
ndash 这里的 Window 是指系统层面的 Window 除了之前的 PhoneWindow 外其它如 Dialog Menu 都拥有一个独立的 Window
ndash ViewRootImpl 的每一个实例都跟通过 addView 传进来一个 View Hierachy 的根节点形成一一对应的关系它是真正意义上的 View Hierachy 的根节点
ndash ViewRootImpl 可以看作是系统层面的 Window 在客户端的代理者
ViewRootImpl
bull The top of a view hierarchy implementing the needed protocol between View and the WindowManager
bull This is for the most part an internal implementation detail WindowManagerImpl
Contbull ViewRootImpl 会打开一个 IWindowSession 用于跟 WM
S 对话bull 并通过 IWindowSession 向 WMS 注册一个窗口(实际上
是让 WMS 在服务端创建一个窗口( WindowState )并且把该服务端的窗口跟 ViewRootImpl 传过来的 IWindow 回调接口绑定在一起)
ndash ActivityThreadhandleLaunchActivityndash -gt ActivityThreadhandleResumeActivity ndash -gt WindowManagerImpladdViewndash -gt ViewRootImplsetView
Contbull IWindow
ndash API back to a client window that the Window Manager uses to inform it of interesting things happening
ndash 回调接口用于接收 WMS 关于窗口的消息 mdashmdash 显示 隐藏大小改变焦点变化等等
bull 除了注册窗口外 ViewRootImpl还向 WMS (通过 InputQueue )注册了一个 InputHandler 用于接收输入事件
bull 接收到的输入事件会先放在 UI 线程的消息循环中然后通过 ViewRootImpl 进行分派在它对应的 View Hierachy 上路由
class Window
Activ ityThread
+ handleLaunchActivity() void+ handleResumeActivity() void+ performLaunchActivity() void
Activ ity
+ attach() void+ onCreate() void+ setContentView() void
Window
+ setContentView() void
PhoneWindow PhoneWindowDecorView
ViewRootImpl
+ setView() void+ scheduleTraversals() void+ performTraversals() void+ relayoutWindow() void
ViewGroup
laquointerfaceraquoWindowManager
laquointerfaceraquoViewManager
WindowLocalWindowManager
WindowManagerImpl
+ addView() void
WindowManagerImplCompatModeWrapper
laquointerfaceraquoViewParent
laquointerfaceraquoIWindowSession
+ add() void+ relayout() void
laquointerfaceraquoIWindow
ViewRootImplW IWindowStub
create +mWindow
+mDecor
+mContentParent
+mWindowManager
+mWindowManager
+mRoots
parent
+mView
+sWindowSession
addView
+mWindow
Overall Flowbull ActivityThead 创建 Activitybull Activity 创建 PhoneWindowbull PhoneWindow 创建 DecorView 作为 View Hierachy 的根节点 Client 端设
置的 Content View 会 attach 到 DecorView 下面(间接)bull PhoneWindow 创建 WindowManagerImplbull ActivityThead 把 DecorView 加到 WindowManagerImpl 里面bull WindowManagerImpl 创建 ViewRootImpl 并把 DecorView 传给它bull ViewRootImpl 打开一个 Window Session 跟 WMS 通讯通过 Session 注册
一个窗口最后客户端拥有一个 IWindow 回调接口服务端拥有一个 WindowState 跟该回调接口绑定
View Hierachy Rendering
bull 当 ViewRootImpl 建立跟 WMS 的联系注册了窗口后会发出第一次渲染 View Hierachy 的请求
ndash ViewRootImplsetViewndash ViewRootImplrequestLayoutndash ViewRootImplscheduleTraversals
bull 在第一次的 View Hierachy 的渲染中( ViewRootImplperformTraversals ) ViewRootImpl需要创建 Surface
Contbull 当 Surface 创建后后续的渲染就可以通过获得
Surface 的 Canvas ( SurfacelockCanvas )bull 然后遍历 View Hierachy 把需要绘制的 Views
通过 Canvas 绘制到 Surface 上面( ViewonDraw )
bull 绘制完后需要解锁( SurfaceunlockCanvasPost )让 SurfaceFlinger 可以将 Surface 绘制到屏幕上( Screen Composite )
Surfacebull Handle onto a raw buffer that is being managed by the
screen compositor
bull 每个 Window 都有一个 Surface 由窗口在客户端的代理者 ViewRootImpl 所拥有
bull Surface 在 ViewRootImpl 第一次渲染 View Hierachy 时创建
ndash ViewRootImplperformTraversalsndash ViewRootImplrelayoutWindowndash IWindowSessionrelayout
Contbull ViewRootImpl预先创建一个空的 Surface 对象( Java )在需要
创建真正的 Surface 的时候它调用 IWindowSessionrelayout 这是一个 RPC 最终是 WMS 的 relayoutWindow 被调用
bull WMS 调用 WindowStatecreateSurfaceLocked 创建了一个 Surface对象( Java )并把这个对象的数据传回给客户端而客户端则负责用这些数据填充预先创建的空 Surface 对象( Java )
ndash 实际上 WMS 是请求 SurfaceFlinger 创建真正的 Surface 然后把 Surface相关的信息再传回给客户端
ndash 客户端利用这些信息来创建一个 native Surface 对象然后把它跟 Java Surface 对象绑定在一起
ndash 客户端的 Java Surface 对象以后就可以通过这个 native Surface 对象来操作图像缓存( GraphicsBuffer )图像缓存可以看作是一块共享内存在客户端和 SurfaceFlinger 之间共享
Surface amp Canvasbull Surface ( Java )包含一个 Canvas ( Java )而 Can
vas ( Java )包含一个 native 的 SkCanvas 对象bull 当调用 SurfacelockCanvas 时
ndash 从图像缓存队列中取出一个可用的缓存ndash 把当前的 Posted Buffer 的内容拷贝到新缓存中(除了 Dirty Regi
on 之外的区域)然后将这块缓存加锁并设置为 Locked Buffer
ndash 获得新缓存的内存地址根据内存地址构建一个 SkBitmapndash 把该 SkBitmap 设置到 SkCanvas 里面ndash 返回跟 SkCanvas 对应的 Canvas ( Java )透过 Canvas ( Ja
va )绘制的内容实际上就是绘制到当前的缓存
Cont
bull 当调用 SurfaceunlockCanvasAndPost 的时候ndash 置空 SkCanvas 设置一个空的 SkBitmapndash 将 Locked Buffer 解锁并返回到图像缓存队列里面ndash 将 Posted Buffer 设置为 Locked Buffer 旧的 Poste
d Buffer 就可以被下次取出来使用设置 Locked Buffer 为空
ndash 当 SurfaceFlinger 下次进行 Screen Composite 的时候就会把当前的 Posted Buffer 绘制到屏幕上
SurfaceFlingerbull 应用跟 SF 之间的关系是就像是生产者与消费者的关系bull 应用从 Surface 的 GraphicsBuffer队列的前端取出一个缓存然后进行绘制
bull 绘制完毕后把该缓存放置回队列的后端(生产)bull 而 SF 则不断地将 Surface 的 GraphicsBuffer队列的最后
一个缓存绘制到屏幕上(消费)bull 两者在不同的进程是异步进行的对队列的访问需要进
行同步
class Surface
ViewRootImpl
+ setView() void+ scheduleTraversals() void+ performTraversals() void+ relayoutWindow() void
Surface
+ lockCanvas () Canvas+ unlockCanvasAndPost (Canvas) void
laquointerfaceraquoIWindowSession
+ add() void+ relayout() void
Canvas
+ isHardwareAccelerated() void
laquonativeraquoSurface
laquonativeraquoSurfaceController
SurfaceCompatibleCanvas
laquonativeraquoSkCanvas
WindowManagerServ ice
+ relayoutWindow() void
SurfaceSession
Session
+ relayout() void
WindowState
+ createSurfaceLocked() void
laquonativeraquoSurfaceFlinger
IWindowSessionStub
laquonativeraquoSurfaceComposerCilent
laquonativeraquoBnSurfaceComposer
laquonativeraquoISurfaceComposerClient
laquonativeraquoSurfaceTextureClient
+mSurface
+sWindowSession
+mCanvas
+mSurfaceControl
+mNativeSurface
+mNativeCanvas
+mSurfaceSession
+mService
+mSessions
+mWindowMap
setBitmapDevice
communication+mClient
+mClient
Overall Flowbull ViewRootImpl 第一次渲染 View Hierachy 的时候会创建一个 Surfac
ebull 客户端请求 WMS 创建 Surface 并返回 Surface相关的数据用于构
建一个 native 的 Surface 对象并把它跟 ViewRootImpl 的 Surface( Java )绑定在一起
bull ViewRootImpl 在渲染时先从 Surface获得 Canvasbull 然后把需要绘制的 Views 通过 Canvas 绘制到 Surface 上面bull 绘制完毕后解锁该 Surfacebull SurfaceFlinger 在做 Screen Composite 的时候把解锁后的 Surface
绘制到屏幕上
Those special Views
SurfaceViewbull Provides a dedicated drawing surface embedded
inside of a view hierarchy You can control the format of this surface and if you like its size the SurfaceView takes care of placing the surface at the correct location on the screen
bull The surface is Z ordered so that it is behind the window holding its SurfaceView the SurfaceView punches a hole in its window to allow its surface to be displayed
Contbull Pros
ndash 可以跟 View Hierachy较好地结合在一起可以移动改变大小在上方叠加其它的 View
ndash 在单独的渲染线程进行渲染渲染效率高
ndash SV 的 Surface 和 Window Surface 之间的混合是由系统( SurfaceFlinger )使用硬件加速完成效率高并且不占用应用本身的 UI 线程时间
bull Consndash SurfaceView 的渲染毕竟跟
真正的 View不一样它不是由 ViewRootImpl渲染到当前的 Window Surface 上面
ndash 不能改变 Alpha 不支持跟下方的 View 进行 Alpha 混合
ndash 不能做 Rotation Skew等变换
GLSurfaceViewbull An implementation of SurfaceView that uses the dedicated surfac
e for displaying OpenGL renderingbull A GLSurfaceView provides the following features
ndash Manages a surface which is a special piece of memory that can be composited into the Android view system
ndash Manages an EGL display which enables OpenGL to render into a surfacendash Accepts a user-provided Renderer object that does the actual renderingndash Renders on a dedicated thread to decouple rendering performance from
the UI threadndash Supports both on-demand and continuous renderingndash Optionally wraps traces andor error-checks the renderers OpenGL call
s
Contbull GLSurfaceView 创建一个内部的线程 GLThreadbull 在该线程运行环境下创建一个 EglContextbull 创建一个 EglSurface ( Window Surface )bull 设置之前创建的 EglContext 为当前的 GL Contex
t 并绑定到创建的 EglSurface 上bull 在该线程内就可以通过 EGL 指令在当前的 GL Co
ntext 上绘图
Contbull GLSurfaceView支持两种不同的绘图模式
ndash 连续模式下 GLThread 会不断调用 RendereronDrawFrame 进行绘图
ndash Dirty 模式下 GLThread处于等待状态直到程序发送绘图请求( GLSurfaceViewrequestRender )才调用 RendereronDrawFrame 进行绘图绘制完一帧后重新进入等待状态
bull 在 RendereronDrawFrame 的回调中应用可以通过 SDK提供的 EGL API 绘图也可以转到 native 端使用 NDK提供的 EGL API 绘图
class SurfaceView
SurfaceView
GLSurfaceView GLSurfaceViewRenderer
+ onDrawFrame() void
GLSurfaceViewGLThread
GLSurfaceViewEglHelper
laquointerfaceraquoSurfaceHolder
laquointerfaceraquoSurfaceHolder
Callback
Surface
+ lockCanvas () Canvas+ unlockCanvasAndPost (Canvas) void
laquointerfaceraquoIWindowSession
+ add() void+ relayout() void
SurfaceViewMyWindow
BaseIWindow IWindowStublaquointerfaceraquo
IWindow
+mSurface
+mSession
+mWindow
+mCallbacks
+mSurfaceHolder
+mRenderer
+mGLThread
call
+mRenderer
+mEglHelper
TextureView
bull Since Android 40只在硬件加速环境下起作用bull 具备 SurfaceView 的特性
ndash 但是可以跟其它普通的 View 一样实现 Rotation Screw等变换
ndash 支持 Alpha 可以跟它下方的 View 进行 Alpha 混合
bull 可以基于 TextureView 创建一个 GL Surface 在上面进行 OpenGL渲染
Things become more complicated after Android 30
HW Accelerated 2D Renderingbull Android 30后开始支持硬件加速的 2D 绘图原
有的绘图流程变得更加复杂bull 所谓硬件加速的 2D 绘图就是将 2D Graphics A
PI 的实现改成使用 OpenGL API 来进行绘图bull OpenGL 的绘图模式跟一般的 2D 绘图有很大区
别它需要先将绘图所需的各种素材如贴图多边形顶点阵列 Shader等先加载到当前的 GLContext 然后流水线式的顺序执行绘图指令通过这种方式来充分利用硬件的能力
ViewRootImplbull 当 Actitity 的 View Hierachy 的根节点被添加到 WindowM
anager 的时候( WindowManageraddView ) WindowManager 的实现类 WindowManagerImpl 会创建一个 ViewRootImpl 并把它跟传进来的 View 绑定在一起( ViewRootImplsetView )并且 ViewRootImpl 会根据是否开启硬件加速来决定是否创建一个 HardwareRenderer
bull 在 ViewRootImpl 第一次渲染 View Hierachy 时会创建 Surface 如果开启硬件加速则通过 HardwareRenderer在当前的 UI 线程初始化EGL 绘图环境(类似 GLSurfaceView )
Contbull 在 ViewRootImpl 真正渲染 View Hierachy
时如果开启硬件加速则从 HardwareRenderer获得一个 HardwareCanvas 然后 View Hierachy 的渲染通过 HardwareCanvas 来进行
bull HardwareCanvas 跟一个 native 的 OpenGLRenderer 绑定通过它调用 EGL API 来完成真正的绘制
DisplayList and Hardware Layerbull 为了充分利用硬件加速的能力 Android 30 还引入了 Di
splayList 和 Hardware Layerbull DisplayList 用于记录一系列OpenGL 绘图指令和缓存所需的各种绘图素材( Bitmap Paint Shape Shader )当 View 的内容不发生变化时可以直接使用 DisplayList 进行绘制而不需要重新调用 onDraw
bull Hardware Layer 用于缓存绘制的内存到 Frame Buffer Object 当内容不发生变化时可以直接使用 Layer 进行Layer Composite获得更快的绘图速度
class Hardward2D
DisplayListHardwareCanv as
+ drawDisplayList() void+ drawHardwareLayer() void
Canv as
+ isHardwareAccelerated() voidHardwareLayer
HardwareRenderer
+ initialize() void
HardwareRendererGlRenderer
HardwareRendererGl20Renderer
GLES20Canv as
GLES20RecordingCanv as
GLES20DisplayList
laquonativeraquoDisplayList
laquonativeraquoOpenGLRenderer
laquonativeraquoDisplayListRenderer
ViewAttachInfo
ViewRootImpl
+ setView() void+ scheduleTraversals() void+ performTraversals() void+ relayoutWindow() void
GLES20Layer
GLES20TextureLayer
+mCanvas
+mNativeDisplayList
draw
+mRenderer
+mAttachInfo
+mHardwareRenderer
+mHardwareCanvas
+mResizeBuffer
Reference
bull Android 圖形系統 -- 設計與實做分析
bull How to replace GLSurfaceView with TextureView in Android Ice Cream Sandwich
The End
Thank you for your listeningYours Sincerely Roger
WindowManagerbull androidviewWindowManager
ndash The interface that apps use to talk to the window managerndash 真正的实现是 WindowManagerImpl 由 PhoneWindow 在 Act
ivity 启动时创建bull ActivityThreadhandleLaunchActivitybull -gt ActivityThreadperformLaunchActivitybull -gt Activityattachbull -gt PhoneWindowsetWindowManager
ndash 当 Activity 启动后 ActivityThread 将 DocorView 添加到 WindowManagerImpl 中
bull ActivityThreadhandleLaunchActivitybull -gt ActivityThreadhandleResumeActivity bull -gt WindowManageraddView
Contbull WindowManagerImpl 负责跟 WMS 通讯
ndash 但实际上每一个 Window 跟 WMS 之间的通讯是由 ViewRootImpl 负责 ViewRootImpl 在 addView 时被创建
ndash 这里的 Window 是指系统层面的 Window 除了之前的 PhoneWindow 外其它如 Dialog Menu 都拥有一个独立的 Window
ndash ViewRootImpl 的每一个实例都跟通过 addView 传进来一个 View Hierachy 的根节点形成一一对应的关系它是真正意义上的 View Hierachy 的根节点
ndash ViewRootImpl 可以看作是系统层面的 Window 在客户端的代理者
ViewRootImpl
bull The top of a view hierarchy implementing the needed protocol between View and the WindowManager
bull This is for the most part an internal implementation detail WindowManagerImpl
Contbull ViewRootImpl 会打开一个 IWindowSession 用于跟 WM
S 对话bull 并通过 IWindowSession 向 WMS 注册一个窗口(实际上
是让 WMS 在服务端创建一个窗口( WindowState )并且把该服务端的窗口跟 ViewRootImpl 传过来的 IWindow 回调接口绑定在一起)
ndash ActivityThreadhandleLaunchActivityndash -gt ActivityThreadhandleResumeActivity ndash -gt WindowManagerImpladdViewndash -gt ViewRootImplsetView
Contbull IWindow
ndash API back to a client window that the Window Manager uses to inform it of interesting things happening
ndash 回调接口用于接收 WMS 关于窗口的消息 mdashmdash 显示 隐藏大小改变焦点变化等等
bull 除了注册窗口外 ViewRootImpl还向 WMS (通过 InputQueue )注册了一个 InputHandler 用于接收输入事件
bull 接收到的输入事件会先放在 UI 线程的消息循环中然后通过 ViewRootImpl 进行分派在它对应的 View Hierachy 上路由
class Window
Activ ityThread
+ handleLaunchActivity() void+ handleResumeActivity() void+ performLaunchActivity() void
Activ ity
+ attach() void+ onCreate() void+ setContentView() void
Window
+ setContentView() void
PhoneWindow PhoneWindowDecorView
ViewRootImpl
+ setView() void+ scheduleTraversals() void+ performTraversals() void+ relayoutWindow() void
ViewGroup
laquointerfaceraquoWindowManager
laquointerfaceraquoViewManager
WindowLocalWindowManager
WindowManagerImpl
+ addView() void
WindowManagerImplCompatModeWrapper
laquointerfaceraquoViewParent
laquointerfaceraquoIWindowSession
+ add() void+ relayout() void
laquointerfaceraquoIWindow
ViewRootImplW IWindowStub
create +mWindow
+mDecor
+mContentParent
+mWindowManager
+mWindowManager
+mRoots
parent
+mView
+sWindowSession
addView
+mWindow
Overall Flowbull ActivityThead 创建 Activitybull Activity 创建 PhoneWindowbull PhoneWindow 创建 DecorView 作为 View Hierachy 的根节点 Client 端设
置的 Content View 会 attach 到 DecorView 下面(间接)bull PhoneWindow 创建 WindowManagerImplbull ActivityThead 把 DecorView 加到 WindowManagerImpl 里面bull WindowManagerImpl 创建 ViewRootImpl 并把 DecorView 传给它bull ViewRootImpl 打开一个 Window Session 跟 WMS 通讯通过 Session 注册
一个窗口最后客户端拥有一个 IWindow 回调接口服务端拥有一个 WindowState 跟该回调接口绑定
View Hierachy Rendering
bull 当 ViewRootImpl 建立跟 WMS 的联系注册了窗口后会发出第一次渲染 View Hierachy 的请求
ndash ViewRootImplsetViewndash ViewRootImplrequestLayoutndash ViewRootImplscheduleTraversals
bull 在第一次的 View Hierachy 的渲染中( ViewRootImplperformTraversals ) ViewRootImpl需要创建 Surface
Contbull 当 Surface 创建后后续的渲染就可以通过获得
Surface 的 Canvas ( SurfacelockCanvas )bull 然后遍历 View Hierachy 把需要绘制的 Views
通过 Canvas 绘制到 Surface 上面( ViewonDraw )
bull 绘制完后需要解锁( SurfaceunlockCanvasPost )让 SurfaceFlinger 可以将 Surface 绘制到屏幕上( Screen Composite )
Surfacebull Handle onto a raw buffer that is being managed by the
screen compositor
bull 每个 Window 都有一个 Surface 由窗口在客户端的代理者 ViewRootImpl 所拥有
bull Surface 在 ViewRootImpl 第一次渲染 View Hierachy 时创建
ndash ViewRootImplperformTraversalsndash ViewRootImplrelayoutWindowndash IWindowSessionrelayout
Contbull ViewRootImpl预先创建一个空的 Surface 对象( Java )在需要
创建真正的 Surface 的时候它调用 IWindowSessionrelayout 这是一个 RPC 最终是 WMS 的 relayoutWindow 被调用
bull WMS 调用 WindowStatecreateSurfaceLocked 创建了一个 Surface对象( Java )并把这个对象的数据传回给客户端而客户端则负责用这些数据填充预先创建的空 Surface 对象( Java )
ndash 实际上 WMS 是请求 SurfaceFlinger 创建真正的 Surface 然后把 Surface相关的信息再传回给客户端
ndash 客户端利用这些信息来创建一个 native Surface 对象然后把它跟 Java Surface 对象绑定在一起
ndash 客户端的 Java Surface 对象以后就可以通过这个 native Surface 对象来操作图像缓存( GraphicsBuffer )图像缓存可以看作是一块共享内存在客户端和 SurfaceFlinger 之间共享
Surface amp Canvasbull Surface ( Java )包含一个 Canvas ( Java )而 Can
vas ( Java )包含一个 native 的 SkCanvas 对象bull 当调用 SurfacelockCanvas 时
ndash 从图像缓存队列中取出一个可用的缓存ndash 把当前的 Posted Buffer 的内容拷贝到新缓存中(除了 Dirty Regi
on 之外的区域)然后将这块缓存加锁并设置为 Locked Buffer
ndash 获得新缓存的内存地址根据内存地址构建一个 SkBitmapndash 把该 SkBitmap 设置到 SkCanvas 里面ndash 返回跟 SkCanvas 对应的 Canvas ( Java )透过 Canvas ( Ja
va )绘制的内容实际上就是绘制到当前的缓存
Cont
bull 当调用 SurfaceunlockCanvasAndPost 的时候ndash 置空 SkCanvas 设置一个空的 SkBitmapndash 将 Locked Buffer 解锁并返回到图像缓存队列里面ndash 将 Posted Buffer 设置为 Locked Buffer 旧的 Poste
d Buffer 就可以被下次取出来使用设置 Locked Buffer 为空
ndash 当 SurfaceFlinger 下次进行 Screen Composite 的时候就会把当前的 Posted Buffer 绘制到屏幕上
SurfaceFlingerbull 应用跟 SF 之间的关系是就像是生产者与消费者的关系bull 应用从 Surface 的 GraphicsBuffer队列的前端取出一个缓存然后进行绘制
bull 绘制完毕后把该缓存放置回队列的后端(生产)bull 而 SF 则不断地将 Surface 的 GraphicsBuffer队列的最后
一个缓存绘制到屏幕上(消费)bull 两者在不同的进程是异步进行的对队列的访问需要进
行同步
class Surface
ViewRootImpl
+ setView() void+ scheduleTraversals() void+ performTraversals() void+ relayoutWindow() void
Surface
+ lockCanvas () Canvas+ unlockCanvasAndPost (Canvas) void
laquointerfaceraquoIWindowSession
+ add() void+ relayout() void
Canvas
+ isHardwareAccelerated() void
laquonativeraquoSurface
laquonativeraquoSurfaceController
SurfaceCompatibleCanvas
laquonativeraquoSkCanvas
WindowManagerServ ice
+ relayoutWindow() void
SurfaceSession
Session
+ relayout() void
WindowState
+ createSurfaceLocked() void
laquonativeraquoSurfaceFlinger
IWindowSessionStub
laquonativeraquoSurfaceComposerCilent
laquonativeraquoBnSurfaceComposer
laquonativeraquoISurfaceComposerClient
laquonativeraquoSurfaceTextureClient
+mSurface
+sWindowSession
+mCanvas
+mSurfaceControl
+mNativeSurface
+mNativeCanvas
+mSurfaceSession
+mService
+mSessions
+mWindowMap
setBitmapDevice
communication+mClient
+mClient
Overall Flowbull ViewRootImpl 第一次渲染 View Hierachy 的时候会创建一个 Surfac
ebull 客户端请求 WMS 创建 Surface 并返回 Surface相关的数据用于构
建一个 native 的 Surface 对象并把它跟 ViewRootImpl 的 Surface( Java )绑定在一起
bull ViewRootImpl 在渲染时先从 Surface获得 Canvasbull 然后把需要绘制的 Views 通过 Canvas 绘制到 Surface 上面bull 绘制完毕后解锁该 Surfacebull SurfaceFlinger 在做 Screen Composite 的时候把解锁后的 Surface
绘制到屏幕上
Those special Views
SurfaceViewbull Provides a dedicated drawing surface embedded
inside of a view hierarchy You can control the format of this surface and if you like its size the SurfaceView takes care of placing the surface at the correct location on the screen
bull The surface is Z ordered so that it is behind the window holding its SurfaceView the SurfaceView punches a hole in its window to allow its surface to be displayed
Contbull Pros
ndash 可以跟 View Hierachy较好地结合在一起可以移动改变大小在上方叠加其它的 View
ndash 在单独的渲染线程进行渲染渲染效率高
ndash SV 的 Surface 和 Window Surface 之间的混合是由系统( SurfaceFlinger )使用硬件加速完成效率高并且不占用应用本身的 UI 线程时间
bull Consndash SurfaceView 的渲染毕竟跟
真正的 View不一样它不是由 ViewRootImpl渲染到当前的 Window Surface 上面
ndash 不能改变 Alpha 不支持跟下方的 View 进行 Alpha 混合
ndash 不能做 Rotation Skew等变换
GLSurfaceViewbull An implementation of SurfaceView that uses the dedicated surfac
e for displaying OpenGL renderingbull A GLSurfaceView provides the following features
ndash Manages a surface which is a special piece of memory that can be composited into the Android view system
ndash Manages an EGL display which enables OpenGL to render into a surfacendash Accepts a user-provided Renderer object that does the actual renderingndash Renders on a dedicated thread to decouple rendering performance from
the UI threadndash Supports both on-demand and continuous renderingndash Optionally wraps traces andor error-checks the renderers OpenGL call
s
Contbull GLSurfaceView 创建一个内部的线程 GLThreadbull 在该线程运行环境下创建一个 EglContextbull 创建一个 EglSurface ( Window Surface )bull 设置之前创建的 EglContext 为当前的 GL Contex
t 并绑定到创建的 EglSurface 上bull 在该线程内就可以通过 EGL 指令在当前的 GL Co
ntext 上绘图
Contbull GLSurfaceView支持两种不同的绘图模式
ndash 连续模式下 GLThread 会不断调用 RendereronDrawFrame 进行绘图
ndash Dirty 模式下 GLThread处于等待状态直到程序发送绘图请求( GLSurfaceViewrequestRender )才调用 RendereronDrawFrame 进行绘图绘制完一帧后重新进入等待状态
bull 在 RendereronDrawFrame 的回调中应用可以通过 SDK提供的 EGL API 绘图也可以转到 native 端使用 NDK提供的 EGL API 绘图
class SurfaceView
SurfaceView
GLSurfaceView GLSurfaceViewRenderer
+ onDrawFrame() void
GLSurfaceViewGLThread
GLSurfaceViewEglHelper
laquointerfaceraquoSurfaceHolder
laquointerfaceraquoSurfaceHolder
Callback
Surface
+ lockCanvas () Canvas+ unlockCanvasAndPost (Canvas) void
laquointerfaceraquoIWindowSession
+ add() void+ relayout() void
SurfaceViewMyWindow
BaseIWindow IWindowStublaquointerfaceraquo
IWindow
+mSurface
+mSession
+mWindow
+mCallbacks
+mSurfaceHolder
+mRenderer
+mGLThread
call
+mRenderer
+mEglHelper
TextureView
bull Since Android 40只在硬件加速环境下起作用bull 具备 SurfaceView 的特性
ndash 但是可以跟其它普通的 View 一样实现 Rotation Screw等变换
ndash 支持 Alpha 可以跟它下方的 View 进行 Alpha 混合
bull 可以基于 TextureView 创建一个 GL Surface 在上面进行 OpenGL渲染
Things become more complicated after Android 30
HW Accelerated 2D Renderingbull Android 30后开始支持硬件加速的 2D 绘图原
有的绘图流程变得更加复杂bull 所谓硬件加速的 2D 绘图就是将 2D Graphics A
PI 的实现改成使用 OpenGL API 来进行绘图bull OpenGL 的绘图模式跟一般的 2D 绘图有很大区
别它需要先将绘图所需的各种素材如贴图多边形顶点阵列 Shader等先加载到当前的 GLContext 然后流水线式的顺序执行绘图指令通过这种方式来充分利用硬件的能力
ViewRootImplbull 当 Actitity 的 View Hierachy 的根节点被添加到 WindowM
anager 的时候( WindowManageraddView ) WindowManager 的实现类 WindowManagerImpl 会创建一个 ViewRootImpl 并把它跟传进来的 View 绑定在一起( ViewRootImplsetView )并且 ViewRootImpl 会根据是否开启硬件加速来决定是否创建一个 HardwareRenderer
bull 在 ViewRootImpl 第一次渲染 View Hierachy 时会创建 Surface 如果开启硬件加速则通过 HardwareRenderer在当前的 UI 线程初始化EGL 绘图环境(类似 GLSurfaceView )
Contbull 在 ViewRootImpl 真正渲染 View Hierachy
时如果开启硬件加速则从 HardwareRenderer获得一个 HardwareCanvas 然后 View Hierachy 的渲染通过 HardwareCanvas 来进行
bull HardwareCanvas 跟一个 native 的 OpenGLRenderer 绑定通过它调用 EGL API 来完成真正的绘制
DisplayList and Hardware Layerbull 为了充分利用硬件加速的能力 Android 30 还引入了 Di
splayList 和 Hardware Layerbull DisplayList 用于记录一系列OpenGL 绘图指令和缓存所需的各种绘图素材( Bitmap Paint Shape Shader )当 View 的内容不发生变化时可以直接使用 DisplayList 进行绘制而不需要重新调用 onDraw
bull Hardware Layer 用于缓存绘制的内存到 Frame Buffer Object 当内容不发生变化时可以直接使用 Layer 进行Layer Composite获得更快的绘图速度
class Hardward2D
DisplayListHardwareCanv as
+ drawDisplayList() void+ drawHardwareLayer() void
Canv as
+ isHardwareAccelerated() voidHardwareLayer
HardwareRenderer
+ initialize() void
HardwareRendererGlRenderer
HardwareRendererGl20Renderer
GLES20Canv as
GLES20RecordingCanv as
GLES20DisplayList
laquonativeraquoDisplayList
laquonativeraquoOpenGLRenderer
laquonativeraquoDisplayListRenderer
ViewAttachInfo
ViewRootImpl
+ setView() void+ scheduleTraversals() void+ performTraversals() void+ relayoutWindow() void
GLES20Layer
GLES20TextureLayer
+mCanvas
+mNativeDisplayList
draw
+mRenderer
+mAttachInfo
+mHardwareRenderer
+mHardwareCanvas
+mResizeBuffer
Reference
bull Android 圖形系統 -- 設計與實做分析
bull How to replace GLSurfaceView with TextureView in Android Ice Cream Sandwich
The End
Thank you for your listeningYours Sincerely Roger
Contbull WindowManagerImpl 负责跟 WMS 通讯
ndash 但实际上每一个 Window 跟 WMS 之间的通讯是由 ViewRootImpl 负责 ViewRootImpl 在 addView 时被创建
ndash 这里的 Window 是指系统层面的 Window 除了之前的 PhoneWindow 外其它如 Dialog Menu 都拥有一个独立的 Window
ndash ViewRootImpl 的每一个实例都跟通过 addView 传进来一个 View Hierachy 的根节点形成一一对应的关系它是真正意义上的 View Hierachy 的根节点
ndash ViewRootImpl 可以看作是系统层面的 Window 在客户端的代理者
ViewRootImpl
bull The top of a view hierarchy implementing the needed protocol between View and the WindowManager
bull This is for the most part an internal implementation detail WindowManagerImpl
Contbull ViewRootImpl 会打开一个 IWindowSession 用于跟 WM
S 对话bull 并通过 IWindowSession 向 WMS 注册一个窗口(实际上
是让 WMS 在服务端创建一个窗口( WindowState )并且把该服务端的窗口跟 ViewRootImpl 传过来的 IWindow 回调接口绑定在一起)
ndash ActivityThreadhandleLaunchActivityndash -gt ActivityThreadhandleResumeActivity ndash -gt WindowManagerImpladdViewndash -gt ViewRootImplsetView
Contbull IWindow
ndash API back to a client window that the Window Manager uses to inform it of interesting things happening
ndash 回调接口用于接收 WMS 关于窗口的消息 mdashmdash 显示 隐藏大小改变焦点变化等等
bull 除了注册窗口外 ViewRootImpl还向 WMS (通过 InputQueue )注册了一个 InputHandler 用于接收输入事件
bull 接收到的输入事件会先放在 UI 线程的消息循环中然后通过 ViewRootImpl 进行分派在它对应的 View Hierachy 上路由
class Window
Activ ityThread
+ handleLaunchActivity() void+ handleResumeActivity() void+ performLaunchActivity() void
Activ ity
+ attach() void+ onCreate() void+ setContentView() void
Window
+ setContentView() void
PhoneWindow PhoneWindowDecorView
ViewRootImpl
+ setView() void+ scheduleTraversals() void+ performTraversals() void+ relayoutWindow() void
ViewGroup
laquointerfaceraquoWindowManager
laquointerfaceraquoViewManager
WindowLocalWindowManager
WindowManagerImpl
+ addView() void
WindowManagerImplCompatModeWrapper
laquointerfaceraquoViewParent
laquointerfaceraquoIWindowSession
+ add() void+ relayout() void
laquointerfaceraquoIWindow
ViewRootImplW IWindowStub
create +mWindow
+mDecor
+mContentParent
+mWindowManager
+mWindowManager
+mRoots
parent
+mView
+sWindowSession
addView
+mWindow
Overall Flowbull ActivityThead 创建 Activitybull Activity 创建 PhoneWindowbull PhoneWindow 创建 DecorView 作为 View Hierachy 的根节点 Client 端设
置的 Content View 会 attach 到 DecorView 下面(间接)bull PhoneWindow 创建 WindowManagerImplbull ActivityThead 把 DecorView 加到 WindowManagerImpl 里面bull WindowManagerImpl 创建 ViewRootImpl 并把 DecorView 传给它bull ViewRootImpl 打开一个 Window Session 跟 WMS 通讯通过 Session 注册
一个窗口最后客户端拥有一个 IWindow 回调接口服务端拥有一个 WindowState 跟该回调接口绑定
View Hierachy Rendering
bull 当 ViewRootImpl 建立跟 WMS 的联系注册了窗口后会发出第一次渲染 View Hierachy 的请求
ndash ViewRootImplsetViewndash ViewRootImplrequestLayoutndash ViewRootImplscheduleTraversals
bull 在第一次的 View Hierachy 的渲染中( ViewRootImplperformTraversals ) ViewRootImpl需要创建 Surface
Contbull 当 Surface 创建后后续的渲染就可以通过获得
Surface 的 Canvas ( SurfacelockCanvas )bull 然后遍历 View Hierachy 把需要绘制的 Views
通过 Canvas 绘制到 Surface 上面( ViewonDraw )
bull 绘制完后需要解锁( SurfaceunlockCanvasPost )让 SurfaceFlinger 可以将 Surface 绘制到屏幕上( Screen Composite )
Surfacebull Handle onto a raw buffer that is being managed by the
screen compositor
bull 每个 Window 都有一个 Surface 由窗口在客户端的代理者 ViewRootImpl 所拥有
bull Surface 在 ViewRootImpl 第一次渲染 View Hierachy 时创建
ndash ViewRootImplperformTraversalsndash ViewRootImplrelayoutWindowndash IWindowSessionrelayout
Contbull ViewRootImpl预先创建一个空的 Surface 对象( Java )在需要
创建真正的 Surface 的时候它调用 IWindowSessionrelayout 这是一个 RPC 最终是 WMS 的 relayoutWindow 被调用
bull WMS 调用 WindowStatecreateSurfaceLocked 创建了一个 Surface对象( Java )并把这个对象的数据传回给客户端而客户端则负责用这些数据填充预先创建的空 Surface 对象( Java )
ndash 实际上 WMS 是请求 SurfaceFlinger 创建真正的 Surface 然后把 Surface相关的信息再传回给客户端
ndash 客户端利用这些信息来创建一个 native Surface 对象然后把它跟 Java Surface 对象绑定在一起
ndash 客户端的 Java Surface 对象以后就可以通过这个 native Surface 对象来操作图像缓存( GraphicsBuffer )图像缓存可以看作是一块共享内存在客户端和 SurfaceFlinger 之间共享
Surface amp Canvasbull Surface ( Java )包含一个 Canvas ( Java )而 Can
vas ( Java )包含一个 native 的 SkCanvas 对象bull 当调用 SurfacelockCanvas 时
ndash 从图像缓存队列中取出一个可用的缓存ndash 把当前的 Posted Buffer 的内容拷贝到新缓存中(除了 Dirty Regi
on 之外的区域)然后将这块缓存加锁并设置为 Locked Buffer
ndash 获得新缓存的内存地址根据内存地址构建一个 SkBitmapndash 把该 SkBitmap 设置到 SkCanvas 里面ndash 返回跟 SkCanvas 对应的 Canvas ( Java )透过 Canvas ( Ja
va )绘制的内容实际上就是绘制到当前的缓存
Cont
bull 当调用 SurfaceunlockCanvasAndPost 的时候ndash 置空 SkCanvas 设置一个空的 SkBitmapndash 将 Locked Buffer 解锁并返回到图像缓存队列里面ndash 将 Posted Buffer 设置为 Locked Buffer 旧的 Poste
d Buffer 就可以被下次取出来使用设置 Locked Buffer 为空
ndash 当 SurfaceFlinger 下次进行 Screen Composite 的时候就会把当前的 Posted Buffer 绘制到屏幕上
SurfaceFlingerbull 应用跟 SF 之间的关系是就像是生产者与消费者的关系bull 应用从 Surface 的 GraphicsBuffer队列的前端取出一个缓存然后进行绘制
bull 绘制完毕后把该缓存放置回队列的后端(生产)bull 而 SF 则不断地将 Surface 的 GraphicsBuffer队列的最后
一个缓存绘制到屏幕上(消费)bull 两者在不同的进程是异步进行的对队列的访问需要进
行同步
class Surface
ViewRootImpl
+ setView() void+ scheduleTraversals() void+ performTraversals() void+ relayoutWindow() void
Surface
+ lockCanvas () Canvas+ unlockCanvasAndPost (Canvas) void
laquointerfaceraquoIWindowSession
+ add() void+ relayout() void
Canvas
+ isHardwareAccelerated() void
laquonativeraquoSurface
laquonativeraquoSurfaceController
SurfaceCompatibleCanvas
laquonativeraquoSkCanvas
WindowManagerServ ice
+ relayoutWindow() void
SurfaceSession
Session
+ relayout() void
WindowState
+ createSurfaceLocked() void
laquonativeraquoSurfaceFlinger
IWindowSessionStub
laquonativeraquoSurfaceComposerCilent
laquonativeraquoBnSurfaceComposer
laquonativeraquoISurfaceComposerClient
laquonativeraquoSurfaceTextureClient
+mSurface
+sWindowSession
+mCanvas
+mSurfaceControl
+mNativeSurface
+mNativeCanvas
+mSurfaceSession
+mService
+mSessions
+mWindowMap
setBitmapDevice
communication+mClient
+mClient
Overall Flowbull ViewRootImpl 第一次渲染 View Hierachy 的时候会创建一个 Surfac
ebull 客户端请求 WMS 创建 Surface 并返回 Surface相关的数据用于构
建一个 native 的 Surface 对象并把它跟 ViewRootImpl 的 Surface( Java )绑定在一起
bull ViewRootImpl 在渲染时先从 Surface获得 Canvasbull 然后把需要绘制的 Views 通过 Canvas 绘制到 Surface 上面bull 绘制完毕后解锁该 Surfacebull SurfaceFlinger 在做 Screen Composite 的时候把解锁后的 Surface
绘制到屏幕上
Those special Views
SurfaceViewbull Provides a dedicated drawing surface embedded
inside of a view hierarchy You can control the format of this surface and if you like its size the SurfaceView takes care of placing the surface at the correct location on the screen
bull The surface is Z ordered so that it is behind the window holding its SurfaceView the SurfaceView punches a hole in its window to allow its surface to be displayed
Contbull Pros
ndash 可以跟 View Hierachy较好地结合在一起可以移动改变大小在上方叠加其它的 View
ndash 在单独的渲染线程进行渲染渲染效率高
ndash SV 的 Surface 和 Window Surface 之间的混合是由系统( SurfaceFlinger )使用硬件加速完成效率高并且不占用应用本身的 UI 线程时间
bull Consndash SurfaceView 的渲染毕竟跟
真正的 View不一样它不是由 ViewRootImpl渲染到当前的 Window Surface 上面
ndash 不能改变 Alpha 不支持跟下方的 View 进行 Alpha 混合
ndash 不能做 Rotation Skew等变换
GLSurfaceViewbull An implementation of SurfaceView that uses the dedicated surfac
e for displaying OpenGL renderingbull A GLSurfaceView provides the following features
ndash Manages a surface which is a special piece of memory that can be composited into the Android view system
ndash Manages an EGL display which enables OpenGL to render into a surfacendash Accepts a user-provided Renderer object that does the actual renderingndash Renders on a dedicated thread to decouple rendering performance from
the UI threadndash Supports both on-demand and continuous renderingndash Optionally wraps traces andor error-checks the renderers OpenGL call
s
Contbull GLSurfaceView 创建一个内部的线程 GLThreadbull 在该线程运行环境下创建一个 EglContextbull 创建一个 EglSurface ( Window Surface )bull 设置之前创建的 EglContext 为当前的 GL Contex
t 并绑定到创建的 EglSurface 上bull 在该线程内就可以通过 EGL 指令在当前的 GL Co
ntext 上绘图
Contbull GLSurfaceView支持两种不同的绘图模式
ndash 连续模式下 GLThread 会不断调用 RendereronDrawFrame 进行绘图
ndash Dirty 模式下 GLThread处于等待状态直到程序发送绘图请求( GLSurfaceViewrequestRender )才调用 RendereronDrawFrame 进行绘图绘制完一帧后重新进入等待状态
bull 在 RendereronDrawFrame 的回调中应用可以通过 SDK提供的 EGL API 绘图也可以转到 native 端使用 NDK提供的 EGL API 绘图
class SurfaceView
SurfaceView
GLSurfaceView GLSurfaceViewRenderer
+ onDrawFrame() void
GLSurfaceViewGLThread
GLSurfaceViewEglHelper
laquointerfaceraquoSurfaceHolder
laquointerfaceraquoSurfaceHolder
Callback
Surface
+ lockCanvas () Canvas+ unlockCanvasAndPost (Canvas) void
laquointerfaceraquoIWindowSession
+ add() void+ relayout() void
SurfaceViewMyWindow
BaseIWindow IWindowStublaquointerfaceraquo
IWindow
+mSurface
+mSession
+mWindow
+mCallbacks
+mSurfaceHolder
+mRenderer
+mGLThread
call
+mRenderer
+mEglHelper
TextureView
bull Since Android 40只在硬件加速环境下起作用bull 具备 SurfaceView 的特性
ndash 但是可以跟其它普通的 View 一样实现 Rotation Screw等变换
ndash 支持 Alpha 可以跟它下方的 View 进行 Alpha 混合
bull 可以基于 TextureView 创建一个 GL Surface 在上面进行 OpenGL渲染
Things become more complicated after Android 30
HW Accelerated 2D Renderingbull Android 30后开始支持硬件加速的 2D 绘图原
有的绘图流程变得更加复杂bull 所谓硬件加速的 2D 绘图就是将 2D Graphics A
PI 的实现改成使用 OpenGL API 来进行绘图bull OpenGL 的绘图模式跟一般的 2D 绘图有很大区
别它需要先将绘图所需的各种素材如贴图多边形顶点阵列 Shader等先加载到当前的 GLContext 然后流水线式的顺序执行绘图指令通过这种方式来充分利用硬件的能力
ViewRootImplbull 当 Actitity 的 View Hierachy 的根节点被添加到 WindowM
anager 的时候( WindowManageraddView ) WindowManager 的实现类 WindowManagerImpl 会创建一个 ViewRootImpl 并把它跟传进来的 View 绑定在一起( ViewRootImplsetView )并且 ViewRootImpl 会根据是否开启硬件加速来决定是否创建一个 HardwareRenderer
bull 在 ViewRootImpl 第一次渲染 View Hierachy 时会创建 Surface 如果开启硬件加速则通过 HardwareRenderer在当前的 UI 线程初始化EGL 绘图环境(类似 GLSurfaceView )
Contbull 在 ViewRootImpl 真正渲染 View Hierachy
时如果开启硬件加速则从 HardwareRenderer获得一个 HardwareCanvas 然后 View Hierachy 的渲染通过 HardwareCanvas 来进行
bull HardwareCanvas 跟一个 native 的 OpenGLRenderer 绑定通过它调用 EGL API 来完成真正的绘制
DisplayList and Hardware Layerbull 为了充分利用硬件加速的能力 Android 30 还引入了 Di
splayList 和 Hardware Layerbull DisplayList 用于记录一系列OpenGL 绘图指令和缓存所需的各种绘图素材( Bitmap Paint Shape Shader )当 View 的内容不发生变化时可以直接使用 DisplayList 进行绘制而不需要重新调用 onDraw
bull Hardware Layer 用于缓存绘制的内存到 Frame Buffer Object 当内容不发生变化时可以直接使用 Layer 进行Layer Composite获得更快的绘图速度
class Hardward2D
DisplayListHardwareCanv as
+ drawDisplayList() void+ drawHardwareLayer() void
Canv as
+ isHardwareAccelerated() voidHardwareLayer
HardwareRenderer
+ initialize() void
HardwareRendererGlRenderer
HardwareRendererGl20Renderer
GLES20Canv as
GLES20RecordingCanv as
GLES20DisplayList
laquonativeraquoDisplayList
laquonativeraquoOpenGLRenderer
laquonativeraquoDisplayListRenderer
ViewAttachInfo
ViewRootImpl
+ setView() void+ scheduleTraversals() void+ performTraversals() void+ relayoutWindow() void
GLES20Layer
GLES20TextureLayer
+mCanvas
+mNativeDisplayList
draw
+mRenderer
+mAttachInfo
+mHardwareRenderer
+mHardwareCanvas
+mResizeBuffer
Reference
bull Android 圖形系統 -- 設計與實做分析
bull How to replace GLSurfaceView with TextureView in Android Ice Cream Sandwich
The End
Thank you for your listeningYours Sincerely Roger
ViewRootImpl
bull The top of a view hierarchy implementing the needed protocol between View and the WindowManager
bull This is for the most part an internal implementation detail WindowManagerImpl
Contbull ViewRootImpl 会打开一个 IWindowSession 用于跟 WM
S 对话bull 并通过 IWindowSession 向 WMS 注册一个窗口(实际上
是让 WMS 在服务端创建一个窗口( WindowState )并且把该服务端的窗口跟 ViewRootImpl 传过来的 IWindow 回调接口绑定在一起)
ndash ActivityThreadhandleLaunchActivityndash -gt ActivityThreadhandleResumeActivity ndash -gt WindowManagerImpladdViewndash -gt ViewRootImplsetView
Contbull IWindow
ndash API back to a client window that the Window Manager uses to inform it of interesting things happening
ndash 回调接口用于接收 WMS 关于窗口的消息 mdashmdash 显示 隐藏大小改变焦点变化等等
bull 除了注册窗口外 ViewRootImpl还向 WMS (通过 InputQueue )注册了一个 InputHandler 用于接收输入事件
bull 接收到的输入事件会先放在 UI 线程的消息循环中然后通过 ViewRootImpl 进行分派在它对应的 View Hierachy 上路由
class Window
Activ ityThread
+ handleLaunchActivity() void+ handleResumeActivity() void+ performLaunchActivity() void
Activ ity
+ attach() void+ onCreate() void+ setContentView() void
Window
+ setContentView() void
PhoneWindow PhoneWindowDecorView
ViewRootImpl
+ setView() void+ scheduleTraversals() void+ performTraversals() void+ relayoutWindow() void
ViewGroup
laquointerfaceraquoWindowManager
laquointerfaceraquoViewManager
WindowLocalWindowManager
WindowManagerImpl
+ addView() void
WindowManagerImplCompatModeWrapper
laquointerfaceraquoViewParent
laquointerfaceraquoIWindowSession
+ add() void+ relayout() void
laquointerfaceraquoIWindow
ViewRootImplW IWindowStub
create +mWindow
+mDecor
+mContentParent
+mWindowManager
+mWindowManager
+mRoots
parent
+mView
+sWindowSession
addView
+mWindow
Overall Flowbull ActivityThead 创建 Activitybull Activity 创建 PhoneWindowbull PhoneWindow 创建 DecorView 作为 View Hierachy 的根节点 Client 端设
置的 Content View 会 attach 到 DecorView 下面(间接)bull PhoneWindow 创建 WindowManagerImplbull ActivityThead 把 DecorView 加到 WindowManagerImpl 里面bull WindowManagerImpl 创建 ViewRootImpl 并把 DecorView 传给它bull ViewRootImpl 打开一个 Window Session 跟 WMS 通讯通过 Session 注册
一个窗口最后客户端拥有一个 IWindow 回调接口服务端拥有一个 WindowState 跟该回调接口绑定
View Hierachy Rendering
bull 当 ViewRootImpl 建立跟 WMS 的联系注册了窗口后会发出第一次渲染 View Hierachy 的请求
ndash ViewRootImplsetViewndash ViewRootImplrequestLayoutndash ViewRootImplscheduleTraversals
bull 在第一次的 View Hierachy 的渲染中( ViewRootImplperformTraversals ) ViewRootImpl需要创建 Surface
Contbull 当 Surface 创建后后续的渲染就可以通过获得
Surface 的 Canvas ( SurfacelockCanvas )bull 然后遍历 View Hierachy 把需要绘制的 Views
通过 Canvas 绘制到 Surface 上面( ViewonDraw )
bull 绘制完后需要解锁( SurfaceunlockCanvasPost )让 SurfaceFlinger 可以将 Surface 绘制到屏幕上( Screen Composite )
Surfacebull Handle onto a raw buffer that is being managed by the
screen compositor
bull 每个 Window 都有一个 Surface 由窗口在客户端的代理者 ViewRootImpl 所拥有
bull Surface 在 ViewRootImpl 第一次渲染 View Hierachy 时创建
ndash ViewRootImplperformTraversalsndash ViewRootImplrelayoutWindowndash IWindowSessionrelayout
Contbull ViewRootImpl预先创建一个空的 Surface 对象( Java )在需要
创建真正的 Surface 的时候它调用 IWindowSessionrelayout 这是一个 RPC 最终是 WMS 的 relayoutWindow 被调用
bull WMS 调用 WindowStatecreateSurfaceLocked 创建了一个 Surface对象( Java )并把这个对象的数据传回给客户端而客户端则负责用这些数据填充预先创建的空 Surface 对象( Java )
ndash 实际上 WMS 是请求 SurfaceFlinger 创建真正的 Surface 然后把 Surface相关的信息再传回给客户端
ndash 客户端利用这些信息来创建一个 native Surface 对象然后把它跟 Java Surface 对象绑定在一起
ndash 客户端的 Java Surface 对象以后就可以通过这个 native Surface 对象来操作图像缓存( GraphicsBuffer )图像缓存可以看作是一块共享内存在客户端和 SurfaceFlinger 之间共享
Surface amp Canvasbull Surface ( Java )包含一个 Canvas ( Java )而 Can
vas ( Java )包含一个 native 的 SkCanvas 对象bull 当调用 SurfacelockCanvas 时
ndash 从图像缓存队列中取出一个可用的缓存ndash 把当前的 Posted Buffer 的内容拷贝到新缓存中(除了 Dirty Regi
on 之外的区域)然后将这块缓存加锁并设置为 Locked Buffer
ndash 获得新缓存的内存地址根据内存地址构建一个 SkBitmapndash 把该 SkBitmap 设置到 SkCanvas 里面ndash 返回跟 SkCanvas 对应的 Canvas ( Java )透过 Canvas ( Ja
va )绘制的内容实际上就是绘制到当前的缓存
Cont
bull 当调用 SurfaceunlockCanvasAndPost 的时候ndash 置空 SkCanvas 设置一个空的 SkBitmapndash 将 Locked Buffer 解锁并返回到图像缓存队列里面ndash 将 Posted Buffer 设置为 Locked Buffer 旧的 Poste
d Buffer 就可以被下次取出来使用设置 Locked Buffer 为空
ndash 当 SurfaceFlinger 下次进行 Screen Composite 的时候就会把当前的 Posted Buffer 绘制到屏幕上
SurfaceFlingerbull 应用跟 SF 之间的关系是就像是生产者与消费者的关系bull 应用从 Surface 的 GraphicsBuffer队列的前端取出一个缓存然后进行绘制
bull 绘制完毕后把该缓存放置回队列的后端(生产)bull 而 SF 则不断地将 Surface 的 GraphicsBuffer队列的最后
一个缓存绘制到屏幕上(消费)bull 两者在不同的进程是异步进行的对队列的访问需要进
行同步
class Surface
ViewRootImpl
+ setView() void+ scheduleTraversals() void+ performTraversals() void+ relayoutWindow() void
Surface
+ lockCanvas () Canvas+ unlockCanvasAndPost (Canvas) void
laquointerfaceraquoIWindowSession
+ add() void+ relayout() void
Canvas
+ isHardwareAccelerated() void
laquonativeraquoSurface
laquonativeraquoSurfaceController
SurfaceCompatibleCanvas
laquonativeraquoSkCanvas
WindowManagerServ ice
+ relayoutWindow() void
SurfaceSession
Session
+ relayout() void
WindowState
+ createSurfaceLocked() void
laquonativeraquoSurfaceFlinger
IWindowSessionStub
laquonativeraquoSurfaceComposerCilent
laquonativeraquoBnSurfaceComposer
laquonativeraquoISurfaceComposerClient
laquonativeraquoSurfaceTextureClient
+mSurface
+sWindowSession
+mCanvas
+mSurfaceControl
+mNativeSurface
+mNativeCanvas
+mSurfaceSession
+mService
+mSessions
+mWindowMap
setBitmapDevice
communication+mClient
+mClient
Overall Flowbull ViewRootImpl 第一次渲染 View Hierachy 的时候会创建一个 Surfac
ebull 客户端请求 WMS 创建 Surface 并返回 Surface相关的数据用于构
建一个 native 的 Surface 对象并把它跟 ViewRootImpl 的 Surface( Java )绑定在一起
bull ViewRootImpl 在渲染时先从 Surface获得 Canvasbull 然后把需要绘制的 Views 通过 Canvas 绘制到 Surface 上面bull 绘制完毕后解锁该 Surfacebull SurfaceFlinger 在做 Screen Composite 的时候把解锁后的 Surface
绘制到屏幕上
Those special Views
SurfaceViewbull Provides a dedicated drawing surface embedded
inside of a view hierarchy You can control the format of this surface and if you like its size the SurfaceView takes care of placing the surface at the correct location on the screen
bull The surface is Z ordered so that it is behind the window holding its SurfaceView the SurfaceView punches a hole in its window to allow its surface to be displayed
Contbull Pros
ndash 可以跟 View Hierachy较好地结合在一起可以移动改变大小在上方叠加其它的 View
ndash 在单独的渲染线程进行渲染渲染效率高
ndash SV 的 Surface 和 Window Surface 之间的混合是由系统( SurfaceFlinger )使用硬件加速完成效率高并且不占用应用本身的 UI 线程时间
bull Consndash SurfaceView 的渲染毕竟跟
真正的 View不一样它不是由 ViewRootImpl渲染到当前的 Window Surface 上面
ndash 不能改变 Alpha 不支持跟下方的 View 进行 Alpha 混合
ndash 不能做 Rotation Skew等变换
GLSurfaceViewbull An implementation of SurfaceView that uses the dedicated surfac
e for displaying OpenGL renderingbull A GLSurfaceView provides the following features
ndash Manages a surface which is a special piece of memory that can be composited into the Android view system
ndash Manages an EGL display which enables OpenGL to render into a surfacendash Accepts a user-provided Renderer object that does the actual renderingndash Renders on a dedicated thread to decouple rendering performance from
the UI threadndash Supports both on-demand and continuous renderingndash Optionally wraps traces andor error-checks the renderers OpenGL call
s
Contbull GLSurfaceView 创建一个内部的线程 GLThreadbull 在该线程运行环境下创建一个 EglContextbull 创建一个 EglSurface ( Window Surface )bull 设置之前创建的 EglContext 为当前的 GL Contex
t 并绑定到创建的 EglSurface 上bull 在该线程内就可以通过 EGL 指令在当前的 GL Co
ntext 上绘图
Contbull GLSurfaceView支持两种不同的绘图模式
ndash 连续模式下 GLThread 会不断调用 RendereronDrawFrame 进行绘图
ndash Dirty 模式下 GLThread处于等待状态直到程序发送绘图请求( GLSurfaceViewrequestRender )才调用 RendereronDrawFrame 进行绘图绘制完一帧后重新进入等待状态
bull 在 RendereronDrawFrame 的回调中应用可以通过 SDK提供的 EGL API 绘图也可以转到 native 端使用 NDK提供的 EGL API 绘图
class SurfaceView
SurfaceView
GLSurfaceView GLSurfaceViewRenderer
+ onDrawFrame() void
GLSurfaceViewGLThread
GLSurfaceViewEglHelper
laquointerfaceraquoSurfaceHolder
laquointerfaceraquoSurfaceHolder
Callback
Surface
+ lockCanvas () Canvas+ unlockCanvasAndPost (Canvas) void
laquointerfaceraquoIWindowSession
+ add() void+ relayout() void
SurfaceViewMyWindow
BaseIWindow IWindowStublaquointerfaceraquo
IWindow
+mSurface
+mSession
+mWindow
+mCallbacks
+mSurfaceHolder
+mRenderer
+mGLThread
call
+mRenderer
+mEglHelper
TextureView
bull Since Android 40只在硬件加速环境下起作用bull 具备 SurfaceView 的特性
ndash 但是可以跟其它普通的 View 一样实现 Rotation Screw等变换
ndash 支持 Alpha 可以跟它下方的 View 进行 Alpha 混合
bull 可以基于 TextureView 创建一个 GL Surface 在上面进行 OpenGL渲染
Things become more complicated after Android 30
HW Accelerated 2D Renderingbull Android 30后开始支持硬件加速的 2D 绘图原
有的绘图流程变得更加复杂bull 所谓硬件加速的 2D 绘图就是将 2D Graphics A
PI 的实现改成使用 OpenGL API 来进行绘图bull OpenGL 的绘图模式跟一般的 2D 绘图有很大区
别它需要先将绘图所需的各种素材如贴图多边形顶点阵列 Shader等先加载到当前的 GLContext 然后流水线式的顺序执行绘图指令通过这种方式来充分利用硬件的能力
ViewRootImplbull 当 Actitity 的 View Hierachy 的根节点被添加到 WindowM
anager 的时候( WindowManageraddView ) WindowManager 的实现类 WindowManagerImpl 会创建一个 ViewRootImpl 并把它跟传进来的 View 绑定在一起( ViewRootImplsetView )并且 ViewRootImpl 会根据是否开启硬件加速来决定是否创建一个 HardwareRenderer
bull 在 ViewRootImpl 第一次渲染 View Hierachy 时会创建 Surface 如果开启硬件加速则通过 HardwareRenderer在当前的 UI 线程初始化EGL 绘图环境(类似 GLSurfaceView )
Contbull 在 ViewRootImpl 真正渲染 View Hierachy
时如果开启硬件加速则从 HardwareRenderer获得一个 HardwareCanvas 然后 View Hierachy 的渲染通过 HardwareCanvas 来进行
bull HardwareCanvas 跟一个 native 的 OpenGLRenderer 绑定通过它调用 EGL API 来完成真正的绘制
DisplayList and Hardware Layerbull 为了充分利用硬件加速的能力 Android 30 还引入了 Di
splayList 和 Hardware Layerbull DisplayList 用于记录一系列OpenGL 绘图指令和缓存所需的各种绘图素材( Bitmap Paint Shape Shader )当 View 的内容不发生变化时可以直接使用 DisplayList 进行绘制而不需要重新调用 onDraw
bull Hardware Layer 用于缓存绘制的内存到 Frame Buffer Object 当内容不发生变化时可以直接使用 Layer 进行Layer Composite获得更快的绘图速度
class Hardward2D
DisplayListHardwareCanv as
+ drawDisplayList() void+ drawHardwareLayer() void
Canv as
+ isHardwareAccelerated() voidHardwareLayer
HardwareRenderer
+ initialize() void
HardwareRendererGlRenderer
HardwareRendererGl20Renderer
GLES20Canv as
GLES20RecordingCanv as
GLES20DisplayList
laquonativeraquoDisplayList
laquonativeraquoOpenGLRenderer
laquonativeraquoDisplayListRenderer
ViewAttachInfo
ViewRootImpl
+ setView() void+ scheduleTraversals() void+ performTraversals() void+ relayoutWindow() void
GLES20Layer
GLES20TextureLayer
+mCanvas
+mNativeDisplayList
draw
+mRenderer
+mAttachInfo
+mHardwareRenderer
+mHardwareCanvas
+mResizeBuffer
Reference
bull Android 圖形系統 -- 設計與實做分析
bull How to replace GLSurfaceView with TextureView in Android Ice Cream Sandwich
The End
Thank you for your listeningYours Sincerely Roger
Contbull ViewRootImpl 会打开一个 IWindowSession 用于跟 WM
S 对话bull 并通过 IWindowSession 向 WMS 注册一个窗口(实际上
是让 WMS 在服务端创建一个窗口( WindowState )并且把该服务端的窗口跟 ViewRootImpl 传过来的 IWindow 回调接口绑定在一起)
ndash ActivityThreadhandleLaunchActivityndash -gt ActivityThreadhandleResumeActivity ndash -gt WindowManagerImpladdViewndash -gt ViewRootImplsetView
Contbull IWindow
ndash API back to a client window that the Window Manager uses to inform it of interesting things happening
ndash 回调接口用于接收 WMS 关于窗口的消息 mdashmdash 显示 隐藏大小改变焦点变化等等
bull 除了注册窗口外 ViewRootImpl还向 WMS (通过 InputQueue )注册了一个 InputHandler 用于接收输入事件
bull 接收到的输入事件会先放在 UI 线程的消息循环中然后通过 ViewRootImpl 进行分派在它对应的 View Hierachy 上路由
class Window
Activ ityThread
+ handleLaunchActivity() void+ handleResumeActivity() void+ performLaunchActivity() void
Activ ity
+ attach() void+ onCreate() void+ setContentView() void
Window
+ setContentView() void
PhoneWindow PhoneWindowDecorView
ViewRootImpl
+ setView() void+ scheduleTraversals() void+ performTraversals() void+ relayoutWindow() void
ViewGroup
laquointerfaceraquoWindowManager
laquointerfaceraquoViewManager
WindowLocalWindowManager
WindowManagerImpl
+ addView() void
WindowManagerImplCompatModeWrapper
laquointerfaceraquoViewParent
laquointerfaceraquoIWindowSession
+ add() void+ relayout() void
laquointerfaceraquoIWindow
ViewRootImplW IWindowStub
create +mWindow
+mDecor
+mContentParent
+mWindowManager
+mWindowManager
+mRoots
parent
+mView
+sWindowSession
addView
+mWindow
Overall Flowbull ActivityThead 创建 Activitybull Activity 创建 PhoneWindowbull PhoneWindow 创建 DecorView 作为 View Hierachy 的根节点 Client 端设
置的 Content View 会 attach 到 DecorView 下面(间接)bull PhoneWindow 创建 WindowManagerImplbull ActivityThead 把 DecorView 加到 WindowManagerImpl 里面bull WindowManagerImpl 创建 ViewRootImpl 并把 DecorView 传给它bull ViewRootImpl 打开一个 Window Session 跟 WMS 通讯通过 Session 注册
一个窗口最后客户端拥有一个 IWindow 回调接口服务端拥有一个 WindowState 跟该回调接口绑定
View Hierachy Rendering
bull 当 ViewRootImpl 建立跟 WMS 的联系注册了窗口后会发出第一次渲染 View Hierachy 的请求
ndash ViewRootImplsetViewndash ViewRootImplrequestLayoutndash ViewRootImplscheduleTraversals
bull 在第一次的 View Hierachy 的渲染中( ViewRootImplperformTraversals ) ViewRootImpl需要创建 Surface
Contbull 当 Surface 创建后后续的渲染就可以通过获得
Surface 的 Canvas ( SurfacelockCanvas )bull 然后遍历 View Hierachy 把需要绘制的 Views
通过 Canvas 绘制到 Surface 上面( ViewonDraw )
bull 绘制完后需要解锁( SurfaceunlockCanvasPost )让 SurfaceFlinger 可以将 Surface 绘制到屏幕上( Screen Composite )
Surfacebull Handle onto a raw buffer that is being managed by the
screen compositor
bull 每个 Window 都有一个 Surface 由窗口在客户端的代理者 ViewRootImpl 所拥有
bull Surface 在 ViewRootImpl 第一次渲染 View Hierachy 时创建
ndash ViewRootImplperformTraversalsndash ViewRootImplrelayoutWindowndash IWindowSessionrelayout
Contbull ViewRootImpl预先创建一个空的 Surface 对象( Java )在需要
创建真正的 Surface 的时候它调用 IWindowSessionrelayout 这是一个 RPC 最终是 WMS 的 relayoutWindow 被调用
bull WMS 调用 WindowStatecreateSurfaceLocked 创建了一个 Surface对象( Java )并把这个对象的数据传回给客户端而客户端则负责用这些数据填充预先创建的空 Surface 对象( Java )
ndash 实际上 WMS 是请求 SurfaceFlinger 创建真正的 Surface 然后把 Surface相关的信息再传回给客户端
ndash 客户端利用这些信息来创建一个 native Surface 对象然后把它跟 Java Surface 对象绑定在一起
ndash 客户端的 Java Surface 对象以后就可以通过这个 native Surface 对象来操作图像缓存( GraphicsBuffer )图像缓存可以看作是一块共享内存在客户端和 SurfaceFlinger 之间共享
Surface amp Canvasbull Surface ( Java )包含一个 Canvas ( Java )而 Can
vas ( Java )包含一个 native 的 SkCanvas 对象bull 当调用 SurfacelockCanvas 时
ndash 从图像缓存队列中取出一个可用的缓存ndash 把当前的 Posted Buffer 的内容拷贝到新缓存中(除了 Dirty Regi
on 之外的区域)然后将这块缓存加锁并设置为 Locked Buffer
ndash 获得新缓存的内存地址根据内存地址构建一个 SkBitmapndash 把该 SkBitmap 设置到 SkCanvas 里面ndash 返回跟 SkCanvas 对应的 Canvas ( Java )透过 Canvas ( Ja
va )绘制的内容实际上就是绘制到当前的缓存
Cont
bull 当调用 SurfaceunlockCanvasAndPost 的时候ndash 置空 SkCanvas 设置一个空的 SkBitmapndash 将 Locked Buffer 解锁并返回到图像缓存队列里面ndash 将 Posted Buffer 设置为 Locked Buffer 旧的 Poste
d Buffer 就可以被下次取出来使用设置 Locked Buffer 为空
ndash 当 SurfaceFlinger 下次进行 Screen Composite 的时候就会把当前的 Posted Buffer 绘制到屏幕上
SurfaceFlingerbull 应用跟 SF 之间的关系是就像是生产者与消费者的关系bull 应用从 Surface 的 GraphicsBuffer队列的前端取出一个缓存然后进行绘制
bull 绘制完毕后把该缓存放置回队列的后端(生产)bull 而 SF 则不断地将 Surface 的 GraphicsBuffer队列的最后
一个缓存绘制到屏幕上(消费)bull 两者在不同的进程是异步进行的对队列的访问需要进
行同步
class Surface
ViewRootImpl
+ setView() void+ scheduleTraversals() void+ performTraversals() void+ relayoutWindow() void
Surface
+ lockCanvas () Canvas+ unlockCanvasAndPost (Canvas) void
laquointerfaceraquoIWindowSession
+ add() void+ relayout() void
Canvas
+ isHardwareAccelerated() void
laquonativeraquoSurface
laquonativeraquoSurfaceController
SurfaceCompatibleCanvas
laquonativeraquoSkCanvas
WindowManagerServ ice
+ relayoutWindow() void
SurfaceSession
Session
+ relayout() void
WindowState
+ createSurfaceLocked() void
laquonativeraquoSurfaceFlinger
IWindowSessionStub
laquonativeraquoSurfaceComposerCilent
laquonativeraquoBnSurfaceComposer
laquonativeraquoISurfaceComposerClient
laquonativeraquoSurfaceTextureClient
+mSurface
+sWindowSession
+mCanvas
+mSurfaceControl
+mNativeSurface
+mNativeCanvas
+mSurfaceSession
+mService
+mSessions
+mWindowMap
setBitmapDevice
communication+mClient
+mClient
Overall Flowbull ViewRootImpl 第一次渲染 View Hierachy 的时候会创建一个 Surfac
ebull 客户端请求 WMS 创建 Surface 并返回 Surface相关的数据用于构
建一个 native 的 Surface 对象并把它跟 ViewRootImpl 的 Surface( Java )绑定在一起
bull ViewRootImpl 在渲染时先从 Surface获得 Canvasbull 然后把需要绘制的 Views 通过 Canvas 绘制到 Surface 上面bull 绘制完毕后解锁该 Surfacebull SurfaceFlinger 在做 Screen Composite 的时候把解锁后的 Surface
绘制到屏幕上
Those special Views
SurfaceViewbull Provides a dedicated drawing surface embedded
inside of a view hierarchy You can control the format of this surface and if you like its size the SurfaceView takes care of placing the surface at the correct location on the screen
bull The surface is Z ordered so that it is behind the window holding its SurfaceView the SurfaceView punches a hole in its window to allow its surface to be displayed
Contbull Pros
ndash 可以跟 View Hierachy较好地结合在一起可以移动改变大小在上方叠加其它的 View
ndash 在单独的渲染线程进行渲染渲染效率高
ndash SV 的 Surface 和 Window Surface 之间的混合是由系统( SurfaceFlinger )使用硬件加速完成效率高并且不占用应用本身的 UI 线程时间
bull Consndash SurfaceView 的渲染毕竟跟
真正的 View不一样它不是由 ViewRootImpl渲染到当前的 Window Surface 上面
ndash 不能改变 Alpha 不支持跟下方的 View 进行 Alpha 混合
ndash 不能做 Rotation Skew等变换
GLSurfaceViewbull An implementation of SurfaceView that uses the dedicated surfac
e for displaying OpenGL renderingbull A GLSurfaceView provides the following features
ndash Manages a surface which is a special piece of memory that can be composited into the Android view system
ndash Manages an EGL display which enables OpenGL to render into a surfacendash Accepts a user-provided Renderer object that does the actual renderingndash Renders on a dedicated thread to decouple rendering performance from
the UI threadndash Supports both on-demand and continuous renderingndash Optionally wraps traces andor error-checks the renderers OpenGL call
s
Contbull GLSurfaceView 创建一个内部的线程 GLThreadbull 在该线程运行环境下创建一个 EglContextbull 创建一个 EglSurface ( Window Surface )bull 设置之前创建的 EglContext 为当前的 GL Contex
t 并绑定到创建的 EglSurface 上bull 在该线程内就可以通过 EGL 指令在当前的 GL Co
ntext 上绘图
Contbull GLSurfaceView支持两种不同的绘图模式
ndash 连续模式下 GLThread 会不断调用 RendereronDrawFrame 进行绘图
ndash Dirty 模式下 GLThread处于等待状态直到程序发送绘图请求( GLSurfaceViewrequestRender )才调用 RendereronDrawFrame 进行绘图绘制完一帧后重新进入等待状态
bull 在 RendereronDrawFrame 的回调中应用可以通过 SDK提供的 EGL API 绘图也可以转到 native 端使用 NDK提供的 EGL API 绘图
class SurfaceView
SurfaceView
GLSurfaceView GLSurfaceViewRenderer
+ onDrawFrame() void
GLSurfaceViewGLThread
GLSurfaceViewEglHelper
laquointerfaceraquoSurfaceHolder
laquointerfaceraquoSurfaceHolder
Callback
Surface
+ lockCanvas () Canvas+ unlockCanvasAndPost (Canvas) void
laquointerfaceraquoIWindowSession
+ add() void+ relayout() void
SurfaceViewMyWindow
BaseIWindow IWindowStublaquointerfaceraquo
IWindow
+mSurface
+mSession
+mWindow
+mCallbacks
+mSurfaceHolder
+mRenderer
+mGLThread
call
+mRenderer
+mEglHelper
TextureView
bull Since Android 40只在硬件加速环境下起作用bull 具备 SurfaceView 的特性
ndash 但是可以跟其它普通的 View 一样实现 Rotation Screw等变换
ndash 支持 Alpha 可以跟它下方的 View 进行 Alpha 混合
bull 可以基于 TextureView 创建一个 GL Surface 在上面进行 OpenGL渲染
Things become more complicated after Android 30
HW Accelerated 2D Renderingbull Android 30后开始支持硬件加速的 2D 绘图原
有的绘图流程变得更加复杂bull 所谓硬件加速的 2D 绘图就是将 2D Graphics A
PI 的实现改成使用 OpenGL API 来进行绘图bull OpenGL 的绘图模式跟一般的 2D 绘图有很大区
别它需要先将绘图所需的各种素材如贴图多边形顶点阵列 Shader等先加载到当前的 GLContext 然后流水线式的顺序执行绘图指令通过这种方式来充分利用硬件的能力
ViewRootImplbull 当 Actitity 的 View Hierachy 的根节点被添加到 WindowM
anager 的时候( WindowManageraddView ) WindowManager 的实现类 WindowManagerImpl 会创建一个 ViewRootImpl 并把它跟传进来的 View 绑定在一起( ViewRootImplsetView )并且 ViewRootImpl 会根据是否开启硬件加速来决定是否创建一个 HardwareRenderer
bull 在 ViewRootImpl 第一次渲染 View Hierachy 时会创建 Surface 如果开启硬件加速则通过 HardwareRenderer在当前的 UI 线程初始化EGL 绘图环境(类似 GLSurfaceView )
Contbull 在 ViewRootImpl 真正渲染 View Hierachy
时如果开启硬件加速则从 HardwareRenderer获得一个 HardwareCanvas 然后 View Hierachy 的渲染通过 HardwareCanvas 来进行
bull HardwareCanvas 跟一个 native 的 OpenGLRenderer 绑定通过它调用 EGL API 来完成真正的绘制
DisplayList and Hardware Layerbull 为了充分利用硬件加速的能力 Android 30 还引入了 Di
splayList 和 Hardware Layerbull DisplayList 用于记录一系列OpenGL 绘图指令和缓存所需的各种绘图素材( Bitmap Paint Shape Shader )当 View 的内容不发生变化时可以直接使用 DisplayList 进行绘制而不需要重新调用 onDraw
bull Hardware Layer 用于缓存绘制的内存到 Frame Buffer Object 当内容不发生变化时可以直接使用 Layer 进行Layer Composite获得更快的绘图速度
class Hardward2D
DisplayListHardwareCanv as
+ drawDisplayList() void+ drawHardwareLayer() void
Canv as
+ isHardwareAccelerated() voidHardwareLayer
HardwareRenderer
+ initialize() void
HardwareRendererGlRenderer
HardwareRendererGl20Renderer
GLES20Canv as
GLES20RecordingCanv as
GLES20DisplayList
laquonativeraquoDisplayList
laquonativeraquoOpenGLRenderer
laquonativeraquoDisplayListRenderer
ViewAttachInfo
ViewRootImpl
+ setView() void+ scheduleTraversals() void+ performTraversals() void+ relayoutWindow() void
GLES20Layer
GLES20TextureLayer
+mCanvas
+mNativeDisplayList
draw
+mRenderer
+mAttachInfo
+mHardwareRenderer
+mHardwareCanvas
+mResizeBuffer
Reference
bull Android 圖形系統 -- 設計與實做分析
bull How to replace GLSurfaceView with TextureView in Android Ice Cream Sandwich
The End
Thank you for your listeningYours Sincerely Roger
Contbull IWindow
ndash API back to a client window that the Window Manager uses to inform it of interesting things happening
ndash 回调接口用于接收 WMS 关于窗口的消息 mdashmdash 显示 隐藏大小改变焦点变化等等
bull 除了注册窗口外 ViewRootImpl还向 WMS (通过 InputQueue )注册了一个 InputHandler 用于接收输入事件
bull 接收到的输入事件会先放在 UI 线程的消息循环中然后通过 ViewRootImpl 进行分派在它对应的 View Hierachy 上路由
class Window
Activ ityThread
+ handleLaunchActivity() void+ handleResumeActivity() void+ performLaunchActivity() void
Activ ity
+ attach() void+ onCreate() void+ setContentView() void
Window
+ setContentView() void
PhoneWindow PhoneWindowDecorView
ViewRootImpl
+ setView() void+ scheduleTraversals() void+ performTraversals() void+ relayoutWindow() void
ViewGroup
laquointerfaceraquoWindowManager
laquointerfaceraquoViewManager
WindowLocalWindowManager
WindowManagerImpl
+ addView() void
WindowManagerImplCompatModeWrapper
laquointerfaceraquoViewParent
laquointerfaceraquoIWindowSession
+ add() void+ relayout() void
laquointerfaceraquoIWindow
ViewRootImplW IWindowStub
create +mWindow
+mDecor
+mContentParent
+mWindowManager
+mWindowManager
+mRoots
parent
+mView
+sWindowSession
addView
+mWindow
Overall Flowbull ActivityThead 创建 Activitybull Activity 创建 PhoneWindowbull PhoneWindow 创建 DecorView 作为 View Hierachy 的根节点 Client 端设
置的 Content View 会 attach 到 DecorView 下面(间接)bull PhoneWindow 创建 WindowManagerImplbull ActivityThead 把 DecorView 加到 WindowManagerImpl 里面bull WindowManagerImpl 创建 ViewRootImpl 并把 DecorView 传给它bull ViewRootImpl 打开一个 Window Session 跟 WMS 通讯通过 Session 注册
一个窗口最后客户端拥有一个 IWindow 回调接口服务端拥有一个 WindowState 跟该回调接口绑定
View Hierachy Rendering
bull 当 ViewRootImpl 建立跟 WMS 的联系注册了窗口后会发出第一次渲染 View Hierachy 的请求
ndash ViewRootImplsetViewndash ViewRootImplrequestLayoutndash ViewRootImplscheduleTraversals
bull 在第一次的 View Hierachy 的渲染中( ViewRootImplperformTraversals ) ViewRootImpl需要创建 Surface
Contbull 当 Surface 创建后后续的渲染就可以通过获得
Surface 的 Canvas ( SurfacelockCanvas )bull 然后遍历 View Hierachy 把需要绘制的 Views
通过 Canvas 绘制到 Surface 上面( ViewonDraw )
bull 绘制完后需要解锁( SurfaceunlockCanvasPost )让 SurfaceFlinger 可以将 Surface 绘制到屏幕上( Screen Composite )
Surfacebull Handle onto a raw buffer that is being managed by the
screen compositor
bull 每个 Window 都有一个 Surface 由窗口在客户端的代理者 ViewRootImpl 所拥有
bull Surface 在 ViewRootImpl 第一次渲染 View Hierachy 时创建
ndash ViewRootImplperformTraversalsndash ViewRootImplrelayoutWindowndash IWindowSessionrelayout
Contbull ViewRootImpl预先创建一个空的 Surface 对象( Java )在需要
创建真正的 Surface 的时候它调用 IWindowSessionrelayout 这是一个 RPC 最终是 WMS 的 relayoutWindow 被调用
bull WMS 调用 WindowStatecreateSurfaceLocked 创建了一个 Surface对象( Java )并把这个对象的数据传回给客户端而客户端则负责用这些数据填充预先创建的空 Surface 对象( Java )
ndash 实际上 WMS 是请求 SurfaceFlinger 创建真正的 Surface 然后把 Surface相关的信息再传回给客户端
ndash 客户端利用这些信息来创建一个 native Surface 对象然后把它跟 Java Surface 对象绑定在一起
ndash 客户端的 Java Surface 对象以后就可以通过这个 native Surface 对象来操作图像缓存( GraphicsBuffer )图像缓存可以看作是一块共享内存在客户端和 SurfaceFlinger 之间共享
Surface amp Canvasbull Surface ( Java )包含一个 Canvas ( Java )而 Can
vas ( Java )包含一个 native 的 SkCanvas 对象bull 当调用 SurfacelockCanvas 时
ndash 从图像缓存队列中取出一个可用的缓存ndash 把当前的 Posted Buffer 的内容拷贝到新缓存中(除了 Dirty Regi
on 之外的区域)然后将这块缓存加锁并设置为 Locked Buffer
ndash 获得新缓存的内存地址根据内存地址构建一个 SkBitmapndash 把该 SkBitmap 设置到 SkCanvas 里面ndash 返回跟 SkCanvas 对应的 Canvas ( Java )透过 Canvas ( Ja
va )绘制的内容实际上就是绘制到当前的缓存
Cont
bull 当调用 SurfaceunlockCanvasAndPost 的时候ndash 置空 SkCanvas 设置一个空的 SkBitmapndash 将 Locked Buffer 解锁并返回到图像缓存队列里面ndash 将 Posted Buffer 设置为 Locked Buffer 旧的 Poste
d Buffer 就可以被下次取出来使用设置 Locked Buffer 为空
ndash 当 SurfaceFlinger 下次进行 Screen Composite 的时候就会把当前的 Posted Buffer 绘制到屏幕上
SurfaceFlingerbull 应用跟 SF 之间的关系是就像是生产者与消费者的关系bull 应用从 Surface 的 GraphicsBuffer队列的前端取出一个缓存然后进行绘制
bull 绘制完毕后把该缓存放置回队列的后端(生产)bull 而 SF 则不断地将 Surface 的 GraphicsBuffer队列的最后
一个缓存绘制到屏幕上(消费)bull 两者在不同的进程是异步进行的对队列的访问需要进
行同步
class Surface
ViewRootImpl
+ setView() void+ scheduleTraversals() void+ performTraversals() void+ relayoutWindow() void
Surface
+ lockCanvas () Canvas+ unlockCanvasAndPost (Canvas) void
laquointerfaceraquoIWindowSession
+ add() void+ relayout() void
Canvas
+ isHardwareAccelerated() void
laquonativeraquoSurface
laquonativeraquoSurfaceController
SurfaceCompatibleCanvas
laquonativeraquoSkCanvas
WindowManagerServ ice
+ relayoutWindow() void
SurfaceSession
Session
+ relayout() void
WindowState
+ createSurfaceLocked() void
laquonativeraquoSurfaceFlinger
IWindowSessionStub
laquonativeraquoSurfaceComposerCilent
laquonativeraquoBnSurfaceComposer
laquonativeraquoISurfaceComposerClient
laquonativeraquoSurfaceTextureClient
+mSurface
+sWindowSession
+mCanvas
+mSurfaceControl
+mNativeSurface
+mNativeCanvas
+mSurfaceSession
+mService
+mSessions
+mWindowMap
setBitmapDevice
communication+mClient
+mClient
Overall Flowbull ViewRootImpl 第一次渲染 View Hierachy 的时候会创建一个 Surfac
ebull 客户端请求 WMS 创建 Surface 并返回 Surface相关的数据用于构
建一个 native 的 Surface 对象并把它跟 ViewRootImpl 的 Surface( Java )绑定在一起
bull ViewRootImpl 在渲染时先从 Surface获得 Canvasbull 然后把需要绘制的 Views 通过 Canvas 绘制到 Surface 上面bull 绘制完毕后解锁该 Surfacebull SurfaceFlinger 在做 Screen Composite 的时候把解锁后的 Surface
绘制到屏幕上
Those special Views
SurfaceViewbull Provides a dedicated drawing surface embedded
inside of a view hierarchy You can control the format of this surface and if you like its size the SurfaceView takes care of placing the surface at the correct location on the screen
bull The surface is Z ordered so that it is behind the window holding its SurfaceView the SurfaceView punches a hole in its window to allow its surface to be displayed
Contbull Pros
ndash 可以跟 View Hierachy较好地结合在一起可以移动改变大小在上方叠加其它的 View
ndash 在单独的渲染线程进行渲染渲染效率高
ndash SV 的 Surface 和 Window Surface 之间的混合是由系统( SurfaceFlinger )使用硬件加速完成效率高并且不占用应用本身的 UI 线程时间
bull Consndash SurfaceView 的渲染毕竟跟
真正的 View不一样它不是由 ViewRootImpl渲染到当前的 Window Surface 上面
ndash 不能改变 Alpha 不支持跟下方的 View 进行 Alpha 混合
ndash 不能做 Rotation Skew等变换
GLSurfaceViewbull An implementation of SurfaceView that uses the dedicated surfac
e for displaying OpenGL renderingbull A GLSurfaceView provides the following features
ndash Manages a surface which is a special piece of memory that can be composited into the Android view system
ndash Manages an EGL display which enables OpenGL to render into a surfacendash Accepts a user-provided Renderer object that does the actual renderingndash Renders on a dedicated thread to decouple rendering performance from
the UI threadndash Supports both on-demand and continuous renderingndash Optionally wraps traces andor error-checks the renderers OpenGL call
s
Contbull GLSurfaceView 创建一个内部的线程 GLThreadbull 在该线程运行环境下创建一个 EglContextbull 创建一个 EglSurface ( Window Surface )bull 设置之前创建的 EglContext 为当前的 GL Contex
t 并绑定到创建的 EglSurface 上bull 在该线程内就可以通过 EGL 指令在当前的 GL Co
ntext 上绘图
Contbull GLSurfaceView支持两种不同的绘图模式
ndash 连续模式下 GLThread 会不断调用 RendereronDrawFrame 进行绘图
ndash Dirty 模式下 GLThread处于等待状态直到程序发送绘图请求( GLSurfaceViewrequestRender )才调用 RendereronDrawFrame 进行绘图绘制完一帧后重新进入等待状态
bull 在 RendereronDrawFrame 的回调中应用可以通过 SDK提供的 EGL API 绘图也可以转到 native 端使用 NDK提供的 EGL API 绘图
class SurfaceView
SurfaceView
GLSurfaceView GLSurfaceViewRenderer
+ onDrawFrame() void
GLSurfaceViewGLThread
GLSurfaceViewEglHelper
laquointerfaceraquoSurfaceHolder
laquointerfaceraquoSurfaceHolder
Callback
Surface
+ lockCanvas () Canvas+ unlockCanvasAndPost (Canvas) void
laquointerfaceraquoIWindowSession
+ add() void+ relayout() void
SurfaceViewMyWindow
BaseIWindow IWindowStublaquointerfaceraquo
IWindow
+mSurface
+mSession
+mWindow
+mCallbacks
+mSurfaceHolder
+mRenderer
+mGLThread
call
+mRenderer
+mEglHelper
TextureView
bull Since Android 40只在硬件加速环境下起作用bull 具备 SurfaceView 的特性
ndash 但是可以跟其它普通的 View 一样实现 Rotation Screw等变换
ndash 支持 Alpha 可以跟它下方的 View 进行 Alpha 混合
bull 可以基于 TextureView 创建一个 GL Surface 在上面进行 OpenGL渲染
Things become more complicated after Android 30
HW Accelerated 2D Renderingbull Android 30后开始支持硬件加速的 2D 绘图原
有的绘图流程变得更加复杂bull 所谓硬件加速的 2D 绘图就是将 2D Graphics A
PI 的实现改成使用 OpenGL API 来进行绘图bull OpenGL 的绘图模式跟一般的 2D 绘图有很大区
别它需要先将绘图所需的各种素材如贴图多边形顶点阵列 Shader等先加载到当前的 GLContext 然后流水线式的顺序执行绘图指令通过这种方式来充分利用硬件的能力
ViewRootImplbull 当 Actitity 的 View Hierachy 的根节点被添加到 WindowM
anager 的时候( WindowManageraddView ) WindowManager 的实现类 WindowManagerImpl 会创建一个 ViewRootImpl 并把它跟传进来的 View 绑定在一起( ViewRootImplsetView )并且 ViewRootImpl 会根据是否开启硬件加速来决定是否创建一个 HardwareRenderer
bull 在 ViewRootImpl 第一次渲染 View Hierachy 时会创建 Surface 如果开启硬件加速则通过 HardwareRenderer在当前的 UI 线程初始化EGL 绘图环境(类似 GLSurfaceView )
Contbull 在 ViewRootImpl 真正渲染 View Hierachy
时如果开启硬件加速则从 HardwareRenderer获得一个 HardwareCanvas 然后 View Hierachy 的渲染通过 HardwareCanvas 来进行
bull HardwareCanvas 跟一个 native 的 OpenGLRenderer 绑定通过它调用 EGL API 来完成真正的绘制
DisplayList and Hardware Layerbull 为了充分利用硬件加速的能力 Android 30 还引入了 Di
splayList 和 Hardware Layerbull DisplayList 用于记录一系列OpenGL 绘图指令和缓存所需的各种绘图素材( Bitmap Paint Shape Shader )当 View 的内容不发生变化时可以直接使用 DisplayList 进行绘制而不需要重新调用 onDraw
bull Hardware Layer 用于缓存绘制的内存到 Frame Buffer Object 当内容不发生变化时可以直接使用 Layer 进行Layer Composite获得更快的绘图速度
class Hardward2D
DisplayListHardwareCanv as
+ drawDisplayList() void+ drawHardwareLayer() void
Canv as
+ isHardwareAccelerated() voidHardwareLayer
HardwareRenderer
+ initialize() void
HardwareRendererGlRenderer
HardwareRendererGl20Renderer
GLES20Canv as
GLES20RecordingCanv as
GLES20DisplayList
laquonativeraquoDisplayList
laquonativeraquoOpenGLRenderer
laquonativeraquoDisplayListRenderer
ViewAttachInfo
ViewRootImpl
+ setView() void+ scheduleTraversals() void+ performTraversals() void+ relayoutWindow() void
GLES20Layer
GLES20TextureLayer
+mCanvas
+mNativeDisplayList
draw
+mRenderer
+mAttachInfo
+mHardwareRenderer
+mHardwareCanvas
+mResizeBuffer
Reference
bull Android 圖形系統 -- 設計與實做分析
bull How to replace GLSurfaceView with TextureView in Android Ice Cream Sandwich
The End
Thank you for your listeningYours Sincerely Roger
class Window
Activ ityThread
+ handleLaunchActivity() void+ handleResumeActivity() void+ performLaunchActivity() void
Activ ity
+ attach() void+ onCreate() void+ setContentView() void
Window
+ setContentView() void
PhoneWindow PhoneWindowDecorView
ViewRootImpl
+ setView() void+ scheduleTraversals() void+ performTraversals() void+ relayoutWindow() void
ViewGroup
laquointerfaceraquoWindowManager
laquointerfaceraquoViewManager
WindowLocalWindowManager
WindowManagerImpl
+ addView() void
WindowManagerImplCompatModeWrapper
laquointerfaceraquoViewParent
laquointerfaceraquoIWindowSession
+ add() void+ relayout() void
laquointerfaceraquoIWindow
ViewRootImplW IWindowStub
create +mWindow
+mDecor
+mContentParent
+mWindowManager
+mWindowManager
+mRoots
parent
+mView
+sWindowSession
addView
+mWindow
Overall Flowbull ActivityThead 创建 Activitybull Activity 创建 PhoneWindowbull PhoneWindow 创建 DecorView 作为 View Hierachy 的根节点 Client 端设
置的 Content View 会 attach 到 DecorView 下面(间接)bull PhoneWindow 创建 WindowManagerImplbull ActivityThead 把 DecorView 加到 WindowManagerImpl 里面bull WindowManagerImpl 创建 ViewRootImpl 并把 DecorView 传给它bull ViewRootImpl 打开一个 Window Session 跟 WMS 通讯通过 Session 注册
一个窗口最后客户端拥有一个 IWindow 回调接口服务端拥有一个 WindowState 跟该回调接口绑定
View Hierachy Rendering
bull 当 ViewRootImpl 建立跟 WMS 的联系注册了窗口后会发出第一次渲染 View Hierachy 的请求
ndash ViewRootImplsetViewndash ViewRootImplrequestLayoutndash ViewRootImplscheduleTraversals
bull 在第一次的 View Hierachy 的渲染中( ViewRootImplperformTraversals ) ViewRootImpl需要创建 Surface
Contbull 当 Surface 创建后后续的渲染就可以通过获得
Surface 的 Canvas ( SurfacelockCanvas )bull 然后遍历 View Hierachy 把需要绘制的 Views
通过 Canvas 绘制到 Surface 上面( ViewonDraw )
bull 绘制完后需要解锁( SurfaceunlockCanvasPost )让 SurfaceFlinger 可以将 Surface 绘制到屏幕上( Screen Composite )
Surfacebull Handle onto a raw buffer that is being managed by the
screen compositor
bull 每个 Window 都有一个 Surface 由窗口在客户端的代理者 ViewRootImpl 所拥有
bull Surface 在 ViewRootImpl 第一次渲染 View Hierachy 时创建
ndash ViewRootImplperformTraversalsndash ViewRootImplrelayoutWindowndash IWindowSessionrelayout
Contbull ViewRootImpl预先创建一个空的 Surface 对象( Java )在需要
创建真正的 Surface 的时候它调用 IWindowSessionrelayout 这是一个 RPC 最终是 WMS 的 relayoutWindow 被调用
bull WMS 调用 WindowStatecreateSurfaceLocked 创建了一个 Surface对象( Java )并把这个对象的数据传回给客户端而客户端则负责用这些数据填充预先创建的空 Surface 对象( Java )
ndash 实际上 WMS 是请求 SurfaceFlinger 创建真正的 Surface 然后把 Surface相关的信息再传回给客户端
ndash 客户端利用这些信息来创建一个 native Surface 对象然后把它跟 Java Surface 对象绑定在一起
ndash 客户端的 Java Surface 对象以后就可以通过这个 native Surface 对象来操作图像缓存( GraphicsBuffer )图像缓存可以看作是一块共享内存在客户端和 SurfaceFlinger 之间共享
Surface amp Canvasbull Surface ( Java )包含一个 Canvas ( Java )而 Can
vas ( Java )包含一个 native 的 SkCanvas 对象bull 当调用 SurfacelockCanvas 时
ndash 从图像缓存队列中取出一个可用的缓存ndash 把当前的 Posted Buffer 的内容拷贝到新缓存中(除了 Dirty Regi
on 之外的区域)然后将这块缓存加锁并设置为 Locked Buffer
ndash 获得新缓存的内存地址根据内存地址构建一个 SkBitmapndash 把该 SkBitmap 设置到 SkCanvas 里面ndash 返回跟 SkCanvas 对应的 Canvas ( Java )透过 Canvas ( Ja
va )绘制的内容实际上就是绘制到当前的缓存
Cont
bull 当调用 SurfaceunlockCanvasAndPost 的时候ndash 置空 SkCanvas 设置一个空的 SkBitmapndash 将 Locked Buffer 解锁并返回到图像缓存队列里面ndash 将 Posted Buffer 设置为 Locked Buffer 旧的 Poste
d Buffer 就可以被下次取出来使用设置 Locked Buffer 为空
ndash 当 SurfaceFlinger 下次进行 Screen Composite 的时候就会把当前的 Posted Buffer 绘制到屏幕上
SurfaceFlingerbull 应用跟 SF 之间的关系是就像是生产者与消费者的关系bull 应用从 Surface 的 GraphicsBuffer队列的前端取出一个缓存然后进行绘制
bull 绘制完毕后把该缓存放置回队列的后端(生产)bull 而 SF 则不断地将 Surface 的 GraphicsBuffer队列的最后
一个缓存绘制到屏幕上(消费)bull 两者在不同的进程是异步进行的对队列的访问需要进
行同步
class Surface
ViewRootImpl
+ setView() void+ scheduleTraversals() void+ performTraversals() void+ relayoutWindow() void
Surface
+ lockCanvas () Canvas+ unlockCanvasAndPost (Canvas) void
laquointerfaceraquoIWindowSession
+ add() void+ relayout() void
Canvas
+ isHardwareAccelerated() void
laquonativeraquoSurface
laquonativeraquoSurfaceController
SurfaceCompatibleCanvas
laquonativeraquoSkCanvas
WindowManagerServ ice
+ relayoutWindow() void
SurfaceSession
Session
+ relayout() void
WindowState
+ createSurfaceLocked() void
laquonativeraquoSurfaceFlinger
IWindowSessionStub
laquonativeraquoSurfaceComposerCilent
laquonativeraquoBnSurfaceComposer
laquonativeraquoISurfaceComposerClient
laquonativeraquoSurfaceTextureClient
+mSurface
+sWindowSession
+mCanvas
+mSurfaceControl
+mNativeSurface
+mNativeCanvas
+mSurfaceSession
+mService
+mSessions
+mWindowMap
setBitmapDevice
communication+mClient
+mClient
Overall Flowbull ViewRootImpl 第一次渲染 View Hierachy 的时候会创建一个 Surfac
ebull 客户端请求 WMS 创建 Surface 并返回 Surface相关的数据用于构
建一个 native 的 Surface 对象并把它跟 ViewRootImpl 的 Surface( Java )绑定在一起
bull ViewRootImpl 在渲染时先从 Surface获得 Canvasbull 然后把需要绘制的 Views 通过 Canvas 绘制到 Surface 上面bull 绘制完毕后解锁该 Surfacebull SurfaceFlinger 在做 Screen Composite 的时候把解锁后的 Surface
绘制到屏幕上
Those special Views
SurfaceViewbull Provides a dedicated drawing surface embedded
inside of a view hierarchy You can control the format of this surface and if you like its size the SurfaceView takes care of placing the surface at the correct location on the screen
bull The surface is Z ordered so that it is behind the window holding its SurfaceView the SurfaceView punches a hole in its window to allow its surface to be displayed
Contbull Pros
ndash 可以跟 View Hierachy较好地结合在一起可以移动改变大小在上方叠加其它的 View
ndash 在单独的渲染线程进行渲染渲染效率高
ndash SV 的 Surface 和 Window Surface 之间的混合是由系统( SurfaceFlinger )使用硬件加速完成效率高并且不占用应用本身的 UI 线程时间
bull Consndash SurfaceView 的渲染毕竟跟
真正的 View不一样它不是由 ViewRootImpl渲染到当前的 Window Surface 上面
ndash 不能改变 Alpha 不支持跟下方的 View 进行 Alpha 混合
ndash 不能做 Rotation Skew等变换
GLSurfaceViewbull An implementation of SurfaceView that uses the dedicated surfac
e for displaying OpenGL renderingbull A GLSurfaceView provides the following features
ndash Manages a surface which is a special piece of memory that can be composited into the Android view system
ndash Manages an EGL display which enables OpenGL to render into a surfacendash Accepts a user-provided Renderer object that does the actual renderingndash Renders on a dedicated thread to decouple rendering performance from
the UI threadndash Supports both on-demand and continuous renderingndash Optionally wraps traces andor error-checks the renderers OpenGL call
s
Contbull GLSurfaceView 创建一个内部的线程 GLThreadbull 在该线程运行环境下创建一个 EglContextbull 创建一个 EglSurface ( Window Surface )bull 设置之前创建的 EglContext 为当前的 GL Contex
t 并绑定到创建的 EglSurface 上bull 在该线程内就可以通过 EGL 指令在当前的 GL Co
ntext 上绘图
Contbull GLSurfaceView支持两种不同的绘图模式
ndash 连续模式下 GLThread 会不断调用 RendereronDrawFrame 进行绘图
ndash Dirty 模式下 GLThread处于等待状态直到程序发送绘图请求( GLSurfaceViewrequestRender )才调用 RendereronDrawFrame 进行绘图绘制完一帧后重新进入等待状态
bull 在 RendereronDrawFrame 的回调中应用可以通过 SDK提供的 EGL API 绘图也可以转到 native 端使用 NDK提供的 EGL API 绘图
class SurfaceView
SurfaceView
GLSurfaceView GLSurfaceViewRenderer
+ onDrawFrame() void
GLSurfaceViewGLThread
GLSurfaceViewEglHelper
laquointerfaceraquoSurfaceHolder
laquointerfaceraquoSurfaceHolder
Callback
Surface
+ lockCanvas () Canvas+ unlockCanvasAndPost (Canvas) void
laquointerfaceraquoIWindowSession
+ add() void+ relayout() void
SurfaceViewMyWindow
BaseIWindow IWindowStublaquointerfaceraquo
IWindow
+mSurface
+mSession
+mWindow
+mCallbacks
+mSurfaceHolder
+mRenderer
+mGLThread
call
+mRenderer
+mEglHelper
TextureView
bull Since Android 40只在硬件加速环境下起作用bull 具备 SurfaceView 的特性
ndash 但是可以跟其它普通的 View 一样实现 Rotation Screw等变换
ndash 支持 Alpha 可以跟它下方的 View 进行 Alpha 混合
bull 可以基于 TextureView 创建一个 GL Surface 在上面进行 OpenGL渲染
Things become more complicated after Android 30
HW Accelerated 2D Renderingbull Android 30后开始支持硬件加速的 2D 绘图原
有的绘图流程变得更加复杂bull 所谓硬件加速的 2D 绘图就是将 2D Graphics A
PI 的实现改成使用 OpenGL API 来进行绘图bull OpenGL 的绘图模式跟一般的 2D 绘图有很大区
别它需要先将绘图所需的各种素材如贴图多边形顶点阵列 Shader等先加载到当前的 GLContext 然后流水线式的顺序执行绘图指令通过这种方式来充分利用硬件的能力
ViewRootImplbull 当 Actitity 的 View Hierachy 的根节点被添加到 WindowM
anager 的时候( WindowManageraddView ) WindowManager 的实现类 WindowManagerImpl 会创建一个 ViewRootImpl 并把它跟传进来的 View 绑定在一起( ViewRootImplsetView )并且 ViewRootImpl 会根据是否开启硬件加速来决定是否创建一个 HardwareRenderer
bull 在 ViewRootImpl 第一次渲染 View Hierachy 时会创建 Surface 如果开启硬件加速则通过 HardwareRenderer在当前的 UI 线程初始化EGL 绘图环境(类似 GLSurfaceView )
Contbull 在 ViewRootImpl 真正渲染 View Hierachy
时如果开启硬件加速则从 HardwareRenderer获得一个 HardwareCanvas 然后 View Hierachy 的渲染通过 HardwareCanvas 来进行
bull HardwareCanvas 跟一个 native 的 OpenGLRenderer 绑定通过它调用 EGL API 来完成真正的绘制
DisplayList and Hardware Layerbull 为了充分利用硬件加速的能力 Android 30 还引入了 Di
splayList 和 Hardware Layerbull DisplayList 用于记录一系列OpenGL 绘图指令和缓存所需的各种绘图素材( Bitmap Paint Shape Shader )当 View 的内容不发生变化时可以直接使用 DisplayList 进行绘制而不需要重新调用 onDraw
bull Hardware Layer 用于缓存绘制的内存到 Frame Buffer Object 当内容不发生变化时可以直接使用 Layer 进行Layer Composite获得更快的绘图速度
class Hardward2D
DisplayListHardwareCanv as
+ drawDisplayList() void+ drawHardwareLayer() void
Canv as
+ isHardwareAccelerated() voidHardwareLayer
HardwareRenderer
+ initialize() void
HardwareRendererGlRenderer
HardwareRendererGl20Renderer
GLES20Canv as
GLES20RecordingCanv as
GLES20DisplayList
laquonativeraquoDisplayList
laquonativeraquoOpenGLRenderer
laquonativeraquoDisplayListRenderer
ViewAttachInfo
ViewRootImpl
+ setView() void+ scheduleTraversals() void+ performTraversals() void+ relayoutWindow() void
GLES20Layer
GLES20TextureLayer
+mCanvas
+mNativeDisplayList
draw
+mRenderer
+mAttachInfo
+mHardwareRenderer
+mHardwareCanvas
+mResizeBuffer
Reference
bull Android 圖形系統 -- 設計與實做分析
bull How to replace GLSurfaceView with TextureView in Android Ice Cream Sandwich
The End
Thank you for your listeningYours Sincerely Roger
Overall Flowbull ActivityThead 创建 Activitybull Activity 创建 PhoneWindowbull PhoneWindow 创建 DecorView 作为 View Hierachy 的根节点 Client 端设
置的 Content View 会 attach 到 DecorView 下面(间接)bull PhoneWindow 创建 WindowManagerImplbull ActivityThead 把 DecorView 加到 WindowManagerImpl 里面bull WindowManagerImpl 创建 ViewRootImpl 并把 DecorView 传给它bull ViewRootImpl 打开一个 Window Session 跟 WMS 通讯通过 Session 注册
一个窗口最后客户端拥有一个 IWindow 回调接口服务端拥有一个 WindowState 跟该回调接口绑定
View Hierachy Rendering
bull 当 ViewRootImpl 建立跟 WMS 的联系注册了窗口后会发出第一次渲染 View Hierachy 的请求
ndash ViewRootImplsetViewndash ViewRootImplrequestLayoutndash ViewRootImplscheduleTraversals
bull 在第一次的 View Hierachy 的渲染中( ViewRootImplperformTraversals ) ViewRootImpl需要创建 Surface
Contbull 当 Surface 创建后后续的渲染就可以通过获得
Surface 的 Canvas ( SurfacelockCanvas )bull 然后遍历 View Hierachy 把需要绘制的 Views
通过 Canvas 绘制到 Surface 上面( ViewonDraw )
bull 绘制完后需要解锁( SurfaceunlockCanvasPost )让 SurfaceFlinger 可以将 Surface 绘制到屏幕上( Screen Composite )
Surfacebull Handle onto a raw buffer that is being managed by the
screen compositor
bull 每个 Window 都有一个 Surface 由窗口在客户端的代理者 ViewRootImpl 所拥有
bull Surface 在 ViewRootImpl 第一次渲染 View Hierachy 时创建
ndash ViewRootImplperformTraversalsndash ViewRootImplrelayoutWindowndash IWindowSessionrelayout
Contbull ViewRootImpl预先创建一个空的 Surface 对象( Java )在需要
创建真正的 Surface 的时候它调用 IWindowSessionrelayout 这是一个 RPC 最终是 WMS 的 relayoutWindow 被调用
bull WMS 调用 WindowStatecreateSurfaceLocked 创建了一个 Surface对象( Java )并把这个对象的数据传回给客户端而客户端则负责用这些数据填充预先创建的空 Surface 对象( Java )
ndash 实际上 WMS 是请求 SurfaceFlinger 创建真正的 Surface 然后把 Surface相关的信息再传回给客户端
ndash 客户端利用这些信息来创建一个 native Surface 对象然后把它跟 Java Surface 对象绑定在一起
ndash 客户端的 Java Surface 对象以后就可以通过这个 native Surface 对象来操作图像缓存( GraphicsBuffer )图像缓存可以看作是一块共享内存在客户端和 SurfaceFlinger 之间共享
Surface amp Canvasbull Surface ( Java )包含一个 Canvas ( Java )而 Can
vas ( Java )包含一个 native 的 SkCanvas 对象bull 当调用 SurfacelockCanvas 时
ndash 从图像缓存队列中取出一个可用的缓存ndash 把当前的 Posted Buffer 的内容拷贝到新缓存中(除了 Dirty Regi
on 之外的区域)然后将这块缓存加锁并设置为 Locked Buffer
ndash 获得新缓存的内存地址根据内存地址构建一个 SkBitmapndash 把该 SkBitmap 设置到 SkCanvas 里面ndash 返回跟 SkCanvas 对应的 Canvas ( Java )透过 Canvas ( Ja
va )绘制的内容实际上就是绘制到当前的缓存
Cont
bull 当调用 SurfaceunlockCanvasAndPost 的时候ndash 置空 SkCanvas 设置一个空的 SkBitmapndash 将 Locked Buffer 解锁并返回到图像缓存队列里面ndash 将 Posted Buffer 设置为 Locked Buffer 旧的 Poste
d Buffer 就可以被下次取出来使用设置 Locked Buffer 为空
ndash 当 SurfaceFlinger 下次进行 Screen Composite 的时候就会把当前的 Posted Buffer 绘制到屏幕上
SurfaceFlingerbull 应用跟 SF 之间的关系是就像是生产者与消费者的关系bull 应用从 Surface 的 GraphicsBuffer队列的前端取出一个缓存然后进行绘制
bull 绘制完毕后把该缓存放置回队列的后端(生产)bull 而 SF 则不断地将 Surface 的 GraphicsBuffer队列的最后
一个缓存绘制到屏幕上(消费)bull 两者在不同的进程是异步进行的对队列的访问需要进
行同步
class Surface
ViewRootImpl
+ setView() void+ scheduleTraversals() void+ performTraversals() void+ relayoutWindow() void
Surface
+ lockCanvas () Canvas+ unlockCanvasAndPost (Canvas) void
laquointerfaceraquoIWindowSession
+ add() void+ relayout() void
Canvas
+ isHardwareAccelerated() void
laquonativeraquoSurface
laquonativeraquoSurfaceController
SurfaceCompatibleCanvas
laquonativeraquoSkCanvas
WindowManagerServ ice
+ relayoutWindow() void
SurfaceSession
Session
+ relayout() void
WindowState
+ createSurfaceLocked() void
laquonativeraquoSurfaceFlinger
IWindowSessionStub
laquonativeraquoSurfaceComposerCilent
laquonativeraquoBnSurfaceComposer
laquonativeraquoISurfaceComposerClient
laquonativeraquoSurfaceTextureClient
+mSurface
+sWindowSession
+mCanvas
+mSurfaceControl
+mNativeSurface
+mNativeCanvas
+mSurfaceSession
+mService
+mSessions
+mWindowMap
setBitmapDevice
communication+mClient
+mClient
Overall Flowbull ViewRootImpl 第一次渲染 View Hierachy 的时候会创建一个 Surfac
ebull 客户端请求 WMS 创建 Surface 并返回 Surface相关的数据用于构
建一个 native 的 Surface 对象并把它跟 ViewRootImpl 的 Surface( Java )绑定在一起
bull ViewRootImpl 在渲染时先从 Surface获得 Canvasbull 然后把需要绘制的 Views 通过 Canvas 绘制到 Surface 上面bull 绘制完毕后解锁该 Surfacebull SurfaceFlinger 在做 Screen Composite 的时候把解锁后的 Surface
绘制到屏幕上
Those special Views
SurfaceViewbull Provides a dedicated drawing surface embedded
inside of a view hierarchy You can control the format of this surface and if you like its size the SurfaceView takes care of placing the surface at the correct location on the screen
bull The surface is Z ordered so that it is behind the window holding its SurfaceView the SurfaceView punches a hole in its window to allow its surface to be displayed
Contbull Pros
ndash 可以跟 View Hierachy较好地结合在一起可以移动改变大小在上方叠加其它的 View
ndash 在单独的渲染线程进行渲染渲染效率高
ndash SV 的 Surface 和 Window Surface 之间的混合是由系统( SurfaceFlinger )使用硬件加速完成效率高并且不占用应用本身的 UI 线程时间
bull Consndash SurfaceView 的渲染毕竟跟
真正的 View不一样它不是由 ViewRootImpl渲染到当前的 Window Surface 上面
ndash 不能改变 Alpha 不支持跟下方的 View 进行 Alpha 混合
ndash 不能做 Rotation Skew等变换
GLSurfaceViewbull An implementation of SurfaceView that uses the dedicated surfac
e for displaying OpenGL renderingbull A GLSurfaceView provides the following features
ndash Manages a surface which is a special piece of memory that can be composited into the Android view system
ndash Manages an EGL display which enables OpenGL to render into a surfacendash Accepts a user-provided Renderer object that does the actual renderingndash Renders on a dedicated thread to decouple rendering performance from
the UI threadndash Supports both on-demand and continuous renderingndash Optionally wraps traces andor error-checks the renderers OpenGL call
s
Contbull GLSurfaceView 创建一个内部的线程 GLThreadbull 在该线程运行环境下创建一个 EglContextbull 创建一个 EglSurface ( Window Surface )bull 设置之前创建的 EglContext 为当前的 GL Contex
t 并绑定到创建的 EglSurface 上bull 在该线程内就可以通过 EGL 指令在当前的 GL Co
ntext 上绘图
Contbull GLSurfaceView支持两种不同的绘图模式
ndash 连续模式下 GLThread 会不断调用 RendereronDrawFrame 进行绘图
ndash Dirty 模式下 GLThread处于等待状态直到程序发送绘图请求( GLSurfaceViewrequestRender )才调用 RendereronDrawFrame 进行绘图绘制完一帧后重新进入等待状态
bull 在 RendereronDrawFrame 的回调中应用可以通过 SDK提供的 EGL API 绘图也可以转到 native 端使用 NDK提供的 EGL API 绘图
class SurfaceView
SurfaceView
GLSurfaceView GLSurfaceViewRenderer
+ onDrawFrame() void
GLSurfaceViewGLThread
GLSurfaceViewEglHelper
laquointerfaceraquoSurfaceHolder
laquointerfaceraquoSurfaceHolder
Callback
Surface
+ lockCanvas () Canvas+ unlockCanvasAndPost (Canvas) void
laquointerfaceraquoIWindowSession
+ add() void+ relayout() void
SurfaceViewMyWindow
BaseIWindow IWindowStublaquointerfaceraquo
IWindow
+mSurface
+mSession
+mWindow
+mCallbacks
+mSurfaceHolder
+mRenderer
+mGLThread
call
+mRenderer
+mEglHelper
TextureView
bull Since Android 40只在硬件加速环境下起作用bull 具备 SurfaceView 的特性
ndash 但是可以跟其它普通的 View 一样实现 Rotation Screw等变换
ndash 支持 Alpha 可以跟它下方的 View 进行 Alpha 混合
bull 可以基于 TextureView 创建一个 GL Surface 在上面进行 OpenGL渲染
Things become more complicated after Android 30
HW Accelerated 2D Renderingbull Android 30后开始支持硬件加速的 2D 绘图原
有的绘图流程变得更加复杂bull 所谓硬件加速的 2D 绘图就是将 2D Graphics A
PI 的实现改成使用 OpenGL API 来进行绘图bull OpenGL 的绘图模式跟一般的 2D 绘图有很大区
别它需要先将绘图所需的各种素材如贴图多边形顶点阵列 Shader等先加载到当前的 GLContext 然后流水线式的顺序执行绘图指令通过这种方式来充分利用硬件的能力
ViewRootImplbull 当 Actitity 的 View Hierachy 的根节点被添加到 WindowM
anager 的时候( WindowManageraddView ) WindowManager 的实现类 WindowManagerImpl 会创建一个 ViewRootImpl 并把它跟传进来的 View 绑定在一起( ViewRootImplsetView )并且 ViewRootImpl 会根据是否开启硬件加速来决定是否创建一个 HardwareRenderer
bull 在 ViewRootImpl 第一次渲染 View Hierachy 时会创建 Surface 如果开启硬件加速则通过 HardwareRenderer在当前的 UI 线程初始化EGL 绘图环境(类似 GLSurfaceView )
Contbull 在 ViewRootImpl 真正渲染 View Hierachy
时如果开启硬件加速则从 HardwareRenderer获得一个 HardwareCanvas 然后 View Hierachy 的渲染通过 HardwareCanvas 来进行
bull HardwareCanvas 跟一个 native 的 OpenGLRenderer 绑定通过它调用 EGL API 来完成真正的绘制
DisplayList and Hardware Layerbull 为了充分利用硬件加速的能力 Android 30 还引入了 Di
splayList 和 Hardware Layerbull DisplayList 用于记录一系列OpenGL 绘图指令和缓存所需的各种绘图素材( Bitmap Paint Shape Shader )当 View 的内容不发生变化时可以直接使用 DisplayList 进行绘制而不需要重新调用 onDraw
bull Hardware Layer 用于缓存绘制的内存到 Frame Buffer Object 当内容不发生变化时可以直接使用 Layer 进行Layer Composite获得更快的绘图速度
class Hardward2D
DisplayListHardwareCanv as
+ drawDisplayList() void+ drawHardwareLayer() void
Canv as
+ isHardwareAccelerated() voidHardwareLayer
HardwareRenderer
+ initialize() void
HardwareRendererGlRenderer
HardwareRendererGl20Renderer
GLES20Canv as
GLES20RecordingCanv as
GLES20DisplayList
laquonativeraquoDisplayList
laquonativeraquoOpenGLRenderer
laquonativeraquoDisplayListRenderer
ViewAttachInfo
ViewRootImpl
+ setView() void+ scheduleTraversals() void+ performTraversals() void+ relayoutWindow() void
GLES20Layer
GLES20TextureLayer
+mCanvas
+mNativeDisplayList
draw
+mRenderer
+mAttachInfo
+mHardwareRenderer
+mHardwareCanvas
+mResizeBuffer
Reference
bull Android 圖形系統 -- 設計與實做分析
bull How to replace GLSurfaceView with TextureView in Android Ice Cream Sandwich
The End
Thank you for your listeningYours Sincerely Roger
View Hierachy Rendering
bull 当 ViewRootImpl 建立跟 WMS 的联系注册了窗口后会发出第一次渲染 View Hierachy 的请求
ndash ViewRootImplsetViewndash ViewRootImplrequestLayoutndash ViewRootImplscheduleTraversals
bull 在第一次的 View Hierachy 的渲染中( ViewRootImplperformTraversals ) ViewRootImpl需要创建 Surface
Contbull 当 Surface 创建后后续的渲染就可以通过获得
Surface 的 Canvas ( SurfacelockCanvas )bull 然后遍历 View Hierachy 把需要绘制的 Views
通过 Canvas 绘制到 Surface 上面( ViewonDraw )
bull 绘制完后需要解锁( SurfaceunlockCanvasPost )让 SurfaceFlinger 可以将 Surface 绘制到屏幕上( Screen Composite )
Surfacebull Handle onto a raw buffer that is being managed by the
screen compositor
bull 每个 Window 都有一个 Surface 由窗口在客户端的代理者 ViewRootImpl 所拥有
bull Surface 在 ViewRootImpl 第一次渲染 View Hierachy 时创建
ndash ViewRootImplperformTraversalsndash ViewRootImplrelayoutWindowndash IWindowSessionrelayout
Contbull ViewRootImpl预先创建一个空的 Surface 对象( Java )在需要
创建真正的 Surface 的时候它调用 IWindowSessionrelayout 这是一个 RPC 最终是 WMS 的 relayoutWindow 被调用
bull WMS 调用 WindowStatecreateSurfaceLocked 创建了一个 Surface对象( Java )并把这个对象的数据传回给客户端而客户端则负责用这些数据填充预先创建的空 Surface 对象( Java )
ndash 实际上 WMS 是请求 SurfaceFlinger 创建真正的 Surface 然后把 Surface相关的信息再传回给客户端
ndash 客户端利用这些信息来创建一个 native Surface 对象然后把它跟 Java Surface 对象绑定在一起
ndash 客户端的 Java Surface 对象以后就可以通过这个 native Surface 对象来操作图像缓存( GraphicsBuffer )图像缓存可以看作是一块共享内存在客户端和 SurfaceFlinger 之间共享
Surface amp Canvasbull Surface ( Java )包含一个 Canvas ( Java )而 Can
vas ( Java )包含一个 native 的 SkCanvas 对象bull 当调用 SurfacelockCanvas 时
ndash 从图像缓存队列中取出一个可用的缓存ndash 把当前的 Posted Buffer 的内容拷贝到新缓存中(除了 Dirty Regi
on 之外的区域)然后将这块缓存加锁并设置为 Locked Buffer
ndash 获得新缓存的内存地址根据内存地址构建一个 SkBitmapndash 把该 SkBitmap 设置到 SkCanvas 里面ndash 返回跟 SkCanvas 对应的 Canvas ( Java )透过 Canvas ( Ja
va )绘制的内容实际上就是绘制到当前的缓存
Cont
bull 当调用 SurfaceunlockCanvasAndPost 的时候ndash 置空 SkCanvas 设置一个空的 SkBitmapndash 将 Locked Buffer 解锁并返回到图像缓存队列里面ndash 将 Posted Buffer 设置为 Locked Buffer 旧的 Poste
d Buffer 就可以被下次取出来使用设置 Locked Buffer 为空
ndash 当 SurfaceFlinger 下次进行 Screen Composite 的时候就会把当前的 Posted Buffer 绘制到屏幕上
SurfaceFlingerbull 应用跟 SF 之间的关系是就像是生产者与消费者的关系bull 应用从 Surface 的 GraphicsBuffer队列的前端取出一个缓存然后进行绘制
bull 绘制完毕后把该缓存放置回队列的后端(生产)bull 而 SF 则不断地将 Surface 的 GraphicsBuffer队列的最后
一个缓存绘制到屏幕上(消费)bull 两者在不同的进程是异步进行的对队列的访问需要进
行同步
class Surface
ViewRootImpl
+ setView() void+ scheduleTraversals() void+ performTraversals() void+ relayoutWindow() void
Surface
+ lockCanvas () Canvas+ unlockCanvasAndPost (Canvas) void
laquointerfaceraquoIWindowSession
+ add() void+ relayout() void
Canvas
+ isHardwareAccelerated() void
laquonativeraquoSurface
laquonativeraquoSurfaceController
SurfaceCompatibleCanvas
laquonativeraquoSkCanvas
WindowManagerServ ice
+ relayoutWindow() void
SurfaceSession
Session
+ relayout() void
WindowState
+ createSurfaceLocked() void
laquonativeraquoSurfaceFlinger
IWindowSessionStub
laquonativeraquoSurfaceComposerCilent
laquonativeraquoBnSurfaceComposer
laquonativeraquoISurfaceComposerClient
laquonativeraquoSurfaceTextureClient
+mSurface
+sWindowSession
+mCanvas
+mSurfaceControl
+mNativeSurface
+mNativeCanvas
+mSurfaceSession
+mService
+mSessions
+mWindowMap
setBitmapDevice
communication+mClient
+mClient
Overall Flowbull ViewRootImpl 第一次渲染 View Hierachy 的时候会创建一个 Surfac
ebull 客户端请求 WMS 创建 Surface 并返回 Surface相关的数据用于构
建一个 native 的 Surface 对象并把它跟 ViewRootImpl 的 Surface( Java )绑定在一起
bull ViewRootImpl 在渲染时先从 Surface获得 Canvasbull 然后把需要绘制的 Views 通过 Canvas 绘制到 Surface 上面bull 绘制完毕后解锁该 Surfacebull SurfaceFlinger 在做 Screen Composite 的时候把解锁后的 Surface
绘制到屏幕上
Those special Views
SurfaceViewbull Provides a dedicated drawing surface embedded
inside of a view hierarchy You can control the format of this surface and if you like its size the SurfaceView takes care of placing the surface at the correct location on the screen
bull The surface is Z ordered so that it is behind the window holding its SurfaceView the SurfaceView punches a hole in its window to allow its surface to be displayed
Contbull Pros
ndash 可以跟 View Hierachy较好地结合在一起可以移动改变大小在上方叠加其它的 View
ndash 在单独的渲染线程进行渲染渲染效率高
ndash SV 的 Surface 和 Window Surface 之间的混合是由系统( SurfaceFlinger )使用硬件加速完成效率高并且不占用应用本身的 UI 线程时间
bull Consndash SurfaceView 的渲染毕竟跟
真正的 View不一样它不是由 ViewRootImpl渲染到当前的 Window Surface 上面
ndash 不能改变 Alpha 不支持跟下方的 View 进行 Alpha 混合
ndash 不能做 Rotation Skew等变换
GLSurfaceViewbull An implementation of SurfaceView that uses the dedicated surfac
e for displaying OpenGL renderingbull A GLSurfaceView provides the following features
ndash Manages a surface which is a special piece of memory that can be composited into the Android view system
ndash Manages an EGL display which enables OpenGL to render into a surfacendash Accepts a user-provided Renderer object that does the actual renderingndash Renders on a dedicated thread to decouple rendering performance from
the UI threadndash Supports both on-demand and continuous renderingndash Optionally wraps traces andor error-checks the renderers OpenGL call
s
Contbull GLSurfaceView 创建一个内部的线程 GLThreadbull 在该线程运行环境下创建一个 EglContextbull 创建一个 EglSurface ( Window Surface )bull 设置之前创建的 EglContext 为当前的 GL Contex
t 并绑定到创建的 EglSurface 上bull 在该线程内就可以通过 EGL 指令在当前的 GL Co
ntext 上绘图
Contbull GLSurfaceView支持两种不同的绘图模式
ndash 连续模式下 GLThread 会不断调用 RendereronDrawFrame 进行绘图
ndash Dirty 模式下 GLThread处于等待状态直到程序发送绘图请求( GLSurfaceViewrequestRender )才调用 RendereronDrawFrame 进行绘图绘制完一帧后重新进入等待状态
bull 在 RendereronDrawFrame 的回调中应用可以通过 SDK提供的 EGL API 绘图也可以转到 native 端使用 NDK提供的 EGL API 绘图
class SurfaceView
SurfaceView
GLSurfaceView GLSurfaceViewRenderer
+ onDrawFrame() void
GLSurfaceViewGLThread
GLSurfaceViewEglHelper
laquointerfaceraquoSurfaceHolder
laquointerfaceraquoSurfaceHolder
Callback
Surface
+ lockCanvas () Canvas+ unlockCanvasAndPost (Canvas) void
laquointerfaceraquoIWindowSession
+ add() void+ relayout() void
SurfaceViewMyWindow
BaseIWindow IWindowStublaquointerfaceraquo
IWindow
+mSurface
+mSession
+mWindow
+mCallbacks
+mSurfaceHolder
+mRenderer
+mGLThread
call
+mRenderer
+mEglHelper
TextureView
bull Since Android 40只在硬件加速环境下起作用bull 具备 SurfaceView 的特性
ndash 但是可以跟其它普通的 View 一样实现 Rotation Screw等变换
ndash 支持 Alpha 可以跟它下方的 View 进行 Alpha 混合
bull 可以基于 TextureView 创建一个 GL Surface 在上面进行 OpenGL渲染
Things become more complicated after Android 30
HW Accelerated 2D Renderingbull Android 30后开始支持硬件加速的 2D 绘图原
有的绘图流程变得更加复杂bull 所谓硬件加速的 2D 绘图就是将 2D Graphics A
PI 的实现改成使用 OpenGL API 来进行绘图bull OpenGL 的绘图模式跟一般的 2D 绘图有很大区
别它需要先将绘图所需的各种素材如贴图多边形顶点阵列 Shader等先加载到当前的 GLContext 然后流水线式的顺序执行绘图指令通过这种方式来充分利用硬件的能力
ViewRootImplbull 当 Actitity 的 View Hierachy 的根节点被添加到 WindowM
anager 的时候( WindowManageraddView ) WindowManager 的实现类 WindowManagerImpl 会创建一个 ViewRootImpl 并把它跟传进来的 View 绑定在一起( ViewRootImplsetView )并且 ViewRootImpl 会根据是否开启硬件加速来决定是否创建一个 HardwareRenderer
bull 在 ViewRootImpl 第一次渲染 View Hierachy 时会创建 Surface 如果开启硬件加速则通过 HardwareRenderer在当前的 UI 线程初始化EGL 绘图环境(类似 GLSurfaceView )
Contbull 在 ViewRootImpl 真正渲染 View Hierachy
时如果开启硬件加速则从 HardwareRenderer获得一个 HardwareCanvas 然后 View Hierachy 的渲染通过 HardwareCanvas 来进行
bull HardwareCanvas 跟一个 native 的 OpenGLRenderer 绑定通过它调用 EGL API 来完成真正的绘制
DisplayList and Hardware Layerbull 为了充分利用硬件加速的能力 Android 30 还引入了 Di
splayList 和 Hardware Layerbull DisplayList 用于记录一系列OpenGL 绘图指令和缓存所需的各种绘图素材( Bitmap Paint Shape Shader )当 View 的内容不发生变化时可以直接使用 DisplayList 进行绘制而不需要重新调用 onDraw
bull Hardware Layer 用于缓存绘制的内存到 Frame Buffer Object 当内容不发生变化时可以直接使用 Layer 进行Layer Composite获得更快的绘图速度
class Hardward2D
DisplayListHardwareCanv as
+ drawDisplayList() void+ drawHardwareLayer() void
Canv as
+ isHardwareAccelerated() voidHardwareLayer
HardwareRenderer
+ initialize() void
HardwareRendererGlRenderer
HardwareRendererGl20Renderer
GLES20Canv as
GLES20RecordingCanv as
GLES20DisplayList
laquonativeraquoDisplayList
laquonativeraquoOpenGLRenderer
laquonativeraquoDisplayListRenderer
ViewAttachInfo
ViewRootImpl
+ setView() void+ scheduleTraversals() void+ performTraversals() void+ relayoutWindow() void
GLES20Layer
GLES20TextureLayer
+mCanvas
+mNativeDisplayList
draw
+mRenderer
+mAttachInfo
+mHardwareRenderer
+mHardwareCanvas
+mResizeBuffer
Reference
bull Android 圖形系統 -- 設計與實做分析
bull How to replace GLSurfaceView with TextureView in Android Ice Cream Sandwich
The End
Thank you for your listeningYours Sincerely Roger
Contbull 当 Surface 创建后后续的渲染就可以通过获得
Surface 的 Canvas ( SurfacelockCanvas )bull 然后遍历 View Hierachy 把需要绘制的 Views
通过 Canvas 绘制到 Surface 上面( ViewonDraw )
bull 绘制完后需要解锁( SurfaceunlockCanvasPost )让 SurfaceFlinger 可以将 Surface 绘制到屏幕上( Screen Composite )
Surfacebull Handle onto a raw buffer that is being managed by the
screen compositor
bull 每个 Window 都有一个 Surface 由窗口在客户端的代理者 ViewRootImpl 所拥有
bull Surface 在 ViewRootImpl 第一次渲染 View Hierachy 时创建
ndash ViewRootImplperformTraversalsndash ViewRootImplrelayoutWindowndash IWindowSessionrelayout
Contbull ViewRootImpl预先创建一个空的 Surface 对象( Java )在需要
创建真正的 Surface 的时候它调用 IWindowSessionrelayout 这是一个 RPC 最终是 WMS 的 relayoutWindow 被调用
bull WMS 调用 WindowStatecreateSurfaceLocked 创建了一个 Surface对象( Java )并把这个对象的数据传回给客户端而客户端则负责用这些数据填充预先创建的空 Surface 对象( Java )
ndash 实际上 WMS 是请求 SurfaceFlinger 创建真正的 Surface 然后把 Surface相关的信息再传回给客户端
ndash 客户端利用这些信息来创建一个 native Surface 对象然后把它跟 Java Surface 对象绑定在一起
ndash 客户端的 Java Surface 对象以后就可以通过这个 native Surface 对象来操作图像缓存( GraphicsBuffer )图像缓存可以看作是一块共享内存在客户端和 SurfaceFlinger 之间共享
Surface amp Canvasbull Surface ( Java )包含一个 Canvas ( Java )而 Can
vas ( Java )包含一个 native 的 SkCanvas 对象bull 当调用 SurfacelockCanvas 时
ndash 从图像缓存队列中取出一个可用的缓存ndash 把当前的 Posted Buffer 的内容拷贝到新缓存中(除了 Dirty Regi
on 之外的区域)然后将这块缓存加锁并设置为 Locked Buffer
ndash 获得新缓存的内存地址根据内存地址构建一个 SkBitmapndash 把该 SkBitmap 设置到 SkCanvas 里面ndash 返回跟 SkCanvas 对应的 Canvas ( Java )透过 Canvas ( Ja
va )绘制的内容实际上就是绘制到当前的缓存
Cont
bull 当调用 SurfaceunlockCanvasAndPost 的时候ndash 置空 SkCanvas 设置一个空的 SkBitmapndash 将 Locked Buffer 解锁并返回到图像缓存队列里面ndash 将 Posted Buffer 设置为 Locked Buffer 旧的 Poste
d Buffer 就可以被下次取出来使用设置 Locked Buffer 为空
ndash 当 SurfaceFlinger 下次进行 Screen Composite 的时候就会把当前的 Posted Buffer 绘制到屏幕上
SurfaceFlingerbull 应用跟 SF 之间的关系是就像是生产者与消费者的关系bull 应用从 Surface 的 GraphicsBuffer队列的前端取出一个缓存然后进行绘制
bull 绘制完毕后把该缓存放置回队列的后端(生产)bull 而 SF 则不断地将 Surface 的 GraphicsBuffer队列的最后
一个缓存绘制到屏幕上(消费)bull 两者在不同的进程是异步进行的对队列的访问需要进
行同步
class Surface
ViewRootImpl
+ setView() void+ scheduleTraversals() void+ performTraversals() void+ relayoutWindow() void
Surface
+ lockCanvas () Canvas+ unlockCanvasAndPost (Canvas) void
laquointerfaceraquoIWindowSession
+ add() void+ relayout() void
Canvas
+ isHardwareAccelerated() void
laquonativeraquoSurface
laquonativeraquoSurfaceController
SurfaceCompatibleCanvas
laquonativeraquoSkCanvas
WindowManagerServ ice
+ relayoutWindow() void
SurfaceSession
Session
+ relayout() void
WindowState
+ createSurfaceLocked() void
laquonativeraquoSurfaceFlinger
IWindowSessionStub
laquonativeraquoSurfaceComposerCilent
laquonativeraquoBnSurfaceComposer
laquonativeraquoISurfaceComposerClient
laquonativeraquoSurfaceTextureClient
+mSurface
+sWindowSession
+mCanvas
+mSurfaceControl
+mNativeSurface
+mNativeCanvas
+mSurfaceSession
+mService
+mSessions
+mWindowMap
setBitmapDevice
communication+mClient
+mClient
Overall Flowbull ViewRootImpl 第一次渲染 View Hierachy 的时候会创建一个 Surfac
ebull 客户端请求 WMS 创建 Surface 并返回 Surface相关的数据用于构
建一个 native 的 Surface 对象并把它跟 ViewRootImpl 的 Surface( Java )绑定在一起
bull ViewRootImpl 在渲染时先从 Surface获得 Canvasbull 然后把需要绘制的 Views 通过 Canvas 绘制到 Surface 上面bull 绘制完毕后解锁该 Surfacebull SurfaceFlinger 在做 Screen Composite 的时候把解锁后的 Surface
绘制到屏幕上
Those special Views
SurfaceViewbull Provides a dedicated drawing surface embedded
inside of a view hierarchy You can control the format of this surface and if you like its size the SurfaceView takes care of placing the surface at the correct location on the screen
bull The surface is Z ordered so that it is behind the window holding its SurfaceView the SurfaceView punches a hole in its window to allow its surface to be displayed
Contbull Pros
ndash 可以跟 View Hierachy较好地结合在一起可以移动改变大小在上方叠加其它的 View
ndash 在单独的渲染线程进行渲染渲染效率高
ndash SV 的 Surface 和 Window Surface 之间的混合是由系统( SurfaceFlinger )使用硬件加速完成效率高并且不占用应用本身的 UI 线程时间
bull Consndash SurfaceView 的渲染毕竟跟
真正的 View不一样它不是由 ViewRootImpl渲染到当前的 Window Surface 上面
ndash 不能改变 Alpha 不支持跟下方的 View 进行 Alpha 混合
ndash 不能做 Rotation Skew等变换
GLSurfaceViewbull An implementation of SurfaceView that uses the dedicated surfac
e for displaying OpenGL renderingbull A GLSurfaceView provides the following features
ndash Manages a surface which is a special piece of memory that can be composited into the Android view system
ndash Manages an EGL display which enables OpenGL to render into a surfacendash Accepts a user-provided Renderer object that does the actual renderingndash Renders on a dedicated thread to decouple rendering performance from
the UI threadndash Supports both on-demand and continuous renderingndash Optionally wraps traces andor error-checks the renderers OpenGL call
s
Contbull GLSurfaceView 创建一个内部的线程 GLThreadbull 在该线程运行环境下创建一个 EglContextbull 创建一个 EglSurface ( Window Surface )bull 设置之前创建的 EglContext 为当前的 GL Contex
t 并绑定到创建的 EglSurface 上bull 在该线程内就可以通过 EGL 指令在当前的 GL Co
ntext 上绘图
Contbull GLSurfaceView支持两种不同的绘图模式
ndash 连续模式下 GLThread 会不断调用 RendereronDrawFrame 进行绘图
ndash Dirty 模式下 GLThread处于等待状态直到程序发送绘图请求( GLSurfaceViewrequestRender )才调用 RendereronDrawFrame 进行绘图绘制完一帧后重新进入等待状态
bull 在 RendereronDrawFrame 的回调中应用可以通过 SDK提供的 EGL API 绘图也可以转到 native 端使用 NDK提供的 EGL API 绘图
class SurfaceView
SurfaceView
GLSurfaceView GLSurfaceViewRenderer
+ onDrawFrame() void
GLSurfaceViewGLThread
GLSurfaceViewEglHelper
laquointerfaceraquoSurfaceHolder
laquointerfaceraquoSurfaceHolder
Callback
Surface
+ lockCanvas () Canvas+ unlockCanvasAndPost (Canvas) void
laquointerfaceraquoIWindowSession
+ add() void+ relayout() void
SurfaceViewMyWindow
BaseIWindow IWindowStublaquointerfaceraquo
IWindow
+mSurface
+mSession
+mWindow
+mCallbacks
+mSurfaceHolder
+mRenderer
+mGLThread
call
+mRenderer
+mEglHelper
TextureView
bull Since Android 40只在硬件加速环境下起作用bull 具备 SurfaceView 的特性
ndash 但是可以跟其它普通的 View 一样实现 Rotation Screw等变换
ndash 支持 Alpha 可以跟它下方的 View 进行 Alpha 混合
bull 可以基于 TextureView 创建一个 GL Surface 在上面进行 OpenGL渲染
Things become more complicated after Android 30
HW Accelerated 2D Renderingbull Android 30后开始支持硬件加速的 2D 绘图原
有的绘图流程变得更加复杂bull 所谓硬件加速的 2D 绘图就是将 2D Graphics A
PI 的实现改成使用 OpenGL API 来进行绘图bull OpenGL 的绘图模式跟一般的 2D 绘图有很大区
别它需要先将绘图所需的各种素材如贴图多边形顶点阵列 Shader等先加载到当前的 GLContext 然后流水线式的顺序执行绘图指令通过这种方式来充分利用硬件的能力
ViewRootImplbull 当 Actitity 的 View Hierachy 的根节点被添加到 WindowM
anager 的时候( WindowManageraddView ) WindowManager 的实现类 WindowManagerImpl 会创建一个 ViewRootImpl 并把它跟传进来的 View 绑定在一起( ViewRootImplsetView )并且 ViewRootImpl 会根据是否开启硬件加速来决定是否创建一个 HardwareRenderer
bull 在 ViewRootImpl 第一次渲染 View Hierachy 时会创建 Surface 如果开启硬件加速则通过 HardwareRenderer在当前的 UI 线程初始化EGL 绘图环境(类似 GLSurfaceView )
Contbull 在 ViewRootImpl 真正渲染 View Hierachy
时如果开启硬件加速则从 HardwareRenderer获得一个 HardwareCanvas 然后 View Hierachy 的渲染通过 HardwareCanvas 来进行
bull HardwareCanvas 跟一个 native 的 OpenGLRenderer 绑定通过它调用 EGL API 来完成真正的绘制
DisplayList and Hardware Layerbull 为了充分利用硬件加速的能力 Android 30 还引入了 Di
splayList 和 Hardware Layerbull DisplayList 用于记录一系列OpenGL 绘图指令和缓存所需的各种绘图素材( Bitmap Paint Shape Shader )当 View 的内容不发生变化时可以直接使用 DisplayList 进行绘制而不需要重新调用 onDraw
bull Hardware Layer 用于缓存绘制的内存到 Frame Buffer Object 当内容不发生变化时可以直接使用 Layer 进行Layer Composite获得更快的绘图速度
class Hardward2D
DisplayListHardwareCanv as
+ drawDisplayList() void+ drawHardwareLayer() void
Canv as
+ isHardwareAccelerated() voidHardwareLayer
HardwareRenderer
+ initialize() void
HardwareRendererGlRenderer
HardwareRendererGl20Renderer
GLES20Canv as
GLES20RecordingCanv as
GLES20DisplayList
laquonativeraquoDisplayList
laquonativeraquoOpenGLRenderer
laquonativeraquoDisplayListRenderer
ViewAttachInfo
ViewRootImpl
+ setView() void+ scheduleTraversals() void+ performTraversals() void+ relayoutWindow() void
GLES20Layer
GLES20TextureLayer
+mCanvas
+mNativeDisplayList
draw
+mRenderer
+mAttachInfo
+mHardwareRenderer
+mHardwareCanvas
+mResizeBuffer
Reference
bull Android 圖形系統 -- 設計與實做分析
bull How to replace GLSurfaceView with TextureView in Android Ice Cream Sandwich
The End
Thank you for your listeningYours Sincerely Roger
Surfacebull Handle onto a raw buffer that is being managed by the
screen compositor
bull 每个 Window 都有一个 Surface 由窗口在客户端的代理者 ViewRootImpl 所拥有
bull Surface 在 ViewRootImpl 第一次渲染 View Hierachy 时创建
ndash ViewRootImplperformTraversalsndash ViewRootImplrelayoutWindowndash IWindowSessionrelayout
Contbull ViewRootImpl预先创建一个空的 Surface 对象( Java )在需要
创建真正的 Surface 的时候它调用 IWindowSessionrelayout 这是一个 RPC 最终是 WMS 的 relayoutWindow 被调用
bull WMS 调用 WindowStatecreateSurfaceLocked 创建了一个 Surface对象( Java )并把这个对象的数据传回给客户端而客户端则负责用这些数据填充预先创建的空 Surface 对象( Java )
ndash 实际上 WMS 是请求 SurfaceFlinger 创建真正的 Surface 然后把 Surface相关的信息再传回给客户端
ndash 客户端利用这些信息来创建一个 native Surface 对象然后把它跟 Java Surface 对象绑定在一起
ndash 客户端的 Java Surface 对象以后就可以通过这个 native Surface 对象来操作图像缓存( GraphicsBuffer )图像缓存可以看作是一块共享内存在客户端和 SurfaceFlinger 之间共享
Surface amp Canvasbull Surface ( Java )包含一个 Canvas ( Java )而 Can
vas ( Java )包含一个 native 的 SkCanvas 对象bull 当调用 SurfacelockCanvas 时
ndash 从图像缓存队列中取出一个可用的缓存ndash 把当前的 Posted Buffer 的内容拷贝到新缓存中(除了 Dirty Regi
on 之外的区域)然后将这块缓存加锁并设置为 Locked Buffer
ndash 获得新缓存的内存地址根据内存地址构建一个 SkBitmapndash 把该 SkBitmap 设置到 SkCanvas 里面ndash 返回跟 SkCanvas 对应的 Canvas ( Java )透过 Canvas ( Ja
va )绘制的内容实际上就是绘制到当前的缓存
Cont
bull 当调用 SurfaceunlockCanvasAndPost 的时候ndash 置空 SkCanvas 设置一个空的 SkBitmapndash 将 Locked Buffer 解锁并返回到图像缓存队列里面ndash 将 Posted Buffer 设置为 Locked Buffer 旧的 Poste
d Buffer 就可以被下次取出来使用设置 Locked Buffer 为空
ndash 当 SurfaceFlinger 下次进行 Screen Composite 的时候就会把当前的 Posted Buffer 绘制到屏幕上
SurfaceFlingerbull 应用跟 SF 之间的关系是就像是生产者与消费者的关系bull 应用从 Surface 的 GraphicsBuffer队列的前端取出一个缓存然后进行绘制
bull 绘制完毕后把该缓存放置回队列的后端(生产)bull 而 SF 则不断地将 Surface 的 GraphicsBuffer队列的最后
一个缓存绘制到屏幕上(消费)bull 两者在不同的进程是异步进行的对队列的访问需要进
行同步
class Surface
ViewRootImpl
+ setView() void+ scheduleTraversals() void+ performTraversals() void+ relayoutWindow() void
Surface
+ lockCanvas () Canvas+ unlockCanvasAndPost (Canvas) void
laquointerfaceraquoIWindowSession
+ add() void+ relayout() void
Canvas
+ isHardwareAccelerated() void
laquonativeraquoSurface
laquonativeraquoSurfaceController
SurfaceCompatibleCanvas
laquonativeraquoSkCanvas
WindowManagerServ ice
+ relayoutWindow() void
SurfaceSession
Session
+ relayout() void
WindowState
+ createSurfaceLocked() void
laquonativeraquoSurfaceFlinger
IWindowSessionStub
laquonativeraquoSurfaceComposerCilent
laquonativeraquoBnSurfaceComposer
laquonativeraquoISurfaceComposerClient
laquonativeraquoSurfaceTextureClient
+mSurface
+sWindowSession
+mCanvas
+mSurfaceControl
+mNativeSurface
+mNativeCanvas
+mSurfaceSession
+mService
+mSessions
+mWindowMap
setBitmapDevice
communication+mClient
+mClient
Overall Flowbull ViewRootImpl 第一次渲染 View Hierachy 的时候会创建一个 Surfac
ebull 客户端请求 WMS 创建 Surface 并返回 Surface相关的数据用于构
建一个 native 的 Surface 对象并把它跟 ViewRootImpl 的 Surface( Java )绑定在一起
bull ViewRootImpl 在渲染时先从 Surface获得 Canvasbull 然后把需要绘制的 Views 通过 Canvas 绘制到 Surface 上面bull 绘制完毕后解锁该 Surfacebull SurfaceFlinger 在做 Screen Composite 的时候把解锁后的 Surface
绘制到屏幕上
Those special Views
SurfaceViewbull Provides a dedicated drawing surface embedded
inside of a view hierarchy You can control the format of this surface and if you like its size the SurfaceView takes care of placing the surface at the correct location on the screen
bull The surface is Z ordered so that it is behind the window holding its SurfaceView the SurfaceView punches a hole in its window to allow its surface to be displayed
Contbull Pros
ndash 可以跟 View Hierachy较好地结合在一起可以移动改变大小在上方叠加其它的 View
ndash 在单独的渲染线程进行渲染渲染效率高
ndash SV 的 Surface 和 Window Surface 之间的混合是由系统( SurfaceFlinger )使用硬件加速完成效率高并且不占用应用本身的 UI 线程时间
bull Consndash SurfaceView 的渲染毕竟跟
真正的 View不一样它不是由 ViewRootImpl渲染到当前的 Window Surface 上面
ndash 不能改变 Alpha 不支持跟下方的 View 进行 Alpha 混合
ndash 不能做 Rotation Skew等变换
GLSurfaceViewbull An implementation of SurfaceView that uses the dedicated surfac
e for displaying OpenGL renderingbull A GLSurfaceView provides the following features
ndash Manages a surface which is a special piece of memory that can be composited into the Android view system
ndash Manages an EGL display which enables OpenGL to render into a surfacendash Accepts a user-provided Renderer object that does the actual renderingndash Renders on a dedicated thread to decouple rendering performance from
the UI threadndash Supports both on-demand and continuous renderingndash Optionally wraps traces andor error-checks the renderers OpenGL call
s
Contbull GLSurfaceView 创建一个内部的线程 GLThreadbull 在该线程运行环境下创建一个 EglContextbull 创建一个 EglSurface ( Window Surface )bull 设置之前创建的 EglContext 为当前的 GL Contex
t 并绑定到创建的 EglSurface 上bull 在该线程内就可以通过 EGL 指令在当前的 GL Co
ntext 上绘图
Contbull GLSurfaceView支持两种不同的绘图模式
ndash 连续模式下 GLThread 会不断调用 RendereronDrawFrame 进行绘图
ndash Dirty 模式下 GLThread处于等待状态直到程序发送绘图请求( GLSurfaceViewrequestRender )才调用 RendereronDrawFrame 进行绘图绘制完一帧后重新进入等待状态
bull 在 RendereronDrawFrame 的回调中应用可以通过 SDK提供的 EGL API 绘图也可以转到 native 端使用 NDK提供的 EGL API 绘图
class SurfaceView
SurfaceView
GLSurfaceView GLSurfaceViewRenderer
+ onDrawFrame() void
GLSurfaceViewGLThread
GLSurfaceViewEglHelper
laquointerfaceraquoSurfaceHolder
laquointerfaceraquoSurfaceHolder
Callback
Surface
+ lockCanvas () Canvas+ unlockCanvasAndPost (Canvas) void
laquointerfaceraquoIWindowSession
+ add() void+ relayout() void
SurfaceViewMyWindow
BaseIWindow IWindowStublaquointerfaceraquo
IWindow
+mSurface
+mSession
+mWindow
+mCallbacks
+mSurfaceHolder
+mRenderer
+mGLThread
call
+mRenderer
+mEglHelper
TextureView
bull Since Android 40只在硬件加速环境下起作用bull 具备 SurfaceView 的特性
ndash 但是可以跟其它普通的 View 一样实现 Rotation Screw等变换
ndash 支持 Alpha 可以跟它下方的 View 进行 Alpha 混合
bull 可以基于 TextureView 创建一个 GL Surface 在上面进行 OpenGL渲染
Things become more complicated after Android 30
HW Accelerated 2D Renderingbull Android 30后开始支持硬件加速的 2D 绘图原
有的绘图流程变得更加复杂bull 所谓硬件加速的 2D 绘图就是将 2D Graphics A
PI 的实现改成使用 OpenGL API 来进行绘图bull OpenGL 的绘图模式跟一般的 2D 绘图有很大区
别它需要先将绘图所需的各种素材如贴图多边形顶点阵列 Shader等先加载到当前的 GLContext 然后流水线式的顺序执行绘图指令通过这种方式来充分利用硬件的能力
ViewRootImplbull 当 Actitity 的 View Hierachy 的根节点被添加到 WindowM
anager 的时候( WindowManageraddView ) WindowManager 的实现类 WindowManagerImpl 会创建一个 ViewRootImpl 并把它跟传进来的 View 绑定在一起( ViewRootImplsetView )并且 ViewRootImpl 会根据是否开启硬件加速来决定是否创建一个 HardwareRenderer
bull 在 ViewRootImpl 第一次渲染 View Hierachy 时会创建 Surface 如果开启硬件加速则通过 HardwareRenderer在当前的 UI 线程初始化EGL 绘图环境(类似 GLSurfaceView )
Contbull 在 ViewRootImpl 真正渲染 View Hierachy
时如果开启硬件加速则从 HardwareRenderer获得一个 HardwareCanvas 然后 View Hierachy 的渲染通过 HardwareCanvas 来进行
bull HardwareCanvas 跟一个 native 的 OpenGLRenderer 绑定通过它调用 EGL API 来完成真正的绘制
DisplayList and Hardware Layerbull 为了充分利用硬件加速的能力 Android 30 还引入了 Di
splayList 和 Hardware Layerbull DisplayList 用于记录一系列OpenGL 绘图指令和缓存所需的各种绘图素材( Bitmap Paint Shape Shader )当 View 的内容不发生变化时可以直接使用 DisplayList 进行绘制而不需要重新调用 onDraw
bull Hardware Layer 用于缓存绘制的内存到 Frame Buffer Object 当内容不发生变化时可以直接使用 Layer 进行Layer Composite获得更快的绘图速度
class Hardward2D
DisplayListHardwareCanv as
+ drawDisplayList() void+ drawHardwareLayer() void
Canv as
+ isHardwareAccelerated() voidHardwareLayer
HardwareRenderer
+ initialize() void
HardwareRendererGlRenderer
HardwareRendererGl20Renderer
GLES20Canv as
GLES20RecordingCanv as
GLES20DisplayList
laquonativeraquoDisplayList
laquonativeraquoOpenGLRenderer
laquonativeraquoDisplayListRenderer
ViewAttachInfo
ViewRootImpl
+ setView() void+ scheduleTraversals() void+ performTraversals() void+ relayoutWindow() void
GLES20Layer
GLES20TextureLayer
+mCanvas
+mNativeDisplayList
draw
+mRenderer
+mAttachInfo
+mHardwareRenderer
+mHardwareCanvas
+mResizeBuffer
Reference
bull Android 圖形系統 -- 設計與實做分析
bull How to replace GLSurfaceView with TextureView in Android Ice Cream Sandwich
The End
Thank you for your listeningYours Sincerely Roger
Contbull ViewRootImpl预先创建一个空的 Surface 对象( Java )在需要
创建真正的 Surface 的时候它调用 IWindowSessionrelayout 这是一个 RPC 最终是 WMS 的 relayoutWindow 被调用
bull WMS 调用 WindowStatecreateSurfaceLocked 创建了一个 Surface对象( Java )并把这个对象的数据传回给客户端而客户端则负责用这些数据填充预先创建的空 Surface 对象( Java )
ndash 实际上 WMS 是请求 SurfaceFlinger 创建真正的 Surface 然后把 Surface相关的信息再传回给客户端
ndash 客户端利用这些信息来创建一个 native Surface 对象然后把它跟 Java Surface 对象绑定在一起
ndash 客户端的 Java Surface 对象以后就可以通过这个 native Surface 对象来操作图像缓存( GraphicsBuffer )图像缓存可以看作是一块共享内存在客户端和 SurfaceFlinger 之间共享
Surface amp Canvasbull Surface ( Java )包含一个 Canvas ( Java )而 Can
vas ( Java )包含一个 native 的 SkCanvas 对象bull 当调用 SurfacelockCanvas 时
ndash 从图像缓存队列中取出一个可用的缓存ndash 把当前的 Posted Buffer 的内容拷贝到新缓存中(除了 Dirty Regi
on 之外的区域)然后将这块缓存加锁并设置为 Locked Buffer
ndash 获得新缓存的内存地址根据内存地址构建一个 SkBitmapndash 把该 SkBitmap 设置到 SkCanvas 里面ndash 返回跟 SkCanvas 对应的 Canvas ( Java )透过 Canvas ( Ja
va )绘制的内容实际上就是绘制到当前的缓存
Cont
bull 当调用 SurfaceunlockCanvasAndPost 的时候ndash 置空 SkCanvas 设置一个空的 SkBitmapndash 将 Locked Buffer 解锁并返回到图像缓存队列里面ndash 将 Posted Buffer 设置为 Locked Buffer 旧的 Poste
d Buffer 就可以被下次取出来使用设置 Locked Buffer 为空
ndash 当 SurfaceFlinger 下次进行 Screen Composite 的时候就会把当前的 Posted Buffer 绘制到屏幕上
SurfaceFlingerbull 应用跟 SF 之间的关系是就像是生产者与消费者的关系bull 应用从 Surface 的 GraphicsBuffer队列的前端取出一个缓存然后进行绘制
bull 绘制完毕后把该缓存放置回队列的后端(生产)bull 而 SF 则不断地将 Surface 的 GraphicsBuffer队列的最后
一个缓存绘制到屏幕上(消费)bull 两者在不同的进程是异步进行的对队列的访问需要进
行同步
class Surface
ViewRootImpl
+ setView() void+ scheduleTraversals() void+ performTraversals() void+ relayoutWindow() void
Surface
+ lockCanvas () Canvas+ unlockCanvasAndPost (Canvas) void
laquointerfaceraquoIWindowSession
+ add() void+ relayout() void
Canvas
+ isHardwareAccelerated() void
laquonativeraquoSurface
laquonativeraquoSurfaceController
SurfaceCompatibleCanvas
laquonativeraquoSkCanvas
WindowManagerServ ice
+ relayoutWindow() void
SurfaceSession
Session
+ relayout() void
WindowState
+ createSurfaceLocked() void
laquonativeraquoSurfaceFlinger
IWindowSessionStub
laquonativeraquoSurfaceComposerCilent
laquonativeraquoBnSurfaceComposer
laquonativeraquoISurfaceComposerClient
laquonativeraquoSurfaceTextureClient
+mSurface
+sWindowSession
+mCanvas
+mSurfaceControl
+mNativeSurface
+mNativeCanvas
+mSurfaceSession
+mService
+mSessions
+mWindowMap
setBitmapDevice
communication+mClient
+mClient
Overall Flowbull ViewRootImpl 第一次渲染 View Hierachy 的时候会创建一个 Surfac
ebull 客户端请求 WMS 创建 Surface 并返回 Surface相关的数据用于构
建一个 native 的 Surface 对象并把它跟 ViewRootImpl 的 Surface( Java )绑定在一起
bull ViewRootImpl 在渲染时先从 Surface获得 Canvasbull 然后把需要绘制的 Views 通过 Canvas 绘制到 Surface 上面bull 绘制完毕后解锁该 Surfacebull SurfaceFlinger 在做 Screen Composite 的时候把解锁后的 Surface
绘制到屏幕上
Those special Views
SurfaceViewbull Provides a dedicated drawing surface embedded
inside of a view hierarchy You can control the format of this surface and if you like its size the SurfaceView takes care of placing the surface at the correct location on the screen
bull The surface is Z ordered so that it is behind the window holding its SurfaceView the SurfaceView punches a hole in its window to allow its surface to be displayed
Contbull Pros
ndash 可以跟 View Hierachy较好地结合在一起可以移动改变大小在上方叠加其它的 View
ndash 在单独的渲染线程进行渲染渲染效率高
ndash SV 的 Surface 和 Window Surface 之间的混合是由系统( SurfaceFlinger )使用硬件加速完成效率高并且不占用应用本身的 UI 线程时间
bull Consndash SurfaceView 的渲染毕竟跟
真正的 View不一样它不是由 ViewRootImpl渲染到当前的 Window Surface 上面
ndash 不能改变 Alpha 不支持跟下方的 View 进行 Alpha 混合
ndash 不能做 Rotation Skew等变换
GLSurfaceViewbull An implementation of SurfaceView that uses the dedicated surfac
e for displaying OpenGL renderingbull A GLSurfaceView provides the following features
ndash Manages a surface which is a special piece of memory that can be composited into the Android view system
ndash Manages an EGL display which enables OpenGL to render into a surfacendash Accepts a user-provided Renderer object that does the actual renderingndash Renders on a dedicated thread to decouple rendering performance from
the UI threadndash Supports both on-demand and continuous renderingndash Optionally wraps traces andor error-checks the renderers OpenGL call
s
Contbull GLSurfaceView 创建一个内部的线程 GLThreadbull 在该线程运行环境下创建一个 EglContextbull 创建一个 EglSurface ( Window Surface )bull 设置之前创建的 EglContext 为当前的 GL Contex
t 并绑定到创建的 EglSurface 上bull 在该线程内就可以通过 EGL 指令在当前的 GL Co
ntext 上绘图
Contbull GLSurfaceView支持两种不同的绘图模式
ndash 连续模式下 GLThread 会不断调用 RendereronDrawFrame 进行绘图
ndash Dirty 模式下 GLThread处于等待状态直到程序发送绘图请求( GLSurfaceViewrequestRender )才调用 RendereronDrawFrame 进行绘图绘制完一帧后重新进入等待状态
bull 在 RendereronDrawFrame 的回调中应用可以通过 SDK提供的 EGL API 绘图也可以转到 native 端使用 NDK提供的 EGL API 绘图
class SurfaceView
SurfaceView
GLSurfaceView GLSurfaceViewRenderer
+ onDrawFrame() void
GLSurfaceViewGLThread
GLSurfaceViewEglHelper
laquointerfaceraquoSurfaceHolder
laquointerfaceraquoSurfaceHolder
Callback
Surface
+ lockCanvas () Canvas+ unlockCanvasAndPost (Canvas) void
laquointerfaceraquoIWindowSession
+ add() void+ relayout() void
SurfaceViewMyWindow
BaseIWindow IWindowStublaquointerfaceraquo
IWindow
+mSurface
+mSession
+mWindow
+mCallbacks
+mSurfaceHolder
+mRenderer
+mGLThread
call
+mRenderer
+mEglHelper
TextureView
bull Since Android 40只在硬件加速环境下起作用bull 具备 SurfaceView 的特性
ndash 但是可以跟其它普通的 View 一样实现 Rotation Screw等变换
ndash 支持 Alpha 可以跟它下方的 View 进行 Alpha 混合
bull 可以基于 TextureView 创建一个 GL Surface 在上面进行 OpenGL渲染
Things become more complicated after Android 30
HW Accelerated 2D Renderingbull Android 30后开始支持硬件加速的 2D 绘图原
有的绘图流程变得更加复杂bull 所谓硬件加速的 2D 绘图就是将 2D Graphics A
PI 的实现改成使用 OpenGL API 来进行绘图bull OpenGL 的绘图模式跟一般的 2D 绘图有很大区
别它需要先将绘图所需的各种素材如贴图多边形顶点阵列 Shader等先加载到当前的 GLContext 然后流水线式的顺序执行绘图指令通过这种方式来充分利用硬件的能力
ViewRootImplbull 当 Actitity 的 View Hierachy 的根节点被添加到 WindowM
anager 的时候( WindowManageraddView ) WindowManager 的实现类 WindowManagerImpl 会创建一个 ViewRootImpl 并把它跟传进来的 View 绑定在一起( ViewRootImplsetView )并且 ViewRootImpl 会根据是否开启硬件加速来决定是否创建一个 HardwareRenderer
bull 在 ViewRootImpl 第一次渲染 View Hierachy 时会创建 Surface 如果开启硬件加速则通过 HardwareRenderer在当前的 UI 线程初始化EGL 绘图环境(类似 GLSurfaceView )
Contbull 在 ViewRootImpl 真正渲染 View Hierachy
时如果开启硬件加速则从 HardwareRenderer获得一个 HardwareCanvas 然后 View Hierachy 的渲染通过 HardwareCanvas 来进行
bull HardwareCanvas 跟一个 native 的 OpenGLRenderer 绑定通过它调用 EGL API 来完成真正的绘制
DisplayList and Hardware Layerbull 为了充分利用硬件加速的能力 Android 30 还引入了 Di
splayList 和 Hardware Layerbull DisplayList 用于记录一系列OpenGL 绘图指令和缓存所需的各种绘图素材( Bitmap Paint Shape Shader )当 View 的内容不发生变化时可以直接使用 DisplayList 进行绘制而不需要重新调用 onDraw
bull Hardware Layer 用于缓存绘制的内存到 Frame Buffer Object 当内容不发生变化时可以直接使用 Layer 进行Layer Composite获得更快的绘图速度
class Hardward2D
DisplayListHardwareCanv as
+ drawDisplayList() void+ drawHardwareLayer() void
Canv as
+ isHardwareAccelerated() voidHardwareLayer
HardwareRenderer
+ initialize() void
HardwareRendererGlRenderer
HardwareRendererGl20Renderer
GLES20Canv as
GLES20RecordingCanv as
GLES20DisplayList
laquonativeraquoDisplayList
laquonativeraquoOpenGLRenderer
laquonativeraquoDisplayListRenderer
ViewAttachInfo
ViewRootImpl
+ setView() void+ scheduleTraversals() void+ performTraversals() void+ relayoutWindow() void
GLES20Layer
GLES20TextureLayer
+mCanvas
+mNativeDisplayList
draw
+mRenderer
+mAttachInfo
+mHardwareRenderer
+mHardwareCanvas
+mResizeBuffer
Reference
bull Android 圖形系統 -- 設計與實做分析
bull How to replace GLSurfaceView with TextureView in Android Ice Cream Sandwich
The End
Thank you for your listeningYours Sincerely Roger
Surface amp Canvasbull Surface ( Java )包含一个 Canvas ( Java )而 Can
vas ( Java )包含一个 native 的 SkCanvas 对象bull 当调用 SurfacelockCanvas 时
ndash 从图像缓存队列中取出一个可用的缓存ndash 把当前的 Posted Buffer 的内容拷贝到新缓存中(除了 Dirty Regi
on 之外的区域)然后将这块缓存加锁并设置为 Locked Buffer
ndash 获得新缓存的内存地址根据内存地址构建一个 SkBitmapndash 把该 SkBitmap 设置到 SkCanvas 里面ndash 返回跟 SkCanvas 对应的 Canvas ( Java )透过 Canvas ( Ja
va )绘制的内容实际上就是绘制到当前的缓存
Cont
bull 当调用 SurfaceunlockCanvasAndPost 的时候ndash 置空 SkCanvas 设置一个空的 SkBitmapndash 将 Locked Buffer 解锁并返回到图像缓存队列里面ndash 将 Posted Buffer 设置为 Locked Buffer 旧的 Poste
d Buffer 就可以被下次取出来使用设置 Locked Buffer 为空
ndash 当 SurfaceFlinger 下次进行 Screen Composite 的时候就会把当前的 Posted Buffer 绘制到屏幕上
SurfaceFlingerbull 应用跟 SF 之间的关系是就像是生产者与消费者的关系bull 应用从 Surface 的 GraphicsBuffer队列的前端取出一个缓存然后进行绘制
bull 绘制完毕后把该缓存放置回队列的后端(生产)bull 而 SF 则不断地将 Surface 的 GraphicsBuffer队列的最后
一个缓存绘制到屏幕上(消费)bull 两者在不同的进程是异步进行的对队列的访问需要进
行同步
class Surface
ViewRootImpl
+ setView() void+ scheduleTraversals() void+ performTraversals() void+ relayoutWindow() void
Surface
+ lockCanvas () Canvas+ unlockCanvasAndPost (Canvas) void
laquointerfaceraquoIWindowSession
+ add() void+ relayout() void
Canvas
+ isHardwareAccelerated() void
laquonativeraquoSurface
laquonativeraquoSurfaceController
SurfaceCompatibleCanvas
laquonativeraquoSkCanvas
WindowManagerServ ice
+ relayoutWindow() void
SurfaceSession
Session
+ relayout() void
WindowState
+ createSurfaceLocked() void
laquonativeraquoSurfaceFlinger
IWindowSessionStub
laquonativeraquoSurfaceComposerCilent
laquonativeraquoBnSurfaceComposer
laquonativeraquoISurfaceComposerClient
laquonativeraquoSurfaceTextureClient
+mSurface
+sWindowSession
+mCanvas
+mSurfaceControl
+mNativeSurface
+mNativeCanvas
+mSurfaceSession
+mService
+mSessions
+mWindowMap
setBitmapDevice
communication+mClient
+mClient
Overall Flowbull ViewRootImpl 第一次渲染 View Hierachy 的时候会创建一个 Surfac
ebull 客户端请求 WMS 创建 Surface 并返回 Surface相关的数据用于构
建一个 native 的 Surface 对象并把它跟 ViewRootImpl 的 Surface( Java )绑定在一起
bull ViewRootImpl 在渲染时先从 Surface获得 Canvasbull 然后把需要绘制的 Views 通过 Canvas 绘制到 Surface 上面bull 绘制完毕后解锁该 Surfacebull SurfaceFlinger 在做 Screen Composite 的时候把解锁后的 Surface
绘制到屏幕上
Those special Views
SurfaceViewbull Provides a dedicated drawing surface embedded
inside of a view hierarchy You can control the format of this surface and if you like its size the SurfaceView takes care of placing the surface at the correct location on the screen
bull The surface is Z ordered so that it is behind the window holding its SurfaceView the SurfaceView punches a hole in its window to allow its surface to be displayed
Contbull Pros
ndash 可以跟 View Hierachy较好地结合在一起可以移动改变大小在上方叠加其它的 View
ndash 在单独的渲染线程进行渲染渲染效率高
ndash SV 的 Surface 和 Window Surface 之间的混合是由系统( SurfaceFlinger )使用硬件加速完成效率高并且不占用应用本身的 UI 线程时间
bull Consndash SurfaceView 的渲染毕竟跟
真正的 View不一样它不是由 ViewRootImpl渲染到当前的 Window Surface 上面
ndash 不能改变 Alpha 不支持跟下方的 View 进行 Alpha 混合
ndash 不能做 Rotation Skew等变换
GLSurfaceViewbull An implementation of SurfaceView that uses the dedicated surfac
e for displaying OpenGL renderingbull A GLSurfaceView provides the following features
ndash Manages a surface which is a special piece of memory that can be composited into the Android view system
ndash Manages an EGL display which enables OpenGL to render into a surfacendash Accepts a user-provided Renderer object that does the actual renderingndash Renders on a dedicated thread to decouple rendering performance from
the UI threadndash Supports both on-demand and continuous renderingndash Optionally wraps traces andor error-checks the renderers OpenGL call
s
Contbull GLSurfaceView 创建一个内部的线程 GLThreadbull 在该线程运行环境下创建一个 EglContextbull 创建一个 EglSurface ( Window Surface )bull 设置之前创建的 EglContext 为当前的 GL Contex
t 并绑定到创建的 EglSurface 上bull 在该线程内就可以通过 EGL 指令在当前的 GL Co
ntext 上绘图
Contbull GLSurfaceView支持两种不同的绘图模式
ndash 连续模式下 GLThread 会不断调用 RendereronDrawFrame 进行绘图
ndash Dirty 模式下 GLThread处于等待状态直到程序发送绘图请求( GLSurfaceViewrequestRender )才调用 RendereronDrawFrame 进行绘图绘制完一帧后重新进入等待状态
bull 在 RendereronDrawFrame 的回调中应用可以通过 SDK提供的 EGL API 绘图也可以转到 native 端使用 NDK提供的 EGL API 绘图
class SurfaceView
SurfaceView
GLSurfaceView GLSurfaceViewRenderer
+ onDrawFrame() void
GLSurfaceViewGLThread
GLSurfaceViewEglHelper
laquointerfaceraquoSurfaceHolder
laquointerfaceraquoSurfaceHolder
Callback
Surface
+ lockCanvas () Canvas+ unlockCanvasAndPost (Canvas) void
laquointerfaceraquoIWindowSession
+ add() void+ relayout() void
SurfaceViewMyWindow
BaseIWindow IWindowStublaquointerfaceraquo
IWindow
+mSurface
+mSession
+mWindow
+mCallbacks
+mSurfaceHolder
+mRenderer
+mGLThread
call
+mRenderer
+mEglHelper
TextureView
bull Since Android 40只在硬件加速环境下起作用bull 具备 SurfaceView 的特性
ndash 但是可以跟其它普通的 View 一样实现 Rotation Screw等变换
ndash 支持 Alpha 可以跟它下方的 View 进行 Alpha 混合
bull 可以基于 TextureView 创建一个 GL Surface 在上面进行 OpenGL渲染
Things become more complicated after Android 30
HW Accelerated 2D Renderingbull Android 30后开始支持硬件加速的 2D 绘图原
有的绘图流程变得更加复杂bull 所谓硬件加速的 2D 绘图就是将 2D Graphics A
PI 的实现改成使用 OpenGL API 来进行绘图bull OpenGL 的绘图模式跟一般的 2D 绘图有很大区
别它需要先将绘图所需的各种素材如贴图多边形顶点阵列 Shader等先加载到当前的 GLContext 然后流水线式的顺序执行绘图指令通过这种方式来充分利用硬件的能力
ViewRootImplbull 当 Actitity 的 View Hierachy 的根节点被添加到 WindowM
anager 的时候( WindowManageraddView ) WindowManager 的实现类 WindowManagerImpl 会创建一个 ViewRootImpl 并把它跟传进来的 View 绑定在一起( ViewRootImplsetView )并且 ViewRootImpl 会根据是否开启硬件加速来决定是否创建一个 HardwareRenderer
bull 在 ViewRootImpl 第一次渲染 View Hierachy 时会创建 Surface 如果开启硬件加速则通过 HardwareRenderer在当前的 UI 线程初始化EGL 绘图环境(类似 GLSurfaceView )
Contbull 在 ViewRootImpl 真正渲染 View Hierachy
时如果开启硬件加速则从 HardwareRenderer获得一个 HardwareCanvas 然后 View Hierachy 的渲染通过 HardwareCanvas 来进行
bull HardwareCanvas 跟一个 native 的 OpenGLRenderer 绑定通过它调用 EGL API 来完成真正的绘制
DisplayList and Hardware Layerbull 为了充分利用硬件加速的能力 Android 30 还引入了 Di
splayList 和 Hardware Layerbull DisplayList 用于记录一系列OpenGL 绘图指令和缓存所需的各种绘图素材( Bitmap Paint Shape Shader )当 View 的内容不发生变化时可以直接使用 DisplayList 进行绘制而不需要重新调用 onDraw
bull Hardware Layer 用于缓存绘制的内存到 Frame Buffer Object 当内容不发生变化时可以直接使用 Layer 进行Layer Composite获得更快的绘图速度
class Hardward2D
DisplayListHardwareCanv as
+ drawDisplayList() void+ drawHardwareLayer() void
Canv as
+ isHardwareAccelerated() voidHardwareLayer
HardwareRenderer
+ initialize() void
HardwareRendererGlRenderer
HardwareRendererGl20Renderer
GLES20Canv as
GLES20RecordingCanv as
GLES20DisplayList
laquonativeraquoDisplayList
laquonativeraquoOpenGLRenderer
laquonativeraquoDisplayListRenderer
ViewAttachInfo
ViewRootImpl
+ setView() void+ scheduleTraversals() void+ performTraversals() void+ relayoutWindow() void
GLES20Layer
GLES20TextureLayer
+mCanvas
+mNativeDisplayList
draw
+mRenderer
+mAttachInfo
+mHardwareRenderer
+mHardwareCanvas
+mResizeBuffer
Reference
bull Android 圖形系統 -- 設計與實做分析
bull How to replace GLSurfaceView with TextureView in Android Ice Cream Sandwich
The End
Thank you for your listeningYours Sincerely Roger
Cont
bull 当调用 SurfaceunlockCanvasAndPost 的时候ndash 置空 SkCanvas 设置一个空的 SkBitmapndash 将 Locked Buffer 解锁并返回到图像缓存队列里面ndash 将 Posted Buffer 设置为 Locked Buffer 旧的 Poste
d Buffer 就可以被下次取出来使用设置 Locked Buffer 为空
ndash 当 SurfaceFlinger 下次进行 Screen Composite 的时候就会把当前的 Posted Buffer 绘制到屏幕上
SurfaceFlingerbull 应用跟 SF 之间的关系是就像是生产者与消费者的关系bull 应用从 Surface 的 GraphicsBuffer队列的前端取出一个缓存然后进行绘制
bull 绘制完毕后把该缓存放置回队列的后端(生产)bull 而 SF 则不断地将 Surface 的 GraphicsBuffer队列的最后
一个缓存绘制到屏幕上(消费)bull 两者在不同的进程是异步进行的对队列的访问需要进
行同步
class Surface
ViewRootImpl
+ setView() void+ scheduleTraversals() void+ performTraversals() void+ relayoutWindow() void
Surface
+ lockCanvas () Canvas+ unlockCanvasAndPost (Canvas) void
laquointerfaceraquoIWindowSession
+ add() void+ relayout() void
Canvas
+ isHardwareAccelerated() void
laquonativeraquoSurface
laquonativeraquoSurfaceController
SurfaceCompatibleCanvas
laquonativeraquoSkCanvas
WindowManagerServ ice
+ relayoutWindow() void
SurfaceSession
Session
+ relayout() void
WindowState
+ createSurfaceLocked() void
laquonativeraquoSurfaceFlinger
IWindowSessionStub
laquonativeraquoSurfaceComposerCilent
laquonativeraquoBnSurfaceComposer
laquonativeraquoISurfaceComposerClient
laquonativeraquoSurfaceTextureClient
+mSurface
+sWindowSession
+mCanvas
+mSurfaceControl
+mNativeSurface
+mNativeCanvas
+mSurfaceSession
+mService
+mSessions
+mWindowMap
setBitmapDevice
communication+mClient
+mClient
Overall Flowbull ViewRootImpl 第一次渲染 View Hierachy 的时候会创建一个 Surfac
ebull 客户端请求 WMS 创建 Surface 并返回 Surface相关的数据用于构
建一个 native 的 Surface 对象并把它跟 ViewRootImpl 的 Surface( Java )绑定在一起
bull ViewRootImpl 在渲染时先从 Surface获得 Canvasbull 然后把需要绘制的 Views 通过 Canvas 绘制到 Surface 上面bull 绘制完毕后解锁该 Surfacebull SurfaceFlinger 在做 Screen Composite 的时候把解锁后的 Surface
绘制到屏幕上
Those special Views
SurfaceViewbull Provides a dedicated drawing surface embedded
inside of a view hierarchy You can control the format of this surface and if you like its size the SurfaceView takes care of placing the surface at the correct location on the screen
bull The surface is Z ordered so that it is behind the window holding its SurfaceView the SurfaceView punches a hole in its window to allow its surface to be displayed
Contbull Pros
ndash 可以跟 View Hierachy较好地结合在一起可以移动改变大小在上方叠加其它的 View
ndash 在单独的渲染线程进行渲染渲染效率高
ndash SV 的 Surface 和 Window Surface 之间的混合是由系统( SurfaceFlinger )使用硬件加速完成效率高并且不占用应用本身的 UI 线程时间
bull Consndash SurfaceView 的渲染毕竟跟
真正的 View不一样它不是由 ViewRootImpl渲染到当前的 Window Surface 上面
ndash 不能改变 Alpha 不支持跟下方的 View 进行 Alpha 混合
ndash 不能做 Rotation Skew等变换
GLSurfaceViewbull An implementation of SurfaceView that uses the dedicated surfac
e for displaying OpenGL renderingbull A GLSurfaceView provides the following features
ndash Manages a surface which is a special piece of memory that can be composited into the Android view system
ndash Manages an EGL display which enables OpenGL to render into a surfacendash Accepts a user-provided Renderer object that does the actual renderingndash Renders on a dedicated thread to decouple rendering performance from
the UI threadndash Supports both on-demand and continuous renderingndash Optionally wraps traces andor error-checks the renderers OpenGL call
s
Contbull GLSurfaceView 创建一个内部的线程 GLThreadbull 在该线程运行环境下创建一个 EglContextbull 创建一个 EglSurface ( Window Surface )bull 设置之前创建的 EglContext 为当前的 GL Contex
t 并绑定到创建的 EglSurface 上bull 在该线程内就可以通过 EGL 指令在当前的 GL Co
ntext 上绘图
Contbull GLSurfaceView支持两种不同的绘图模式
ndash 连续模式下 GLThread 会不断调用 RendereronDrawFrame 进行绘图
ndash Dirty 模式下 GLThread处于等待状态直到程序发送绘图请求( GLSurfaceViewrequestRender )才调用 RendereronDrawFrame 进行绘图绘制完一帧后重新进入等待状态
bull 在 RendereronDrawFrame 的回调中应用可以通过 SDK提供的 EGL API 绘图也可以转到 native 端使用 NDK提供的 EGL API 绘图
class SurfaceView
SurfaceView
GLSurfaceView GLSurfaceViewRenderer
+ onDrawFrame() void
GLSurfaceViewGLThread
GLSurfaceViewEglHelper
laquointerfaceraquoSurfaceHolder
laquointerfaceraquoSurfaceHolder
Callback
Surface
+ lockCanvas () Canvas+ unlockCanvasAndPost (Canvas) void
laquointerfaceraquoIWindowSession
+ add() void+ relayout() void
SurfaceViewMyWindow
BaseIWindow IWindowStublaquointerfaceraquo
IWindow
+mSurface
+mSession
+mWindow
+mCallbacks
+mSurfaceHolder
+mRenderer
+mGLThread
call
+mRenderer
+mEglHelper
TextureView
bull Since Android 40只在硬件加速环境下起作用bull 具备 SurfaceView 的特性
ndash 但是可以跟其它普通的 View 一样实现 Rotation Screw等变换
ndash 支持 Alpha 可以跟它下方的 View 进行 Alpha 混合
bull 可以基于 TextureView 创建一个 GL Surface 在上面进行 OpenGL渲染
Things become more complicated after Android 30
HW Accelerated 2D Renderingbull Android 30后开始支持硬件加速的 2D 绘图原
有的绘图流程变得更加复杂bull 所谓硬件加速的 2D 绘图就是将 2D Graphics A
PI 的实现改成使用 OpenGL API 来进行绘图bull OpenGL 的绘图模式跟一般的 2D 绘图有很大区
别它需要先将绘图所需的各种素材如贴图多边形顶点阵列 Shader等先加载到当前的 GLContext 然后流水线式的顺序执行绘图指令通过这种方式来充分利用硬件的能力
ViewRootImplbull 当 Actitity 的 View Hierachy 的根节点被添加到 WindowM
anager 的时候( WindowManageraddView ) WindowManager 的实现类 WindowManagerImpl 会创建一个 ViewRootImpl 并把它跟传进来的 View 绑定在一起( ViewRootImplsetView )并且 ViewRootImpl 会根据是否开启硬件加速来决定是否创建一个 HardwareRenderer
bull 在 ViewRootImpl 第一次渲染 View Hierachy 时会创建 Surface 如果开启硬件加速则通过 HardwareRenderer在当前的 UI 线程初始化EGL 绘图环境(类似 GLSurfaceView )
Contbull 在 ViewRootImpl 真正渲染 View Hierachy
时如果开启硬件加速则从 HardwareRenderer获得一个 HardwareCanvas 然后 View Hierachy 的渲染通过 HardwareCanvas 来进行
bull HardwareCanvas 跟一个 native 的 OpenGLRenderer 绑定通过它调用 EGL API 来完成真正的绘制
DisplayList and Hardware Layerbull 为了充分利用硬件加速的能力 Android 30 还引入了 Di
splayList 和 Hardware Layerbull DisplayList 用于记录一系列OpenGL 绘图指令和缓存所需的各种绘图素材( Bitmap Paint Shape Shader )当 View 的内容不发生变化时可以直接使用 DisplayList 进行绘制而不需要重新调用 onDraw
bull Hardware Layer 用于缓存绘制的内存到 Frame Buffer Object 当内容不发生变化时可以直接使用 Layer 进行Layer Composite获得更快的绘图速度
class Hardward2D
DisplayListHardwareCanv as
+ drawDisplayList() void+ drawHardwareLayer() void
Canv as
+ isHardwareAccelerated() voidHardwareLayer
HardwareRenderer
+ initialize() void
HardwareRendererGlRenderer
HardwareRendererGl20Renderer
GLES20Canv as
GLES20RecordingCanv as
GLES20DisplayList
laquonativeraquoDisplayList
laquonativeraquoOpenGLRenderer
laquonativeraquoDisplayListRenderer
ViewAttachInfo
ViewRootImpl
+ setView() void+ scheduleTraversals() void+ performTraversals() void+ relayoutWindow() void
GLES20Layer
GLES20TextureLayer
+mCanvas
+mNativeDisplayList
draw
+mRenderer
+mAttachInfo
+mHardwareRenderer
+mHardwareCanvas
+mResizeBuffer
Reference
bull Android 圖形系統 -- 設計與實做分析
bull How to replace GLSurfaceView with TextureView in Android Ice Cream Sandwich
The End
Thank you for your listeningYours Sincerely Roger
SurfaceFlingerbull 应用跟 SF 之间的关系是就像是生产者与消费者的关系bull 应用从 Surface 的 GraphicsBuffer队列的前端取出一个缓存然后进行绘制
bull 绘制完毕后把该缓存放置回队列的后端(生产)bull 而 SF 则不断地将 Surface 的 GraphicsBuffer队列的最后
一个缓存绘制到屏幕上(消费)bull 两者在不同的进程是异步进行的对队列的访问需要进
行同步
class Surface
ViewRootImpl
+ setView() void+ scheduleTraversals() void+ performTraversals() void+ relayoutWindow() void
Surface
+ lockCanvas () Canvas+ unlockCanvasAndPost (Canvas) void
laquointerfaceraquoIWindowSession
+ add() void+ relayout() void
Canvas
+ isHardwareAccelerated() void
laquonativeraquoSurface
laquonativeraquoSurfaceController
SurfaceCompatibleCanvas
laquonativeraquoSkCanvas
WindowManagerServ ice
+ relayoutWindow() void
SurfaceSession
Session
+ relayout() void
WindowState
+ createSurfaceLocked() void
laquonativeraquoSurfaceFlinger
IWindowSessionStub
laquonativeraquoSurfaceComposerCilent
laquonativeraquoBnSurfaceComposer
laquonativeraquoISurfaceComposerClient
laquonativeraquoSurfaceTextureClient
+mSurface
+sWindowSession
+mCanvas
+mSurfaceControl
+mNativeSurface
+mNativeCanvas
+mSurfaceSession
+mService
+mSessions
+mWindowMap
setBitmapDevice
communication+mClient
+mClient
Overall Flowbull ViewRootImpl 第一次渲染 View Hierachy 的时候会创建一个 Surfac
ebull 客户端请求 WMS 创建 Surface 并返回 Surface相关的数据用于构
建一个 native 的 Surface 对象并把它跟 ViewRootImpl 的 Surface( Java )绑定在一起
bull ViewRootImpl 在渲染时先从 Surface获得 Canvasbull 然后把需要绘制的 Views 通过 Canvas 绘制到 Surface 上面bull 绘制完毕后解锁该 Surfacebull SurfaceFlinger 在做 Screen Composite 的时候把解锁后的 Surface
绘制到屏幕上
Those special Views
SurfaceViewbull Provides a dedicated drawing surface embedded
inside of a view hierarchy You can control the format of this surface and if you like its size the SurfaceView takes care of placing the surface at the correct location on the screen
bull The surface is Z ordered so that it is behind the window holding its SurfaceView the SurfaceView punches a hole in its window to allow its surface to be displayed
Contbull Pros
ndash 可以跟 View Hierachy较好地结合在一起可以移动改变大小在上方叠加其它的 View
ndash 在单独的渲染线程进行渲染渲染效率高
ndash SV 的 Surface 和 Window Surface 之间的混合是由系统( SurfaceFlinger )使用硬件加速完成效率高并且不占用应用本身的 UI 线程时间
bull Consndash SurfaceView 的渲染毕竟跟
真正的 View不一样它不是由 ViewRootImpl渲染到当前的 Window Surface 上面
ndash 不能改变 Alpha 不支持跟下方的 View 进行 Alpha 混合
ndash 不能做 Rotation Skew等变换
GLSurfaceViewbull An implementation of SurfaceView that uses the dedicated surfac
e for displaying OpenGL renderingbull A GLSurfaceView provides the following features
ndash Manages a surface which is a special piece of memory that can be composited into the Android view system
ndash Manages an EGL display which enables OpenGL to render into a surfacendash Accepts a user-provided Renderer object that does the actual renderingndash Renders on a dedicated thread to decouple rendering performance from
the UI threadndash Supports both on-demand and continuous renderingndash Optionally wraps traces andor error-checks the renderers OpenGL call
s
Contbull GLSurfaceView 创建一个内部的线程 GLThreadbull 在该线程运行环境下创建一个 EglContextbull 创建一个 EglSurface ( Window Surface )bull 设置之前创建的 EglContext 为当前的 GL Contex
t 并绑定到创建的 EglSurface 上bull 在该线程内就可以通过 EGL 指令在当前的 GL Co
ntext 上绘图
Contbull GLSurfaceView支持两种不同的绘图模式
ndash 连续模式下 GLThread 会不断调用 RendereronDrawFrame 进行绘图
ndash Dirty 模式下 GLThread处于等待状态直到程序发送绘图请求( GLSurfaceViewrequestRender )才调用 RendereronDrawFrame 进行绘图绘制完一帧后重新进入等待状态
bull 在 RendereronDrawFrame 的回调中应用可以通过 SDK提供的 EGL API 绘图也可以转到 native 端使用 NDK提供的 EGL API 绘图
class SurfaceView
SurfaceView
GLSurfaceView GLSurfaceViewRenderer
+ onDrawFrame() void
GLSurfaceViewGLThread
GLSurfaceViewEglHelper
laquointerfaceraquoSurfaceHolder
laquointerfaceraquoSurfaceHolder
Callback
Surface
+ lockCanvas () Canvas+ unlockCanvasAndPost (Canvas) void
laquointerfaceraquoIWindowSession
+ add() void+ relayout() void
SurfaceViewMyWindow
BaseIWindow IWindowStublaquointerfaceraquo
IWindow
+mSurface
+mSession
+mWindow
+mCallbacks
+mSurfaceHolder
+mRenderer
+mGLThread
call
+mRenderer
+mEglHelper
TextureView
bull Since Android 40只在硬件加速环境下起作用bull 具备 SurfaceView 的特性
ndash 但是可以跟其它普通的 View 一样实现 Rotation Screw等变换
ndash 支持 Alpha 可以跟它下方的 View 进行 Alpha 混合
bull 可以基于 TextureView 创建一个 GL Surface 在上面进行 OpenGL渲染
Things become more complicated after Android 30
HW Accelerated 2D Renderingbull Android 30后开始支持硬件加速的 2D 绘图原
有的绘图流程变得更加复杂bull 所谓硬件加速的 2D 绘图就是将 2D Graphics A
PI 的实现改成使用 OpenGL API 来进行绘图bull OpenGL 的绘图模式跟一般的 2D 绘图有很大区
别它需要先将绘图所需的各种素材如贴图多边形顶点阵列 Shader等先加载到当前的 GLContext 然后流水线式的顺序执行绘图指令通过这种方式来充分利用硬件的能力
ViewRootImplbull 当 Actitity 的 View Hierachy 的根节点被添加到 WindowM
anager 的时候( WindowManageraddView ) WindowManager 的实现类 WindowManagerImpl 会创建一个 ViewRootImpl 并把它跟传进来的 View 绑定在一起( ViewRootImplsetView )并且 ViewRootImpl 会根据是否开启硬件加速来决定是否创建一个 HardwareRenderer
bull 在 ViewRootImpl 第一次渲染 View Hierachy 时会创建 Surface 如果开启硬件加速则通过 HardwareRenderer在当前的 UI 线程初始化EGL 绘图环境(类似 GLSurfaceView )
Contbull 在 ViewRootImpl 真正渲染 View Hierachy
时如果开启硬件加速则从 HardwareRenderer获得一个 HardwareCanvas 然后 View Hierachy 的渲染通过 HardwareCanvas 来进行
bull HardwareCanvas 跟一个 native 的 OpenGLRenderer 绑定通过它调用 EGL API 来完成真正的绘制
DisplayList and Hardware Layerbull 为了充分利用硬件加速的能力 Android 30 还引入了 Di
splayList 和 Hardware Layerbull DisplayList 用于记录一系列OpenGL 绘图指令和缓存所需的各种绘图素材( Bitmap Paint Shape Shader )当 View 的内容不发生变化时可以直接使用 DisplayList 进行绘制而不需要重新调用 onDraw
bull Hardware Layer 用于缓存绘制的内存到 Frame Buffer Object 当内容不发生变化时可以直接使用 Layer 进行Layer Composite获得更快的绘图速度
class Hardward2D
DisplayListHardwareCanv as
+ drawDisplayList() void+ drawHardwareLayer() void
Canv as
+ isHardwareAccelerated() voidHardwareLayer
HardwareRenderer
+ initialize() void
HardwareRendererGlRenderer
HardwareRendererGl20Renderer
GLES20Canv as
GLES20RecordingCanv as
GLES20DisplayList
laquonativeraquoDisplayList
laquonativeraquoOpenGLRenderer
laquonativeraquoDisplayListRenderer
ViewAttachInfo
ViewRootImpl
+ setView() void+ scheduleTraversals() void+ performTraversals() void+ relayoutWindow() void
GLES20Layer
GLES20TextureLayer
+mCanvas
+mNativeDisplayList
draw
+mRenderer
+mAttachInfo
+mHardwareRenderer
+mHardwareCanvas
+mResizeBuffer
Reference
bull Android 圖形系統 -- 設計與實做分析
bull How to replace GLSurfaceView with TextureView in Android Ice Cream Sandwich
The End
Thank you for your listeningYours Sincerely Roger
class Surface
ViewRootImpl
+ setView() void+ scheduleTraversals() void+ performTraversals() void+ relayoutWindow() void
Surface
+ lockCanvas () Canvas+ unlockCanvasAndPost (Canvas) void
laquointerfaceraquoIWindowSession
+ add() void+ relayout() void
Canvas
+ isHardwareAccelerated() void
laquonativeraquoSurface
laquonativeraquoSurfaceController
SurfaceCompatibleCanvas
laquonativeraquoSkCanvas
WindowManagerServ ice
+ relayoutWindow() void
SurfaceSession
Session
+ relayout() void
WindowState
+ createSurfaceLocked() void
laquonativeraquoSurfaceFlinger
IWindowSessionStub
laquonativeraquoSurfaceComposerCilent
laquonativeraquoBnSurfaceComposer
laquonativeraquoISurfaceComposerClient
laquonativeraquoSurfaceTextureClient
+mSurface
+sWindowSession
+mCanvas
+mSurfaceControl
+mNativeSurface
+mNativeCanvas
+mSurfaceSession
+mService
+mSessions
+mWindowMap
setBitmapDevice
communication+mClient
+mClient
Overall Flowbull ViewRootImpl 第一次渲染 View Hierachy 的时候会创建一个 Surfac
ebull 客户端请求 WMS 创建 Surface 并返回 Surface相关的数据用于构
建一个 native 的 Surface 对象并把它跟 ViewRootImpl 的 Surface( Java )绑定在一起
bull ViewRootImpl 在渲染时先从 Surface获得 Canvasbull 然后把需要绘制的 Views 通过 Canvas 绘制到 Surface 上面bull 绘制完毕后解锁该 Surfacebull SurfaceFlinger 在做 Screen Composite 的时候把解锁后的 Surface
绘制到屏幕上
Those special Views
SurfaceViewbull Provides a dedicated drawing surface embedded
inside of a view hierarchy You can control the format of this surface and if you like its size the SurfaceView takes care of placing the surface at the correct location on the screen
bull The surface is Z ordered so that it is behind the window holding its SurfaceView the SurfaceView punches a hole in its window to allow its surface to be displayed
Contbull Pros
ndash 可以跟 View Hierachy较好地结合在一起可以移动改变大小在上方叠加其它的 View
ndash 在单独的渲染线程进行渲染渲染效率高
ndash SV 的 Surface 和 Window Surface 之间的混合是由系统( SurfaceFlinger )使用硬件加速完成效率高并且不占用应用本身的 UI 线程时间
bull Consndash SurfaceView 的渲染毕竟跟
真正的 View不一样它不是由 ViewRootImpl渲染到当前的 Window Surface 上面
ndash 不能改变 Alpha 不支持跟下方的 View 进行 Alpha 混合
ndash 不能做 Rotation Skew等变换
GLSurfaceViewbull An implementation of SurfaceView that uses the dedicated surfac
e for displaying OpenGL renderingbull A GLSurfaceView provides the following features
ndash Manages a surface which is a special piece of memory that can be composited into the Android view system
ndash Manages an EGL display which enables OpenGL to render into a surfacendash Accepts a user-provided Renderer object that does the actual renderingndash Renders on a dedicated thread to decouple rendering performance from
the UI threadndash Supports both on-demand and continuous renderingndash Optionally wraps traces andor error-checks the renderers OpenGL call
s
Contbull GLSurfaceView 创建一个内部的线程 GLThreadbull 在该线程运行环境下创建一个 EglContextbull 创建一个 EglSurface ( Window Surface )bull 设置之前创建的 EglContext 为当前的 GL Contex
t 并绑定到创建的 EglSurface 上bull 在该线程内就可以通过 EGL 指令在当前的 GL Co
ntext 上绘图
Contbull GLSurfaceView支持两种不同的绘图模式
ndash 连续模式下 GLThread 会不断调用 RendereronDrawFrame 进行绘图
ndash Dirty 模式下 GLThread处于等待状态直到程序发送绘图请求( GLSurfaceViewrequestRender )才调用 RendereronDrawFrame 进行绘图绘制完一帧后重新进入等待状态
bull 在 RendereronDrawFrame 的回调中应用可以通过 SDK提供的 EGL API 绘图也可以转到 native 端使用 NDK提供的 EGL API 绘图
class SurfaceView
SurfaceView
GLSurfaceView GLSurfaceViewRenderer
+ onDrawFrame() void
GLSurfaceViewGLThread
GLSurfaceViewEglHelper
laquointerfaceraquoSurfaceHolder
laquointerfaceraquoSurfaceHolder
Callback
Surface
+ lockCanvas () Canvas+ unlockCanvasAndPost (Canvas) void
laquointerfaceraquoIWindowSession
+ add() void+ relayout() void
SurfaceViewMyWindow
BaseIWindow IWindowStublaquointerfaceraquo
IWindow
+mSurface
+mSession
+mWindow
+mCallbacks
+mSurfaceHolder
+mRenderer
+mGLThread
call
+mRenderer
+mEglHelper
TextureView
bull Since Android 40只在硬件加速环境下起作用bull 具备 SurfaceView 的特性
ndash 但是可以跟其它普通的 View 一样实现 Rotation Screw等变换
ndash 支持 Alpha 可以跟它下方的 View 进行 Alpha 混合
bull 可以基于 TextureView 创建一个 GL Surface 在上面进行 OpenGL渲染
Things become more complicated after Android 30
HW Accelerated 2D Renderingbull Android 30后开始支持硬件加速的 2D 绘图原
有的绘图流程变得更加复杂bull 所谓硬件加速的 2D 绘图就是将 2D Graphics A
PI 的实现改成使用 OpenGL API 来进行绘图bull OpenGL 的绘图模式跟一般的 2D 绘图有很大区
别它需要先将绘图所需的各种素材如贴图多边形顶点阵列 Shader等先加载到当前的 GLContext 然后流水线式的顺序执行绘图指令通过这种方式来充分利用硬件的能力
ViewRootImplbull 当 Actitity 的 View Hierachy 的根节点被添加到 WindowM
anager 的时候( WindowManageraddView ) WindowManager 的实现类 WindowManagerImpl 会创建一个 ViewRootImpl 并把它跟传进来的 View 绑定在一起( ViewRootImplsetView )并且 ViewRootImpl 会根据是否开启硬件加速来决定是否创建一个 HardwareRenderer
bull 在 ViewRootImpl 第一次渲染 View Hierachy 时会创建 Surface 如果开启硬件加速则通过 HardwareRenderer在当前的 UI 线程初始化EGL 绘图环境(类似 GLSurfaceView )
Contbull 在 ViewRootImpl 真正渲染 View Hierachy
时如果开启硬件加速则从 HardwareRenderer获得一个 HardwareCanvas 然后 View Hierachy 的渲染通过 HardwareCanvas 来进行
bull HardwareCanvas 跟一个 native 的 OpenGLRenderer 绑定通过它调用 EGL API 来完成真正的绘制
DisplayList and Hardware Layerbull 为了充分利用硬件加速的能力 Android 30 还引入了 Di
splayList 和 Hardware Layerbull DisplayList 用于记录一系列OpenGL 绘图指令和缓存所需的各种绘图素材( Bitmap Paint Shape Shader )当 View 的内容不发生变化时可以直接使用 DisplayList 进行绘制而不需要重新调用 onDraw
bull Hardware Layer 用于缓存绘制的内存到 Frame Buffer Object 当内容不发生变化时可以直接使用 Layer 进行Layer Composite获得更快的绘图速度
class Hardward2D
DisplayListHardwareCanv as
+ drawDisplayList() void+ drawHardwareLayer() void
Canv as
+ isHardwareAccelerated() voidHardwareLayer
HardwareRenderer
+ initialize() void
HardwareRendererGlRenderer
HardwareRendererGl20Renderer
GLES20Canv as
GLES20RecordingCanv as
GLES20DisplayList
laquonativeraquoDisplayList
laquonativeraquoOpenGLRenderer
laquonativeraquoDisplayListRenderer
ViewAttachInfo
ViewRootImpl
+ setView() void+ scheduleTraversals() void+ performTraversals() void+ relayoutWindow() void
GLES20Layer
GLES20TextureLayer
+mCanvas
+mNativeDisplayList
draw
+mRenderer
+mAttachInfo
+mHardwareRenderer
+mHardwareCanvas
+mResizeBuffer
Reference
bull Android 圖形系統 -- 設計與實做分析
bull How to replace GLSurfaceView with TextureView in Android Ice Cream Sandwich
The End
Thank you for your listeningYours Sincerely Roger
Overall Flowbull ViewRootImpl 第一次渲染 View Hierachy 的时候会创建一个 Surfac
ebull 客户端请求 WMS 创建 Surface 并返回 Surface相关的数据用于构
建一个 native 的 Surface 对象并把它跟 ViewRootImpl 的 Surface( Java )绑定在一起
bull ViewRootImpl 在渲染时先从 Surface获得 Canvasbull 然后把需要绘制的 Views 通过 Canvas 绘制到 Surface 上面bull 绘制完毕后解锁该 Surfacebull SurfaceFlinger 在做 Screen Composite 的时候把解锁后的 Surface
绘制到屏幕上
Those special Views
SurfaceViewbull Provides a dedicated drawing surface embedded
inside of a view hierarchy You can control the format of this surface and if you like its size the SurfaceView takes care of placing the surface at the correct location on the screen
bull The surface is Z ordered so that it is behind the window holding its SurfaceView the SurfaceView punches a hole in its window to allow its surface to be displayed
Contbull Pros
ndash 可以跟 View Hierachy较好地结合在一起可以移动改变大小在上方叠加其它的 View
ndash 在单独的渲染线程进行渲染渲染效率高
ndash SV 的 Surface 和 Window Surface 之间的混合是由系统( SurfaceFlinger )使用硬件加速完成效率高并且不占用应用本身的 UI 线程时间
bull Consndash SurfaceView 的渲染毕竟跟
真正的 View不一样它不是由 ViewRootImpl渲染到当前的 Window Surface 上面
ndash 不能改变 Alpha 不支持跟下方的 View 进行 Alpha 混合
ndash 不能做 Rotation Skew等变换
GLSurfaceViewbull An implementation of SurfaceView that uses the dedicated surfac
e for displaying OpenGL renderingbull A GLSurfaceView provides the following features
ndash Manages a surface which is a special piece of memory that can be composited into the Android view system
ndash Manages an EGL display which enables OpenGL to render into a surfacendash Accepts a user-provided Renderer object that does the actual renderingndash Renders on a dedicated thread to decouple rendering performance from
the UI threadndash Supports both on-demand and continuous renderingndash Optionally wraps traces andor error-checks the renderers OpenGL call
s
Contbull GLSurfaceView 创建一个内部的线程 GLThreadbull 在该线程运行环境下创建一个 EglContextbull 创建一个 EglSurface ( Window Surface )bull 设置之前创建的 EglContext 为当前的 GL Contex
t 并绑定到创建的 EglSurface 上bull 在该线程内就可以通过 EGL 指令在当前的 GL Co
ntext 上绘图
Contbull GLSurfaceView支持两种不同的绘图模式
ndash 连续模式下 GLThread 会不断调用 RendereronDrawFrame 进行绘图
ndash Dirty 模式下 GLThread处于等待状态直到程序发送绘图请求( GLSurfaceViewrequestRender )才调用 RendereronDrawFrame 进行绘图绘制完一帧后重新进入等待状态
bull 在 RendereronDrawFrame 的回调中应用可以通过 SDK提供的 EGL API 绘图也可以转到 native 端使用 NDK提供的 EGL API 绘图
class SurfaceView
SurfaceView
GLSurfaceView GLSurfaceViewRenderer
+ onDrawFrame() void
GLSurfaceViewGLThread
GLSurfaceViewEglHelper
laquointerfaceraquoSurfaceHolder
laquointerfaceraquoSurfaceHolder
Callback
Surface
+ lockCanvas () Canvas+ unlockCanvasAndPost (Canvas) void
laquointerfaceraquoIWindowSession
+ add() void+ relayout() void
SurfaceViewMyWindow
BaseIWindow IWindowStublaquointerfaceraquo
IWindow
+mSurface
+mSession
+mWindow
+mCallbacks
+mSurfaceHolder
+mRenderer
+mGLThread
call
+mRenderer
+mEglHelper
TextureView
bull Since Android 40只在硬件加速环境下起作用bull 具备 SurfaceView 的特性
ndash 但是可以跟其它普通的 View 一样实现 Rotation Screw等变换
ndash 支持 Alpha 可以跟它下方的 View 进行 Alpha 混合
bull 可以基于 TextureView 创建一个 GL Surface 在上面进行 OpenGL渲染
Things become more complicated after Android 30
HW Accelerated 2D Renderingbull Android 30后开始支持硬件加速的 2D 绘图原
有的绘图流程变得更加复杂bull 所谓硬件加速的 2D 绘图就是将 2D Graphics A
PI 的实现改成使用 OpenGL API 来进行绘图bull OpenGL 的绘图模式跟一般的 2D 绘图有很大区
别它需要先将绘图所需的各种素材如贴图多边形顶点阵列 Shader等先加载到当前的 GLContext 然后流水线式的顺序执行绘图指令通过这种方式来充分利用硬件的能力
ViewRootImplbull 当 Actitity 的 View Hierachy 的根节点被添加到 WindowM
anager 的时候( WindowManageraddView ) WindowManager 的实现类 WindowManagerImpl 会创建一个 ViewRootImpl 并把它跟传进来的 View 绑定在一起( ViewRootImplsetView )并且 ViewRootImpl 会根据是否开启硬件加速来决定是否创建一个 HardwareRenderer
bull 在 ViewRootImpl 第一次渲染 View Hierachy 时会创建 Surface 如果开启硬件加速则通过 HardwareRenderer在当前的 UI 线程初始化EGL 绘图环境(类似 GLSurfaceView )
Contbull 在 ViewRootImpl 真正渲染 View Hierachy
时如果开启硬件加速则从 HardwareRenderer获得一个 HardwareCanvas 然后 View Hierachy 的渲染通过 HardwareCanvas 来进行
bull HardwareCanvas 跟一个 native 的 OpenGLRenderer 绑定通过它调用 EGL API 来完成真正的绘制
DisplayList and Hardware Layerbull 为了充分利用硬件加速的能力 Android 30 还引入了 Di
splayList 和 Hardware Layerbull DisplayList 用于记录一系列OpenGL 绘图指令和缓存所需的各种绘图素材( Bitmap Paint Shape Shader )当 View 的内容不发生变化时可以直接使用 DisplayList 进行绘制而不需要重新调用 onDraw
bull Hardware Layer 用于缓存绘制的内存到 Frame Buffer Object 当内容不发生变化时可以直接使用 Layer 进行Layer Composite获得更快的绘图速度
class Hardward2D
DisplayListHardwareCanv as
+ drawDisplayList() void+ drawHardwareLayer() void
Canv as
+ isHardwareAccelerated() voidHardwareLayer
HardwareRenderer
+ initialize() void
HardwareRendererGlRenderer
HardwareRendererGl20Renderer
GLES20Canv as
GLES20RecordingCanv as
GLES20DisplayList
laquonativeraquoDisplayList
laquonativeraquoOpenGLRenderer
laquonativeraquoDisplayListRenderer
ViewAttachInfo
ViewRootImpl
+ setView() void+ scheduleTraversals() void+ performTraversals() void+ relayoutWindow() void
GLES20Layer
GLES20TextureLayer
+mCanvas
+mNativeDisplayList
draw
+mRenderer
+mAttachInfo
+mHardwareRenderer
+mHardwareCanvas
+mResizeBuffer
Reference
bull Android 圖形系統 -- 設計與實做分析
bull How to replace GLSurfaceView with TextureView in Android Ice Cream Sandwich
The End
Thank you for your listeningYours Sincerely Roger
Those special Views
SurfaceViewbull Provides a dedicated drawing surface embedded
inside of a view hierarchy You can control the format of this surface and if you like its size the SurfaceView takes care of placing the surface at the correct location on the screen
bull The surface is Z ordered so that it is behind the window holding its SurfaceView the SurfaceView punches a hole in its window to allow its surface to be displayed
Contbull Pros
ndash 可以跟 View Hierachy较好地结合在一起可以移动改变大小在上方叠加其它的 View
ndash 在单独的渲染线程进行渲染渲染效率高
ndash SV 的 Surface 和 Window Surface 之间的混合是由系统( SurfaceFlinger )使用硬件加速完成效率高并且不占用应用本身的 UI 线程时间
bull Consndash SurfaceView 的渲染毕竟跟
真正的 View不一样它不是由 ViewRootImpl渲染到当前的 Window Surface 上面
ndash 不能改变 Alpha 不支持跟下方的 View 进行 Alpha 混合
ndash 不能做 Rotation Skew等变换
GLSurfaceViewbull An implementation of SurfaceView that uses the dedicated surfac
e for displaying OpenGL renderingbull A GLSurfaceView provides the following features
ndash Manages a surface which is a special piece of memory that can be composited into the Android view system
ndash Manages an EGL display which enables OpenGL to render into a surfacendash Accepts a user-provided Renderer object that does the actual renderingndash Renders on a dedicated thread to decouple rendering performance from
the UI threadndash Supports both on-demand and continuous renderingndash Optionally wraps traces andor error-checks the renderers OpenGL call
s
Contbull GLSurfaceView 创建一个内部的线程 GLThreadbull 在该线程运行环境下创建一个 EglContextbull 创建一个 EglSurface ( Window Surface )bull 设置之前创建的 EglContext 为当前的 GL Contex
t 并绑定到创建的 EglSurface 上bull 在该线程内就可以通过 EGL 指令在当前的 GL Co
ntext 上绘图
Contbull GLSurfaceView支持两种不同的绘图模式
ndash 连续模式下 GLThread 会不断调用 RendereronDrawFrame 进行绘图
ndash Dirty 模式下 GLThread处于等待状态直到程序发送绘图请求( GLSurfaceViewrequestRender )才调用 RendereronDrawFrame 进行绘图绘制完一帧后重新进入等待状态
bull 在 RendereronDrawFrame 的回调中应用可以通过 SDK提供的 EGL API 绘图也可以转到 native 端使用 NDK提供的 EGL API 绘图
class SurfaceView
SurfaceView
GLSurfaceView GLSurfaceViewRenderer
+ onDrawFrame() void
GLSurfaceViewGLThread
GLSurfaceViewEglHelper
laquointerfaceraquoSurfaceHolder
laquointerfaceraquoSurfaceHolder
Callback
Surface
+ lockCanvas () Canvas+ unlockCanvasAndPost (Canvas) void
laquointerfaceraquoIWindowSession
+ add() void+ relayout() void
SurfaceViewMyWindow
BaseIWindow IWindowStublaquointerfaceraquo
IWindow
+mSurface
+mSession
+mWindow
+mCallbacks
+mSurfaceHolder
+mRenderer
+mGLThread
call
+mRenderer
+mEglHelper
TextureView
bull Since Android 40只在硬件加速环境下起作用bull 具备 SurfaceView 的特性
ndash 但是可以跟其它普通的 View 一样实现 Rotation Screw等变换
ndash 支持 Alpha 可以跟它下方的 View 进行 Alpha 混合
bull 可以基于 TextureView 创建一个 GL Surface 在上面进行 OpenGL渲染
Things become more complicated after Android 30
HW Accelerated 2D Renderingbull Android 30后开始支持硬件加速的 2D 绘图原
有的绘图流程变得更加复杂bull 所谓硬件加速的 2D 绘图就是将 2D Graphics A
PI 的实现改成使用 OpenGL API 来进行绘图bull OpenGL 的绘图模式跟一般的 2D 绘图有很大区
别它需要先将绘图所需的各种素材如贴图多边形顶点阵列 Shader等先加载到当前的 GLContext 然后流水线式的顺序执行绘图指令通过这种方式来充分利用硬件的能力
ViewRootImplbull 当 Actitity 的 View Hierachy 的根节点被添加到 WindowM
anager 的时候( WindowManageraddView ) WindowManager 的实现类 WindowManagerImpl 会创建一个 ViewRootImpl 并把它跟传进来的 View 绑定在一起( ViewRootImplsetView )并且 ViewRootImpl 会根据是否开启硬件加速来决定是否创建一个 HardwareRenderer
bull 在 ViewRootImpl 第一次渲染 View Hierachy 时会创建 Surface 如果开启硬件加速则通过 HardwareRenderer在当前的 UI 线程初始化EGL 绘图环境(类似 GLSurfaceView )
Contbull 在 ViewRootImpl 真正渲染 View Hierachy
时如果开启硬件加速则从 HardwareRenderer获得一个 HardwareCanvas 然后 View Hierachy 的渲染通过 HardwareCanvas 来进行
bull HardwareCanvas 跟一个 native 的 OpenGLRenderer 绑定通过它调用 EGL API 来完成真正的绘制
DisplayList and Hardware Layerbull 为了充分利用硬件加速的能力 Android 30 还引入了 Di
splayList 和 Hardware Layerbull DisplayList 用于记录一系列OpenGL 绘图指令和缓存所需的各种绘图素材( Bitmap Paint Shape Shader )当 View 的内容不发生变化时可以直接使用 DisplayList 进行绘制而不需要重新调用 onDraw
bull Hardware Layer 用于缓存绘制的内存到 Frame Buffer Object 当内容不发生变化时可以直接使用 Layer 进行Layer Composite获得更快的绘图速度
class Hardward2D
DisplayListHardwareCanv as
+ drawDisplayList() void+ drawHardwareLayer() void
Canv as
+ isHardwareAccelerated() voidHardwareLayer
HardwareRenderer
+ initialize() void
HardwareRendererGlRenderer
HardwareRendererGl20Renderer
GLES20Canv as
GLES20RecordingCanv as
GLES20DisplayList
laquonativeraquoDisplayList
laquonativeraquoOpenGLRenderer
laquonativeraquoDisplayListRenderer
ViewAttachInfo
ViewRootImpl
+ setView() void+ scheduleTraversals() void+ performTraversals() void+ relayoutWindow() void
GLES20Layer
GLES20TextureLayer
+mCanvas
+mNativeDisplayList
draw
+mRenderer
+mAttachInfo
+mHardwareRenderer
+mHardwareCanvas
+mResizeBuffer
Reference
bull Android 圖形系統 -- 設計與實做分析
bull How to replace GLSurfaceView with TextureView in Android Ice Cream Sandwich
The End
Thank you for your listeningYours Sincerely Roger
SurfaceViewbull Provides a dedicated drawing surface embedded
inside of a view hierarchy You can control the format of this surface and if you like its size the SurfaceView takes care of placing the surface at the correct location on the screen
bull The surface is Z ordered so that it is behind the window holding its SurfaceView the SurfaceView punches a hole in its window to allow its surface to be displayed
Contbull Pros
ndash 可以跟 View Hierachy较好地结合在一起可以移动改变大小在上方叠加其它的 View
ndash 在单独的渲染线程进行渲染渲染效率高
ndash SV 的 Surface 和 Window Surface 之间的混合是由系统( SurfaceFlinger )使用硬件加速完成效率高并且不占用应用本身的 UI 线程时间
bull Consndash SurfaceView 的渲染毕竟跟
真正的 View不一样它不是由 ViewRootImpl渲染到当前的 Window Surface 上面
ndash 不能改变 Alpha 不支持跟下方的 View 进行 Alpha 混合
ndash 不能做 Rotation Skew等变换
GLSurfaceViewbull An implementation of SurfaceView that uses the dedicated surfac
e for displaying OpenGL renderingbull A GLSurfaceView provides the following features
ndash Manages a surface which is a special piece of memory that can be composited into the Android view system
ndash Manages an EGL display which enables OpenGL to render into a surfacendash Accepts a user-provided Renderer object that does the actual renderingndash Renders on a dedicated thread to decouple rendering performance from
the UI threadndash Supports both on-demand and continuous renderingndash Optionally wraps traces andor error-checks the renderers OpenGL call
s
Contbull GLSurfaceView 创建一个内部的线程 GLThreadbull 在该线程运行环境下创建一个 EglContextbull 创建一个 EglSurface ( Window Surface )bull 设置之前创建的 EglContext 为当前的 GL Contex
t 并绑定到创建的 EglSurface 上bull 在该线程内就可以通过 EGL 指令在当前的 GL Co
ntext 上绘图
Contbull GLSurfaceView支持两种不同的绘图模式
ndash 连续模式下 GLThread 会不断调用 RendereronDrawFrame 进行绘图
ndash Dirty 模式下 GLThread处于等待状态直到程序发送绘图请求( GLSurfaceViewrequestRender )才调用 RendereronDrawFrame 进行绘图绘制完一帧后重新进入等待状态
bull 在 RendereronDrawFrame 的回调中应用可以通过 SDK提供的 EGL API 绘图也可以转到 native 端使用 NDK提供的 EGL API 绘图
class SurfaceView
SurfaceView
GLSurfaceView GLSurfaceViewRenderer
+ onDrawFrame() void
GLSurfaceViewGLThread
GLSurfaceViewEglHelper
laquointerfaceraquoSurfaceHolder
laquointerfaceraquoSurfaceHolder
Callback
Surface
+ lockCanvas () Canvas+ unlockCanvasAndPost (Canvas) void
laquointerfaceraquoIWindowSession
+ add() void+ relayout() void
SurfaceViewMyWindow
BaseIWindow IWindowStublaquointerfaceraquo
IWindow
+mSurface
+mSession
+mWindow
+mCallbacks
+mSurfaceHolder
+mRenderer
+mGLThread
call
+mRenderer
+mEglHelper
TextureView
bull Since Android 40只在硬件加速环境下起作用bull 具备 SurfaceView 的特性
ndash 但是可以跟其它普通的 View 一样实现 Rotation Screw等变换
ndash 支持 Alpha 可以跟它下方的 View 进行 Alpha 混合
bull 可以基于 TextureView 创建一个 GL Surface 在上面进行 OpenGL渲染
Things become more complicated after Android 30
HW Accelerated 2D Renderingbull Android 30后开始支持硬件加速的 2D 绘图原
有的绘图流程变得更加复杂bull 所谓硬件加速的 2D 绘图就是将 2D Graphics A
PI 的实现改成使用 OpenGL API 来进行绘图bull OpenGL 的绘图模式跟一般的 2D 绘图有很大区
别它需要先将绘图所需的各种素材如贴图多边形顶点阵列 Shader等先加载到当前的 GLContext 然后流水线式的顺序执行绘图指令通过这种方式来充分利用硬件的能力
ViewRootImplbull 当 Actitity 的 View Hierachy 的根节点被添加到 WindowM
anager 的时候( WindowManageraddView ) WindowManager 的实现类 WindowManagerImpl 会创建一个 ViewRootImpl 并把它跟传进来的 View 绑定在一起( ViewRootImplsetView )并且 ViewRootImpl 会根据是否开启硬件加速来决定是否创建一个 HardwareRenderer
bull 在 ViewRootImpl 第一次渲染 View Hierachy 时会创建 Surface 如果开启硬件加速则通过 HardwareRenderer在当前的 UI 线程初始化EGL 绘图环境(类似 GLSurfaceView )
Contbull 在 ViewRootImpl 真正渲染 View Hierachy
时如果开启硬件加速则从 HardwareRenderer获得一个 HardwareCanvas 然后 View Hierachy 的渲染通过 HardwareCanvas 来进行
bull HardwareCanvas 跟一个 native 的 OpenGLRenderer 绑定通过它调用 EGL API 来完成真正的绘制
DisplayList and Hardware Layerbull 为了充分利用硬件加速的能力 Android 30 还引入了 Di
splayList 和 Hardware Layerbull DisplayList 用于记录一系列OpenGL 绘图指令和缓存所需的各种绘图素材( Bitmap Paint Shape Shader )当 View 的内容不发生变化时可以直接使用 DisplayList 进行绘制而不需要重新调用 onDraw
bull Hardware Layer 用于缓存绘制的内存到 Frame Buffer Object 当内容不发生变化时可以直接使用 Layer 进行Layer Composite获得更快的绘图速度
class Hardward2D
DisplayListHardwareCanv as
+ drawDisplayList() void+ drawHardwareLayer() void
Canv as
+ isHardwareAccelerated() voidHardwareLayer
HardwareRenderer
+ initialize() void
HardwareRendererGlRenderer
HardwareRendererGl20Renderer
GLES20Canv as
GLES20RecordingCanv as
GLES20DisplayList
laquonativeraquoDisplayList
laquonativeraquoOpenGLRenderer
laquonativeraquoDisplayListRenderer
ViewAttachInfo
ViewRootImpl
+ setView() void+ scheduleTraversals() void+ performTraversals() void+ relayoutWindow() void
GLES20Layer
GLES20TextureLayer
+mCanvas
+mNativeDisplayList
draw
+mRenderer
+mAttachInfo
+mHardwareRenderer
+mHardwareCanvas
+mResizeBuffer
Reference
bull Android 圖形系統 -- 設計與實做分析
bull How to replace GLSurfaceView with TextureView in Android Ice Cream Sandwich
The End
Thank you for your listeningYours Sincerely Roger
Contbull Pros
ndash 可以跟 View Hierachy较好地结合在一起可以移动改变大小在上方叠加其它的 View
ndash 在单独的渲染线程进行渲染渲染效率高
ndash SV 的 Surface 和 Window Surface 之间的混合是由系统( SurfaceFlinger )使用硬件加速完成效率高并且不占用应用本身的 UI 线程时间
bull Consndash SurfaceView 的渲染毕竟跟
真正的 View不一样它不是由 ViewRootImpl渲染到当前的 Window Surface 上面
ndash 不能改变 Alpha 不支持跟下方的 View 进行 Alpha 混合
ndash 不能做 Rotation Skew等变换
GLSurfaceViewbull An implementation of SurfaceView that uses the dedicated surfac
e for displaying OpenGL renderingbull A GLSurfaceView provides the following features
ndash Manages a surface which is a special piece of memory that can be composited into the Android view system
ndash Manages an EGL display which enables OpenGL to render into a surfacendash Accepts a user-provided Renderer object that does the actual renderingndash Renders on a dedicated thread to decouple rendering performance from
the UI threadndash Supports both on-demand and continuous renderingndash Optionally wraps traces andor error-checks the renderers OpenGL call
s
Contbull GLSurfaceView 创建一个内部的线程 GLThreadbull 在该线程运行环境下创建一个 EglContextbull 创建一个 EglSurface ( Window Surface )bull 设置之前创建的 EglContext 为当前的 GL Contex
t 并绑定到创建的 EglSurface 上bull 在该线程内就可以通过 EGL 指令在当前的 GL Co
ntext 上绘图
Contbull GLSurfaceView支持两种不同的绘图模式
ndash 连续模式下 GLThread 会不断调用 RendereronDrawFrame 进行绘图
ndash Dirty 模式下 GLThread处于等待状态直到程序发送绘图请求( GLSurfaceViewrequestRender )才调用 RendereronDrawFrame 进行绘图绘制完一帧后重新进入等待状态
bull 在 RendereronDrawFrame 的回调中应用可以通过 SDK提供的 EGL API 绘图也可以转到 native 端使用 NDK提供的 EGL API 绘图
class SurfaceView
SurfaceView
GLSurfaceView GLSurfaceViewRenderer
+ onDrawFrame() void
GLSurfaceViewGLThread
GLSurfaceViewEglHelper
laquointerfaceraquoSurfaceHolder
laquointerfaceraquoSurfaceHolder
Callback
Surface
+ lockCanvas () Canvas+ unlockCanvasAndPost (Canvas) void
laquointerfaceraquoIWindowSession
+ add() void+ relayout() void
SurfaceViewMyWindow
BaseIWindow IWindowStublaquointerfaceraquo
IWindow
+mSurface
+mSession
+mWindow
+mCallbacks
+mSurfaceHolder
+mRenderer
+mGLThread
call
+mRenderer
+mEglHelper
TextureView
bull Since Android 40只在硬件加速环境下起作用bull 具备 SurfaceView 的特性
ndash 但是可以跟其它普通的 View 一样实现 Rotation Screw等变换
ndash 支持 Alpha 可以跟它下方的 View 进行 Alpha 混合
bull 可以基于 TextureView 创建一个 GL Surface 在上面进行 OpenGL渲染
Things become more complicated after Android 30
HW Accelerated 2D Renderingbull Android 30后开始支持硬件加速的 2D 绘图原
有的绘图流程变得更加复杂bull 所谓硬件加速的 2D 绘图就是将 2D Graphics A
PI 的实现改成使用 OpenGL API 来进行绘图bull OpenGL 的绘图模式跟一般的 2D 绘图有很大区
别它需要先将绘图所需的各种素材如贴图多边形顶点阵列 Shader等先加载到当前的 GLContext 然后流水线式的顺序执行绘图指令通过这种方式来充分利用硬件的能力
ViewRootImplbull 当 Actitity 的 View Hierachy 的根节点被添加到 WindowM
anager 的时候( WindowManageraddView ) WindowManager 的实现类 WindowManagerImpl 会创建一个 ViewRootImpl 并把它跟传进来的 View 绑定在一起( ViewRootImplsetView )并且 ViewRootImpl 会根据是否开启硬件加速来决定是否创建一个 HardwareRenderer
bull 在 ViewRootImpl 第一次渲染 View Hierachy 时会创建 Surface 如果开启硬件加速则通过 HardwareRenderer在当前的 UI 线程初始化EGL 绘图环境(类似 GLSurfaceView )
Contbull 在 ViewRootImpl 真正渲染 View Hierachy
时如果开启硬件加速则从 HardwareRenderer获得一个 HardwareCanvas 然后 View Hierachy 的渲染通过 HardwareCanvas 来进行
bull HardwareCanvas 跟一个 native 的 OpenGLRenderer 绑定通过它调用 EGL API 来完成真正的绘制
DisplayList and Hardware Layerbull 为了充分利用硬件加速的能力 Android 30 还引入了 Di
splayList 和 Hardware Layerbull DisplayList 用于记录一系列OpenGL 绘图指令和缓存所需的各种绘图素材( Bitmap Paint Shape Shader )当 View 的内容不发生变化时可以直接使用 DisplayList 进行绘制而不需要重新调用 onDraw
bull Hardware Layer 用于缓存绘制的内存到 Frame Buffer Object 当内容不发生变化时可以直接使用 Layer 进行Layer Composite获得更快的绘图速度
class Hardward2D
DisplayListHardwareCanv as
+ drawDisplayList() void+ drawHardwareLayer() void
Canv as
+ isHardwareAccelerated() voidHardwareLayer
HardwareRenderer
+ initialize() void
HardwareRendererGlRenderer
HardwareRendererGl20Renderer
GLES20Canv as
GLES20RecordingCanv as
GLES20DisplayList
laquonativeraquoDisplayList
laquonativeraquoOpenGLRenderer
laquonativeraquoDisplayListRenderer
ViewAttachInfo
ViewRootImpl
+ setView() void+ scheduleTraversals() void+ performTraversals() void+ relayoutWindow() void
GLES20Layer
GLES20TextureLayer
+mCanvas
+mNativeDisplayList
draw
+mRenderer
+mAttachInfo
+mHardwareRenderer
+mHardwareCanvas
+mResizeBuffer
Reference
bull Android 圖形系統 -- 設計與實做分析
bull How to replace GLSurfaceView with TextureView in Android Ice Cream Sandwich
The End
Thank you for your listeningYours Sincerely Roger
GLSurfaceViewbull An implementation of SurfaceView that uses the dedicated surfac
e for displaying OpenGL renderingbull A GLSurfaceView provides the following features
ndash Manages a surface which is a special piece of memory that can be composited into the Android view system
ndash Manages an EGL display which enables OpenGL to render into a surfacendash Accepts a user-provided Renderer object that does the actual renderingndash Renders on a dedicated thread to decouple rendering performance from
the UI threadndash Supports both on-demand and continuous renderingndash Optionally wraps traces andor error-checks the renderers OpenGL call
s
Contbull GLSurfaceView 创建一个内部的线程 GLThreadbull 在该线程运行环境下创建一个 EglContextbull 创建一个 EglSurface ( Window Surface )bull 设置之前创建的 EglContext 为当前的 GL Contex
t 并绑定到创建的 EglSurface 上bull 在该线程内就可以通过 EGL 指令在当前的 GL Co
ntext 上绘图
Contbull GLSurfaceView支持两种不同的绘图模式
ndash 连续模式下 GLThread 会不断调用 RendereronDrawFrame 进行绘图
ndash Dirty 模式下 GLThread处于等待状态直到程序发送绘图请求( GLSurfaceViewrequestRender )才调用 RendereronDrawFrame 进行绘图绘制完一帧后重新进入等待状态
bull 在 RendereronDrawFrame 的回调中应用可以通过 SDK提供的 EGL API 绘图也可以转到 native 端使用 NDK提供的 EGL API 绘图
class SurfaceView
SurfaceView
GLSurfaceView GLSurfaceViewRenderer
+ onDrawFrame() void
GLSurfaceViewGLThread
GLSurfaceViewEglHelper
laquointerfaceraquoSurfaceHolder
laquointerfaceraquoSurfaceHolder
Callback
Surface
+ lockCanvas () Canvas+ unlockCanvasAndPost (Canvas) void
laquointerfaceraquoIWindowSession
+ add() void+ relayout() void
SurfaceViewMyWindow
BaseIWindow IWindowStublaquointerfaceraquo
IWindow
+mSurface
+mSession
+mWindow
+mCallbacks
+mSurfaceHolder
+mRenderer
+mGLThread
call
+mRenderer
+mEglHelper
TextureView
bull Since Android 40只在硬件加速环境下起作用bull 具备 SurfaceView 的特性
ndash 但是可以跟其它普通的 View 一样实现 Rotation Screw等变换
ndash 支持 Alpha 可以跟它下方的 View 进行 Alpha 混合
bull 可以基于 TextureView 创建一个 GL Surface 在上面进行 OpenGL渲染
Things become more complicated after Android 30
HW Accelerated 2D Renderingbull Android 30后开始支持硬件加速的 2D 绘图原
有的绘图流程变得更加复杂bull 所谓硬件加速的 2D 绘图就是将 2D Graphics A
PI 的实现改成使用 OpenGL API 来进行绘图bull OpenGL 的绘图模式跟一般的 2D 绘图有很大区
别它需要先将绘图所需的各种素材如贴图多边形顶点阵列 Shader等先加载到当前的 GLContext 然后流水线式的顺序执行绘图指令通过这种方式来充分利用硬件的能力
ViewRootImplbull 当 Actitity 的 View Hierachy 的根节点被添加到 WindowM
anager 的时候( WindowManageraddView ) WindowManager 的实现类 WindowManagerImpl 会创建一个 ViewRootImpl 并把它跟传进来的 View 绑定在一起( ViewRootImplsetView )并且 ViewRootImpl 会根据是否开启硬件加速来决定是否创建一个 HardwareRenderer
bull 在 ViewRootImpl 第一次渲染 View Hierachy 时会创建 Surface 如果开启硬件加速则通过 HardwareRenderer在当前的 UI 线程初始化EGL 绘图环境(类似 GLSurfaceView )
Contbull 在 ViewRootImpl 真正渲染 View Hierachy
时如果开启硬件加速则从 HardwareRenderer获得一个 HardwareCanvas 然后 View Hierachy 的渲染通过 HardwareCanvas 来进行
bull HardwareCanvas 跟一个 native 的 OpenGLRenderer 绑定通过它调用 EGL API 来完成真正的绘制
DisplayList and Hardware Layerbull 为了充分利用硬件加速的能力 Android 30 还引入了 Di
splayList 和 Hardware Layerbull DisplayList 用于记录一系列OpenGL 绘图指令和缓存所需的各种绘图素材( Bitmap Paint Shape Shader )当 View 的内容不发生变化时可以直接使用 DisplayList 进行绘制而不需要重新调用 onDraw
bull Hardware Layer 用于缓存绘制的内存到 Frame Buffer Object 当内容不发生变化时可以直接使用 Layer 进行Layer Composite获得更快的绘图速度
class Hardward2D
DisplayListHardwareCanv as
+ drawDisplayList() void+ drawHardwareLayer() void
Canv as
+ isHardwareAccelerated() voidHardwareLayer
HardwareRenderer
+ initialize() void
HardwareRendererGlRenderer
HardwareRendererGl20Renderer
GLES20Canv as
GLES20RecordingCanv as
GLES20DisplayList
laquonativeraquoDisplayList
laquonativeraquoOpenGLRenderer
laquonativeraquoDisplayListRenderer
ViewAttachInfo
ViewRootImpl
+ setView() void+ scheduleTraversals() void+ performTraversals() void+ relayoutWindow() void
GLES20Layer
GLES20TextureLayer
+mCanvas
+mNativeDisplayList
draw
+mRenderer
+mAttachInfo
+mHardwareRenderer
+mHardwareCanvas
+mResizeBuffer
Reference
bull Android 圖形系統 -- 設計與實做分析
bull How to replace GLSurfaceView with TextureView in Android Ice Cream Sandwich
The End
Thank you for your listeningYours Sincerely Roger
Contbull GLSurfaceView 创建一个内部的线程 GLThreadbull 在该线程运行环境下创建一个 EglContextbull 创建一个 EglSurface ( Window Surface )bull 设置之前创建的 EglContext 为当前的 GL Contex
t 并绑定到创建的 EglSurface 上bull 在该线程内就可以通过 EGL 指令在当前的 GL Co
ntext 上绘图
Contbull GLSurfaceView支持两种不同的绘图模式
ndash 连续模式下 GLThread 会不断调用 RendereronDrawFrame 进行绘图
ndash Dirty 模式下 GLThread处于等待状态直到程序发送绘图请求( GLSurfaceViewrequestRender )才调用 RendereronDrawFrame 进行绘图绘制完一帧后重新进入等待状态
bull 在 RendereronDrawFrame 的回调中应用可以通过 SDK提供的 EGL API 绘图也可以转到 native 端使用 NDK提供的 EGL API 绘图
class SurfaceView
SurfaceView
GLSurfaceView GLSurfaceViewRenderer
+ onDrawFrame() void
GLSurfaceViewGLThread
GLSurfaceViewEglHelper
laquointerfaceraquoSurfaceHolder
laquointerfaceraquoSurfaceHolder
Callback
Surface
+ lockCanvas () Canvas+ unlockCanvasAndPost (Canvas) void
laquointerfaceraquoIWindowSession
+ add() void+ relayout() void
SurfaceViewMyWindow
BaseIWindow IWindowStublaquointerfaceraquo
IWindow
+mSurface
+mSession
+mWindow
+mCallbacks
+mSurfaceHolder
+mRenderer
+mGLThread
call
+mRenderer
+mEglHelper
TextureView
bull Since Android 40只在硬件加速环境下起作用bull 具备 SurfaceView 的特性
ndash 但是可以跟其它普通的 View 一样实现 Rotation Screw等变换
ndash 支持 Alpha 可以跟它下方的 View 进行 Alpha 混合
bull 可以基于 TextureView 创建一个 GL Surface 在上面进行 OpenGL渲染
Things become more complicated after Android 30
HW Accelerated 2D Renderingbull Android 30后开始支持硬件加速的 2D 绘图原
有的绘图流程变得更加复杂bull 所谓硬件加速的 2D 绘图就是将 2D Graphics A
PI 的实现改成使用 OpenGL API 来进行绘图bull OpenGL 的绘图模式跟一般的 2D 绘图有很大区
别它需要先将绘图所需的各种素材如贴图多边形顶点阵列 Shader等先加载到当前的 GLContext 然后流水线式的顺序执行绘图指令通过这种方式来充分利用硬件的能力
ViewRootImplbull 当 Actitity 的 View Hierachy 的根节点被添加到 WindowM
anager 的时候( WindowManageraddView ) WindowManager 的实现类 WindowManagerImpl 会创建一个 ViewRootImpl 并把它跟传进来的 View 绑定在一起( ViewRootImplsetView )并且 ViewRootImpl 会根据是否开启硬件加速来决定是否创建一个 HardwareRenderer
bull 在 ViewRootImpl 第一次渲染 View Hierachy 时会创建 Surface 如果开启硬件加速则通过 HardwareRenderer在当前的 UI 线程初始化EGL 绘图环境(类似 GLSurfaceView )
Contbull 在 ViewRootImpl 真正渲染 View Hierachy
时如果开启硬件加速则从 HardwareRenderer获得一个 HardwareCanvas 然后 View Hierachy 的渲染通过 HardwareCanvas 来进行
bull HardwareCanvas 跟一个 native 的 OpenGLRenderer 绑定通过它调用 EGL API 来完成真正的绘制
DisplayList and Hardware Layerbull 为了充分利用硬件加速的能力 Android 30 还引入了 Di
splayList 和 Hardware Layerbull DisplayList 用于记录一系列OpenGL 绘图指令和缓存所需的各种绘图素材( Bitmap Paint Shape Shader )当 View 的内容不发生变化时可以直接使用 DisplayList 进行绘制而不需要重新调用 onDraw
bull Hardware Layer 用于缓存绘制的内存到 Frame Buffer Object 当内容不发生变化时可以直接使用 Layer 进行Layer Composite获得更快的绘图速度
class Hardward2D
DisplayListHardwareCanv as
+ drawDisplayList() void+ drawHardwareLayer() void
Canv as
+ isHardwareAccelerated() voidHardwareLayer
HardwareRenderer
+ initialize() void
HardwareRendererGlRenderer
HardwareRendererGl20Renderer
GLES20Canv as
GLES20RecordingCanv as
GLES20DisplayList
laquonativeraquoDisplayList
laquonativeraquoOpenGLRenderer
laquonativeraquoDisplayListRenderer
ViewAttachInfo
ViewRootImpl
+ setView() void+ scheduleTraversals() void+ performTraversals() void+ relayoutWindow() void
GLES20Layer
GLES20TextureLayer
+mCanvas
+mNativeDisplayList
draw
+mRenderer
+mAttachInfo
+mHardwareRenderer
+mHardwareCanvas
+mResizeBuffer
Reference
bull Android 圖形系統 -- 設計與實做分析
bull How to replace GLSurfaceView with TextureView in Android Ice Cream Sandwich
The End
Thank you for your listeningYours Sincerely Roger
Contbull GLSurfaceView支持两种不同的绘图模式
ndash 连续模式下 GLThread 会不断调用 RendereronDrawFrame 进行绘图
ndash Dirty 模式下 GLThread处于等待状态直到程序发送绘图请求( GLSurfaceViewrequestRender )才调用 RendereronDrawFrame 进行绘图绘制完一帧后重新进入等待状态
bull 在 RendereronDrawFrame 的回调中应用可以通过 SDK提供的 EGL API 绘图也可以转到 native 端使用 NDK提供的 EGL API 绘图
class SurfaceView
SurfaceView
GLSurfaceView GLSurfaceViewRenderer
+ onDrawFrame() void
GLSurfaceViewGLThread
GLSurfaceViewEglHelper
laquointerfaceraquoSurfaceHolder
laquointerfaceraquoSurfaceHolder
Callback
Surface
+ lockCanvas () Canvas+ unlockCanvasAndPost (Canvas) void
laquointerfaceraquoIWindowSession
+ add() void+ relayout() void
SurfaceViewMyWindow
BaseIWindow IWindowStublaquointerfaceraquo
IWindow
+mSurface
+mSession
+mWindow
+mCallbacks
+mSurfaceHolder
+mRenderer
+mGLThread
call
+mRenderer
+mEglHelper
TextureView
bull Since Android 40只在硬件加速环境下起作用bull 具备 SurfaceView 的特性
ndash 但是可以跟其它普通的 View 一样实现 Rotation Screw等变换
ndash 支持 Alpha 可以跟它下方的 View 进行 Alpha 混合
bull 可以基于 TextureView 创建一个 GL Surface 在上面进行 OpenGL渲染
Things become more complicated after Android 30
HW Accelerated 2D Renderingbull Android 30后开始支持硬件加速的 2D 绘图原
有的绘图流程变得更加复杂bull 所谓硬件加速的 2D 绘图就是将 2D Graphics A
PI 的实现改成使用 OpenGL API 来进行绘图bull OpenGL 的绘图模式跟一般的 2D 绘图有很大区
别它需要先将绘图所需的各种素材如贴图多边形顶点阵列 Shader等先加载到当前的 GLContext 然后流水线式的顺序执行绘图指令通过这种方式来充分利用硬件的能力
ViewRootImplbull 当 Actitity 的 View Hierachy 的根节点被添加到 WindowM
anager 的时候( WindowManageraddView ) WindowManager 的实现类 WindowManagerImpl 会创建一个 ViewRootImpl 并把它跟传进来的 View 绑定在一起( ViewRootImplsetView )并且 ViewRootImpl 会根据是否开启硬件加速来决定是否创建一个 HardwareRenderer
bull 在 ViewRootImpl 第一次渲染 View Hierachy 时会创建 Surface 如果开启硬件加速则通过 HardwareRenderer在当前的 UI 线程初始化EGL 绘图环境(类似 GLSurfaceView )
Contbull 在 ViewRootImpl 真正渲染 View Hierachy
时如果开启硬件加速则从 HardwareRenderer获得一个 HardwareCanvas 然后 View Hierachy 的渲染通过 HardwareCanvas 来进行
bull HardwareCanvas 跟一个 native 的 OpenGLRenderer 绑定通过它调用 EGL API 来完成真正的绘制
DisplayList and Hardware Layerbull 为了充分利用硬件加速的能力 Android 30 还引入了 Di
splayList 和 Hardware Layerbull DisplayList 用于记录一系列OpenGL 绘图指令和缓存所需的各种绘图素材( Bitmap Paint Shape Shader )当 View 的内容不发生变化时可以直接使用 DisplayList 进行绘制而不需要重新调用 onDraw
bull Hardware Layer 用于缓存绘制的内存到 Frame Buffer Object 当内容不发生变化时可以直接使用 Layer 进行Layer Composite获得更快的绘图速度
class Hardward2D
DisplayListHardwareCanv as
+ drawDisplayList() void+ drawHardwareLayer() void
Canv as
+ isHardwareAccelerated() voidHardwareLayer
HardwareRenderer
+ initialize() void
HardwareRendererGlRenderer
HardwareRendererGl20Renderer
GLES20Canv as
GLES20RecordingCanv as
GLES20DisplayList
laquonativeraquoDisplayList
laquonativeraquoOpenGLRenderer
laquonativeraquoDisplayListRenderer
ViewAttachInfo
ViewRootImpl
+ setView() void+ scheduleTraversals() void+ performTraversals() void+ relayoutWindow() void
GLES20Layer
GLES20TextureLayer
+mCanvas
+mNativeDisplayList
draw
+mRenderer
+mAttachInfo
+mHardwareRenderer
+mHardwareCanvas
+mResizeBuffer
Reference
bull Android 圖形系統 -- 設計與實做分析
bull How to replace GLSurfaceView with TextureView in Android Ice Cream Sandwich
The End
Thank you for your listeningYours Sincerely Roger
class SurfaceView
SurfaceView
GLSurfaceView GLSurfaceViewRenderer
+ onDrawFrame() void
GLSurfaceViewGLThread
GLSurfaceViewEglHelper
laquointerfaceraquoSurfaceHolder
laquointerfaceraquoSurfaceHolder
Callback
Surface
+ lockCanvas () Canvas+ unlockCanvasAndPost (Canvas) void
laquointerfaceraquoIWindowSession
+ add() void+ relayout() void
SurfaceViewMyWindow
BaseIWindow IWindowStublaquointerfaceraquo
IWindow
+mSurface
+mSession
+mWindow
+mCallbacks
+mSurfaceHolder
+mRenderer
+mGLThread
call
+mRenderer
+mEglHelper
TextureView
bull Since Android 40只在硬件加速环境下起作用bull 具备 SurfaceView 的特性
ndash 但是可以跟其它普通的 View 一样实现 Rotation Screw等变换
ndash 支持 Alpha 可以跟它下方的 View 进行 Alpha 混合
bull 可以基于 TextureView 创建一个 GL Surface 在上面进行 OpenGL渲染
Things become more complicated after Android 30
HW Accelerated 2D Renderingbull Android 30后开始支持硬件加速的 2D 绘图原
有的绘图流程变得更加复杂bull 所谓硬件加速的 2D 绘图就是将 2D Graphics A
PI 的实现改成使用 OpenGL API 来进行绘图bull OpenGL 的绘图模式跟一般的 2D 绘图有很大区
别它需要先将绘图所需的各种素材如贴图多边形顶点阵列 Shader等先加载到当前的 GLContext 然后流水线式的顺序执行绘图指令通过这种方式来充分利用硬件的能力
ViewRootImplbull 当 Actitity 的 View Hierachy 的根节点被添加到 WindowM
anager 的时候( WindowManageraddView ) WindowManager 的实现类 WindowManagerImpl 会创建一个 ViewRootImpl 并把它跟传进来的 View 绑定在一起( ViewRootImplsetView )并且 ViewRootImpl 会根据是否开启硬件加速来决定是否创建一个 HardwareRenderer
bull 在 ViewRootImpl 第一次渲染 View Hierachy 时会创建 Surface 如果开启硬件加速则通过 HardwareRenderer在当前的 UI 线程初始化EGL 绘图环境(类似 GLSurfaceView )
Contbull 在 ViewRootImpl 真正渲染 View Hierachy
时如果开启硬件加速则从 HardwareRenderer获得一个 HardwareCanvas 然后 View Hierachy 的渲染通过 HardwareCanvas 来进行
bull HardwareCanvas 跟一个 native 的 OpenGLRenderer 绑定通过它调用 EGL API 来完成真正的绘制
DisplayList and Hardware Layerbull 为了充分利用硬件加速的能力 Android 30 还引入了 Di
splayList 和 Hardware Layerbull DisplayList 用于记录一系列OpenGL 绘图指令和缓存所需的各种绘图素材( Bitmap Paint Shape Shader )当 View 的内容不发生变化时可以直接使用 DisplayList 进行绘制而不需要重新调用 onDraw
bull Hardware Layer 用于缓存绘制的内存到 Frame Buffer Object 当内容不发生变化时可以直接使用 Layer 进行Layer Composite获得更快的绘图速度
class Hardward2D
DisplayListHardwareCanv as
+ drawDisplayList() void+ drawHardwareLayer() void
Canv as
+ isHardwareAccelerated() voidHardwareLayer
HardwareRenderer
+ initialize() void
HardwareRendererGlRenderer
HardwareRendererGl20Renderer
GLES20Canv as
GLES20RecordingCanv as
GLES20DisplayList
laquonativeraquoDisplayList
laquonativeraquoOpenGLRenderer
laquonativeraquoDisplayListRenderer
ViewAttachInfo
ViewRootImpl
+ setView() void+ scheduleTraversals() void+ performTraversals() void+ relayoutWindow() void
GLES20Layer
GLES20TextureLayer
+mCanvas
+mNativeDisplayList
draw
+mRenderer
+mAttachInfo
+mHardwareRenderer
+mHardwareCanvas
+mResizeBuffer
Reference
bull Android 圖形系統 -- 設計與實做分析
bull How to replace GLSurfaceView with TextureView in Android Ice Cream Sandwich
The End
Thank you for your listeningYours Sincerely Roger
TextureView
bull Since Android 40只在硬件加速环境下起作用bull 具备 SurfaceView 的特性
ndash 但是可以跟其它普通的 View 一样实现 Rotation Screw等变换
ndash 支持 Alpha 可以跟它下方的 View 进行 Alpha 混合
bull 可以基于 TextureView 创建一个 GL Surface 在上面进行 OpenGL渲染
Things become more complicated after Android 30
HW Accelerated 2D Renderingbull Android 30后开始支持硬件加速的 2D 绘图原
有的绘图流程变得更加复杂bull 所谓硬件加速的 2D 绘图就是将 2D Graphics A
PI 的实现改成使用 OpenGL API 来进行绘图bull OpenGL 的绘图模式跟一般的 2D 绘图有很大区
别它需要先将绘图所需的各种素材如贴图多边形顶点阵列 Shader等先加载到当前的 GLContext 然后流水线式的顺序执行绘图指令通过这种方式来充分利用硬件的能力
ViewRootImplbull 当 Actitity 的 View Hierachy 的根节点被添加到 WindowM
anager 的时候( WindowManageraddView ) WindowManager 的实现类 WindowManagerImpl 会创建一个 ViewRootImpl 并把它跟传进来的 View 绑定在一起( ViewRootImplsetView )并且 ViewRootImpl 会根据是否开启硬件加速来决定是否创建一个 HardwareRenderer
bull 在 ViewRootImpl 第一次渲染 View Hierachy 时会创建 Surface 如果开启硬件加速则通过 HardwareRenderer在当前的 UI 线程初始化EGL 绘图环境(类似 GLSurfaceView )
Contbull 在 ViewRootImpl 真正渲染 View Hierachy
时如果开启硬件加速则从 HardwareRenderer获得一个 HardwareCanvas 然后 View Hierachy 的渲染通过 HardwareCanvas 来进行
bull HardwareCanvas 跟一个 native 的 OpenGLRenderer 绑定通过它调用 EGL API 来完成真正的绘制
DisplayList and Hardware Layerbull 为了充分利用硬件加速的能力 Android 30 还引入了 Di
splayList 和 Hardware Layerbull DisplayList 用于记录一系列OpenGL 绘图指令和缓存所需的各种绘图素材( Bitmap Paint Shape Shader )当 View 的内容不发生变化时可以直接使用 DisplayList 进行绘制而不需要重新调用 onDraw
bull Hardware Layer 用于缓存绘制的内存到 Frame Buffer Object 当内容不发生变化时可以直接使用 Layer 进行Layer Composite获得更快的绘图速度
class Hardward2D
DisplayListHardwareCanv as
+ drawDisplayList() void+ drawHardwareLayer() void
Canv as
+ isHardwareAccelerated() voidHardwareLayer
HardwareRenderer
+ initialize() void
HardwareRendererGlRenderer
HardwareRendererGl20Renderer
GLES20Canv as
GLES20RecordingCanv as
GLES20DisplayList
laquonativeraquoDisplayList
laquonativeraquoOpenGLRenderer
laquonativeraquoDisplayListRenderer
ViewAttachInfo
ViewRootImpl
+ setView() void+ scheduleTraversals() void+ performTraversals() void+ relayoutWindow() void
GLES20Layer
GLES20TextureLayer
+mCanvas
+mNativeDisplayList
draw
+mRenderer
+mAttachInfo
+mHardwareRenderer
+mHardwareCanvas
+mResizeBuffer
Reference
bull Android 圖形系統 -- 設計與實做分析
bull How to replace GLSurfaceView with TextureView in Android Ice Cream Sandwich
The End
Thank you for your listeningYours Sincerely Roger
Things become more complicated after Android 30
HW Accelerated 2D Renderingbull Android 30后开始支持硬件加速的 2D 绘图原
有的绘图流程变得更加复杂bull 所谓硬件加速的 2D 绘图就是将 2D Graphics A
PI 的实现改成使用 OpenGL API 来进行绘图bull OpenGL 的绘图模式跟一般的 2D 绘图有很大区
别它需要先将绘图所需的各种素材如贴图多边形顶点阵列 Shader等先加载到当前的 GLContext 然后流水线式的顺序执行绘图指令通过这种方式来充分利用硬件的能力
ViewRootImplbull 当 Actitity 的 View Hierachy 的根节点被添加到 WindowM
anager 的时候( WindowManageraddView ) WindowManager 的实现类 WindowManagerImpl 会创建一个 ViewRootImpl 并把它跟传进来的 View 绑定在一起( ViewRootImplsetView )并且 ViewRootImpl 会根据是否开启硬件加速来决定是否创建一个 HardwareRenderer
bull 在 ViewRootImpl 第一次渲染 View Hierachy 时会创建 Surface 如果开启硬件加速则通过 HardwareRenderer在当前的 UI 线程初始化EGL 绘图环境(类似 GLSurfaceView )
Contbull 在 ViewRootImpl 真正渲染 View Hierachy
时如果开启硬件加速则从 HardwareRenderer获得一个 HardwareCanvas 然后 View Hierachy 的渲染通过 HardwareCanvas 来进行
bull HardwareCanvas 跟一个 native 的 OpenGLRenderer 绑定通过它调用 EGL API 来完成真正的绘制
DisplayList and Hardware Layerbull 为了充分利用硬件加速的能力 Android 30 还引入了 Di
splayList 和 Hardware Layerbull DisplayList 用于记录一系列OpenGL 绘图指令和缓存所需的各种绘图素材( Bitmap Paint Shape Shader )当 View 的内容不发生变化时可以直接使用 DisplayList 进行绘制而不需要重新调用 onDraw
bull Hardware Layer 用于缓存绘制的内存到 Frame Buffer Object 当内容不发生变化时可以直接使用 Layer 进行Layer Composite获得更快的绘图速度
class Hardward2D
DisplayListHardwareCanv as
+ drawDisplayList() void+ drawHardwareLayer() void
Canv as
+ isHardwareAccelerated() voidHardwareLayer
HardwareRenderer
+ initialize() void
HardwareRendererGlRenderer
HardwareRendererGl20Renderer
GLES20Canv as
GLES20RecordingCanv as
GLES20DisplayList
laquonativeraquoDisplayList
laquonativeraquoOpenGLRenderer
laquonativeraquoDisplayListRenderer
ViewAttachInfo
ViewRootImpl
+ setView() void+ scheduleTraversals() void+ performTraversals() void+ relayoutWindow() void
GLES20Layer
GLES20TextureLayer
+mCanvas
+mNativeDisplayList
draw
+mRenderer
+mAttachInfo
+mHardwareRenderer
+mHardwareCanvas
+mResizeBuffer
Reference
bull Android 圖形系統 -- 設計與實做分析
bull How to replace GLSurfaceView with TextureView in Android Ice Cream Sandwich
The End
Thank you for your listeningYours Sincerely Roger
HW Accelerated 2D Renderingbull Android 30后开始支持硬件加速的 2D 绘图原
有的绘图流程变得更加复杂bull 所谓硬件加速的 2D 绘图就是将 2D Graphics A
PI 的实现改成使用 OpenGL API 来进行绘图bull OpenGL 的绘图模式跟一般的 2D 绘图有很大区
别它需要先将绘图所需的各种素材如贴图多边形顶点阵列 Shader等先加载到当前的 GLContext 然后流水线式的顺序执行绘图指令通过这种方式来充分利用硬件的能力
ViewRootImplbull 当 Actitity 的 View Hierachy 的根节点被添加到 WindowM
anager 的时候( WindowManageraddView ) WindowManager 的实现类 WindowManagerImpl 会创建一个 ViewRootImpl 并把它跟传进来的 View 绑定在一起( ViewRootImplsetView )并且 ViewRootImpl 会根据是否开启硬件加速来决定是否创建一个 HardwareRenderer
bull 在 ViewRootImpl 第一次渲染 View Hierachy 时会创建 Surface 如果开启硬件加速则通过 HardwareRenderer在当前的 UI 线程初始化EGL 绘图环境(类似 GLSurfaceView )
Contbull 在 ViewRootImpl 真正渲染 View Hierachy
时如果开启硬件加速则从 HardwareRenderer获得一个 HardwareCanvas 然后 View Hierachy 的渲染通过 HardwareCanvas 来进行
bull HardwareCanvas 跟一个 native 的 OpenGLRenderer 绑定通过它调用 EGL API 来完成真正的绘制
DisplayList and Hardware Layerbull 为了充分利用硬件加速的能力 Android 30 还引入了 Di
splayList 和 Hardware Layerbull DisplayList 用于记录一系列OpenGL 绘图指令和缓存所需的各种绘图素材( Bitmap Paint Shape Shader )当 View 的内容不发生变化时可以直接使用 DisplayList 进行绘制而不需要重新调用 onDraw
bull Hardware Layer 用于缓存绘制的内存到 Frame Buffer Object 当内容不发生变化时可以直接使用 Layer 进行Layer Composite获得更快的绘图速度
class Hardward2D
DisplayListHardwareCanv as
+ drawDisplayList() void+ drawHardwareLayer() void
Canv as
+ isHardwareAccelerated() voidHardwareLayer
HardwareRenderer
+ initialize() void
HardwareRendererGlRenderer
HardwareRendererGl20Renderer
GLES20Canv as
GLES20RecordingCanv as
GLES20DisplayList
laquonativeraquoDisplayList
laquonativeraquoOpenGLRenderer
laquonativeraquoDisplayListRenderer
ViewAttachInfo
ViewRootImpl
+ setView() void+ scheduleTraversals() void+ performTraversals() void+ relayoutWindow() void
GLES20Layer
GLES20TextureLayer
+mCanvas
+mNativeDisplayList
draw
+mRenderer
+mAttachInfo
+mHardwareRenderer
+mHardwareCanvas
+mResizeBuffer
Reference
bull Android 圖形系統 -- 設計與實做分析
bull How to replace GLSurfaceView with TextureView in Android Ice Cream Sandwich
The End
Thank you for your listeningYours Sincerely Roger
ViewRootImplbull 当 Actitity 的 View Hierachy 的根节点被添加到 WindowM
anager 的时候( WindowManageraddView ) WindowManager 的实现类 WindowManagerImpl 会创建一个 ViewRootImpl 并把它跟传进来的 View 绑定在一起( ViewRootImplsetView )并且 ViewRootImpl 会根据是否开启硬件加速来决定是否创建一个 HardwareRenderer
bull 在 ViewRootImpl 第一次渲染 View Hierachy 时会创建 Surface 如果开启硬件加速则通过 HardwareRenderer在当前的 UI 线程初始化EGL 绘图环境(类似 GLSurfaceView )
Contbull 在 ViewRootImpl 真正渲染 View Hierachy
时如果开启硬件加速则从 HardwareRenderer获得一个 HardwareCanvas 然后 View Hierachy 的渲染通过 HardwareCanvas 来进行
bull HardwareCanvas 跟一个 native 的 OpenGLRenderer 绑定通过它调用 EGL API 来完成真正的绘制
DisplayList and Hardware Layerbull 为了充分利用硬件加速的能力 Android 30 还引入了 Di
splayList 和 Hardware Layerbull DisplayList 用于记录一系列OpenGL 绘图指令和缓存所需的各种绘图素材( Bitmap Paint Shape Shader )当 View 的内容不发生变化时可以直接使用 DisplayList 进行绘制而不需要重新调用 onDraw
bull Hardware Layer 用于缓存绘制的内存到 Frame Buffer Object 当内容不发生变化时可以直接使用 Layer 进行Layer Composite获得更快的绘图速度
class Hardward2D
DisplayListHardwareCanv as
+ drawDisplayList() void+ drawHardwareLayer() void
Canv as
+ isHardwareAccelerated() voidHardwareLayer
HardwareRenderer
+ initialize() void
HardwareRendererGlRenderer
HardwareRendererGl20Renderer
GLES20Canv as
GLES20RecordingCanv as
GLES20DisplayList
laquonativeraquoDisplayList
laquonativeraquoOpenGLRenderer
laquonativeraquoDisplayListRenderer
ViewAttachInfo
ViewRootImpl
+ setView() void+ scheduleTraversals() void+ performTraversals() void+ relayoutWindow() void
GLES20Layer
GLES20TextureLayer
+mCanvas
+mNativeDisplayList
draw
+mRenderer
+mAttachInfo
+mHardwareRenderer
+mHardwareCanvas
+mResizeBuffer
Reference
bull Android 圖形系統 -- 設計與實做分析
bull How to replace GLSurfaceView with TextureView in Android Ice Cream Sandwich
The End
Thank you for your listeningYours Sincerely Roger
Contbull 在 ViewRootImpl 真正渲染 View Hierachy
时如果开启硬件加速则从 HardwareRenderer获得一个 HardwareCanvas 然后 View Hierachy 的渲染通过 HardwareCanvas 来进行
bull HardwareCanvas 跟一个 native 的 OpenGLRenderer 绑定通过它调用 EGL API 来完成真正的绘制
DisplayList and Hardware Layerbull 为了充分利用硬件加速的能力 Android 30 还引入了 Di
splayList 和 Hardware Layerbull DisplayList 用于记录一系列OpenGL 绘图指令和缓存所需的各种绘图素材( Bitmap Paint Shape Shader )当 View 的内容不发生变化时可以直接使用 DisplayList 进行绘制而不需要重新调用 onDraw
bull Hardware Layer 用于缓存绘制的内存到 Frame Buffer Object 当内容不发生变化时可以直接使用 Layer 进行Layer Composite获得更快的绘图速度
class Hardward2D
DisplayListHardwareCanv as
+ drawDisplayList() void+ drawHardwareLayer() void
Canv as
+ isHardwareAccelerated() voidHardwareLayer
HardwareRenderer
+ initialize() void
HardwareRendererGlRenderer
HardwareRendererGl20Renderer
GLES20Canv as
GLES20RecordingCanv as
GLES20DisplayList
laquonativeraquoDisplayList
laquonativeraquoOpenGLRenderer
laquonativeraquoDisplayListRenderer
ViewAttachInfo
ViewRootImpl
+ setView() void+ scheduleTraversals() void+ performTraversals() void+ relayoutWindow() void
GLES20Layer
GLES20TextureLayer
+mCanvas
+mNativeDisplayList
draw
+mRenderer
+mAttachInfo
+mHardwareRenderer
+mHardwareCanvas
+mResizeBuffer
Reference
bull Android 圖形系統 -- 設計與實做分析
bull How to replace GLSurfaceView with TextureView in Android Ice Cream Sandwich
The End
Thank you for your listeningYours Sincerely Roger
DisplayList and Hardware Layerbull 为了充分利用硬件加速的能力 Android 30 还引入了 Di
splayList 和 Hardware Layerbull DisplayList 用于记录一系列OpenGL 绘图指令和缓存所需的各种绘图素材( Bitmap Paint Shape Shader )当 View 的内容不发生变化时可以直接使用 DisplayList 进行绘制而不需要重新调用 onDraw
bull Hardware Layer 用于缓存绘制的内存到 Frame Buffer Object 当内容不发生变化时可以直接使用 Layer 进行Layer Composite获得更快的绘图速度
class Hardward2D
DisplayListHardwareCanv as
+ drawDisplayList() void+ drawHardwareLayer() void
Canv as
+ isHardwareAccelerated() voidHardwareLayer
HardwareRenderer
+ initialize() void
HardwareRendererGlRenderer
HardwareRendererGl20Renderer
GLES20Canv as
GLES20RecordingCanv as
GLES20DisplayList
laquonativeraquoDisplayList
laquonativeraquoOpenGLRenderer
laquonativeraquoDisplayListRenderer
ViewAttachInfo
ViewRootImpl
+ setView() void+ scheduleTraversals() void+ performTraversals() void+ relayoutWindow() void
GLES20Layer
GLES20TextureLayer
+mCanvas
+mNativeDisplayList
draw
+mRenderer
+mAttachInfo
+mHardwareRenderer
+mHardwareCanvas
+mResizeBuffer
Reference
bull Android 圖形系統 -- 設計與實做分析
bull How to replace GLSurfaceView with TextureView in Android Ice Cream Sandwich
The End
Thank you for your listeningYours Sincerely Roger
class Hardward2D
DisplayListHardwareCanv as
+ drawDisplayList() void+ drawHardwareLayer() void
Canv as
+ isHardwareAccelerated() voidHardwareLayer
HardwareRenderer
+ initialize() void
HardwareRendererGlRenderer
HardwareRendererGl20Renderer
GLES20Canv as
GLES20RecordingCanv as
GLES20DisplayList
laquonativeraquoDisplayList
laquonativeraquoOpenGLRenderer
laquonativeraquoDisplayListRenderer
ViewAttachInfo
ViewRootImpl
+ setView() void+ scheduleTraversals() void+ performTraversals() void+ relayoutWindow() void
GLES20Layer
GLES20TextureLayer
+mCanvas
+mNativeDisplayList
draw
+mRenderer
+mAttachInfo
+mHardwareRenderer
+mHardwareCanvas
+mResizeBuffer
Reference
bull Android 圖形系統 -- 設計與實做分析
bull How to replace GLSurfaceView with TextureView in Android Ice Cream Sandwich
The End
Thank you for your listeningYours Sincerely Roger
Reference
bull Android 圖形系統 -- 設計與實做分析
bull How to replace GLSurfaceView with TextureView in Android Ice Cream Sandwich
The End
Thank you for your listeningYours Sincerely Roger
The End
Thank you for your listeningYours Sincerely Roger